From 2692193e54e4dd6c0117dcdb85368dc83bb04f1a Mon Sep 17 00:00:00 2001 From: Roman / Nea Date: Mon, 18 Apr 2022 17:33:32 +0200 Subject: Mob loot recipe PR (#81) * entity renderer (somewhat functionaL) * more modifiers and entities * Fix cookie fuckup * add neu repo as resource pack, cause why not at this point * add tabs, because i can * add extra skin parts and make less tabs * hot tall men * fix texture offsets and also parts:true * some untested changes * still broken, but better (just like me (stop being edgy nea ( no u )))) * stuff (with er skeletons * niceities * skytils interop * horseys * horseys ouch * panos * stupid tests :angery: * NPE * add drop chance * colored leather armo * finish off * move shit into hover cause items look pretty terrible * Update 2.1.md * better recipe display name * always show mobs toggle * moving parts --- .github/CODEOWNERS | 2 + Update Notes/2.1.md | 1 + build.gradle.kts | 193 ++++----- .../moulberry/notenoughupdates/NEUManager.java | 18 +- .../moulberry/notenoughupdates/NEUOverlay.java | 2 +- .../notenoughupdates/NEURepoResourcePack.java | 75 ++++ .../notenoughupdates/NotEnoughUpdates.java | 9 + .../commands/EntityViewerCommand.java | 81 ++++ .../commands/dev/DevTestCommand.java | 2 +- .../miscfeatures/entityviewer/AgeModifier.java | 30 ++ .../miscfeatures/entityviewer/ChargedModifier.java | 17 + .../miscfeatures/entityviewer/EntityViewer.java | 177 +++++++++ .../entityviewer/EntityViewerModifier.java | 8 + .../entityviewer/EquipmentModifier.java | 72 ++++ .../miscfeatures/entityviewer/GUIClientPlayer.java | 40 ++ .../miscfeatures/entityviewer/HorseModifier.java | 66 +++ .../entityviewer/InvisibleModifier.java | 12 + .../miscfeatures/entityviewer/RidingModifier.java | 14 + .../miscfeatures/entityviewer/SkinModifier.java | 46 +++ .../miscfeatures/entityviewer/WitherModifier.java | 29 ++ .../notenoughupdates/miscgui/GuiItemRecipe.java | 199 +++++++--- .../mixins/AccessorEntityAgeable.java | 12 + .../mixins/AccessorEntityArmorStand.java | 12 + .../notenoughupdates/mixins/AccessorMinecraft.java | 14 + .../mixins/MixinEntityAgeable.java | 1 + .../notenoughupdates/mixins/MixinEntityHorse.java | 17 + .../mixins/MixinEntitySkeleton.java | 17 + .../notenoughupdates/options/NEUConfig.java | 4 + .../options/seperateSections/Itemlist.java | 10 + .../profileviewer/GuiProfileViewer.java | 36 +- .../notenoughupdates/profileviewer/Panorama.java | 38 ++ .../notenoughupdates/recipes/CraftingOverlay.java | 2 +- .../notenoughupdates/recipes/CraftingRecipe.java | 257 ++++++------ .../notenoughupdates/recipes/ForgeRecipe.java | 442 ++++++++++----------- .../notenoughupdates/recipes/Ingredient.java | 5 +- .../notenoughupdates/recipes/MobLootRecipe.java | 309 ++++++++++++++ .../notenoughupdates/recipes/NeuRecipe.java | 24 +- .../notenoughupdates/recipes/RecipeGenerator.java | 169 +++++++- .../notenoughupdates/recipes/RecipeType.java | 59 +++ .../recipes/VillagerTradeRecipe.java | 256 ++++++------ .../moulberry/notenoughupdates/util/ItemUtils.java | 33 ++ .../moulberry/notenoughupdates/util/JsonUtils.java | 42 ++ .../notenoughupdates/util/SkytilsCompat.java | 82 ++++ .../moulberry/notenoughupdates/util/Utils.java | 17 +- .../resources/assets/notenoughupdates/dream.json | 49 +++ .../textures/gui/crafting_table_tall.png | Bin 0 -> 12019 bytes .../textures/gui/entity_viewer.png | Bin 0 -> 8085 bytes .../notenoughupdates/textures/gui/forge_recipe.png | Bin 889 -> 0 bytes .../textures/gui/forge_recipe_tall.png | Bin 0 -> 9257 bytes .../textures/gui/mob_loot_tall.png | Bin 0 -> 9503 bytes .../assets/notenoughupdates/textures/gui/tab.png | Bin 0 -> 1247 bytes .../textures/gui/villager_recipe.png | Bin 8633 -> 0 bytes .../textures/gui/villager_recipe_tall.png | Bin 0 -> 9218 bytes src/main/resources/mixins.notenoughupdates.json | 7 + 54 files changed, 2302 insertions(+), 705 deletions(-) create mode 100644 .github/CODEOWNERS create mode 100644 src/main/java/io/github/moulberry/notenoughupdates/NEURepoResourcePack.java create mode 100644 src/main/java/io/github/moulberry/notenoughupdates/commands/EntityViewerCommand.java create mode 100644 src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/AgeModifier.java create mode 100644 src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/ChargedModifier.java create mode 100644 src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/EntityViewer.java create mode 100644 src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/EntityViewerModifier.java create mode 100644 src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/EquipmentModifier.java create mode 100644 src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/GUIClientPlayer.java create mode 100644 src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/HorseModifier.java create mode 100644 src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/InvisibleModifier.java create mode 100644 src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/RidingModifier.java create mode 100644 src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/SkinModifier.java create mode 100644 src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/WitherModifier.java create mode 100644 src/main/java/io/github/moulberry/notenoughupdates/mixins/AccessorEntityAgeable.java create mode 100644 src/main/java/io/github/moulberry/notenoughupdates/mixins/AccessorEntityArmorStand.java create mode 100644 src/main/java/io/github/moulberry/notenoughupdates/mixins/AccessorMinecraft.java create mode 100644 src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityHorse.java create mode 100644 src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntitySkeleton.java create mode 100644 src/main/java/io/github/moulberry/notenoughupdates/recipes/MobLootRecipe.java create mode 100644 src/main/java/io/github/moulberry/notenoughupdates/recipes/RecipeType.java create mode 100644 src/main/java/io/github/moulberry/notenoughupdates/util/ItemUtils.java create mode 100644 src/main/java/io/github/moulberry/notenoughupdates/util/JsonUtils.java create mode 100644 src/main/java/io/github/moulberry/notenoughupdates/util/SkytilsCompat.java create mode 100644 src/main/resources/assets/notenoughupdates/dream.json create mode 100644 src/main/resources/assets/notenoughupdates/textures/gui/crafting_table_tall.png create mode 100644 src/main/resources/assets/notenoughupdates/textures/gui/entity_viewer.png delete mode 100644 src/main/resources/assets/notenoughupdates/textures/gui/forge_recipe.png create mode 100644 src/main/resources/assets/notenoughupdates/textures/gui/forge_recipe_tall.png create mode 100644 src/main/resources/assets/notenoughupdates/textures/gui/mob_loot_tall.png create mode 100644 src/main/resources/assets/notenoughupdates/textures/gui/tab.png delete mode 100644 src/main/resources/assets/notenoughupdates/textures/gui/villager_recipe.png create mode 100644 src/main/resources/assets/notenoughupdates/textures/gui/villager_recipe_tall.png diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..2381ceb8 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,2 @@ +/src/main/java/io/github/moulberry/notenoughupdates/recipes/* @romangraef +/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiItemRecipe.java @romangraef diff --git a/Update Notes/2.1.md b/Update Notes/2.1.md index 18a4ba8a..dff52a65 100644 --- a/Update Notes/2.1.md +++ b/Update Notes/2.1.md @@ -19,6 +19,7 @@ - Added support for official Hypixel wiki, can be toggled in /neu misc - DeDiamondPro ### **Minor Changes:** - Add built-in recipes for forge crafts - nea89 +- Add mob drop viewer in the recipe viewer - nea89 - Add Stranded Villager Trades to the item list - nea89 - Make cata xp in /pv be calculated on how many runs you have and shows master mode xp rates - Added a config option to hide Dwarven Mines waypoints when already at the location - Lulonaut diff --git a/build.gradle.kts b/build.gradle.kts index e134387e..3ffaf61a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,58 +1,76 @@ -import java.io.ByteArrayOutputStream import net.minecraftforge.gradle.user.ReobfMappingType +import java.io.ByteArrayOutputStream + plugins { - java - id("net.minecraftforge.gradle.forge") version "6f5327738df" - id("com.github.johnrengelman.shadow") version "6.1.0" - id("org.spongepowered.mixin") version "d75e32e" + java + id("net.minecraftforge.gradle.forge") version "6f5327738df" + id("com.github.johnrengelman.shadow") version "6.1.0" + id("org.spongepowered.mixin") version "d75e32e" } group = "io.github.moulberry" val baseVersion = "2.1" -var buildVersion = properties["BUILD_VERSION"] -if (buildVersion == null) { - val stdout = ByteArrayOutputStream() - val execResult = exec { - commandLine("git", "describe", "--always", "--first-parent", "--abbrev=7") - standardOutput = stdout - } - if (execResult.exitValue == 0) - buildVersion = String(stdout.toByteArray()).trim() +val buildExtra = mutableListOf() +val buildVersion = properties["BUILD_VERSION"] as? String +if (buildVersion != null) + buildExtra.add(buildVersion) +val githubCi = properties["GITHUB_ACTIONS"] as? String +if (githubCi == "true") + buildExtra.add("ci") + +val stdout = ByteArrayOutputStream() +val execResult = exec { + commandLine("git", "describe", "--always", "--first-parent", "--abbrev=7") + standardOutput = stdout + isIgnoreExitValue = true +} +if (execResult.exitValue == 0) { + buildExtra.add(String(stdout.toByteArray()).trim()) +} + +val gitDiffStdout = ByteArrayOutputStream() +val gitDiffResult = exec { + commandLine("git", "status", "--porcelain") + standardOutput = gitDiffStdout + isIgnoreExitValue = true +} +if (gitDiffStdout.toByteArray().isNotEmpty()) { + buildExtra.add("dirty") } -version = baseVersion + (buildVersion?.let { "+$it" } ?: "") +version = baseVersion + (if (buildExtra.isEmpty()) "" else buildExtra.joinToString(prefix = "+", separator = ".")) // Toolchains: java { - // Forge Gradle currently prevents using the toolchain: toolchain.languageVersion.set(JavaLanguageVersion.of(8)) - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 + // Forge Gradle currently prevents using the toolchain: toolchain.languageVersion.set(JavaLanguageVersion.of(8)) + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 } minecraft { - version = "1.8.9-11.15.1.2318-1.8.9" - runDir = "run" - mappings = "stable_22" - clientJvmArgs.addAll( - listOf( - "-Dmixin.debug=true", - "-Dasmhelper.verbose=true" - ) - ) - clientRunArgs.addAll( - listOf( - "--tweakClass org.spongepowered.asm.launch.MixinTweaker", - "--mixin mixins.notenoughupdates.json" - ) - ) + version = "1.8.9-11.15.1.2318-1.8.9" + runDir = "run" + mappings = "stable_22" + clientJvmArgs.addAll( + listOf( + "-Dmixin.debug=true", + "-Dasmhelper.verbose=true" + ) + ) + clientRunArgs.addAll( + listOf( + "--tweakClass org.spongepowered.asm.launch.MixinTweaker", + "--mixin mixins.notenoughupdates.json" + ) + ) } mixin { - add(sourceSets.main.get(), "mixins.notenoughupdates.refmap.json") + add(sourceSets.main.get(), "mixins.notenoughupdates.refmap.json") } // Dependencies: @@ -67,14 +85,14 @@ dependencies { annotationProcessor("org.spongepowered:mixin:0.7.11-SNAPSHOT") implementation("com.fasterxml.jackson.core:jackson-core:2.13.1") implementation("info.bliki.wiki:bliki-core:3.1.0") - testImplementation("org.junit.jupiter:junit-jupiter:5.8.2") + testImplementation("org.junit.jupiter:junit-jupiter:5.8.2") } // Tasks: tasks.withType(JavaCompile::class) { - options.encoding = "UTF-8" + options.encoding = "UTF-8" } tasks.named("test") { @@ -82,72 +100,61 @@ tasks.named("test") { } tasks.withType(Jar::class) { - archiveBaseName.set("NotEnoughUpdates") - manifest.attributes.run { - this["Main-Class"] = "NotSkyblockAddonsInstallerFrame" - this["TweakClass"] = "org.spongepowered.asm.launch.MixinTweaker" - this["MixinConfigs"] = "mixins.notenoughupdates.json" - this["FMLCorePluginContainsFMLMod"] = "true" - this["ForceLoadAsMod"] = "true" - this["FMLAT"] = "notenoughupdates_at.cfg" - } + archiveBaseName.set("NotEnoughUpdates") + manifest.attributes.run { + this["Main-Class"] = "NotSkyblockAddonsInstallerFrame" + this["TweakClass"] = "org.spongepowered.asm.launch.MixinTweaker" + this["MixinConfigs"] = "mixins.notenoughupdates.json" + this["FMLCorePluginContainsFMLMod"] = "true" + this["ForceLoadAsMod"] = "true" + this["FMLAT"] = "notenoughupdates_at.cfg" + } } tasks.shadowJar { - archiveClassifier.set("dep") - exclude( - "module-info.class", - "LICENSE.txt" - ) - dependencies { - include(dependency("org.spongepowered:mixin:0.7.11-SNAPSHOT")) - - include(dependency("commons-io:commons-io")) - include(dependency("org.apache.commons:commons-lang3")) - include(dependency("com.fasterxml.jackson.core:jackson-databind:2.10.2")) - include(dependency("com.fasterxml.jackson.core:jackson-annotations:2.10.2")) - include(dependency("com.fasterxml.jackson.core:jackson-core:2.10.2")) - - include(dependency("info.bliki.wiki:bliki-core:3.1.0")) - include(dependency("org.slf4j:slf4j-api:1.7.18")) - include(dependency("org.luaj:luaj-jse:3.0.1")) - } - fun relocate(name: String) = relocate(name, "io.github.moulberry.notenoughupdates.deps.$name") - relocate("com.fasterxml.jackson") - relocate("org.eclipse") - relocate("org.slf4j") + archiveClassifier.set("dep") + exclude( + "module-info.class", + "LICENSE.txt" + ) + dependencies { + include(dependency("org.spongepowered:mixin:0.7.11-SNAPSHOT")) + + include(dependency("commons-io:commons-io")) + include(dependency("org.apache.commons:commons-lang3")) + include(dependency("com.fasterxml.jackson.core:jackson-databind:2.10.2")) + include(dependency("com.fasterxml.jackson.core:jackson-annotations:2.10.2")) + include(dependency("com.fasterxml.jackson.core:jackson-core:2.10.2")) + + include(dependency("info.bliki.wiki:bliki-core:3.1.0")) + include(dependency("org.slf4j:slf4j-api:1.7.18")) + include(dependency("org.luaj:luaj-jse:3.0.1")) + } + fun relocate(name: String) = relocate(name, "io.github.moulberry.notenoughupdates.deps.$name") + relocate("com.fasterxml.jackson") + relocate("org.eclipse") + relocate("org.slf4j") } tasks.build.get().dependsOn(tasks.shadowJar) reobf { - create("shadowJar") { - mappingType = ReobfMappingType.SEARGE - } + create("shadowJar") { + mappingType = ReobfMappingType.SEARGE + } } tasks.processResources { - from(sourceSets.main.get().resources.srcDirs) - filesMatching("mcmod.info") { - expand( - "version" to project.version, - "mcversion" to minecraft.version - ) - } - rename("(.+_at.cfg)".toPattern(), "META-INF/$1") -} - -val moveResources by tasks.creating { - doLast { - ant.withGroovyBuilder { - "move"( - "file" to "$buildDir/resources/main", - "todir" to "$buildDir/classes/java" - ) - } - } - dependsOn(tasks.processResources) -} - -tasks.classes { dependsOn(moveResources) } + from(sourceSets.main.get().resources.srcDirs) + filesMatching("mcmod.info") { + expand( + "version" to project.version, + "mcversion" to minecraft.version + ) + } + rename("(.+_at.cfg)".toPattern(), "META-INF/$1") +} +sourceSets.main { + output.setResourcesDir(file("$buildDir/classes/java/main")) +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java index abe0bdcf..6572431b 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java @@ -895,12 +895,12 @@ public class NEUManager { String clickcommand = item.get("clickcommand").getAsString(); switch (clickcommand.intern()) { case "viewrecipe": - displayGuiItemRecipe(internalName, null); + displayGuiItemRecipe(internalName); break; case "viewoption": neu.sendChatMessage("/viewpotion " + internalName.split(";")[0].toLowerCase(Locale.ROOT)); } - displayGuiItemRecipe(internalName, ""); + displayGuiItemRecipe(internalName); } public void showRecipe(String internalName) { @@ -990,16 +990,16 @@ public class NEUManager { List usages = getAvailableUsagesFor(internalName); if (usages.isEmpty()) return false; Minecraft.getMinecraft().displayGuiScreen( - new GuiItemRecipe("Item Usages", usages, this)); + new GuiItemRecipe(usages, this)); return true; } - public boolean displayGuiItemRecipe(String internalName, String text) { + public boolean displayGuiItemRecipe(String internalName) { if (!recipesMap.containsKey(internalName)) return false; List recipes = getAvailableRecipesFor(internalName); if (recipes.isEmpty()) return false; Minecraft.getMinecraft().displayGuiScreen( - new GuiItemRecipe(text != null ? text : "Item Recipe", recipes, this)); + new GuiItemRecipe(recipes, this)); return true; } @@ -1010,7 +1010,7 @@ public class NEUManager { public boolean failViewItem(String text) { if (viewItemAttemptID != null && !viewItemAttemptID.isEmpty()) { if (System.currentTimeMillis() - viewItemAttemptTime < 500) { - return displayGuiItemRecipe(viewItemAttemptID, text); + return displayGuiItemRecipe(viewItemAttemptID); } } return false; @@ -1570,4 +1570,10 @@ public class NEUManager { } } } + + public ItemStack createItem(String internalname) { + JsonObject jsonObject = itemMap.get(internalname); + if (jsonObject == null) return null; + return jsonToStack(jsonObject); + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java index 7965abae..8d0955bb 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java @@ -1358,7 +1358,7 @@ public class NEUOverlay extends Gui { } if (getSortMode() == SORT_MODE_ALL) { - return !internalname.matches(mobRegex); + return NotEnoughUpdates.INSTANCE.config.itemlist.alwaysShowMonsters || !internalname.matches(mobRegex); } else if (getSortMode() == SORT_MODE_MOB) { return internalname.matches(mobRegex); } else if (getSortMode() == SORT_MODE_PET) { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEURepoResourcePack.java b/src/main/java/io/github/moulberry/notenoughupdates/NEURepoResourcePack.java new file mode 100644 index 00000000..2a5cda92 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/NEURepoResourcePack.java @@ -0,0 +1,75 @@ +package io.github.moulberry.notenoughupdates; + +import com.google.gson.JsonObject; +import net.minecraft.client.resources.IResourcePack; +import net.minecraft.client.resources.data.IMetadataSection; +import net.minecraft.client.resources.data.IMetadataSerializer; +import net.minecraft.util.ResourceLocation; + +import java.awt.image.BufferedImage; +import java.io.*; +import java.util.HashSet; +import java.util.Set; + +public class NEURepoResourcePack implements IResourcePack { + + File repoLocation; + Set resourceDomains = new HashSet<>(); + + public NEURepoResourcePack(File repoLocation, String domain) { + this.repoLocation = repoLocation; + resourceDomains.add(domain); + } + + public boolean loadRepoLocation() { + if (repoLocation != null) return true; + NotEnoughUpdates instance = NotEnoughUpdates.INSTANCE; + if (instance == null) return false; + NEUManager manager = instance.manager; + if (manager == null) return false; + repoLocation = manager.repoLocation; + return repoLocation != null; + } + + public File getFileForResource(ResourceLocation loc) { + if (repoLocation == null) { + if (!loadRepoLocation()) + return null; + } + if (!"neurepo".equals(loc.getResourceDomain())) { + return null; + } + return new File(repoLocation, loc.getResourcePath()); + } + + @Override + public InputStream getInputStream(ResourceLocation resourceLocation) throws IOException { + return new BufferedInputStream(new FileInputStream(getFileForResource(resourceLocation))); + } + + @Override + public boolean resourceExists(ResourceLocation resourceLocation) { + File file = getFileForResource(resourceLocation); + return file != null && file.exists(); + } + + @Override + public Set getResourceDomains() { + return resourceDomains; + } + + @Override + public T getPackMetadata(IMetadataSerializer iMetadataSerializer, String s) throws IOException { + return iMetadataSerializer.parseMetadataSection(s, new JsonObject()); + } + + @Override + public BufferedImage getPackImage() throws IOException { + return null; + } + + @Override + public String getPackName() { + return "NEU Repo Resources"; + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java index 0a77c677..6b2fd09e 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java @@ -35,6 +35,7 @@ import io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.Custom import io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.DwarvenMinesTextures; import io.github.moulberry.notenoughupdates.miscgui.CalendarOverlay; import io.github.moulberry.notenoughupdates.miscgui.InventoryStorageSelector; +import io.github.moulberry.notenoughupdates.mixins.AccessorMinecraft; import io.github.moulberry.notenoughupdates.options.NEUConfig; import io.github.moulberry.notenoughupdates.overlays.FuelBar; import io.github.moulberry.notenoughupdates.overlays.OverlayManager; @@ -58,6 +59,7 @@ import net.minecraft.world.biome.BiomeGenJungle; import net.minecraft.world.biome.BiomeGenMesa; import net.minecraft.world.biome.BiomeGenSnow; import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.client.FMLClientHandler; import net.minecraftforge.fml.client.registry.ClientRegistry; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod.EventHandler; @@ -160,6 +162,13 @@ public class NotEnoughUpdates { return this.neuDir; } + public NotEnoughUpdates() { + // Budget Construction Event + ((AccessorMinecraft) FMLClientHandler.instance().getClient()) + .onGetDefaultResourcePacks() + .add(new NEURepoResourcePack(null, "neurepo")); + } + /** * Instantiates NEUIo, NEUManager and NEUOverlay instances. Registers keybinds and adds a shutdown hook to clear tmp folder. */ diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/EntityViewerCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/EntityViewerCommand.java new file mode 100644 index 00000000..c7b1862e --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/EntityViewerCommand.java @@ -0,0 +1,81 @@ +package io.github.moulberry.notenoughupdates.commands; + +import com.google.common.collect.Lists; +import io.github.moulberry.notenoughupdates.miscfeatures.entityviewer.EntityViewer; +import net.minecraft.client.Minecraft; +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.event.ClickEvent; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.ChatStyle; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; + +import java.util.Arrays; +import java.util.List; +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedDeque; + +public class EntityViewerCommand extends ClientCommandBase { + public EntityViewerCommand() { + super("neushowentity"); + MinecraftForge.EVENT_BUS.register(this); + } + + @Override + public List getCommandAliases() { + return Lists.newArrayList("neuentityviewer"); + } + + @Override + public String getCommandUsage(ICommandSender sender) { + return EnumChatFormatting.RED + "Use /neushowentity list"; + } + + public void showUsage(ICommandSender sender) { + sender.addChatMessage(new ChatComponentText(getCommandUsage(sender))); + } + + private final Queue queuedGUIS = new ConcurrentLinkedDeque<>(); + + @SubscribeEvent + public void onTick(TickEvent event) { + if (Minecraft.getMinecraft().currentScreen == null) { + EntityViewer poll = queuedGUIS.poll(); + if (poll == null) return; + Minecraft.getMinecraft().displayGuiScreen(poll); + } + } + + @Override + public void processCommand(ICommandSender sender, String[] strings) throws CommandException { + if (strings.length == 0) { + showUsage(sender); + return; + } + if (strings[0].equals("list")) { + for (String label : EntityViewer.validEntities.keySet()) { + sender.addChatMessage(new ChatComponentText(EnumChatFormatting.BLUE + " " + label) + .setChatStyle(new ChatStyle().setChatClickEvent( + new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/neuentityviewer " + label)))); + } + return; + } + EntityLivingBase entityLivingBase; + if (strings[0].startsWith("@")) { + ResourceLocation resourceLocation = new ResourceLocation(strings[0].substring(1)); + entityLivingBase = EntityViewer.constructEntity(resourceLocation); + } else { + entityLivingBase = EntityViewer.constructEntity(strings[0], Arrays.copyOfRange(strings, 1, strings.length)); + } + if (entityLivingBase == null) { + sender.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + "Could not create that entity")); + return; + } + queuedGUIS.add(new EntityViewer(strings[0], entityLivingBase)); + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DevTestCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DevTestCommand.java index 53a7894b..27944c92 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DevTestCommand.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DevTestCommand.java @@ -1,4 +1,4 @@ -package io.github.moulberry.notenoughupdates.commands.dev; + package io.github.moulberry.notenoughupdates.commands.dev; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/AgeModifier.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/AgeModifier.java new file mode 100644 index 00000000..5884512f --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/AgeModifier.java @@ -0,0 +1,30 @@ +package io.github.moulberry.notenoughupdates.miscfeatures.entityviewer; + +import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.mixins.AccessorEntityAgeable; +import io.github.moulberry.notenoughupdates.mixins.AccessorEntityArmorStand; +import net.minecraft.entity.EntityAgeable; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.item.EntityArmorStand; +import net.minecraft.entity.monster.EntityZombie; + +public class AgeModifier extends EntityViewerModifier { + @Override + public EntityLivingBase applyModifier(EntityLivingBase base, JsonObject info) { + boolean baby = info.has("baby") && info.get("baby").getAsBoolean(); + if (base instanceof EntityAgeable) { + ((AccessorEntityAgeable) base).setGrowingAgeDirect(baby ? -1 : 1); + return base; + } + if (base instanceof EntityZombie) { + ((EntityZombie) base).setChild(baby); + return base; + } + if (base instanceof EntityArmorStand) { + ((AccessorEntityArmorStand) base).setSmallDirect(baby); + return base; + } + System.out.println("Cannot apply age to a non ageable entity: " + base); + return null; + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/ChargedModifier.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/ChargedModifier.java new file mode 100644 index 00000000..17dce66d --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/ChargedModifier.java @@ -0,0 +1,17 @@ +package io.github.moulberry.notenoughupdates.miscfeatures.entityviewer; + +import com.google.gson.JsonObject; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.monster.EntityCreeper; + +public class ChargedModifier extends EntityViewerModifier { + + @Override + public EntityLivingBase applyModifier(EntityLivingBase base, JsonObject info) { + if (base instanceof EntityCreeper) { + base.getDataWatcher().updateObject(17, (byte) 1); + return base; + } + return null; + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/EntityViewer.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/EntityViewer.java new file mode 100644 index 00000000..e9075e47 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/EntityViewer.java @@ -0,0 +1,177 @@ +package io.github.moulberry.notenoughupdates.miscfeatures.entityviewer; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.util.Utils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.gui.inventory.GuiInventory; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.boss.EntityDragon; +import net.minecraft.entity.boss.EntityWither; +import net.minecraft.entity.item.EntityArmorStand; +import net.minecraft.entity.monster.*; +import net.minecraft.entity.passive.*; +import net.minecraft.util.ResourceLocation; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.function.Supplier; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; + +public class EntityViewer extends GuiScreen { + + public static Map> validEntities = new HashMap>() {{ + put("Zombie", () -> new EntityZombie(null)); + put("Chicken", () -> new EntityChicken(null)); + put("Slime", () -> new EntitySlime(null)); + put("Wolf", () -> new EntityWolf(null)); + put("Skeleton", () -> new EntitySkeleton(null)); + put("Creeper", () -> new EntityCreeper(null)); + put("Ocelot", () -> new EntityOcelot(null)); + put("Blaze", () -> new EntityBlaze(null)); + put("Rabbit", () -> new EntityRabbit(null)); + put("Sheep", () -> new EntitySheep(null)); + put("Horse", () -> new EntityHorse(null)); + put("Eisengolem", () -> new EntityIronGolem(null)); + put("Silverfish", () -> new EntitySilverfish(null)); + put("Witch", () -> new EntityWitch(null)); + put("Endermite", () -> new EntityEndermite(null)); + put("Snowman", () -> new EntitySnowman(null)); + put("Villager", () -> new EntityVillager(null)); + put("Guardian", () -> new EntityGuardian(null)); + put("ArmorStand", () -> new EntityArmorStand(null)); + put("Squid", () -> new EntitySquid(null)); + put("Bat", () -> new EntityBat(null)); + put("Spider", () -> new EntitySpider(null)); + put("CaveSpider", () -> new EntityCaveSpider(null)); + put("Pigman", () -> new EntityPigZombie(null)); + put("Ghast", () -> new EntityGhast(null)); + put("MagmaCube", () -> new EntityMagmaCube(null)); + put("Wither", () -> new EntityWither(null)); + put("Enderman", () -> new EntityEnderman(null)); + put("Mooshroom", ()-> new EntityMooshroom(null)); + put("WitherSkeleton", () -> { + EntitySkeleton skeleton = new EntitySkeleton(null); + skeleton.setSkeletonType(1); + return skeleton; + }); + put("Cow", () -> new EntityCow(null)); + put("Dragon", ()-> new EntityDragon(null)); + put("Player", () -> new GUIClientPlayer()); + }}; + + public static Map validModifiers = new HashMap() {{ + put("playerdata", new SkinModifier()); + put("equipment", new EquipmentModifier()); + put("riding", new RidingModifier()); + put("charged", new ChargedModifier()); + put("witherdata", new WitherModifier()); + put("invisible", new InvisibleModifier()); + put("age", new AgeModifier()); + put("horse", new HorseModifier()); + }}; + + public int guiLeft = 0; + public int guiTop = 0; + public int xSize = 176; + public int ySize = 166; + + private final String label; + private final EntityLivingBase entity; + private static final ResourceLocation BACKGROUND = new ResourceLocation("notenoughupdates", "textures/gui/entity_viewer.png"); + + public EntityViewer(String label, EntityLivingBase entity) { + this.label = label; + this.entity = entity; + } + + public static EntityLivingBase constructEntity(ResourceLocation resourceLocation) { + Gson gson = NotEnoughUpdates.INSTANCE.manager.gson; + try (Reader is = new InputStreamReader( + Minecraft.getMinecraft().getResourceManager().getResource(resourceLocation).getInputStream(), StandardCharsets.UTF_8)) { + return constructEntity(gson.fromJson(is, JsonObject.class)); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + public static EntityLivingBase constructEntity(JsonObject info) { + List modifiers = info.has("modifiers") ? + StreamSupport.stream(info.get("modifiers").getAsJsonArray().spliterator(), false) + .map(JsonElement::getAsJsonObject).collect(Collectors.toList()) + : Collections.emptyList(); + return EntityViewer.constructEntity(info.get("entity").getAsString(), modifiers); + } + + public static EntityLivingBase constructEntity(String string, String[] modifiers) { + Gson gson = NotEnoughUpdates.INSTANCE.manager.gson; + return constructEntity(string, Arrays.stream(modifiers).map(it -> gson.fromJson(it, JsonObject.class)).collect(Collectors.toList())); + } + + public static EntityLivingBase constructEntity(String string, List modifiers) { + Supplier aClass = validEntities.get(string); + if (aClass == null) { + System.err.println("Could not find entity of type: " + string); + return null; + } + try { + EntityLivingBase entity = aClass.get(); + for (JsonObject modifier : modifiers) { + String type = modifier.get("type").getAsString(); + EntityViewerModifier entityViewerModifier = validModifiers.get(type); + entity = entityViewerModifier.applyModifier(entity, modifier); + if (entity == null) break; + } + return entity; + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + @Override + public void drawScreen(int mouseX, int mouseY, float partialTicks) { + drawDefaultBackground(); + FontRenderer fontRenderer = Minecraft.getMinecraft().fontRendererObj; + + this.guiLeft = (width - this.xSize) / 2; + this.guiTop = (height - this.ySize) / 2; + + + Minecraft.getMinecraft().getTextureManager().bindTexture(BACKGROUND); + drawTexturedModalRect(guiLeft, guiTop, 0, 0, this.xSize, this.ySize); + + + Utils.drawStringScaledMaxWidth(label, fontRenderer, guiLeft + 10, guiTop + 10, false, 100, 0xFF00FF); + renderEntity(entity, guiLeft + 90, guiTop + 75, mouseX, mouseY); + } + + public static void renderEntity(EntityLivingBase entity, int posX, int posY, int mouseX, int mouseY) { + GlStateManager.color(1F, 1F, 1F, 1F); + + int scale = 30; + float bottomOffset = 0F; + EntityLivingBase stack = entity; + while (true) { + + stack.ticksExisted = Minecraft.getMinecraft().thePlayer.ticksExisted; + GuiInventory.drawEntityOnScreen(posX, (int) (posY - bottomOffset * scale), scale, posX - mouseX, (int) (posY - stack.getEyeHeight() * scale - mouseY), stack); + bottomOffset += stack.getMountedYOffset(); + if (!(stack.riddenByEntity instanceof EntityLivingBase)) { + break; + } + stack = (EntityLivingBase) stack.riddenByEntity; + } + + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/EntityViewerModifier.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/EntityViewerModifier.java new file mode 100644 index 00000000..bab6c354 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/EntityViewerModifier.java @@ -0,0 +1,8 @@ +package io.github.moulberry.notenoughupdates.miscfeatures.entityviewer; + +import com.google.gson.JsonObject; +import net.minecraft.entity.EntityLivingBase; + +public abstract class EntityViewerModifier { + public abstract EntityLivingBase applyModifier(EntityLivingBase base, JsonObject info); +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/EquipmentModifier.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/EquipmentModifier.java new file mode 100644 index 00000000..3011e479 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/EquipmentModifier.java @@ -0,0 +1,72 @@ +package io.github.moulberry.notenoughupdates.miscfeatures.entityviewer; + +import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.NEUManager; +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Items; +import net.minecraft.item.ItemArmor; +import net.minecraft.item.ItemStack; + +public class EquipmentModifier extends EntityViewerModifier { + + private ItemStack createItem(String item) { + NEUManager manager = NotEnoughUpdates.INSTANCE.manager; + String[] split = item.split("#"); + if (split.length == 2) { + switch (split[0].intern()) { + case "LEATHER_LEGGINGS": + return coloredLeatherArmor(Items.leather_leggings, split[1]); + case "LEATHER_HELMET": + return coloredLeatherArmor(Items.leather_helmet, split[1]); + case "LEATHER_CHESTPLATE": + return coloredLeatherArmor(Items.leather_chestplate, split[1]); + case "LEATHER_BOOTS": + return coloredLeatherArmor(Items.leather_boots, split[1]); + default: + throw new RuntimeException("Unknown leather piece: " + item); + } + } + return manager.createItem(item); + } + + private ItemStack coloredLeatherArmor(ItemArmor item, String colorHex) { + ItemStack is = new ItemStack(item); + item.setColor(is, Integer.parseInt(colorHex, 16)); + return is; + } + + @Override + public EntityLivingBase applyModifier(EntityLivingBase base, JsonObject info) { + if (info.has("hand")) + setCurrentItemOrArmor(base, 0, createItem(info.get("hand").getAsString())); + if (info.has("helmet")) + setCurrentItemOrArmor(base, 4, createItem(info.get("helmet").getAsString())); + if (info.has("chestplate")) + setCurrentItemOrArmor(base, 3, createItem(info.get("chestplate").getAsString())); + if (info.has("leggings")) + setCurrentItemOrArmor(base, 2, createItem(info.get("leggings").getAsString())); + if (info.has("feet")) + setCurrentItemOrArmor(base, 1, createItem(info.get("feet").getAsString())); + return base; + } + + public void setCurrentItemOrArmor(EntityLivingBase entity, int slot, ItemStack itemStack) { + if (entity instanceof EntityPlayer) { + setPlayerCurrentItemOrArmor((EntityPlayer) entity, slot, itemStack); + } else { + entity.setCurrentItemOrArmor(slot, itemStack); + } + } + + // Biscuit person needs to learn how to code and not fuck up valid vanilla behaviour + public static void setPlayerCurrentItemOrArmor(EntityPlayer player, int slot, ItemStack itemStack) { + if (slot == 0) { + player.inventory.mainInventory[player.inventory.currentItem] = itemStack; + } else { + player.inventory.armorInventory[slot - 1] = itemStack; + } + } + +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/GUIClientPlayer.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/GUIClientPlayer.java new file mode 100644 index 00000000..bbff2db1 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/GUIClientPlayer.java @@ -0,0 +1,40 @@ +package io.github.moulberry.notenoughupdates.miscfeatures.entityviewer; + +import com.mojang.authlib.GameProfile; +import net.minecraft.client.entity.AbstractClientPlayer; +import net.minecraft.client.network.NetworkPlayerInfo; +import net.minecraft.client.resources.DefaultPlayerSkin; +import net.minecraft.util.ResourceLocation; + +import java.util.UUID; + +public class GUIClientPlayer extends AbstractClientPlayer { + public GUIClientPlayer() { + super(null, new GameProfile(UUID.randomUUID(), "GuiPlayer")); + } + + ResourceLocation overrideSkin = DefaultPlayerSkin.getDefaultSkinLegacy(); + ResourceLocation overrideCape = null; + boolean overrideIsSlim = false; + NetworkPlayerInfo playerInfo = new NetworkPlayerInfo(this.getGameProfile()) { + @Override + public String getSkinType() { + return overrideIsSlim ? "slim" : "default"; + } + + @Override + public ResourceLocation getLocationSkin() { + return overrideSkin; + } + + @Override + public ResourceLocation getLocationCape() { + return overrideCape; + } + }; + + @Override + protected NetworkPlayerInfo getPlayerInfo() { + return playerInfo; + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/HorseModifier.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/HorseModifier.java new file mode 100644 index 00000000..7fd2dadd --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/HorseModifier.java @@ -0,0 +1,66 @@ +package io.github.moulberry.notenoughupdates.miscfeatures.entityviewer; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.passive.EntityHorse; +import net.minecraft.init.Items; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; + +public class HorseModifier extends EntityViewerModifier { + @Override + public EntityLivingBase applyModifier(EntityLivingBase base, JsonObject info) { + if (!(base instanceof EntityHorse)) + return null; + EntityHorse horse = (EntityHorse) base; + if (info.has("kind")) { + String type = info.get("kind").getAsString().intern(); + switch (type) { + case "skeleton": + horse.setHorseType(4); + break; + case "zombie": + horse.setHorseType(3); + break; + case "mule": + horse.setHorseType(2); + break; + case "donkey": + horse.setHorseType(1); + break; + case "horse": + horse.setHorseType(0); + break; + default: + throw new IllegalArgumentException("Unknown horse type: " + type); + } + } + if (info.has("armor")) { + JsonElement el = info.get("armor"); + if (el.isJsonNull()) { + horse.setHorseArmorStack(null); + } else { + Item item; + switch (el.getAsString().intern()) { + case "iron": + item = Items.iron_horse_armor; + break; + case "golden": + item = Items.golden_horse_armor; + break; + case "diamond": + item = Items.diamond_horse_armor; + break; + default: + throw new IllegalArgumentException("Unknown horse armor: " + el.getAsString()); + } + horse.setHorseArmorStack(new ItemStack(item)); + } + } + if (info.has("saddled")) { + horse.setHorseSaddled(info.get("saddled").getAsBoolean()); + } + return horse; + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/InvisibleModifier.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/InvisibleModifier.java new file mode 100644 index 00000000..c2138b3f --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/InvisibleModifier.java @@ -0,0 +1,12 @@ +package io.github.moulberry.notenoughupdates.miscfeatures.entityviewer; + +import com.google.gson.JsonObject; +import net.minecraft.entity.EntityLivingBase; + +public class InvisibleModifier extends EntityViewerModifier { + @Override + public EntityLivingBase applyModifier(EntityLivingBase base, JsonObject info) { + base.setInvisible(!info.has("invisible") || info.get("invisible").getAsBoolean()); + return base; + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/RidingModifier.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/RidingModifier.java new file mode 100644 index 00000000..9879542a --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/RidingModifier.java @@ -0,0 +1,14 @@ +package io.github.moulberry.notenoughupdates.miscfeatures.entityviewer; + +import com.google.gson.JsonObject; +import net.minecraft.entity.EntityLivingBase; + +public class RidingModifier extends EntityViewerModifier { + @Override + public EntityLivingBase applyModifier(EntityLivingBase base, JsonObject info) { + EntityLivingBase newEntity = EntityViewer.constructEntity(info); + if (newEntity == null) return null; + newEntity.mountEntity(base); + return base; + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/SkinModifier.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/SkinModifier.java new file mode 100644 index 00000000..55e8a432 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/SkinModifier.java @@ -0,0 +1,46 @@ +package io.github.moulberry.notenoughupdates.miscfeatures.entityviewer; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EnumPlayerModelParts; +import net.minecraft.util.ResourceLocation; + +import java.util.Map; + +public class SkinModifier extends EntityViewerModifier { + @Override + public EntityLivingBase applyModifier(EntityLivingBase base, JsonObject info) { + if (base instanceof GUIClientPlayer) { + GUIClientPlayer player = (GUIClientPlayer) base; + if (info.has("cape")) { + player.overrideCape = new ResourceLocation(info.get("cape").getAsString()); + } + if (info.has("skin")) { + player.overrideSkin = new ResourceLocation(info.get("skin").getAsString()); + } + if (info.has("slim")) { + player.overrideIsSlim = info.get("slim").getAsBoolean(); + } + if (info.has("parts")) { + JsonElement parts = info.get("parts"); + byte partBitField = player.getDataWatcher().getWatchableObjectByte(10); + if (parts.isJsonPrimitive() && parts.getAsJsonPrimitive().isBoolean()) { + partBitField = parts.getAsBoolean() ? (byte) -1 : 0; + } else { + JsonObject obj = parts.getAsJsonObject(); + for (Map.Entry part : obj.entrySet()) { + EnumPlayerModelParts modelPart = EnumPlayerModelParts.valueOf(part.getKey()); + if (part.getValue().getAsBoolean()) { + partBitField |= modelPart.getPartMask(); + } else { + partBitField &= ~modelPart.getPartMask(); + } + } + } + player.getDataWatcher().updateObject(10, partBitField); + } + } + return base; + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/WitherModifier.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/WitherModifier.java new file mode 100644 index 00000000..c5580f17 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/WitherModifier.java @@ -0,0 +1,29 @@ +package io.github.moulberry.notenoughupdates.miscfeatures.entityviewer; + +import com.google.gson.JsonObject; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.boss.EntityWither; + +public class WitherModifier extends EntityViewerModifier { + @Override + public EntityLivingBase applyModifier(EntityLivingBase base, JsonObject info) { + if (!(base instanceof EntityWither)) + return null; + EntityWither wither = (EntityWither) base; + if (info.has("tiny")) { + if (info.get("tiny").getAsBoolean()) { + wither.setInvulTime(800); + } else { + wither.setInvulTime(0); + } + } + if (info.has("armored")) { + if (info.get("armored").getAsBoolean()) { + wither.setHealth(1); + } else { + wither.setHealth(wither.getMaxHealth()); + } + } + return base; + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiItemRecipe.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiItemRecipe.java index 63a4d6d8..be9ce6c7 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiItemRecipe.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiItemRecipe.java @@ -4,6 +4,7 @@ import com.google.common.collect.ImmutableList; import io.github.moulberry.notenoughupdates.NEUManager; import io.github.moulberry.notenoughupdates.recipes.NeuRecipe; import io.github.moulberry.notenoughupdates.recipes.RecipeSlot; +import io.github.moulberry.notenoughupdates.recipes.RecipeType; import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.FontRenderer; @@ -12,6 +13,7 @@ import net.minecraft.client.gui.ScaledResolution; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.MathHelper; import net.minecraft.util.ResourceLocation; import org.lwjgl.input.Keyboard; @@ -20,48 +22,65 @@ import org.lwjgl.opengl.GL11; import java.awt.*; import java.io.IOException; -import java.util.ArrayList; import java.util.List; +import java.util.*; public class GuiItemRecipe extends GuiScreen { public static final ResourceLocation resourcePacksTexture = new ResourceLocation("textures/gui/resource_packs.png"); + public static final ResourceLocation tabsTexture = new ResourceLocation("notenoughupdates", "textures/gui/tab.png"); public static final int SLOT_SIZE = 16; public static final int SLOT_SPACING = SLOT_SIZE + 2; public static final int BUTTON_WIDTH = 7; public static final int BUTTON_HEIGHT = 11; - public static final int BUTTON_POSITION_Y = 63; - public static final int BUTTON_POSITION_LEFT_X = 110; - public static final int BUTTON_POSITION_RIGHT_X = 147; - public static final int PAGE_STRING_X = 132; - public static final int PAGE_STRING_Y = 69; public static final int TITLE_X = 28; public static final int TITLE_Y = 6; public static final int HOTBAR_SLOT_X = 8; - public static final int HOTBAR_SLOT_Y = 142; + public static final int HOTBAR_SLOT_Y = 197; public static final int PLAYER_INVENTORY_X = 8; - public static final int PLAYER_INVENTORY_Y = 84; + public static final int PLAYER_INVENTORY_Y = 140; + public static final int TAB_POS_X = -26; + public static final int TAB_POS_Y = 8; + public static final int TAB_OFFSET_Y = 30; + public static final int TAB_SIZE_X = 26; + public static final int TAB_SIZE_Y = 30; + public static final int TAB_TEXTURE_SIZE_X = 29; private int currentIndex = 0; + private int currentTab = 0; - private final String title; - private final List craftingRecipes; + private final Map> craftingRecipes = new HashMap<>(); + private final List tabs = new ArrayList<>(); private final NEUManager manager; public int guiLeft = 0; public int guiTop = 0; public int xSize = 176; - public int ySize = 166; + public int ySize = 222; - public GuiItemRecipe(String title, List craftingRecipes, NEUManager manager) { - this.craftingRecipes = craftingRecipes; + public GuiItemRecipe(List unsortedRecipes, NEUManager manager) { this.manager = manager; - this.title = title; + + for (NeuRecipe recipe : unsortedRecipes) { + craftingRecipes.computeIfAbsent(recipe.getType(), ignored -> new ArrayList<>()).add(recipe); + if (!tabs.contains(recipe.getType())) + tabs.add(recipe.getType()); + } } public NeuRecipe getCurrentRecipe() { - currentIndex = MathHelper.clamp_int(currentIndex, 0, craftingRecipes.size()); - return craftingRecipes.get(currentIndex); + List currentRecipes = getCurrentRecipeList(); + currentIndex = MathHelper.clamp_int(currentIndex, 0, currentRecipes.size() - 1); + return currentRecipes.get(currentIndex); + } + + public List getCurrentRecipeList() { + return craftingRecipes.get(getCurrentTab()); + } + + public RecipeType getCurrentTab() { + currentTab = MathHelper.clamp_int(currentTab, 0, tabs.size() - 1); + return tabs.get(currentTab); } public boolean isWithinRect(int x, int y, int topLeftX, int topLeftY, int width, int height) { @@ -90,17 +109,19 @@ public class GuiItemRecipe extends GuiScreen { Minecraft.getMinecraft().getTextureManager().bindTexture(currentRecipe.getBackground()); this.drawTexturedModalRect(guiLeft, guiTop, 0, 0, this.xSize, this.ySize); + drawTabs(); + currentRecipe.drawExtraBackground(this, mouseX, mouseY); List slots = getAllRenderedSlots(); for (RecipeSlot slot : slots) { - Utils.drawItemStack(slot.getItemStack(), slot.getX(this), slot.getY(this)); + Utils.drawItemStack(slot.getItemStack(), slot.getX(this), slot.getY(this), true); } - if (craftingRecipes.size() > 1) drawArrows(mouseX, mouseY); + drawArrows(currentRecipe, mouseX, mouseY); Utils.drawStringScaledMaxWidth( - title, + currentRecipe.getTitle(), fontRendererObj, guiLeft + TITLE_X, guiTop + TITLE_Y, @@ -126,42 +147,104 @@ public class GuiItemRecipe extends GuiScreen { } } currentRecipe.drawHoverInformation(this, mouseX, mouseY); + drawTabHoverInformation(mouseX, mouseY); + } + + private void drawTabHoverInformation(int mouseX, int mouseY) { + if (tabs.size() < 2) return; + for (int i = 0; i < tabs.size(); i++) { + if (isWithinRect( + mouseX - guiLeft, + mouseY - guiTop, + TAB_POS_X, + TAB_POS_Y + TAB_OFFSET_Y * i, + TAB_SIZE_X, + TAB_SIZE_Y + )) { + RecipeType type = tabs.get(i); + Utils.drawHoveringText( + Arrays.asList( + "" + EnumChatFormatting.RESET + EnumChatFormatting.GREEN + type.getLabel(), + "" + EnumChatFormatting.RESET + EnumChatFormatting.GRAY + craftingRecipes.get(type).size() + " Recipes" + ), + mouseX, mouseY, width, height, -1, Minecraft.getMinecraft().fontRendererObj + ); + return; + } + } } - private void drawArrows(int mouseX, int mouseY) { + private void drawTabs() { + if (tabs.size() < 2) return; + for (int i = 0; i < tabs.size(); i++) { + RecipeType recipeType = tabs.get(i); + int tabPosX = guiLeft + TAB_POS_X, tabPosY = guiTop + TAB_OFFSET_Y * i + TAB_POS_Y; + int textureOffset = 0; + if (currentTab == i) { + textureOffset = 30; + } + Minecraft.getMinecraft().getTextureManager().bindTexture(tabsTexture); + drawTexturedModalRect( + tabPosX, tabPosY, + 0, textureOffset, + TAB_TEXTURE_SIZE_X, TAB_SIZE_Y + ); + Utils.drawItemStack(recipeType.getIcon(), tabPosX + 7, tabPosY + 7); + } + } + + public static final int BUTTON_POSITION_RIGHT_OFFSET_X = 37; + public static final int PAGE_STRING_OFFSET_X = 22; + public static final int PAGE_STRING_OFFSET_Y = 6; + + private void drawArrows( + NeuRecipe currentRecipe, + int mouseX, + int mouseY + ) { + int recipeCount = getCurrentRecipeList().size(); + if (recipeCount < 2) return; + int[] topLeft = currentRecipe.getPageFlipPositionLeftTopCorner(); + int buttonPositionLeftX = topLeft[0]; + int buttonPositionRightX = buttonPositionLeftX + BUTTON_POSITION_RIGHT_OFFSET_X; + int pageStringX = buttonPositionLeftX + PAGE_STRING_OFFSET_X; + int buttonPositionY = topLeft[1]; + int pageStringY = buttonPositionY + PAGE_STRING_OFFSET_Y; + boolean leftSelected = isWithinRect( mouseX - guiLeft, mouseY - guiTop, - BUTTON_POSITION_LEFT_X, - BUTTON_POSITION_Y, + buttonPositionLeftX, + buttonPositionY, BUTTON_WIDTH, BUTTON_HEIGHT ); boolean rightSelected = isWithinRect( mouseX - guiLeft, mouseY - guiTop, - BUTTON_POSITION_RIGHT_X, - BUTTON_POSITION_Y, + buttonPositionRightX, + buttonPositionY, BUTTON_WIDTH, BUTTON_HEIGHT ); - Minecraft.getMinecraft().getTextureManager().bindTexture(resourcePacksTexture); - Utils.drawTexturedRect(guiLeft + BUTTON_POSITION_LEFT_X, guiTop + BUTTON_POSITION_Y, BUTTON_WIDTH, BUTTON_HEIGHT, - 34 / 256f, 48 / 256f, - leftSelected ? 37 / 256f : 5 / 256f, leftSelected ? 59 / 256f : 27 / 256f - ); - Utils.drawTexturedRect(guiLeft + BUTTON_POSITION_RIGHT_X, guiTop + BUTTON_POSITION_Y, BUTTON_WIDTH, BUTTON_HEIGHT, - 10 / 256f, 24 / 256f, - rightSelected ? 37 / 256f : 5 / 256f, rightSelected ? 59 / 256f : 27 / 256f - ); + if (currentIndex != 0) + Utils.drawTexturedRect(guiLeft + buttonPositionLeftX, guiTop + buttonPositionY, BUTTON_WIDTH, BUTTON_HEIGHT, + 34 / 256f, 48 / 256f, + leftSelected ? 37 / 256f : 5 / 256f, leftSelected ? 59 / 256f : 27 / 256f + ); + if (currentIndex != recipeCount - 1) + Utils.drawTexturedRect(guiLeft + buttonPositionRightX, guiTop + buttonPositionY, BUTTON_WIDTH, BUTTON_HEIGHT, + 10 / 256f, 24 / 256f, + rightSelected ? 37 / 256f : 5 / 256f, rightSelected ? 59 / 256f : 27 / 256f + ); GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0); - String selectedPage = (currentIndex + 1) + "/" + craftingRecipes.size(); + String selectedPage = (currentIndex + 1) + "/" + recipeCount; Utils.drawStringCenteredScaledMaxWidth(selectedPage, fontRendererObj, - guiLeft + PAGE_STRING_X, guiTop + PAGE_STRING_Y, false, 24, Color.BLACK.getRGB() + guiLeft + pageStringX, guiTop + pageStringY, false, 24, Color.BLACK.getRGB() ); } @@ -196,12 +279,12 @@ public class GuiItemRecipe extends GuiScreen { int mouseX = Mouse.getX() * width / Minecraft.getMinecraft().displayWidth; int mouseY = height - Mouse.getY() * height / Minecraft.getMinecraft().displayHeight - 1; int keyPressed = Keyboard.getEventKey() == 0 ? Keyboard.getEventCharacter() + 256 : Keyboard.getEventKey(); - + if (Keyboard.getEventKeyState()) return; for (RecipeSlot slot : getAllRenderedSlots()) { if (isWithinRect(mouseX, mouseY, slot.getX(this), slot.getY(this), SLOT_SIZE, SLOT_SIZE)) { ItemStack itemStack = slot.getItemStack(); - if (keyPressed == manager.keybindViewRecipe.getKeyCode()) { // TODO: rework this so it doesnt skip recipe chains - manager.displayGuiItemRecipe(manager.getInternalNameForItem(itemStack), ""); + if (keyPressed == manager.keybindViewRecipe.getKeyCode()) { + manager.displayGuiItemRecipe(manager.getInternalNameForItem(itemStack)); } else if (keyPressed == manager.keybindViewUsages.getKeyCode()) { manager.displayGuiItemUsages(manager.getInternalNameForItem(itemStack)); } @@ -212,16 +295,22 @@ public class GuiItemRecipe extends GuiScreen { @Override protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException { super.mouseClicked(mouseX, mouseY, mouseButton); + NeuRecipe currentRecipe = getCurrentRecipe(); + int[] topLeft = currentRecipe.getPageFlipPositionLeftTopCorner(); + int buttonPositionLeftX = topLeft[0]; + int buttonPositionRightX = buttonPositionLeftX + BUTTON_POSITION_RIGHT_OFFSET_X; + int buttonPositionY = topLeft[1]; if (isWithinRect( mouseX - guiLeft, mouseY - guiTop, - BUTTON_POSITION_LEFT_X, - BUTTON_POSITION_Y, + buttonPositionLeftX, + buttonPositionY, BUTTON_WIDTH, BUTTON_HEIGHT - )) { - currentIndex = currentIndex == 0 ? 0 : currentIndex - 1; + ) && + currentIndex > 0) { + currentIndex = currentIndex - 1; Utils.playPressSound(); return; } @@ -229,21 +318,37 @@ public class GuiItemRecipe extends GuiScreen { if (isWithinRect( mouseX - guiLeft, mouseY - guiTop, - BUTTON_POSITION_RIGHT_X, - BUTTON_POSITION_Y, + buttonPositionRightX, + buttonPositionY, BUTTON_WIDTH, BUTTON_HEIGHT - )) { - currentIndex = currentIndex == craftingRecipes.size() - 1 ? currentIndex : currentIndex + 1; + ) && + currentIndex < getCurrentRecipeList().size()) { + currentIndex = currentIndex + 1; Utils.playPressSound(); return; } + for (int i = 0; i < tabs.size(); i++) { + if (isWithinRect( + mouseX - guiLeft, + mouseY - guiTop, + TAB_POS_X, + TAB_POS_Y + TAB_OFFSET_Y * i, + TAB_SIZE_X, + TAB_SIZE_Y + )) { + currentTab = i; + Utils.playPressSound(); + return; + } + } + for (RecipeSlot slot : getAllRenderedSlots()) { if (isWithinRect(mouseX, mouseY, slot.getX(this), slot.getY(this), SLOT_SIZE, SLOT_SIZE)) { ItemStack itemStack = slot.getItemStack(); if (mouseButton == 0) { - manager.displayGuiItemRecipe(manager.getInternalNameForItem(itemStack), ""); + man