aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/CODEOWNERS2
-rw-r--r--build.gradle.kts175
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java6
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java9
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiItemRecipe.java593
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/recipes/MobLootRecipe.java446
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/recipes/NeuRecipe.java61
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/recipes/RecipeGenerator.java2
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/JsonUtils.java42
9 files changed, 769 insertions, 567 deletions
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/build.gradle.kts b/build.gradle.kts
index 2b45fe9a..2ab7ee48 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<String>()
+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,13 @@ 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")
}
// Tasks:
tasks.withType(JavaCompile::class) {
- options.encoding = "UTF-8"
+ options.encoding = "UTF-8"
}
tasks.named<Test>("test") {
@@ -82,61 +99,61 @@ tasks.named<Test>("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")
+ 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"))
+ 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..0e683e5a 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java
@@ -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/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/miscgui/GuiItemRecipe.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiItemRecipe.java
index 127fa911..9256a193 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiItemRecipe.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiItemRecipe.java
@@ -6,15 +6,12 @@ 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.block.state.BlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.ScaledResolution;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.entity.player.InventoryPlayer;
-import net.minecraft.init.Blocks;
-import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.MathHelper;
@@ -23,264 +20,342 @@ import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.GL11;
-import java.awt.Color;
+import java.awt.*;
import java.io.IOException;
+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 = 90;
- 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 = BUTTON_POSITION_Y+6;
- 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 = 197;
- public static final int PLAYER_INVENTORY_X = 8;
- 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 Map<RecipeType, List<NeuRecipe>> craftingRecipes = new HashMap<>();
- private final List<RecipeType> tabs = new ArrayList<>();
- private final NEUManager manager;
-
- public int guiLeft = 0;
- public int guiTop = 0;
- public int xSize = 176;
- public int ySize = 222;
-
- public GuiItemRecipe(String title, List<NeuRecipe> 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() {
- List<NeuRecipe> currentRecipes = getCurrentRecipeList();
- currentIndex = MathHelper.clamp_int(currentIndex, 0, currentRecipes.size() - 1);
- return currentRecipes.get(currentIndex);
- }
-
- public List<NeuRecipe> 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) {
- return topLeftX <= x && x <= topLeftX + width
- && topLeftY <= y && y <= topLeftY + height;
- }
-
- private ImmutableList<RecipeSlot> getAllRenderedSlots() {
- return ImmutableList.<RecipeSlot>builder()
- .addAll(getPlayerInventory())
- .addAll(getCurrentRecipe().getSlots()).build();
- }
-
- @Override
- public void drawScreen(int mouseX, int mouseY, float partialTicks) {
- drawDefaultBackground();
- FontRenderer fontRendererObj = Minecraft.getMinecraft().fontRendererObj;
-
- this.guiLeft = (width - this.xSize) / 2;
- this.guiTop = (height - this.ySize) / 2;
-
- GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
-
- NeuRecipe currentRecipe = getCurrentRecipe();
-
- Minecraft.getMinecraft().getTextureManager().bindTexture(currentRecipe.getBackground());
- this.drawTexturedModalRect(guiLeft, guiTop, 0, 0, this.xSize, this.ySize);
-
- drawTabs();
-
- currentRecipe.drawExtraBackground(this, mouseX, mouseY);
-
- List<RecipeSlot> slots = getAllRenderedSlots();
- for (RecipeSlot slot : slots) {
- Utils.drawItemStack(slot.getItemStack(), slot.getX(this), slot.getY(this));
- }
-
- drawArrows(mouseX, mouseY);
-
- Utils.drawStringScaledMaxWidth(title, fontRendererObj, guiLeft + TITLE_X, guiTop + TITLE_Y, false, xSize - 38, 0x404040);
-
- currentRecipe.drawExtraInfo(this, mouseX, mouseY);
-
- for (RecipeSlot slot : slots) {
- if (isWithinRect(mouseX, mouseY, slot.getX(this), slot.getY(this), SLOT_SIZE, SLOT_SIZE)) {
- if (slot.getItemStack() == null) continue;
- Utils.drawHoveringText(slot.getItemStack().getTooltip(Minecraft.getMinecraft().thePlayer, false), mouseX, mouseY, width, height, -1, fontRendererObj);
- }
- }
- 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 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
- );
- Minecraft.getMinecraft().getTextureManager().bindTexture(recipeType.getIcon());
- drawTexturedModalRect(tabPosX + 7, tabPosY + 7, 6, 0, 16, 16);
- }
- }
-
- private void drawArrows(int mouseX, int mouseY) {
- int recipeCount = getCurrentRecipeList().size();
- if (recipeCount < 2) return;
- boolean leftSelected = isWithinRect(mouseX - guiLeft, mouseY - guiTop, BUTTON_POSITION_LEFT_X, BUTTON_POSITION_Y, BUTTON_WIDTH, BUTTON_HEIGHT);
- boolean rightSelected = isWithinRect(mouseX - guiLeft, mouseY - guiTop, BUTTON_POSITION_RIGHT_X, BUTTON_POSITION_Y, BUTTON_WIDTH, BUTTON_HEIGHT);
- Minecraft.getMinecraft().getTextureManager().bindTexture(resourcePacksTexture);
-
- if (currentIndex != 0)
- 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
- );
- if (currentIndex != recipeCount - 1)
- 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
- );
- GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
-
- String selectedPage = (currentIndex + 1) + "/" + recipeCount;
-
- Utils.drawStringCenteredScaledMaxWidth(selectedPage, fontRendererObj,
- guiLeft + PAGE_STRING_X, guiTop + PAGE_STRING_Y, false, 24, Color.BLACK.getRGB());
- }
-
- public List<RecipeSlot> getPlayerInventory() {
- List<RecipeSlot> slots = new ArrayList<>();
- ItemStack[] inventory = Minecraft.getMinecraft().thePlayer.inventory.mainInventory;
- int hotbarSize = InventoryPlayer.getHotbarSize();
- for (int i = 0; i < inventory.length; i++) {
- ItemStack item = inventory[i];
- if (item == null || item.stackSize == 0) continue;
- int row = i / hotbarSize;
- int col = i % hotbarSize;
- if (row == 0)
- slots.add(new RecipeSlot(HOTBAR_SLOT_X + i * SLOT_SPACING, HOTBAR_SLOT_Y, item));
- else
- slots.add(new RecipeSlot(PLAYER_INVENTORY_X + col * SLOT_SPACING, PLAYER_INVENTORY_Y + (row - 1) * SLOT_SPACING, item));
- }
- return slots;
- }
-
- @Override
- public void handleKeyboardInput() throws IOException {
- super.handleKeyboardInput();
-
- ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
- int width = scaledResolution.getScaledWidth();
- int height = scaledResolution.getScaledHeight();
- 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()) {
- manager.displayGuiItemRecipe(manager.getInternalNameForItem(itemStack), null);
- } else if (keyPressed == manager.keybindViewUsages.getKeyCode()) {
- manager.displayGuiItemUsages(manager.getInternalNameForItem(itemStack));
- }
- }
- }
- }
-
- @Override
- protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException {
- super.mouseClicked(mouseX, mouseY, mouseButton);
-
- if (isWithinRect(mouseX - guiLeft, mouseY - guiTop, BUTTON_POSITION_LEFT_X, BUTTON_POSITION_Y, BUTTON_WIDTH, BUTTON_HEIGHT) &&
- currentIndex > 0) {
- currentIndex = currentIndex - 1;
- Utils.playPressSound();
- return;
- }
-
- if (isWithinRect(mouseX - guiLeft, mouseY - guiTop, BUTTON_POSITION_RIGHT_X, BUTTON_POSITION_Y, BUTTON_WIDTH, BUTTON_HEIGHT) &&
- 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), null);
- } else if (mouseButton == 1) {
- manager.displayGuiItemUsages(manager.getInternalNameForItem(itemStack));
- }
- }
- }
- }
+ 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 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 = 197;
+ public static final int PLAYER_INVENTORY_X = 8;
+ 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 Map<RecipeType, List<NeuRecipe>> craftingRecipes = new HashMap<>();
+ private final List<RecipeType> tabs = new ArrayList<>();
+ private final NEUManager manager;
+
+ public int guiLeft = 0;
+ public int guiTop = 0;
+ public int xSize = 176;
+ public int ySize = 222;
+
+ public GuiItemRecipe(String title, List<NeuRecipe> 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() {
+ List<NeuRecipe> currentRecipes = getCurrentRecipeList();
+ currentIndex = MathHelper.clamp_int(currentIndex, 0, currentRecipes.size() - 1);
+ return currentRecipes.get(currentIndex);
+ }
+
+ public List<NeuRecipe> 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) {
+ return topLeftX <= x && x <= topLeftX + width
+ && topLeftY <= y && y <= topLeftY + height;
+ }
+
+ private ImmutableList<RecipeSlot> getAllRenderedSlots() {
+ return ImmutableList.<RecipeSlot>builder()
+ .addAll(getPlayerInventory())
+ .addAll(getCurrentRecipe().getSlots()).build();
+ }
+
+ @Override
+ public void drawScreen(int mouseX, int mouseY, float partialTicks) {
+ drawDefaultBackground();
+ FontRenderer fontRendererObj = Minecraft.getMinecraft().fontRendererObj;
+
+ this.guiLeft = (width - this.xSize) / 2;
+ this.guiTop = (height - this.ySize) / 2;
+
+ GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
+
+ NeuRecipe currentRecipe = getCurrentRecipe();
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(currentRecipe.getBackground());
+ this.drawTexturedModalRect(guiLeft, guiTop, 0, 0, this.xSize, this.ySize);
+
+ drawTabs();
+
+ currentRecipe.drawExtraBackground(this, mouseX, mouseY);
+
+ List<RecipeSlot> slots = getAllRenderedSlots();
+ for (RecipeSlot slot : slots) {
+ Utils.drawItemStack(slot.getItemStack(), slot.getX(this), slot.getY(this));
+ }
+
+ drawArrows(currentRecipe, mouseX, mouseY);
+
+ Utils.drawStringScaledMaxWidth(
+ title,
+ fontRendererObj,
+ guiLeft + TITLE_X,
+ guiTop + TITLE_Y,
+ false,
+ xSize - 38,
+ 0x404040
+ );
+
+ currentRecipe.drawExtraInfo(this, mouseX, mouseY);
+
+ for (RecipeSlot slot : slots) {
+ if (isWithinRect(mouseX, mouseY, slot.getX(this), slot.getY(this), SLOT_SIZE, SLOT_SIZE)) {
+ if (slot.getItemStack() == null) continue;
+ Utils.drawHoveringText(
+ slot.getItemStack().getTooltip(Minecraft.getMinecraft().thePlayer, false),
+ mouseX,
+ mouseY,
+ width,
+ height,
+ -1,
+ fontRendererObj
+ );
+ }
+ }
+ 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 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
+ );
+ Minecraft.getMinecraft().getTextureManager().bindTexture(recipeType.getIcon());
+ drawTexturedModalRect(tabPosX + 7, tabPosY + 7, 6, 0, 16, 16);
+ }
+ }
+
+ 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,
+ buttonPositionLeftX,
+ buttonPositionY,
+ BUTTON_WIDTH,
+ BUTTON_HEIGHT
+ );
+ boolean rightSelected = isWithinRect(
+ mouseX - guiLeft,
+ mouseY - guiTop,
+ buttonPositionRightX,
+ buttonPositionY,
+ BUTTON_WIDTH,
+ BUTTON_HEIGHT
+ );
+ Minecraft.getMinecraft().getTextureManager().bindTexture(resourcePacksTexture);
+
+ 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) + "/" + recipeCount;
+
+ Utils.drawStringCenteredScaledMaxWidth(selectedPage, fontRendererObj,
+ guiLeft + pageStringX, guiTop + pageStringY, false, 24, Color.BLACK.getRGB()
+ );
+ }
+
+ public List<RecipeSlot> getPlayerInventory() {
+ List<RecipeSlot> slots = new ArrayList<>();
+ ItemStack[] inventory = Minecraft.getMinecraft().thePlayer.inventory.mainInventory;
+ int hotbarSize = InventoryPlayer.getHotbarSize();
+ for (int i = 0; i < inventory.length; i++) {
+ ItemStack item = inventory[i];
+ if (item == null || item.stackSize == 0) continue;
+ int row = i / hotbarSize;
+ int col = i % hotbarSize;
+ if (row == 0)
+ slots.add(new RecipeSlot(HOTBAR_SLOT_X + i * SLOT_SPACING, HOTBAR_SLOT_Y, item));
+ else
+ slots.add(new RecipeSlot(
+ PLAYER_INVENTORY_X + col * SLOT_SPACING,
+ PLAYER_INVENTORY_Y + (row - 1) * SLOT_SPACING,
+ item
+ ));
+ }
+ return slots;
+ }
+
+ @Override
+ public void handleKeyboardInput() throws IOException {
+ super.handleKeyboardInput();
+
+ ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
+ int width = scaledResolution.getScaledWidth();
+ int height = scaledResolution.getScaledHeight();
+ 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()) {
+ manager.displayGuiItemRecipe(manager.getInternalNameForItem(itemStack), null);
+ } else if (keyPressed == manager.keybindViewUsages.getKeyCode()) {
+ manager.displayGuiItemUsages(manager.getInternalNameForItem(itemStack));
+ }
+ }
+ }
+ }
+
+ @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,
+ buttonPositionLeftX,
+ buttonPositionY,
+ BUTTON_WIDTH,
+ BUTTON_HEIGHT
+ ) &&
+ currentIndex > 0) {
+ currentIndex = currentIndex - 1;
+ Utils.playPressSound();
+ return;
+ }
+
+ if (isWithinRect(
+ mouseX - guiLeft,
+ mouseY - guiTop,
+ buttonPositionRightX,
+ buttonPositionY,
+ BUTTON_WIDTH,
+ BUTTON_HEIGHT
+ ) &&
+ 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), null);
+ } else if (mouseButton == 1) {
+ manager.displayGuiItemUsages(manager.getInternalNameForItem(itemStack));
+ }
+ }
+ }
+ }
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/recipes/MobLootRecipe.java b/src/main/java/io/github/moulberry/notenoughupdates/recipes/MobLootRecipe.java
index 5670f1bd..5cc32528 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/recipes/MobLootRecipe.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/recipes/MobLootRecipe.java
@@ -8,214 +8,258 @@ import io.github.moulberry.notenoughupdates.NEUManager;
import io.github.moulberry.notenoughupdates.miscfeatures.entityviewer.EntityViewer;
import io.github.moulberry.notenoughupdates.miscgui.GuiItemRecipe;
import io.github.moulberry.notenoughupdates.profileviewer.Panorama;
+import io.github.moulberry.notenoughupdates.util.JsonUtils;
import io.github.moulberry.notenoughupdates.util.Utils;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.util.ResourceLocation;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
import java.util.stream.Collectors;
-import java.util.stream.StreamSupport;
public class MobLootRecipe implements NeuRecipe {
- private static final int MOB_POS_X = 38, MOB_POS_Y = 100;
- private static final int SLOT_POS_X = 82, SLOT_POS_Y = 23;
-
- public static class MobDrop {
- public final Ingredient drop;
- public final String chance;
- public final List<String> extra;
-
- public MobDrop(Ingredient drop, String chance, List<String> extra) {
- this.drop = drop;
- this.chance = chance;
- this.extra = extra;
- }
- }
-
- public static ResourceLocation[] PANORAMAS = new ResourceLocation[6];
-
- static {
- for (int i = 0; i < 6; i++)
- PANORAMAS[i] = new ResourceLocation("notenoughupdates:panoramas/unknown/panorama_" + i + ".jpg");
- }
-
- public static ResourceLocation BACKGROUND = new ResourceLocation("notenoughupdates", "textures/gui/mob_loot_tall.png");
- private final List<MobDrop> drops;
- private final int coins;
- private final int combatXp;
- private final int xp;
- private final String name;
- private final String render;
- private final int level;
- private EntityLivingBase entityLivingBase;
-
- public MobLootRecipe(List<MobDrop> drops, int level, int coins, int xp, int combatXp, String name, String render) {
- this.drops = drops;
- this.level = level;
- this.coins = coins;
- this.xp = xp;
- this.combatXp = combatXp;
- this.name = name;
- this.render = render;
- }
-
- public String getName() {
- return name;
- }
-
- public List<MobDrop> getDrops() {
- return drops;
- }
-
- public int getCoins() {
- return coins;
- }
-
- public int getCombatXp() {
- return combatXp;
- }
-
- public int getXp() {
- return xp;
- }
-
- public String getRender() {
- return render;
- }
-
- public synchronized EntityLivingBase getRenderEntity() {
- if (entityLivingBase == null) {
- if (render == null) return null;
- if (render.startsWith("@")) {
- entityLivingBase = EntityViewer.constructEntity(new ResourceLocation(render.substring(1)));
- } else {
- entityLivingBase = EntityViewer.constructEntity(render, Collections.emptyList());
- }
- }
- return entityLivingBase;
- }
-
- @Override
- public Set<Ingredient> getIngredients() {
- return Collections.emptySet();
- }
-
- @Override
- public Set<Ingredient> getOutputs() {
- return drops.stream().map(it -> it.drop).collect(Collectors.toSet());
- }
-
- @Override
- public List<RecipeSlot> getSlots() {
- List<RecipeSlot> slots = new ArrayList<>();
- for (int i = 0; i < drops.size(); i++) {
- MobDrop mobDrop = drops.get(i);
- int x = i % 5;
- int y = i / 5;
- slots.add(new RecipeSlot(
- SLOT_POS_X + x * 16,
- SLOT_POS_Y + y * 16,
- mobDrop.drop.getItemStack()
- ));
- }
- return slots;
- }
-
- @Override
- public RecipeType getType() {
- return RecipeType.MOB_LOOT;
- }
-
- @Override
- public boolean shouldUseForCraftCost() {
- return false;
- }
-
- @Override
- public boolean hasVariableCost() {
- return true;
- }
-
- public static final int PANORAMA_POS_X = 13;
- public static final int PANORAMA_POS_Y = 23;
- public static final int PANORAMA_WIDTH = 50;
- public static final int PANORAMA_HEIGHT = 80;
-
- @Override
- public void drawExtraBackground(GuiItemRecipe gui, int mouseX, int mouseY) {
- Panorama.drawPanorama(((System.nanoTime() / 20000000000F) % 1) * 360, gui.guiLeft + PANORAMA_POS_X, gui.guiTop + PANORAMA_POS_Y, PANORAMA_WIDTH, PANORAMA_HEIGHT, 0F, 0F, PANORAMAS);
- if (getRenderEntity() != null)
- EntityViewer.renderEntity(entityLivingBase, gui.guiLeft + MOB_POS_X, gui.guiTop + MOB_POS_Y, mouseX, mouseY);
- }
-
- @Override
- public void drawHoverInformation(GuiItemRecipe gui, int mouseX, int mouseY) {
- if (gui.isWithinRect(mouseX, mouseY, gui.guiLeft + PANORAMA_POS_X, gui.guiTop + PANORAMA_POS_Y, PANORAMA_WIDTH, PANORAMA_HEIGHT)) {
- Utils.drawHoveringText(Arrays.asList("Hehe", name), mouseX, mouseY, gui.width, gui.height, -1, Minecraft.getMinecraft().fontRendererObj);
- }
-
- }
-
- @Override
- public JsonObject serialize() {
- JsonObject recipe = new JsonObject();
- recipe.addProperty("level", level);
- recipe.addProperty("coins", coins);
- recipe.addProperty("xp", xp);
- recipe.addProperty("combat_xp", combatXp);
- recipe.addProperty("name", name);
- recipe.addProperty("render", render);
- recipe.addProperty("type", getType().getId());
- JsonArray drops = new JsonArray();
- for (MobDrop drop : this.drops) {
- JsonObject dropObject = new JsonObject();
- dropObject.addProperty("id", drop.drop.serialize());
- JsonArray extraText = new JsonArray();
- for (String extraLine : drop.extra) {
- extraText.add(new JsonPrimitive(extraLine));
- }
- dropObject.add("extra", extraText);
- dropObject.addProperty("chance", drop.chance);
- drops.add(dropObject);
- }
- recipe.add("drops", drops);
- return recipe;
- }
-
- @Override
- public ResourceLocation getBackground() {
- return BACKGROUND;
- }
-
- public static MobLootRecipe parseRecipe(NEUManager manager, JsonObject recipe, JsonObject outputItemJson) {
- List<MobDrop> drops = new ArrayList<>();
- for (JsonElement jsonElement : recipe.getAsJsonArray("drops")) {
- if (jsonElement.isJsonPrimitive()) {
- drops.add(new MobDrop(new Ingredient(manager, jsonElement.getAsString()), null, Collections.emptyList()));
- } else {
- JsonObject jsonObject = jsonElement.getAsJsonObject();
- drops.add(
- new MobDrop(
- new Ingredient(manager, jsonObject.get("id").getAsString()),
- jsonObject.has("chance") ? jsonObject.get("chance").getAsString() : null,
- jsonObject.has("extra") ?
- StreamSupport.stream(jsonObject.getAsJsonArray("extra").spliterator(), false)
- .map(JsonElement::getAsString)
- .collect(Collectors.toList()) : Collections.emptyList()
- ));
- }
- }
-
- return new MobLootRecipe(
- drops,
- recipe.has("level") ? recipe.get("level").getAsInt() : 0,
- recipe.has("coins") ? recipe.get("coins").getAsInt() : 0,
- recipe.has("xp") ? recipe.get("xp").getAsInt() : 0,
- recipe.has("combat_xp") ? recipe.get("combat_xp").getAsInt() : 0,
- recipe.get("name").getAsString(),
- recipe.has("render") && !recipe.get("render").isJsonNull() ? recipe.get("render").getAsString() : null
- );
- }
+ private static final int MOB_POS_X = 38, MOB_POS_Y = 100;
+ private static final int SLOT_POS_X = 82, SLOT_POS_Y = 23;
+
+ public static class MobDrop {
+ public final Ingredient drop;
+ public final String chance;
+ public final List<String> extra;
+
+ public MobDrop(Ingredient drop, String chance, List<String> extra) {
+ this.drop = drop;
+ this.chance = chance;
+ this.extra = extra;
+ }
+ }
+
+ public static ResourceLocation[] PANORAMAS = new ResourceLocation[6];
+
+ static {
+ for (int i = 0; i < 6; i++)
+ PANORAMAS[i] = new ResourceLocation("notenoughupdates:panoramas/unknown/panorama_" + i + ".jpg");
+ }
+
+ public static ResourceLocation BACKGROUND = new ResourceLocation(
+ "notenoughupdates",
+ "textures/gui/mob_loot_tall.png"
+ );
+ private final List<MobDrop> drops;
+ private final int coins;
+ private final int combatXp;
+ private final int xp;
+ private final String name;
+ private final String render;
+ private final int level;
+ private final List<String> extra;
+ private EntityLivingBase entityLivingBase;
+
+ public MobLootRecipe(
+ List<MobDrop> drops,
+ int level,
+ int coins,
+ int xp,
+ int combatXp,
+ String name,
+ String render,
+ List<String> extra
+ ) {
+ this.drops = drops;
+ this.level = level;
+ this.coins = coins;
+ this.xp = xp;
+ this.extra = extra;
+ this.combatXp = combatXp;
+ this.name = name;
+ this.render = render;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public List<MobDrop> getDrops() {
+ return drops;
+ }
+
+ public int getCoins() {
+ return coins;
+ }
+
+ public int getCombatXp() {
+ return combatXp;
+ }
+
+ public int getXp() {
+ return xp;
+ }
+
+ public String getRender() {
+ return render;
+ }
+
+ public synchronized EntityLivingBase getRenderEntity() {
+ if (entityLivingBase == null) {
+ if (render == null) return null;
+ if (render.startsWith("@")) {
+ entityLivingBase = EntityViewer.constructEntity(new ResourceLocation(render.substring(1)));
+ } else {
+ entityLivingBase = EntityViewer.constructEntity(render, Collections.emptyList());
+ }
+ }
+ return entityLivingBase;
+ }
+
+ @Override
+ public Set<Ingredient> getIngredients() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public Set<Ingredient> getOutputs() {
+ return drops.stream().map(it -> it.drop).collect(Collectors.toSet());
+ }
+
+ @Override
+ public List<RecipeSlot> getSlots() {
+ List<RecipeSlot> slots = new ArrayList<>();
+ for (int i = 0; i < drops.size(); i++) {
+ MobDrop mobDrop = drops.get(i);
+ int x = i % 5;
+ int y = i / 5;
+ slots.add(new RecipeSlot(
+ SLOT_POS_X + x * 16,
+ SLOT_POS_Y + y * 16,
+ mobDrop.drop.getItemStack()
+ ));
+ }
+ return slots;
+ }
+
+ @Override
+ public RecipeType getType() {
+ return RecipeType.MOB_LOOT;
+ }
+
+ @Override
+ public boolean shouldUseForCraftCost() {
+ return false;
+ }
+
+ @Override
+ public boolean hasVariableCost() {
+ return true;
+ }
+
+ public static final int PANORAMA_POS_X = 13;
+ public static final int PANORAMA_POS_Y = 23;
+ public static final int PANORAMA_WIDTH = 50;
+ public static final int PANORAMA_HEIGHT = 80;
+
+ @Override
+ public void drawExtraBackground(GuiItemRecipe gui, int mouseX, int mouseY) {
+ Panorama.drawPanorama(
+ ((System.nanoTime() / 20000000000F) % 1) * 360,
+ gui.guiLeft + PANORAMA_POS_X,
+ gui.guiTop + PANORAMA_POS_Y,
+ PANORAMA_WIDTH,
+ PANORAMA_HEIGHT,
+ 0F,
+ 0F,
+ PANORAMAS
+ );
+ if (getRenderEntity() != null)
+ EntityViewer.renderEntity(entityLivingBase, gui.guiLeft + MOB_POS_X, gui.guiTop + MOB_POS_Y, mouseX, mouseY);
+ }
+
+ @Override
+ public void drawHoverInformation(GuiItemRecipe gui, int mouseX, int mouseY) {
+ if (gui.isWithinRect(
+ mouseX,
+ mouseY,
+ gui.guiLeft + PANORAMA_POS_X,
+ gui.guiTop + PANORAMA_POS_Y,
+ PANORAMA_WIDTH,
+ PANORAMA_HEIGHT
+ )) {
+ List<String> stuff = new ArrayList<>(extra);
+ stuff.add(0, "[Lvl " + level + "] " + name);
+ Utils.drawHoveringText(
+ stuff,
+ mouseX,
+ mouseY,
+ gui.width,
+ gui.height,
+ -1,
+ Minecraft.getMinecraft().fontRendererObj
+ );
+ }
+ }
+
+ @Override
+ public int[] getPageFlipPositionLeftTopCorner() {
+ return new int[]{14, 118};
+ }
+
+ @Override
+ public JsonObject serialize() {
+ JsonObject recipe = new JsonObject();
+ recipe.addProperty("level", level);
+ recipe.addProperty("coins", coins);
+ recipe.addProperty("xp", xp);
+ recipe.addProperty("combat_xp", combatXp);
+ recipe.addProperty("name", name);
+ recipe.addProperty("render", render);
+ recipe.addProperty("type", getType().getId());
+ recipe.add("extra", JsonUtils.transformListToJsonArray(extra, JsonPrimitive::new));
+ recipe.add("drops", JsonUtils.transformListToJsonArray(drops, drop -> {
+ JsonObject dropObject = new JsonObject();
+ dropObject.addProperty("id", drop.drop.serialize());
+ JsonArray extraText = new JsonArray();
+ for (String extraLine : drop.extra) {
+ extraText.add(new JsonPrimitive(extraLine));
+ }
+ dropObject.add("extra", extraText);
+ dropObject.addProperty("chance", drop.chance);
+ return dropObject;
+ }));
+ return recipe;
+ }
+
+ @Override
+ public ResourceLocation getBackground() {
+ return BACKGROUND;
+ }
+
+ public static MobLootRecipe parseRecipe(NEUManager manager, JsonObject recipe, JsonObject outputItemJson) {
+ List<MobDrop> drops = new ArrayList<>();
+ for (JsonElement jsonElement : recipe.getAsJsonArray("drops")) {
+ if (jsonElement.isJsonPrimitive()) {
+ drops.add(new MobDrop(new Ingredient(manager, jsonElement.getAsString()), null, Collections.emptyList()));
+ } else {
+ JsonObject jsonObject = jsonElement.getAsJsonObject();
+ drops.add(
+ new MobDrop(
+ new Ingredient(manager, jsonObject.get("id").getAsString()),
+ jsonObject.has("chance") ? jsonObject.get("chance").getAsString() : null,
+ JsonUtils.getJsonArrayOrEmpty(jsonObject, "extra", JsonElement::getAsString)
+ ));
+ }
+ }
+
+ return new MobLootRecipe(
+ drops,
+ recipe.has("level") ? recipe.get("level").getAsInt() : 0,
+ recipe.has("coins") ? recipe.get("coins").getAsInt() : 0,
+ recipe.has("xp") ? recipe.get("xp").getAsInt() : 0,
+ recipe.has("combat_xp") ? recipe.get("combat_xp").getAsInt() : 0,
+ recipe.get("name").getAsString(),
+ recipe.has("render") && !recipe.get("render").isJsonNull() ? recipe.get("render").getAsString() : null,
+ JsonUtils.getJsonArrayOrEmpty(recipe, "extra", JsonElement::getAsString)
+ );
+ }
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/recipes/NeuRecipe.java b/src/main/java/io/github/moulberry/notenoughupdates/recipes/NeuRecipe.java
index b14a724e..232e1629 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/recipes/NeuRecipe.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/recipes/NeuRecipe.java
@@ -9,43 +9,50 @@ import java.util.List;
import java.util.Set;
public interface NeuRecipe {
- Set<Ingredient> getIngredients();
+ Set<Ingredient> getIngredients();
- Set<Ingredient> getOutputs();
+ Set<Ingredient> getOutputs();
- List<RecipeSlot> getSlots();
+ List<RecipeSlot> getSlots();
- RecipeType getType();
+ RecipeType getType();
- default void drawExtraInfo(GuiItemRecipe gui, int mouseX, int mouseY) {
- }
+ default void drawExtraInfo(GuiItemRecipe gui, int mouseX, int mouseY) {
+ }
- default void drawExtraBackground(GuiItemRecipe gui, int mouseX, int mouseY) {
- }
+ default void drawExtraBackground(GuiItemRecipe gui, int mouseX, int mouseY) {
+ }
- default void drawHoverInformation(GuiItemRecipe gui, int mouseX, int mouseY) {
- }
+ default void drawHoverInformation(GuiItemRecipe gui, int mouseX, int mouseY) {
+ }
- boolean hasVariableCost();
+ boolean hasVariableCost();
- JsonObject serialize();
+ JsonObject serialize();
- ResourceLocation getBackground();
+ ResourceLocation getBackground();
- static NeuRecipe parseRecipe(NEUManager manager, JsonObject recipe, JsonObject output) {
- RecipeType recipeType = RecipeType.CRAFTING;
- if (recipe.has("type")) {
- recipeType = RecipeType.getRecipeTypeForId(recipe.get("type").getAsString());
- }
- if (recipeType == null) return null;
- return recipeType.createRecipe(manager, recipe, output);
- }
+ static NeuRecipe parseRecipe(NEUManager manager, JsonObject recipe, JsonObject output) {
+ RecipeType recipeType = RecipeType.CRAFTING;
+ if (recipe.has("type")) {
+ recipeType = RecipeType.getRecipeTypeForId(recipe.get("type").getAsString());
+ }
+ if (recipeType == null) return null;
+ return recipeType.createRecipe(manager, recipe, output);
+ }
- default boolean shouldUseForCraftCost() {
- return true;
- }
+ default boolean shouldUseForCraftCost() {
+ return true;
+ }
- default boolean isAvailable() {
- return true;
- }
+ default boolean isAvailable() {
+ return true;
+ }
+
+ /**
+ * @return an array of length two in the format [leftmost x, topmost y] of the page buttons
+ */
+ default int[] getPageFlipPositionLeftTopCorner() {
+ return new int[]{110, 90};
+ }
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/recipes/RecipeGenerator.java b/src/main/java/io/github/moulberry/notenoughupdates/recipes/RecipeGenerator.java
index 09e60003..6c2d1102 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/recipes/RecipeGenerator.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/recipes/RecipeGenerator.java
@@ -165,7 +165,7 @@ public class RecipeGenerator {
}
}
- recipes.add(new MobLootRecipe(drops, level, coins, xp, combatXp, name, null));
+ recipes.add(new MobLootRecipe(drops, level, coins, xp, combatXp, name, null, new ArrayList<>()));
}
boolean saved = false;
try {
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/JsonUtils.java b/src/main/java/io/github/moulberry/notenoughupdates/util/JsonUtils.java
new file mode 100644
index 00000000..916631b7
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/JsonUtils.java
@@ -0,0 +1,42 @@
+package io.github.moulberry.notenoughupdates.util;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+
+public class JsonUtils {
+ public static Stream<JsonElement> getJsonArrayAsStream(JsonArray array) {
+ return StreamSupport.stream(array.spliterator(), false);
+ }
+
+ public static <T> List<T> transformJsonArrayToList(JsonArray array, Function<? super JsonElement, ? extends T> mapper) {
+ return getJsonArrayAsStream(array).map(mapper).collect(Collectors.toList());
+ }
+
+ public static <T> List<T> getJsonArrayOrEmpty(JsonObject rootObject, String name, Function<? super JsonElement, ? extends T> mapper) {
+ if (!rootObject.has(name)) {
+ return Collections.emptyList();
+ }
+ JsonElement jsonElement = rootObject.get(name);
+ if (jsonElement.isJsonArray()) {
+ return transformJsonArrayToList(jsonElement.getAsJsonArray(), mapper);
+ }
+ return Collections.emptyList();
+ }
+
+ public static <T> JsonArray transformListToJsonArray(List<T> things, Function<? super T, ? extends JsonElement> mapper) {
+ JsonArray array = new JsonArray();
+ for (T t : things) {
+ array.add(mapper.apply(t));
+ }
+ return array;
+ }
+
+}