From 25e20662e4efee96ff2089026d147b3a3ca0bb0b Mon Sep 17 00:00:00 2001 From: Boblet Date: Wed, 4 Jun 2025 16:11:38 +0200 Subject: [PATCH] a little gift for future me --- .../gui/GUIMachineChemicalPlant.java | 40 +++- .../gui/GUIScreenRecipeSelector.java | 199 +++++++++++++++--- .../hbm/inventory/gui/GuiInfoContainer.java | 24 ++- .../recipes/loader/GenericRecipe.java | 28 ++- .../recipes/loader/GenericRecipes.java | 20 ++ .../hbm/module/ModuleMachineChemplant.java | 26 ++- .../TileEntityMachineChemicalPlant.java | 27 ++- .../textures/gui/processing/gui_chemplant.png | Bin 4029 -> 3535 bytes .../gui/processing/gui_recipe_selector.png | Bin 1802 -> 1894 bytes 9 files changed, 326 insertions(+), 38 deletions(-) diff --git a/src/main/java/com/hbm/inventory/gui/GUIMachineChemicalPlant.java b/src/main/java/com/hbm/inventory/gui/GUIMachineChemicalPlant.java index d2812ab1f..c960eea0c 100644 --- a/src/main/java/com/hbm/inventory/gui/GUIMachineChemicalPlant.java +++ b/src/main/java/com/hbm/inventory/gui/GUIMachineChemicalPlant.java @@ -4,12 +4,16 @@ import org.lwjgl.opengl.GL11; import com.hbm.inventory.container.ContainerMachineChemicalPlant; import com.hbm.inventory.recipes.ChemicalPlantRecipes; +import com.hbm.inventory.recipes.loader.GenericRecipe; import com.hbm.lib.RefStrings; import com.hbm.tileentity.machine.TileEntityMachineChemicalPlant; import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.OpenGlHelper; import net.minecraft.client.resources.I18n; import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.inventory.Slot; +import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.ResourceLocation; public class GUIMachineChemicalPlant extends GuiInfoContainer { @@ -35,6 +39,15 @@ public class GUIMachineChemicalPlant extends GuiInfoContainer { } this.drawElectricityInfo(this, mouseX, mouseY, guiLeft + 152, guiTop + 18, 16, 61, chemplant.power, chemplant.maxPower); + + if(guiLeft + 7 <= mouseX && guiLeft + 7 + 18 > mouseX && guiTop + 125 < mouseY && guiTop + 125 + 18 >= mouseY) { + if(this.chemplant.chemplantModule.recipe != null && ChemicalPlantRecipes.INSTANCE.recipeNameMap.containsKey(this.chemplant.chemplantModule.recipe)) { + GenericRecipe recipe = (GenericRecipe) ChemicalPlantRecipes.INSTANCE.recipeNameMap.get(this.chemplant.chemplantModule.recipe); + this.func_146283_a(recipe.print(), mouseX, mouseY); + } else { + this.drawCreativeTabHoveringText(EnumChatFormatting.YELLOW + "Click to set recipe", mouseX, mouseY); + } + } } @Override @@ -61,10 +74,33 @@ public class GUIMachineChemicalPlant extends GuiInfoContainer { int p = (int) (chemplant.power * 61 / chemplant.maxPower); drawTexturedModalRect(guiLeft + 152, guiTop + 79 - p, 176, 61 - p, 16, p); - if(chemplant.maxProgress > 0) { - int j = chemplant.progress * 70 / chemplant.maxProgress; + if(chemplant.chemplantModule.progress > 0) { + int j = (int) Math.ceil(70 * chemplant.chemplantModule.progress); drawTexturedModalRect(guiLeft + 62, guiTop + 126, 176, 61, j, 16); } + + GenericRecipe recipe = ChemicalPlantRecipes.INSTANCE.recipeNameMap.get(chemplant.chemplantModule.recipe); + this.renderItem(recipe != null ? recipe.getIcon() : TEMPLATE_FOLDER, 8, 126); + + if(recipe != null && recipe.inputItem != null) { + for(int i = 0; i < recipe.inputItem.length; i++) { + Slot slot = (Slot) this.inventorySlots.inventorySlots.get(chemplant.chemplantModule.inputSlots[i]); + if(!slot.getHasStack()) this.renderItem(recipe.inputItem[i].extractForCyclingDisplay(20), slot.xDisplayPosition, slot.yDisplayPosition, 10F); + } + + Minecraft.getMinecraft().getTextureManager().bindTexture(texture); + OpenGlHelper.glBlendFunc(770, 771, 1, 0); + GL11.glColor4f(1F, 1F, 1F, 0.5F); + GL11.glEnable(GL11.GL_BLEND); + this.zLevel = 300F; + for(int i = 0; i < recipe.inputItem.length; i++) { + Slot slot = (Slot) this.inventorySlots.inventorySlots.get(chemplant.chemplantModule.inputSlots[i]); + if(!slot.getHasStack()) drawTexturedModalRect(guiLeft + slot.xDisplayPosition, guiTop + slot.yDisplayPosition, slot.xDisplayPosition, slot.yDisplayPosition, 16, 16); + } + this.zLevel = 0F; + GL11.glColor4f(1F, 1F, 1F, 1F); + GL11.glDisable(GL11.GL_BLEND); + } for(int i = 0; i < 3; i++) { chemplant.inputTanks[i].renderTank(guiLeft + 8, guiTop + 52, this.zLevel, 16, 34); diff --git a/src/main/java/com/hbm/inventory/gui/GUIScreenRecipeSelector.java b/src/main/java/com/hbm/inventory/gui/GUIScreenRecipeSelector.java index 9fedd4ef0..418fc2dbd 100644 --- a/src/main/java/com/hbm/inventory/gui/GUIScreenRecipeSelector.java +++ b/src/main/java/com/hbm/inventory/gui/GUIScreenRecipeSelector.java @@ -12,13 +12,20 @@ import com.hbm.interfaces.IControlReceiver; import com.hbm.inventory.recipes.loader.GenericRecipe; import com.hbm.inventory.recipes.loader.GenericRecipes; import com.hbm.lib.RefStrings; +import com.hbm.packet.PacketDispatcher; +import com.hbm.packet.toserver.NBTControlPacket; import cpw.mods.fml.common.FMLCommonHandler; import net.minecraft.client.Minecraft; +import net.minecraft.client.audio.PositionedSoundRecord; import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.GuiTextField; import net.minecraft.client.renderer.RenderHelper; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.ResourceLocation; public class GUIScreenRecipeSelector extends GuiScreen { @@ -37,6 +44,7 @@ public class GUIScreenRecipeSelector extends GuiScreen { protected int pageIndex; protected int size; protected String selection; + public static final String NULL_SELECTION = "null"; // callback protected int index; protected IControlReceiver tile; @@ -52,6 +60,7 @@ public class GUIScreenRecipeSelector extends GuiScreen { this.selection = selection; this.index = index; this.previousScreen = previousScreen; + if(this.selection == null) this.selection = NULL_SELECTION; regenerateRecipes(); } @@ -106,6 +115,40 @@ public class GUIScreenRecipeSelector extends GuiScreen { this.drawGuiContainerForegroundLayer(mouseX, mouseY); GL11.glEnable(GL11.GL_LIGHTING); this.handleScroll(); + + if(guiLeft + 7 <= mouseX && guiLeft + 7 + 144 > mouseX && guiTop + 17 < mouseY && guiTop + 17 + 90 >= mouseY) { + for(int i = pageIndex * 8; i < pageIndex * 8 + 40; i++) { + if(i >= this.recipes.size()) break; + + int ind = i - pageIndex * 8; + int ix = 7 + 18 * (ind % 8); + int iy = 17 + 18 * (ind / 8); + + if(guiLeft + ix <= mouseX && guiLeft + ix + 18 > mouseX && guiTop + iy < mouseY && guiTop + iy + 18 >= mouseY) { + GenericRecipe recipe = recipes.get(i); + this.func_146283_a(recipe.print(), mouseX, mouseY); + } + } + } + + if(guiLeft + 151 <= mouseX && guiLeft + 151 + 18 > mouseX && guiTop + 71 < mouseY && guiTop + 71 + 18 >= mouseY) { + if(this.selection != null && this.recipeSet.recipeNameMap.containsKey(selection)) { + GenericRecipe recipe = (GenericRecipe) this.recipeSet.recipeNameMap.get(selection); + this.func_146283_a(recipe.print(), mouseX, mouseY); + } + } + + if(guiLeft + 152 <= mouseX && guiLeft + 152 + 16 > mouseX && guiTop + 90 < mouseY && guiTop + 90 + 16 >= mouseY) { + this.drawCreativeTabHoveringText(EnumChatFormatting.YELLOW + "Close", mouseX, mouseY); + } + + if(guiLeft + 134 <= mouseX && guiLeft + 134 + 16 > mouseX && guiTop + 108 < mouseY && guiTop + 108 + 16 >= mouseY) { + this.drawCreativeTabHoveringText(EnumChatFormatting.YELLOW + "Clear search", mouseX, mouseY); + } + + if(guiLeft + 8 <= mouseX && guiLeft + 8 + 16 > mouseX && guiTop + 108 < mouseY && guiTop + 108 + 16 >= mouseY) { + this.drawCreativeTabHoveringText(EnumChatFormatting.ITALIC + "Press ENTER to toggle focus", mouseX, mouseY); + } } protected void handleScroll() { @@ -118,7 +161,7 @@ public class GUIScreenRecipeSelector extends GuiScreen { } private void drawGuiContainerForegroundLayer(int x, int y) { - + this.search.drawTextBox(); } private void drawGuiContainerBackgroundLayer(float f, int mouseX, int mouseY) { @@ -126,38 +169,148 @@ public class GUIScreenRecipeSelector extends GuiScreen { Minecraft.getMinecraft().getTextureManager().bindTexture(texture); drawTexturedModalRect(guiLeft, guiTop, 0, 0, xSize, ySize); + if(this.search.isFocused()) { + drawTexturedModalRect(guiLeft + 26, guiTop + 108, 0, 132, 106, 16); + } + + if(guiLeft + 152 <= mouseX && guiLeft + 152 + 16 > mouseX && guiTop + 18 < mouseY && guiTop + 18 + 16 >= mouseY) { + drawTexturedModalRect(guiLeft + 152, guiTop + 18, 176, 0, 16, 16); + } + + if(guiLeft + 152 <= mouseX && guiLeft + 152 + 16 > mouseX && guiTop + 36 < mouseY && guiTop + 36 + 16 >= mouseY) { + drawTexturedModalRect(guiLeft + 152, guiTop + 36, 176, 16, 16, 16); + } + + if(guiLeft + 152 <= mouseX && guiLeft + 152 + 16 > mouseX && guiTop + 90 < mouseY && guiTop + 90 + 16 >= mouseY) { + drawTexturedModalRect(guiLeft + 152, guiTop + 90, 176, 32, 16, 16); + } + + if(guiLeft + 134 <= mouseX && guiLeft + 134 + 16 > mouseX && guiTop + 108 < mouseY && guiTop + 108 + 16 >= mouseY) { + drawTexturedModalRect(guiLeft + 134, guiTop + 108, 176, 48, 16, 16); + } + + if(guiLeft + 8 <= mouseX && guiLeft + 8 + 16 > mouseX && guiTop + 108 < mouseY && guiTop + 108 + 16 >= mouseY) { + drawTexturedModalRect(guiLeft + 8, guiTop + 108, 176, 64, 16, 16); + } + + for(int i = pageIndex * 8; i < pageIndex * 8 + 40; i++) { + if(i >= recipes.size()) break; + int ind = i - pageIndex * 8; + GenericRecipe recipe = recipes.get(i); + if(recipe.getInternalName().equals(this.selection)) this.drawTexturedModalRect(guiLeft + 7 + 18 * (ind % 8), guiTop + 17 + 18 * (ind / 8), 192, 0, 18, 18); + } + for(int i = pageIndex * 8; i < pageIndex * 8 + 40; i++) { if(i >= recipes.size()) break; int ind = i - pageIndex * 8; - - GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); - RenderHelper.enableGUIStandardItemLighting(); - GL11.glDisable(GL11.GL_LIGHTING); - GL11.glEnable(GL12.GL_RESCALE_NORMAL); - GenericRecipe recipe = recipes.get(i); - FontRenderer font = recipe.getIcon().getItem().getFontRenderer(recipe.getIcon()); - if(font == null) font = fontRendererObj; - - itemRender.zLevel = 100.0F; - itemRender.renderItemAndEffectIntoGUI(font, this.mc.getTextureManager(), recipe.getIcon(), guiLeft + 8 + 18 * (ind % 8), guiTop + 18 + 18 * (ind / 8)); - - itemRender.zLevel = 0.0F; - - GL11.glEnable(GL11.GL_ALPHA_TEST); - GL11.glDisable(GL11.GL_LIGHTING); + this.renderItem(recipe.getIcon(), 8 + 18 * (ind % 8), 18 + 18 * (ind / 8)); this.mc.getTextureManager().bindTexture(texture); + } + + if(this.selection != null && this.recipeSet.recipeNameMap.containsKey(selection)) { + GenericRecipe recipe = (GenericRecipe) this.recipeSet.recipeNameMap.get(selection); + this.renderItem(recipe.getIcon(), 152, 72); + } + } + + public void renderItem(ItemStack stack, int x, int y) { + + FontRenderer font = stack.getItem().getFontRenderer(stack); + if(font == null) font = fontRendererObj; + + GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); + RenderHelper.enableGUIStandardItemLighting(); + GL11.glDisable(GL11.GL_LIGHTING); + GL11.glEnable(GL12.GL_RESCALE_NORMAL); + + itemRender.zLevel = 100.0F; + itemRender.renderItemAndEffectIntoGUI(font, this.mc.getTextureManager(), stack, guiLeft + x, guiTop + y); + itemRender.zLevel = 0.0F; + + GL11.glEnable(GL11.GL_ALPHA_TEST); + GL11.glDisable(GL11.GL_LIGHTING); + } + + @Override + protected void mouseClicked(int x, int y, int k) { + super.mouseClicked(x, y, k); + + this.search.mouseClicked(x, y, k); + + if(guiLeft + 152 <= x && guiLeft + 152 + 16 > x && guiTop + 18 < y && guiTop + 18 + 16 >= y) { + click(); + if(this.pageIndex > 0) this.pageIndex--; + return; + } + + if(guiLeft + 152 <= x && guiLeft + 152 + 16 > x && guiTop + 36 < y && guiTop + 36 + 16 >= y) { + click(); + if(this.pageIndex < this.size) this.pageIndex++; + return; + } + + if(guiLeft + 134 <= x && guiLeft + 134 + 16 > x && guiTop + 108 < y && guiTop + 108 + 16 >= y) { + this.search.setText(""); + this.search(""); + this.search.setFocused(true); + return; + } + + for(int i = pageIndex * 8; i < pageIndex * 8 + 40; i++) { + if(i >= this.recipes.size()) break; - if(recipe.name.equals(this.selection)) - this.drawTexturedModalRect(guiLeft + 7 + 18 * (ind % 8), guiTop + 17 + 18 * (ind / 8), 192, 0, 18, 18); + int ind = i - pageIndex * 8; + int ix = 7 + 18 * (ind % 8); + int iy = 17 + 18 * (ind / 8); + + if(guiLeft + ix <= x && guiLeft + ix + 18 > x && guiTop + iy < y && guiTop + iy + 18 >= y) { + + String newSelection = ((GenericRecipe) recipes.get(i)).getInternalName(); + + if(!newSelection.equals(selection)) + this.selection = newSelection; + else + this.selection = NULL_SELECTION; + + NBTTagCompound data = new NBTTagCompound(); + data.setInteger("index", this.index); + data.setString("selection", this.selection); + TileEntity te = (TileEntity) tile; + PacketDispatcher.wrapper.sendToServer(new NBTControlPacket(data, te.xCoord, te.yCoord, te.zCoord)); + click(); + return; + } + } + + if(guiLeft + 151 <= x && guiLeft + 151 + 18 > x && guiTop + 71 < y && guiTop + 71 + 18 >= y) { + if(!NULL_SELECTION.equals(this.selection)) { + this.selection = this.NULL_SELECTION; + NBTTagCompound data = new NBTTagCompound(); + data.setInteger("index", this.index); + data.setString("selection", this.selection); + TileEntity te = (TileEntity) tile; + PacketDispatcher.wrapper.sendToServer(new NBTControlPacket(data, te.xCoord, te.yCoord, te.zCoord)); + click(); + return; + } + } + + if(guiLeft + 152 <= x && guiLeft + 152 + 16 > x && guiTop + 90 < y && guiTop + 90 + 16 >= y) { + FMLCommonHandler.instance().showGuiScreen(previousScreen); } } @Override protected void keyTyped(char typedChar, int keyCode) { + if(keyCode == Keyboard.KEY_RETURN) { + this.search.setFocused(!this.search.isFocused()); + return; + } + if(this.search.textboxKeyTyped(typedChar, keyCode)) { search(this.search.getText()); return; @@ -168,10 +321,8 @@ public class GUIScreenRecipeSelector extends GuiScreen { } } - @Override - public void onGuiClosed() { - Keyboard.enableRepeatEvents(false); - } - + @Override public void onGuiClosed() { Keyboard.enableRepeatEvents(false); } @Override public boolean doesGuiPauseGame() { return false; } + + public void click() { mc.getSoundHandler().playSound(PositionedSoundRecord.func_147674_a(new ResourceLocation("gui.button.press"), 1.0F)); } } diff --git a/src/main/java/com/hbm/inventory/gui/GuiInfoContainer.java b/src/main/java/com/hbm/inventory/gui/GuiInfoContainer.java index ea8e989b5..33a0a828d 100644 --- a/src/main/java/com/hbm/inventory/gui/GuiInfoContainer.java +++ b/src/main/java/com/hbm/inventory/gui/GuiInfoContainer.java @@ -15,6 +15,7 @@ import net.minecraft.nbt.NBTTagCompound; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL12; +import com.hbm.items.ModItems; import com.hbm.items.machine.ItemMachineUpgrade.UpgradeType; import com.hbm.lib.RefStrings; import com.hbm.tileentity.IUpgradeInfoProvider; @@ -161,7 +162,7 @@ public abstract class GuiInfoContainer extends GuiContainer implements INEIGuiHa return this.fontRendererObj; } - + /** Draws item with label, excludes all the GL state setup */ protected void drawItemStack(ItemStack stack, int x, int y, String label) { GL11.glTranslatef(0.0F, 0.0F, 32.0F); this.zLevel = 200.0F; @@ -174,6 +175,27 @@ public abstract class GuiInfoContainer extends GuiContainer implements INEIGuiHa this.zLevel = 0.0F; itemRender.zLevel = 0.0F; } + + public static final ItemStack TEMPLATE_FOLDER = new ItemStack(ModItems.template_folder); + + /** Standardsized item rendering from GUIScreenRecipeSelector */ + public void renderItem(ItemStack stack, int x, int y) { + renderItem(stack, x, y, 100F); + } + + public void renderItem(ItemStack stack, int x, int y, float layer) { + FontRenderer font = stack.getItem().getFontRenderer(stack); + if(font == null) font = fontRendererObj; + GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); + RenderHelper.enableGUIStandardItemLighting(); + GL11.glDisable(GL11.GL_LIGHTING); + GL11.glEnable(GL12.GL_RESCALE_NORMAL); + itemRender.zLevel = layer; + itemRender.renderItemAndEffectIntoGUI(font, this.mc.getTextureManager(), stack, guiLeft + x, guiTop + y); + itemRender.zLevel = 0.0F; + GL11.glEnable(GL11.GL_ALPHA_TEST); + GL11.glDisable(GL11.GL_LIGHTING); + } protected void drawStackText(List lines, int x, int y, FontRenderer font) { diff --git a/src/main/java/com/hbm/inventory/recipes/loader/GenericRecipe.java b/src/main/java/com/hbm/inventory/recipes/loader/GenericRecipe.java index 9199580d1..823f97e81 100644 --- a/src/main/java/com/hbm/inventory/recipes/loader/GenericRecipe.java +++ b/src/main/java/com/hbm/inventory/recipes/loader/GenericRecipe.java @@ -1,5 +1,7 @@ package com.hbm.inventory.recipes.loader; +import java.util.ArrayList; +import java.util.List; import java.util.Locale; import com.hbm.inventory.FluidStack; @@ -13,10 +15,11 @@ import com.hbm.util.i18n.I18nUtil; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumChatFormatting; public class GenericRecipe { - public String name; + protected final String name; public AStack[] inputItem; public FluidStack[] inputFluid; public IOutput[] outputItem; @@ -62,12 +65,31 @@ public class GenericRecipe { return icon; } - public String getName() { + public String getInternalName() { + return this.name; + } + + public String getLocalizedName() { if(customLocalization) return I18nUtil.resolveKey(name); return this.getIcon().getDisplayName(); } + public List print() { + List list = new ArrayList(); + list.add(EnumChatFormatting.YELLOW + this.getLocalizedName()); + list.add(EnumChatFormatting.BOLD + "Input:"); + if(inputItem != null) for(AStack stack : inputItem) { + ItemStack display = stack.extractForCyclingDisplay(20); + list.add(" " + EnumChatFormatting.GRAY + display.stackSize + "x " + display.getDisplayName()); + } + if(inputFluid != null) for(FluidStack fluid : inputFluid) list.add(" " + EnumChatFormatting.BLUE + fluid.fill + "mB " + fluid.type.getLocalizedName() + (fluid.pressure == 0 ? "" : "at " + EnumChatFormatting.RED + fluid.pressure + " PU")); + list.add(EnumChatFormatting.BOLD + "Output:"); + if(outputItem != null) for(IOutput output : outputItem) for(String line : output.getLabel()) list.add(" " + line); + if(outputFluid != null) for(FluidStack fluid : outputFluid) list.add(" " + EnumChatFormatting.BLUE + fluid.fill + "mB " + fluid.type.getLocalizedName() + (fluid.pressure == 0 ? "" : "at " + EnumChatFormatting.RED + fluid.pressure + " PU")); + return list; + } + public boolean matchesSearch(String substring) { - return getName().toLowerCase(Locale.US).contains(substring.toLowerCase(Locale.US)); + return getLocalizedName().toLowerCase(Locale.US).contains(substring.toLowerCase(Locale.US)); } } diff --git a/src/main/java/com/hbm/inventory/recipes/loader/GenericRecipes.java b/src/main/java/com/hbm/inventory/recipes/loader/GenericRecipes.java index 5c33d09d4..53de13faa 100644 --- a/src/main/java/com/hbm/inventory/recipes/loader/GenericRecipes.java +++ b/src/main/java/com/hbm/inventory/recipes/loader/GenericRecipes.java @@ -14,6 +14,7 @@ import com.hbm.inventory.FluidStack; import com.hbm.inventory.RecipesCommon.AStack; import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.WeightedRandom; /** @@ -157,6 +158,7 @@ public abstract class GenericRecipes extends Serializab public ItemStack collapse(); public void serialize(JsonWriter writer) throws IOException; public void deserialize(JsonArray array); + public String[] getLabel(); } /** A chance output, produces either an ItemStack or null */ @@ -216,6 +218,11 @@ public abstract class GenericRecipes extends Serializab if(array.size() > 2) this.itemWeight = array.get(2).getAsInt(); } } + + @Override + public String[] getLabel() { + return new String[] {EnumChatFormatting.GRAY + "" + this.stack.stackSize + "x " + this.stack.getDisplayName() + (this.chance >= 1 ? "" : " (" + (int)(this.chance * 1000) / 10F + "%)")}; + } } /** Multiple choice chance output, produces a ChanceOutput chosen randomly by weight */ @@ -242,5 +249,18 @@ public abstract class GenericRecipes extends Serializab pool.add(output); } } + + @Override + public String[] getLabel() { + String[] label = new String[pool.size() + 1]; + label[0] = "One of:"; + int totalWeight = WeightedRandom.getTotalWeight(pool); + for(int i = 1; i < label.length; i++) { + ChanceOutput output = pool.get(i - 1); + float chance = (float) output.itemWeight / (float) totalWeight * output.chance; + label[i] = " " + EnumChatFormatting.GRAY + output.stack.stackSize + "x " + output.stack.getDisplayName() + " (" + (int)(chance * 1000F) / 10F + "%)"; + } + return label; + } } } diff --git a/src/main/java/com/hbm/module/ModuleMachineChemplant.java b/src/main/java/com/hbm/module/ModuleMachineChemplant.java index 9775ab26a..2d5d0ffbc 100644 --- a/src/main/java/com/hbm/module/ModuleMachineChemplant.java +++ b/src/main/java/com/hbm/module/ModuleMachineChemplant.java @@ -5,6 +5,8 @@ import com.hbm.inventory.recipes.ChemicalPlantRecipes; import com.hbm.inventory.recipes.loader.GenericRecipe; import api.hbm.energymk2.IEnergyHandlerMK2; +import cpw.mods.fml.common.network.ByteBufUtils; +import io.netty.buffer.ByteBuf; import net.minecraft.item.ItemStack; /** @@ -23,7 +25,7 @@ public class ModuleMachineChemplant { public FluidTank[] inputTanks = new FluidTank[3]; public FluidTank[] outputTanks = new FluidTank[3]; - public String recipe; + public String recipe = "null"; public float progress; public ModuleMachineChemplant(int index, IEnergyHandlerMK2 battery, ItemStack[] slots) { @@ -45,11 +47,33 @@ public class ModuleMachineChemplant { public void resetProgress() { this.progress = 0F; } public void update() { + //TBI + } + + public boolean isItemValid(int slot, ItemStack stack) { + GenericRecipe recipe = ChemicalPlantRecipes.INSTANCE.recipeNameMap.get(this.recipe); + if(recipe == null) return false; + if(recipe.inputItem == null) return false; + for(int i = 0; i < Math.min(inputSlots.length, recipe.inputItem.length); i++) { + if(recipe.inputItem[i].matchesRecipe(stack, true)) return true; + } + + return false; } public ModuleMachineChemplant iInput(int a, int b, int c) { inputSlots[0] = a; inputSlots[1] = b; inputSlots[2] = c; return this; } public ModuleMachineChemplant iOutput(int a, int b, int c) { outputSlots[0] = a; outputSlots[1] = b; outputSlots[2] = c; return this; } public ModuleMachineChemplant fInput(FluidTank a, FluidTank b, FluidTank c) { inputTanks[0] = a; inputTanks[1] = b; inputTanks[2] = c; return this; } public ModuleMachineChemplant fOutput(FluidTank a, FluidTank b, FluidTank c) { outputTanks[0] = a; outputTanks[1] = b; outputTanks[2] = c; return this; } + + public void serialize(ByteBuf buf) { + buf.writeFloat(progress); + ByteBufUtils.writeUTF8String(buf, recipe); + } + + public void deserialize(ByteBuf buf) { + this.progress = buf.readFloat(); + this.recipe = ByteBufUtils.readUTF8String(buf); + } } diff --git a/src/main/java/com/hbm/tileentity/machine/TileEntityMachineChemicalPlant.java b/src/main/java/com/hbm/tileentity/machine/TileEntityMachineChemicalPlant.java index d0579ad9a..6686267ad 100644 --- a/src/main/java/com/hbm/tileentity/machine/TileEntityMachineChemicalPlant.java +++ b/src/main/java/com/hbm/tileentity/machine/TileEntityMachineChemicalPlant.java @@ -10,6 +10,7 @@ import com.hbm.inventory.container.ContainerMachineChemicalPlant; import com.hbm.inventory.fluid.Fluids; import com.hbm.inventory.fluid.tank.FluidTank; import com.hbm.inventory.gui.GUIMachineChemicalPlant; +import com.hbm.items.machine.ItemMachineUpgrade; import com.hbm.items.machine.ItemMachineUpgrade.UpgradeType; import com.hbm.lib.Library; import com.hbm.module.ModuleMachineChemplant; @@ -26,6 +27,7 @@ import cpw.mods.fml.relauncher.SideOnly; import io.netty.buffer.ByteBuf; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.Container; +import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.AxisAlignedBB; import net.minecraft.util.EnumChatFormatting; @@ -38,8 +40,6 @@ public class TileEntityMachineChemicalPlant extends TileEntityMachineBase implem public long power; public long maxPower = 1_000_000; - public int progress; - public int maxProgress; public ModuleMachineChemplant chemplantModule; public UpgradeManagerNT upgradeManager = new UpgradeManagerNT(this); @@ -85,8 +85,7 @@ public class TileEntityMachineChemicalPlant extends TileEntityMachineBase implem for(FluidTank tank : outputTanks) tank.serialize(buf); buf.writeLong(power); buf.writeLong(maxPower); - buf.writeInt(progress); - buf.writeInt(maxProgress); + this.chemplantModule.serialize(buf); } @Override @@ -96,8 +95,7 @@ public class TileEntityMachineChemicalPlant extends TileEntityMachineBase implem for(FluidTank tank : outputTanks) tank.deserialize(buf); this.power = buf.readLong(); this.maxPower = buf.readLong(); - this.progress = buf.readInt(); - this.maxProgress = buf.readInt(); + this.chemplantModule.deserialize(buf); } @Override @@ -122,6 +120,16 @@ public class TileEntityMachineChemicalPlant extends TileEntityMachineBase implem } } + @Override + public boolean isItemValidForSlot(int slot, ItemStack stack) { + if(slot == 0) return true; // battery + if(slot >= 2 && slot <= 3 && stack.getItem() instanceof ItemMachineUpgrade) return true; // upgades + if(slot >= 10 && slot <= 12) return true; // input fluid + if(slot >= 16 && slot <= 18) return true; // output fluid + if(this.chemplantModule.isItemValid(slot, stack)) return true; // recipe input crap + return false; + } + @Override public long getPower() { return power; } @Override public void setPower(long power) { this.power = power; } @Override public long getMaxPower() { return maxPower; } @@ -137,7 +145,12 @@ public class TileEntityMachineChemicalPlant extends TileEntityMachineBase implem @Override public void receiveControl(NBTTagCompound data) { - + if(data.hasKey("index") && data.hasKey("selection")) { + int index = data.getInteger("index"); + String selection = data.getString("selection"); + if(index == 0) this.chemplantModule.recipe = selection; + this.markChanged(); + } } AxisAlignedBB bb = null; diff --git a/src/main/resources/assets/hbm/textures/gui/processing/gui_chemplant.png b/src/main/resources/assets/hbm/textures/gui/processing/gui_chemplant.png index ef8c8fc45a752b63dd48f4d63e53efc915476d80..d58713d9c3f848312cd58d877fd04d93f618154d 100644 GIT binary patch literal 3535 zcma)8c|6ox8~^=gX@)n$6mh4qMcFE3Ez1nqNwTM6sH{n(!N|}iA$8jX6!xQqE z*NFnc#)&W!jx4)I+E}8ozcPG$jM}!s1vlCW&jybdSFBXdRreonDf+UZkXLkN{fi@u(HTSf@DTS_fRyEJ#pzqkkUcekIBivBedf; zBnjyOErLB=-BZK6x+|#jC~oNTe0Ibp_EKYsB;-;c)4I=Yk>3VhEf6SQP;JpMzX z8#S4BSb0T%5BRc*I`1ckTFSgT7%@Amb?g-Ca@w);eu9$v&sx2o`OA{}C(9>CldX1? zmX&!qIXQ(%=)mT=)n5fyxGjGPa11P4`+FNS`xz~X10QPz^w9mKpZxWjT z7p-KgTd7O0#lX646m$@I(w|Lxd>Kc?Zvyt6qfmU`4FxZs^EOafP>ecjBxqogb!c)A ziIo-_R~xAYK~@JduUhjZ!Rn+b-VXOpYT_}8=``_)bHiXf&?lsaP^b{3$3kX7H$_d6 z(z#%rG)Oe;DgdoO-tKdsIWW|8hV^`BQ~Bn{GSK}g<%0AvF3=2FDjopbUcQW3Msm3! z-=?PS+Usm-y|Q~&S^}sgGqVTNmjZ`IGM2|g z$zeY%^3(22J7-f%uo)~aFzh(zRVso?hShc8D*G^YbF;pq4>H@8OXk(DV~MGMW@-@_ z=f%o8Z@TE@<<45}(swunk9p?|Gdt&b$WKnBgql~MqxcXAyk%Ofol_WYvc4!M47t&m zl|weM)nVlE4&H~J@|#L;)qRc3)x#TY#`li;JMxl3kPn6H0I6vIkhaR5maC? zh5}N=eA%16;ldoBBh~^^{2Ecjc*HXmWK4hQ29=1VhmPTlj7KyCdAoka#cib2N3BOX z4ESTc5)OE6Dk0mhBBhuJNLf!I4LoDdT9l9tTYBSUqU$ppMx64=WaDLmFQA$WA}kyb z_9N_~1OycGz$5TnnfjXI_Tsc+&;}9zM+6`eIKVa%kiyLUhcFj_JRXd3sc!4D6M=+k z16&^RG{5{mypFC)A+sul!$%a4vFR$~{GU?p;YlectnthFKE+=|>eJ`#>|2edeLY$V zqY-uQXDFadfE*|2r@?>Q{u8woQd{N3HS1l~i9u*f@`Rs%D9mif^qP-inSG0@1I?>Hx3)<|bqQ-AKlD^@K4$LdhnjdmhB@Os z8!%mWJ3(D{en5MRJ)&^W%c7v~4r@;aMY-sN$Y=D$uLH0eVu@HD3(3Lb#&k1_CEIwx zXGl@dE3wmKT_X6dLiC*^o>=f*hY~@%=Di}EpE4QDIb-EjdD(z+$z;RjckezFl4HAu zCD$$|(leJZ>x|7s@|X+0sEs8G*o`>RCL5nNN7uUhRSSNCHVu52e0B8S4YlcWzcF$( zpYn=lhIgDz-P2rw!>Mi!%_Z+U`832fW>Trz_|8yW>t`DB+dy?A|7;mYt3US10>K`8 zl6OXk>(~R2xTg#0L`o2Kaaan+= zx(VnN;{(pbBcdGrUwkYZ+90hSHwUAiqm99dTr*%0fqJ=N6M%zgFIa45iYhB-MjGUY zWMrR`dvEH7%?MheX4LD}AtThC#Ygm?=8uq57Q7$tJ54!Hzh3Yw1U++TMC(`p>?WR1 z3NQz>1o)(cpy3*4>je+YXK1gn=q~(N5Dj2e)pJ)w1CZS_x+z~Z!OQ72qNW>Dmquvf zz4bR1JE7GtnqXUfjpXSrPGm!W;LvnDqSF9|X4bg%JQRd?%($4qMtc>B#`wigJ8n0= zJ*@wEKf(BXQW?5;B1Lj)9H(c+6gInbdq%&9Kc{ z@EcB*nv7hJjohnj-U z4`!tAsU5?pOF;tx2ZthnikYiPRy)26R&-x`)6&A$FSCpoetTlilgdgx$lMod3#{G_ zJWK)JFOQwF0{SPl8zsNY%(N{mQG<090wcm0JDYIa@Lk=aHb=4EUDMv(?OO2qbk&@9 zc}HO?;T2iO-!F0Jwu*0mvhC)*t<$HOH6&8x@|PfYpRTjsl1i|lTNc3m{nLHcPsf0- zbT%`VnDSs#)Zq`TRJALm9)`+qrkkofWmySnRhw0s_V82sLY1R5pJR!w!TXNkM1-r; zw}Wql7o4$XHx|)SO?zn8Ii97I3FWG2wJQ?c|DqqHB7j{`uOiyx>JBw4ijjIsF!S4z zAmE*_h$aPoAkZ*pHXjTzyoZldUx?1xAY`<5*JL7%K)@FetRqCOGge6 z4ch>gSP^XSHV!;-*mG{YXPlyDM6gg(S|k&LDEviayelav5BrXl}^|4(({*?b10lx^f%DnIK>$fMFZ%Se4T9GKD0WH{y7BJ2?+}F@Vq-_UAM)u0Csi)UiEmV_FBQGQCqK89mV$e;va$x6d915Kv40JM+3Q{GbeH+z}PjQBpKXcrT=>sv}x4^Q?`05Xfn!RJtlx zmzPVGN2xKe#BnH)X{XUb7hxn^Jur}V3MrIuiEv>B&f@zhvCKAH%{g;pYoj7V(#3xR DKjunf literal 4029 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 Onx1aHt`(#+$$tPLPZMMS literal 1802 zcmcgt`#aQW6n|$-`O?}Z3eC0|WGE`-+OSOXj5Ju;Tyl#_<<2}9B9|FvDn+YD=DYkp}=M zkPng$1Au^C1c27U;2BnY8U|E2k?aJ)77Lxc0KnR2GHJilncUeoyugkAsSUKE zHF&{;eRK}v1&t|zi1yk8D#%e3VC^}Sw2oc|JCz50*3oT|KoJM9$G?M56q5K0cc4Pm z8l>r4gWA`UktWADEeN>JO5T)HRs}8vt5K_zkE0VKl*}>nloCW`6vcB{W?9^6qv+0B zc-imjvGb_!)^Wr}6CuPN8q)iWSo{#eOiy>DD&8?Tv$88l99Ba~6+hfRtNw!NyZn?Q zPnd0=DKHVd$(wGtG&ne2+HAr>5?W9owcpH?bCQ+(7Ixc=8_|B30rvibb1KMAG$0w3 z^Pe)BG%m#`gWYnVFsrC}`e#IE!Zm=sXoacgpr4DRy{7j~W?SY1c6zl!#gcZoHkNhk zlW#Z*$c3W_8wbJ%yLmc7(7plGy7xzeRY{c7C*`}B0NZ8H!gFZ{MgZ=s<$dX8ygH+@ zst&)X*>I|3#d)}Kuc)*HK?w_U$7}7zbrh$2v0Rnt)mtrM@KxM6tyiW>^q!J(`;KHn zg_rpfe>hq_Eja${s%ZDW1d;w$2B=4Y0olihqX~SB|xfbEA+aurpc{LOvL5`Y<4uJ ze#SBBK;q8UQ-s3TjZtUcYBg79NJ?Y9cc1|O9h1NxH(Af#f*@#Ct2> z`xxp}HWU#dvS6TLC5Avl@#nX0@@Ei7If1-nCcpjLzXyt zuyznnu2S@k-P%a(sm!k@MAe}Zy{WOW9=m3Yo6L`7{!Zmvfra(5*M3qdu=rMnPquL0 zv!NLOErNIO_;f}NGjJ?b=7zh03~1khSMD&aTy{fkyV#I4%C+A<5vTU@s{*-3@v%sn zPMyK|x#-lqxZr`~35H0TAC5^I4~4Z_%7<0hsR&3JunKvbzi!xtkX{Y!CkPZ`ew)ar zQfV<#?Mla)tqCri=ndeZ{m#KR{maB0)T4>x*uuTprrH!V(G z8PqbSYB)ISP1Rbn(ql_cXgE*{S;z;Xl|@%ItNq><`Ang3ITEFpUmOVF=&{IDd4A+! z5oNUXb5)=9pTl}R)bmz^+po<`w+4QB(C4SUh|vF|j&B`0R>kR7xQlA)e^N0rGunr@ z=>}&-f-qQ+x|_hloPXuw2Tluuy;L9ig4^hrDA0-6gdGqivIpjf*p+OopGgKH%ilfS z4C8l?SOoe#tW0`cv?T@g=DZ;VW*;y#C9=gfN7tZ{5Ir(n4cwBWFDL@1w;CutsLr;w zOiGryUd`h1vMGkWG@xw*=2vn?MCM}_0rG}$6m+K?vln68h5_5`fb^Xx58H#j8gPe! zj=3i=S8a@yyt3T24QF;Z`mdUr?pNoUG*VC%t&^6+l~>AXkNqX`^9zzC+wR@m&!4A9 z`i8cCVHSnys>iOZ@rf4C3lDVX5UjcK(&bCjNBk%7aP#H~{0-n==KnI<2Z?Njj7@7+ RONp