From e5f465e231eb04bf998c91659f9ddac7c6cc6361 Mon Sep 17 00:00:00 2001 From: ArshdipKhinda Date: Wed, 5 Nov 2025 22:00:03 -0800 Subject: [PATCH 1/5] Added the ability to change ME Item Output Bus stack limit. Memory Card functionality still needs to be added WIP --- .../mmce/client/gui/GuiMEItemOutputBus.java | 39 ++- .../gui/GuiMEItemOutputBusStackSize.java | 316 ++++++++++++++++++ .../ContainerMEItemOutputBusStackSize.java | 80 +++++ .../PktMEOutputBusStackSizeChange.java | 87 +++++ .../network/PktSwitchGuiMEOutputBus.java | 112 +++++++ .../mmce/common/tile/MEItemOutputBus.java | 65 +++- .../modularmachinery/ModularMachinery.java | 32 +- .../modularmachinery/client/ClientProxy.java | 12 +- .../modularmachinery/common/CommonProxy.java | 11 +- 9 files changed, 730 insertions(+), 24 deletions(-) create mode 100644 src/main/java/github/kasuminova/mmce/client/gui/GuiMEItemOutputBusStackSize.java create mode 100644 src/main/java/github/kasuminova/mmce/common/container/ContainerMEItemOutputBusStackSize.java create mode 100644 src/main/java/github/kasuminova/mmce/common/network/PktMEOutputBusStackSizeChange.java create mode 100644 src/main/java/github/kasuminova/mmce/common/network/PktSwitchGuiMEOutputBus.java diff --git a/src/main/java/github/kasuminova/mmce/client/gui/GuiMEItemOutputBus.java b/src/main/java/github/kasuminova/mmce/client/gui/GuiMEItemOutputBus.java index 9897a277..5ecf286e 100644 --- a/src/main/java/github/kasuminova/mmce/client/gui/GuiMEItemOutputBus.java +++ b/src/main/java/github/kasuminova/mmce/client/gui/GuiMEItemOutputBus.java @@ -1,22 +1,59 @@ package github.kasuminova.mmce.client.gui; +import appeng.client.gui.widgets.GuiTabButton; import appeng.core.localization.GuiText; import github.kasuminova.mmce.common.container.ContainerMEItemOutputBus; +import github.kasuminova.mmce.common.network.PktSwitchGuiMEOutputBus; import github.kasuminova.mmce.common.tile.MEItemOutputBus; +import hellfirepvp.modularmachinery.ModularMachinery; +import net.minecraft.client.gui.GuiButton; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.resources.I18n; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.ResourceLocation; +import java.io.IOException; + public class GuiMEItemOutputBus extends GuiMEItemBus { // For convenience, the Sky Chest resource was used :P private static final ResourceLocation TEXTURES_OUTPUT_BUS = new ResourceLocation("appliedenergistics2", "textures/guis/skychest.png"); + private GuiTabButton stackSizeBtn; + private final MEItemOutputBus outputBus; + public GuiMEItemOutputBus(final MEItemOutputBus te, final EntityPlayer player) { super(new ContainerMEItemOutputBus(te, player)); + this.outputBus = te; this.ySize = 195; } + @Override + public void initGui() { + super.initGui(); + + // Add wrench button for stack size configuration + // Icon ID: 2 + 4 * 16 = 66 (wrench icon in AE2's states.png texture) + this.buttonList.add(this.stackSizeBtn = new GuiTabButton( + this.guiLeft + 154, + this.guiTop, + 2 + 4 * 16, + "Stack Size", + this.itemRender + )); + } + + @Override + protected void actionPerformed(final GuiButton btn) throws IOException { + super.actionPerformed(btn); + + if (btn == this.stackSizeBtn) { + // Switch to stack size configuration GUI + ModularMachinery.NET_CHANNEL.sendToServer( + new PktSwitchGuiMEOutputBus(this.outputBus.getPos(), 1) + ); + } + } + @Override public void drawFG(int offsetX, int offsetY, int mouseX, int mouseY) { this.fontRenderer.drawString(I18n.format("gui.meitemoutputbus.title"), 8, 8, 0x404040); @@ -30,4 +67,4 @@ public void drawBG(int offsetX, int offsetY, int mouseX, int mouseY) { this.drawTexturedModalRect(offsetX, offsetY, 0, 0, this.xSize, this.ySize); } -} +} \ No newline at end of file diff --git a/src/main/java/github/kasuminova/mmce/client/gui/GuiMEItemOutputBusStackSize.java b/src/main/java/github/kasuminova/mmce/client/gui/GuiMEItemOutputBusStackSize.java new file mode 100644 index 00000000..b009f15d --- /dev/null +++ b/src/main/java/github/kasuminova/mmce/client/gui/GuiMEItemOutputBusStackSize.java @@ -0,0 +1,316 @@ +package github.kasuminova.mmce.client.gui; + +import appeng.client.gui.AEBaseGui; +import appeng.client.gui.widgets.GuiNumberBox; +import appeng.client.gui.widgets.GuiTabButton; +import github.kasuminova.mmce.common.container.ContainerMEItemOutputBusStackSize; +import github.kasuminova.mmce.common.network.PktMEOutputBusStackSizeChange; +import github.kasuminova.mmce.common.network.PktSwitchGuiMEOutputBus; +import github.kasuminova.mmce.common.tile.MEItemOutputBus; +import hellfirepvp.modularmachinery.ModularMachinery; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.item.ItemStack; +import org.lwjgl.input.Keyboard; +import org.lwjgl.input.Mouse; + +import java.io.IOException; + +/** + * GUI for configuring the stack size limit of an ME Item Output Bus. + * This GUI mimics AE2's Priority GUI design but is adapted for stack size configuration. + */ +public class GuiMEItemOutputBusStackSize extends AEBaseGui { + + private GuiNumberBox stackSizeBox; + private GuiTabButton originalGuiBtn; + private final MEItemOutputBus outputBus; + + // Button references + private GuiButton plus1; + private GuiButton plus10; + private GuiButton plus100; + private GuiButton plus1000; + private GuiButton minus1; + private GuiButton minus10; + private GuiButton minus100; + private GuiButton minus1000; + + public GuiMEItemOutputBusStackSize(final InventoryPlayer inventoryPlayer, final MEItemOutputBus outputBus) { + super(new ContainerMEItemOutputBusStackSize(inventoryPlayer, outputBus)); + this.outputBus = outputBus; + this.ySize = 105; // Same height as AE2's Priority GUI + } + + @Override + public void initGui() { + super.initGui(); + + // Create the +/- buttons (matching AE2's Priority GUI layout) + this.buttonList.add(this.plus1 = new GuiButton(0, this.guiLeft + 20, this.guiTop + 32, 22, 20, "+1")); + this.buttonList.add(this.plus10 = new GuiButton(0, this.guiLeft + 48, this.guiTop + 32, 28, 20, "+10")); + this.buttonList.add(this.plus100 = new GuiButton(0, this.guiLeft + 82, this.guiTop + 32, 32, 20, "+100")); + this.buttonList.add(this.plus1000 = new GuiButton(0, this.guiLeft + 120, this.guiTop + 32, 38, 20, "+1000")); + + this.buttonList.add(this.minus1 = new GuiButton(0, this.guiLeft + 20, this.guiTop + 69, 22, 20, "-1")); + this.buttonList.add(this.minus10 = new GuiButton(0, this.guiLeft + 48, this.guiTop + 69, 28, 20, "-10")); + this.buttonList.add(this.minus100 = new GuiButton(0, this.guiLeft + 82, this.guiTop + 69, 32, 20, "-100")); + this.buttonList.add(this.minus1000 = new GuiButton(0, this.guiLeft + 120, this.guiTop + 69, 38, 20, "-1000")); + + // Create button to return to main Output Bus GUI + final ContainerMEItemOutputBusStackSize container = (ContainerMEItemOutputBusStackSize) this.inventorySlots; + final ItemStack busIcon = new ItemStack(this.outputBus.getBlockType()); + + if (!busIcon.isEmpty()) { + this.buttonList.add(this.originalGuiBtn = new GuiTabButton( + this.guiLeft + 154, + this.guiTop, + busIcon, + "ME Item Output Bus", + this.itemRender + )); + } + + // Create the number input box (centered, matching AE2's Priority GUI) + this.stackSizeBox = new GuiNumberBox( + this.fontRenderer, + this.guiLeft + 62, + this.guiTop + 57, + 59, + this.fontRenderer.FONT_HEIGHT, + Integer.class + ); + this.stackSizeBox.setEnableBackgroundDrawing(false); + this.stackSizeBox.setMaxStringLength(10); // Max int is 10 digits + this.stackSizeBox.setTextColor(0xFFFFFF); + this.stackSizeBox.setVisible(true); + this.stackSizeBox.setFocused(true); + + // Set initial value from container + this.stackSizeBox.setText(String.valueOf(container.getStackSize())); + } + + @Override + public void drawFG(final int offsetX, final int offsetY, final int mouseX, final int mouseY) { + // Draw title + this.fontRenderer.drawString("Stack Size", 8, 6, 4210752); + } + + @Override + public void drawBG(final int offsetX, final int offsetY, final int mouseX, final int mouseY) { + // Use AE2's priority.png texture + this.bindTexture("guis/priority.png"); + this.drawTexturedModalRect(offsetX, offsetY, 0, 0, this.xSize, this.ySize); + + // Draw the number box + this.stackSizeBox.drawTextBox(); + } + + @Override + protected void actionPerformed(final GuiButton btn) throws IOException { + super.actionPerformed(btn); + + // Handle return to main GUI button + if (btn == this.originalGuiBtn) { + // Send packet to switch back to main Output Bus GUI + ModularMachinery.NET_CHANNEL.sendToServer( + new PktSwitchGuiMEOutputBus(this.outputBus.getPos(), 0) + ); + return; + } + + // Handle +/- buttons + if (btn == this.plus1) { + this.addQty(1); + } else if (btn == this.plus10) { + this.addQty(10); + } else if (btn == this.plus100) { + this.addQty(100); + } else if (btn == this.plus1000) { + this.addQty(1000); + } else if (btn == this.minus1) { + this.addQty(-1); + } else if (btn == this.minus10) { + this.addQty(-10); + } else if (btn == this.minus100) { + this.addQty(-100); + } else if (btn == this.minus1000) { + this.addQty(-1000); + } + } + + /** + * Adds the specified amount to the current stack size value + */ + private void addQty(final int amount) { + try { + String text = this.stackSizeBox.getText(); + + // Remove leading zeros + boolean fixed = false; + while (text.startsWith("0") && text.length() > 1) { + text = text.substring(1); + fixed = true; + } + + if (fixed) { + this.stackSizeBox.setText(text); + } + + if (text.isEmpty()) { + text = "1"; // Minimum value is 1 + } + + int currentValue = Integer.parseInt(text); + int newValue = currentValue + amount; + + // Clamp to valid range (minimum 1, maximum Integer.MAX_VALUE) + if (newValue < 1) { + newValue = 1; + } + // Handle overflow + if (amount > 0 && newValue < currentValue) { + newValue = Integer.MAX_VALUE; + } + + this.stackSizeBox.setText(String.valueOf(newValue)); + this.sendStackSizeToServer(newValue); + } catch (final NumberFormatException e) { + // If parsing fails, reset to 1 + this.stackSizeBox.setText("1"); + this.sendStackSizeToServer(1); + } + } + + /** + * Sends the new stack size value to the server + */ + private void sendStackSizeToServer(int stackSize) { + ModularMachinery.NET_CHANNEL.sendToServer( + new PktMEOutputBusStackSizeChange(this.outputBus.getPos(), stackSize) + ); + } + + @Override + protected void keyTyped(final char character, final int key) throws IOException { + if (!this.checkHotbarKeys(key)) { + // Allow typing numbers and navigation keys + if ((key == 211 || key == 205 || key == 203 || key == 14 || Character.isDigit(character)) + && this.stackSizeBox.textboxKeyTyped(character, key)) { + try { + String text = this.stackSizeBox.getText(); + + // Remove leading zeros + boolean fixed = false; + while (text.startsWith("0") && text.length() > 1) { + text = text.substring(1); + fixed = true; + } + + if (fixed) { + this.stackSizeBox.setText(text); + } + + if (text.isEmpty()) { + text = "1"; + this.stackSizeBox.setText(text); + } + + int value = Integer.parseInt(text); + value = Math.max(1, value); // Minimum 1 + + this.sendStackSizeToServer(value); + } catch (final NumberFormatException e) { + this.stackSizeBox.setText("1"); + this.sendStackSizeToServer(1); + } + } else { + super.keyTyped(character, key); + } + } + } + + @Override + public void handleMouseInput() throws IOException { + super.handleMouseInput(); + + final int wheel = Mouse.getEventDWheel(); + if (wheel != 0) { + // Get mouse position + final int x = Mouse.getEventX() * this.width / this.mc.displayWidth; + final int y = this.height - Mouse.getEventY() * this.height / this.mc.displayHeight - 1; + + // Check if mouse is over the number box + int boxX = this.guiLeft + 62; + int boxY = this.guiTop + 57; + int boxWidth = 59; + int boxHeight = this.fontRenderer.FONT_HEIGHT; + + if (x >= boxX && x <= boxX + boxWidth && y >= boxY && y <= boxY + boxHeight) { + this.onMouseWheelEvent(wheel); + } + } + } + + /** + * Handles mouse wheel scrolling for the stack size value. + * Matches the behavior of GuiMEItemInputBus: + * - SHIFT+CTRL + scroll up = double + * - SHIFT+CTRL + scroll down = halve + * - SHIFT + scroll up = +1 + * - SHIFT + scroll down = -1 + */ + private void onMouseWheelEvent(final int wheel) { + boolean shiftHeld = Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT); + boolean ctrlHeld = Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL); + + // Only process if SHIFT is held (to match Input Bus behavior) + if (!shiftHeld) { + return; + } + + try { + int currentValue = Integer.parseInt(this.stackSizeBox.getText()); + int newValue; + boolean isScrollingUp = wheel > 0; + + if (ctrlHeld) { + // SHIFT+CTRL: Double or halve + if (isScrollingUp) { + // Double (with overflow protection) + if (currentValue <= Integer.MAX_VALUE / 2) { + newValue = currentValue * 2; + } else { + newValue = Integer.MAX_VALUE; + } + } else { + // Halve + newValue = Math.max(1, currentValue / 2); + } + } else { + // SHIFT only: +1 or -1 + if (isScrollingUp) { + // +1 (with overflow protection) + if (currentValue < Integer.MAX_VALUE) { + newValue = currentValue + 1; + } else { + newValue = Integer.MAX_VALUE; + } + } else { + // -1 + newValue = Math.max(1, currentValue - 1); + } + } + + this.stackSizeBox.setText(String.valueOf(newValue)); + this.sendStackSizeToServer(newValue); + } catch (NumberFormatException e) { + this.stackSizeBox.setText("1"); + this.sendStackSizeToServer(1); + } + } + + protected String getBackground() { + return "guis/priority.png"; + } +} \ No newline at end of file diff --git a/src/main/java/github/kasuminova/mmce/common/container/ContainerMEItemOutputBusStackSize.java b/src/main/java/github/kasuminova/mmce/common/container/ContainerMEItemOutputBusStackSize.java new file mode 100644 index 00000000..a0aa7c1c --- /dev/null +++ b/src/main/java/github/kasuminova/mmce/common/container/ContainerMEItemOutputBusStackSize.java @@ -0,0 +1,80 @@ +package github.kasuminova.mmce.common.container; + +import appeng.api.config.SecurityPermissions; +import appeng.container.AEBaseContainer; +import appeng.container.guisync.GuiSync; +import github.kasuminova.mmce.common.tile.MEItemOutputBus; +import net.minecraft.entity.player.InventoryPlayer; + +/** + * Container for the ME Item Output Bus Stack Size configuration GUI. + * Handles synchronization of the stack size value between client and server. + * + * NOTE: This container does NOT apply changes to the tile entity in real-time. + * Changes are only applied when the GUI is closed via onContainerClosed(). + */ +public class ContainerMEItemOutputBusStackSize extends AEBaseContainer { + + private final MEItemOutputBus outputBus; + + /** + * The stack size value displayed and edited in the GUI. + * Synced from server to client automatically via @GuiSync. + * This is a TEMPORARY value that gets applied when the GUI closes. + */ + @GuiSync(0) + public int stackSize = Integer.MAX_VALUE; + + public ContainerMEItemOutputBusStackSize(final InventoryPlayer inventoryPlayer, final MEItemOutputBus outputBus) { + super(inventoryPlayer, outputBus); + this.outputBus = outputBus; + + // Initialize with the current value from the tile entity + // This must be done in the constructor, not in detectAndSendChanges, + // to ensure the value is set before the GUI tries to read it + this.stackSize = outputBus.getConfiguredStackSize(); + } + + /** + * Returns the current stack size value being displayed/edited in the GUI. + * This is NOT necessarily the actual stack size in the tile entity. + */ + public int getStackSize() { + return this.stackSize; + } + + /** + * Returns the Output Bus tile entity. + */ + public MEItemOutputBus getOwner() { + return this.outputBus; + } + + /** + * Called periodically on the server to detect changes and sync to client. + * We don't read from the tile entity here to avoid overwriting user edits. + */ + @Override + public void detectAndSendChanges() { + this.verifyPermissions(SecurityPermissions.BUILD, false); + + // Let AE2's @GuiSync system handle synchronization + // Don't read from tile entity - we want to preserve user edits + super.detectAndSendChanges(); + } + + /** + * Called when the container is closed (player closes the GUI). + * This is where we apply the configured stack size to the tile entity. + */ + @Override + public void onContainerClosed(net.minecraft.entity.player.EntityPlayer playerIn) { + super.onContainerClosed(playerIn); + + // Only apply on server side + if (!playerIn.world.isRemote) { + // Apply the configured stack size to the tile entity + this.outputBus.setConfiguredStackSize(this.stackSize); + } + } +} \ No newline at end of file diff --git a/src/main/java/github/kasuminova/mmce/common/network/PktMEOutputBusStackSizeChange.java b/src/main/java/github/kasuminova/mmce/common/network/PktMEOutputBusStackSizeChange.java new file mode 100644 index 00000000..05c4a251 --- /dev/null +++ b/src/main/java/github/kasuminova/mmce/common/network/PktMEOutputBusStackSizeChange.java @@ -0,0 +1,87 @@ +package github.kasuminova.mmce.common.network; + +import github.kasuminova.mmce.common.container.ContainerMEItemOutputBusStackSize; +import io.netty.buffer.ByteBuf; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.inventory.Container; +import net.minecraft.util.math.BlockPos; +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; +import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; + +/** + * Packet sent from client to server when the player changes the stack size value in the GUI. + * Updates the CONTAINER's temporary stack size value, NOT the tile entity. + * The actual tile entity is only updated when the GUI is closed. + */ +public class PktMEOutputBusStackSizeChange implements IMessage, IMessageHandler { + + private BlockPos pos = BlockPos.ORIGIN; + private int stackSize = Integer.MAX_VALUE; + + /** + * Default constructor required by Forge's packet system + */ + public PktMEOutputBusStackSizeChange() { + } + + /** + * Constructor for creating a packet to send + * @param pos The position of the Output Bus tile entity + * @param stackSize The new stack size value + */ + public PktMEOutputBusStackSizeChange(final BlockPos pos, final int stackSize) { + this.pos = pos; + this.stackSize = stackSize; + } + + /** + * Reads packet data from the byte buffer (client -> server) + */ + @Override + public void fromBytes(final ByteBuf buf) { + this.pos = BlockPos.fromLong(buf.readLong()); + this.stackSize = buf.readInt(); + } + + /** + * Writes packet data to the byte buffer (client -> server) + */ + @Override + public void toBytes(final ByteBuf buf) { + buf.writeLong(this.pos.toLong()); + buf.writeInt(this.stackSize); + } + + /** + * Handles the packet on the server side. + * Updates the container's temporary stack size value. + * Does NOT update the tile entity directly. + */ + @Override + public IMessage onMessage(final PktMEOutputBusStackSizeChange message, final MessageContext ctx) { + EntityPlayerMP player = ctx.getServerHandler().player; + + // Schedule the action on the server thread + player.getServerWorld().addScheduledTask(() -> { + // Get the player's currently open container + Container container = player.openContainer; + + // Verify it's the stack size container + if (!(container instanceof ContainerMEItemOutputBusStackSize)) { + return; + } + + ContainerMEItemOutputBusStackSize stackSizeContainer = (ContainerMEItemOutputBusStackSize) container; + + // Validate the stack size (minimum 1) + int validatedStackSize = Math.max(1, message.stackSize); + + // Update the container's temporary stack size value + // This will be synced to the client automatically via @GuiSync + stackSizeContainer.stackSize = validatedStackSize; + }); + + return null; + } +} \ No newline at end of file diff --git a/src/main/java/github/kasuminova/mmce/common/network/PktSwitchGuiMEOutputBus.java b/src/main/java/github/kasuminova/mmce/common/network/PktSwitchGuiMEOutputBus.java new file mode 100644 index 00000000..c9d8ec86 --- /dev/null +++ b/src/main/java/github/kasuminova/mmce/common/network/PktSwitchGuiMEOutputBus.java @@ -0,0 +1,112 @@ +package github.kasuminova.mmce.common.network; + +import github.kasuminova.mmce.common.tile.MEItemOutputBus; +import hellfirepvp.modularmachinery.ModularMachinery; +import hellfirepvp.modularmachinery.common.CommonProxy.GuiType; +import io.netty.buffer.ByteBuf; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; +import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; + +/** + * Packet for switching between the main ME Item Output Bus GUI and the Stack Size configuration GUI. + * Sent from client to server when the player clicks the wrench button or return button. + * + * GUI Type: 0 = Main Output Bus GUI, 1 = Stack Size Configuration GUI + */ +public class PktSwitchGuiMEOutputBus implements IMessage, IMessageHandler { + + private BlockPos pos = BlockPos.ORIGIN; + private int guiType = 0; // 0 = main GUI, 1 = stack size GUI + + /** + * Default constructor required by Forge's packet system + */ + public PktSwitchGuiMEOutputBus() { + } + + /** + * Constructor for creating a packet to send + * @param pos The position of the Output Bus tile entity + * @param guiType The GUI type to open (0 = main, 1 = stack size) + */ + public PktSwitchGuiMEOutputBus(final BlockPos pos, final int guiType) { + this.pos = pos; + this.guiType = guiType; + } + + /** + * Reads packet data from the byte buffer (client -> server) + */ + @Override + public void fromBytes(final ByteBuf buf) { + this.pos = BlockPos.fromLong(buf.readLong()); + this.guiType = buf.readInt(); + } + + /** + * Writes packet data to the byte buffer (client -> server) + */ + @Override + public void toBytes(final ByteBuf buf) { + buf.writeLong(this.pos.toLong()); + buf.writeInt(this.guiType); + } + + /** + * Handles the packet on the server side + */ + @Override + public IMessage onMessage(final PktSwitchGuiMEOutputBus message, final MessageContext ctx) { + EntityPlayerMP player = ctx.getServerHandler().player; + + System.out.println("PktSwitchGuiMEOutputBus received! GUI Type: " + message.guiType + ", Pos: " + message.pos); + + // Schedule the action on the server thread + player.getServerWorld().addScheduledTask(() -> { + TileEntity te = player.world.getTileEntity(message.pos); + + System.out.println("Tile entity: " + (te != null ? te.getClass().getSimpleName() : "null")); + + // Verify it's an ME Item Output Bus + if (!(te instanceof MEItemOutputBus)) { + return; + } + + // Close current GUI + player.closeScreen(); + + // Open the requested GUI + if (message.guiType == 0) { + // Open main Output Bus GUI + player.openGui( + ModularMachinery.MODID, + GuiType.ME_ITEM_OUTPUT_BUS.ordinal(), + player.world, + message.pos.getX(), + message.pos.getY(), + message.pos.getZ() + ); + } else if (message.guiType == 1) { + + System.out.println("Opening stack size GUI with ID: " + GuiType.ME_ITEM_OUTPUT_BUS_STACK_SIZE.ordinal()); + + + // Open stack size configuration GUI + player.openGui( + ModularMachinery.MODID, + GuiType.ME_ITEM_OUTPUT_BUS_STACK_SIZE.ordinal(), + player.world, + message.pos.getX(), + message.pos.getY(), + message.pos.getZ() + ); + } + }); + + return null; + } +} \ No newline at end of file diff --git a/src/main/java/github/kasuminova/mmce/common/tile/MEItemOutputBus.java b/src/main/java/github/kasuminova/mmce/common/tile/MEItemOutputBus.java index 4e574622..a904f95e 100644 --- a/src/main/java/github/kasuminova/mmce/common/tile/MEItemOutputBus.java +++ b/src/main/java/github/kasuminova/mmce/common/tile/MEItemOutputBus.java @@ -13,6 +13,7 @@ import hellfirepvp.modularmachinery.common.machine.MachineComponent; import hellfirepvp.modularmachinery.common.util.IOInventory; import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -20,6 +21,9 @@ public class MEItemOutputBus extends MEItemBus { + // Stack size configuration field + private int configuredStackSize = Integer.MAX_VALUE; + @Override public IOInventory buildInventory() { int size = 36; @@ -29,7 +33,7 @@ public IOInventory buildInventory() { slotIDs[slotID] = slotID; } IOInventory inv = new IOInventory(this, new int[]{}, slotIDs); - inv.setStackLimit(Integer.MAX_VALUE, slotIDs); + inv.setStackLimit(this.configuredStackSize, slotIDs); inv.setListener(slot -> { synchronized (this) { changedSlots[slot] = true; @@ -131,4 +135,61 @@ public void markNoUpdate() { super.markNoUpdate(); } -} + + // ==================== Stack Size Configuration Methods ==================== + + /** + * Gets the currently configured stack size limit for this Output Bus + * @return the configured stack size (minimum 1, maximum Integer.MAX_VALUE) + */ + public int getConfiguredStackSize() { + return this.configuredStackSize; + } + + /** + * Sets the stack size limit for all slots in this Output Bus + * @param size the new stack size limit (will be clamped to minimum 1) + */ + public void setConfiguredStackSize(int size) { + // Clamp to valid range (minimum 1) + this.configuredStackSize = Math.max(1, size); + this.applyStackSizeToInventory(); + this.markForUpdate(); + } + + /** + * Applies the configured stack size to the inventory + */ + private void applyStackSizeToInventory() { + if (this.inventory != null) { + int[] slotIDs = new int[this.inventory.getSlots()]; + for (int slotID = 0; slotID < slotIDs.length; slotID++) { + slotIDs[slotID] = slotID; + } + this.inventory.setStackLimit(this.configuredStackSize, slotIDs); + } + } + + // ==================== NBT Serialization ==================== + + @Override + public void readCustomNBT(final NBTTagCompound compound) { + super.readCustomNBT(compound); + + // Read configured stack size from NBT + if (compound.hasKey("configuredStackSize")) { + this.configuredStackSize = compound.getInteger("configuredStackSize"); + } + + // Apply stack size after reading + this.applyStackSizeToInventory(); + } + + @Override + public void writeCustomNBT(final NBTTagCompound compound) { + super.writeCustomNBT(compound); + + // Write configured stack size to NBT + compound.setInteger("configuredStackSize", this.configuredStackSize); + } +} \ No newline at end of file diff --git a/src/main/java/hellfirepvp/modularmachinery/ModularMachinery.java b/src/main/java/hellfirepvp/modularmachinery/ModularMachinery.java index 36d7324a..a6cbfa70 100644 --- a/src/main/java/hellfirepvp/modularmachinery/ModularMachinery.java +++ b/src/main/java/hellfirepvp/modularmachinery/ModularMachinery.java @@ -11,9 +11,11 @@ import github.kasuminova.mmce.common.concurrent.TaskExecutor; import github.kasuminova.mmce.common.network.PktAutoAssemblyRequest; import github.kasuminova.mmce.common.network.PktMEInputBusInvAction; +import github.kasuminova.mmce.common.network.PktMEOutputBusStackSizeChange; import github.kasuminova.mmce.common.network.PktMEPatternProviderAction; import github.kasuminova.mmce.common.network.PktMEPatternProviderHandlerItems; import github.kasuminova.mmce.common.network.PktPerformanceReport; +import github.kasuminova.mmce.common.network.PktSwitchGuiMEOutputBus; import hellfirepvp.modularmachinery.common.CommonProxy; import hellfirepvp.modularmachinery.common.base.Mods; import hellfirepvp.modularmachinery.common.command.CommandGetBluePrint; @@ -47,23 +49,23 @@ /** * This class is part of the Modular Machinery Mod - * The complete source code for this mod can be found on GitHub. + * The complete source code for this mod can be found on github. * Class: ModularMachinery * Created by HellFirePvP * Date: 26.06.2017 / 20:26 */ @Mod(modid = ModularMachinery.MODID, name = ModularMachinery.NAME, version = ModularMachinery.VERSION, - dependencies = "required-after:forge@[14.21.0.2371,);" + - "required-after:crafttweaker@[4.0.4,);" + - "after:zenutils@[1.12.8,);" + - "after:jei@[4.13.1.222,);" + - "after:gregtech@[2.7.4-beta,);" + - "after:appliedenergistics2@[rv6-stable-7,);" + - "after:fluxnetworks@[4.1.0,);" + - "after:tconstruct@[1.12.2-2.12.0.157,);" + - "after:thermalexpansion@[5.5.0,);", - acceptedMinecraftVersions = "[1.12, 1.13)", - acceptableRemoteVersions = "[2.1.0, 2.3.0)" + dependencies = "required-after:forge@[14.21.0.2371,);" + + "required-after:crafttweaker@[4.0.4,);" + + "after:zenutils@[1.12.8,);" + + "after:jei@[4.13.1.222,);" + + "after:gregtech@[2.7.4-beta,);" + + "after:appliedenergistics2@[rv6-stable-7,);" + + "after:fluxnetworks@[4.1.0,);" + + "after:tconstruct@[1.12.2-2.12.0.157,);" + + "after:thermalexpansion@[5.5.0,);", + acceptedMinecraftVersions = "[1.12, 1.13)", + acceptableRemoteVersions = "[2.1.0, 2.3.0)" ) public class ModularMachinery { @@ -125,6 +127,10 @@ public void preInit(FMLPreInitializationEvent event) { if (Mods.ASTRAL_SORCERY.isPresent()) { NET_CHANNEL.registerMessage(StarlightMessage.StarlightMessageHandler.class, StarlightMessage.class, 106, Side.SERVER); } + if (Mods.AE2.isPresent()) { + NET_CHANNEL.registerMessage(PktMEOutputBusStackSizeChange.class, PktMEOutputBusStackSizeChange.class, 107, Side.SERVER); + NET_CHANNEL.registerMessage(PktSwitchGuiMEOutputBus.class, PktSwitchGuiMEOutputBus.class, 108, Side.SERVER); + } CommonProxy.loadModData(event.getModConfigurationDirectory()); proxy.preInit(); @@ -158,4 +164,4 @@ public void onServerStart(FMLServerStartingEvent event) { } } -} +} \ No newline at end of file diff --git a/src/main/java/hellfirepvp/modularmachinery/client/ClientProxy.java b/src/main/java/hellfirepvp/modularmachinery/client/ClientProxy.java index 9165cd72..00de56be 100644 --- a/src/main/java/hellfirepvp/modularmachinery/client/ClientProxy.java +++ b/src/main/java/hellfirepvp/modularmachinery/client/ClientProxy.java @@ -8,13 +8,7 @@ package hellfirepvp.modularmachinery.client; -import github.kasuminova.mmce.client.gui.GuiMEFluidInputBus; -import github.kasuminova.mmce.client.gui.GuiMEFluidOutputBus; -import github.kasuminova.mmce.client.gui.GuiMEGasInputBus; -import github.kasuminova.mmce.client.gui.GuiMEGasOutputBus; -import github.kasuminova.mmce.client.gui.GuiMEItemInputBus; -import github.kasuminova.mmce.client.gui.GuiMEItemOutputBus; -import github.kasuminova.mmce.client.gui.GuiMEPatternProvider; +import github.kasuminova.mmce.client.gui.*; import github.kasuminova.mmce.client.renderer.MachineControllerRenderer; import github.kasuminova.mmce.client.resource.GeoModelExternalLoader; import github.kasuminova.mmce.common.handler.ClientHandler; @@ -25,6 +19,7 @@ import github.kasuminova.mmce.common.tile.MEItemInputBus; import github.kasuminova.mmce.common.tile.MEItemOutputBus; import github.kasuminova.mmce.common.tile.MEPatternProvider; +import github.kasuminova.mmce.client.gui.GuiMEItemOutputBusStackSize; import hellfirepvp.modularmachinery.ModularMachinery; import hellfirepvp.modularmachinery.client.gui.GuiContainerEnergyHatch; import hellfirepvp.modularmachinery.client.gui.GuiContainerFluidHatch; @@ -324,6 +319,9 @@ public Object getClientGuiElement(int ID, EntityPlayer player, World world, int } return new GuiMEItemInputBus((MEItemInputBus) present, player); } + case ME_ITEM_OUTPUT_BUS_STACK_SIZE -> { + return new GuiMEItemOutputBusStackSize(player.inventory, (MEItemOutputBus) present); + } case ME_FLUID_OUTPUT_BUS -> { if (!Mods.AE2.isPresent()) { return null; diff --git a/src/main/java/hellfirepvp/modularmachinery/common/CommonProxy.java b/src/main/java/hellfirepvp/modularmachinery/common/CommonProxy.java index fafc9b0b..213813df 100644 --- a/src/main/java/hellfirepvp/modularmachinery/common/CommonProxy.java +++ b/src/main/java/hellfirepvp/modularmachinery/common/CommonProxy.java @@ -17,6 +17,7 @@ import github.kasuminova.mmce.common.container.ContainerMEGasOutputBus; import github.kasuminova.mmce.common.container.ContainerMEItemInputBus; import github.kasuminova.mmce.common.container.ContainerMEItemOutputBus; +import github.kasuminova.mmce.common.container.ContainerMEItemOutputBusStackSize; import github.kasuminova.mmce.common.container.ContainerMEPatternProvider; import github.kasuminova.mmce.common.handler.EventHandler; import github.kasuminova.mmce.common.handler.UpgradeEventHandler; @@ -31,6 +32,7 @@ import github.kasuminova.mmce.common.tile.MEPatternProvider; import github.kasuminova.mmce.common.util.concurrent.Action; import github.kasuminova.mmce.common.world.MMWorldEventListener; +import github.kasuminova.mmce.client.gui.GuiMEItemOutputBusStackSize; import hellfirepvp.modularmachinery.ModularMachinery; import hellfirepvp.modularmachinery.common.base.Mods; import hellfirepvp.modularmachinery.common.container.ContainerController; @@ -302,6 +304,12 @@ public Object getServerGuiElement(int ID, EntityPlayer player, World world, int } return new ContainerLifeEssence((TileLifeEssenceProvider) present, player); } + case ME_ITEM_OUTPUT_BUS_STACK_SIZE -> { + if (aeSecurityCheck(player, present)) { + return null; + } + return new ContainerMEItemOutputBusStackSize(player.inventory, (MEItemOutputBus) present); + } } return null; @@ -325,6 +333,7 @@ public enum GuiType { UPGRADE_BUS(TileUpgradeBus.class), BLUEPRINT_PREVIEW(null), ME_ITEM_OUTPUT_BUS(Mods.AE2.isPresent() ? MEItemOutputBus.class : null), + ME_ITEM_OUTPUT_BUS_STACK_SIZE(Mods.AE2.isPresent() ? MEItemOutputBus.class : null), ME_ITEM_INPUT_BUS(Mods.AE2.isPresent() ? MEItemInputBus.class : null), ME_FLUID_OUTPUT_BUS(Mods.AE2.isPresent() ? MEFluidOutputBus.class : null), ME_FLUID_INPUT_BUS(Mods.AE2.isPresent() ? MEFluidInputBus.class : null), @@ -340,4 +349,4 @@ public enum GuiType { this.requiredTileEntity = requiredTileEntity; } } -} +} \ No newline at end of file From 63569f926b01a66959884f6afd31872dacee38f3 Mon Sep 17 00:00:00 2001 From: ArshdipKhinda Date: Wed, 5 Nov 2025 23:20:27 -0800 Subject: [PATCH 2/5] Configure stack size button moved to the left --- .../mmce/client/gui/GuiMEItemOutputBus.java | 36 +++++++++++++------ 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/src/main/java/github/kasuminova/mmce/client/gui/GuiMEItemOutputBus.java b/src/main/java/github/kasuminova/mmce/client/gui/GuiMEItemOutputBus.java index 5ecf286e..c47a0928 100644 --- a/src/main/java/github/kasuminova/mmce/client/gui/GuiMEItemOutputBus.java +++ b/src/main/java/github/kasuminova/mmce/client/gui/GuiMEItemOutputBus.java @@ -1,6 +1,8 @@ package github.kasuminova.mmce.client.gui; -import appeng.client.gui.widgets.GuiTabButton; +import appeng.api.config.ActionItems; +import appeng.api.config.Settings; +import appeng.client.gui.widgets.GuiImgButton; import appeng.core.localization.GuiText; import github.kasuminova.mmce.common.container.ContainerMEItemOutputBus; import github.kasuminova.mmce.common.network.PktSwitchGuiMEOutputBus; @@ -13,12 +15,13 @@ import net.minecraft.util.ResourceLocation; import java.io.IOException; +import java.util.List; public class GuiMEItemOutputBus extends GuiMEItemBus { // For convenience, the Sky Chest resource was used :P private static final ResourceLocation TEXTURES_OUTPUT_BUS = new ResourceLocation("appliedenergistics2", "textures/guis/skychest.png"); - private GuiTabButton stackSizeBtn; + private CustomStackSizeButton stackSizeBtn; private final MEItemOutputBus outputBus; public GuiMEItemOutputBus(final MEItemOutputBus te, final EntityPlayer player) { @@ -32,14 +35,12 @@ public void initGui() { super.initGui(); // Add wrench button for stack size configuration - // Icon ID: 2 + 4 * 16 = 66 (wrench icon in AE2's states.png texture) - this.buttonList.add(this.stackSizeBtn = new GuiTabButton( - this.guiLeft + 154, - this.guiTop, - 2 + 4 * 16, - "Stack Size", - this.itemRender - )); + // Position: Left side, matching AE2's Partition Storage button position + this.stackSizeBtn = new CustomStackSizeButton( + this.guiLeft - 18, // Left side of GUI + this.guiTop + 8 // Top position + ); + this.buttonList.add(this.stackSizeBtn); } @Override @@ -67,4 +68,19 @@ public void drawBG(int offsetX, int offsetY, int mouseX, int mouseY) { this.drawTexturedModalRect(offsetX, offsetY, 0, 0, this.xSize, this.ySize); } + /** + * Custom button that extends GuiImgButton but overrides the tooltip message + */ + private static class CustomStackSizeButton extends GuiImgButton { + public CustomStackSizeButton(int x, int y) { + super(x, y, Settings.ACTIONS, ActionItems.WRENCH); + } + + @Override + public String getMessage() { + // Return our custom tooltip instead of AE2's default + return "Configure Stack Size"; + } + } + } \ No newline at end of file From 39cdcd077dba04b25c4539c46f7e142fe73e4836 Mon Sep 17 00:00:00 2001 From: ArshdipKhinda Date: Thu, 6 Nov 2025 22:02:35 -0800 Subject: [PATCH 3/5] Fully functioning with additional Memory Card support now. Changes to en_US.lang GuiMEItemInputBus.java and PktMEInputBusInvAction.java are from Alecsio's PR to harmonize scrolling behavior. --- .../mmce/client/gui/GuiMEItemInputBus.java | 120 +++--- .../gui/GuiMEItemOutputBusStackSize.java | 368 ++++++++++-------- .../block/appeng/BlockMEItemOutputBus.java | 35 +- .../network/PktMEInputBusInvAction.java | 28 +- .../PktMEOutputBusStackSizeChange.java | 28 +- .../mmce/common/tile/MEItemOutputBus.java | 25 +- .../assets/modularmachinery/lang/en_US.lang | 5 +- .../textures/gui/stacksize.png | Bin 0 -> 736 bytes 8 files changed, 338 insertions(+), 271 deletions(-) create mode 100644 src/main/resources/assets/modularmachinery/textures/gui/stacksize.png diff --git a/src/main/java/github/kasuminova/mmce/client/gui/GuiMEItemInputBus.java b/src/main/java/github/kasuminova/mmce/client/gui/GuiMEItemInputBus.java index 52d141a3..6c4f89ad 100644 --- a/src/main/java/github/kasuminova/mmce/client/gui/GuiMEItemInputBus.java +++ b/src/main/java/github/kasuminova/mmce/client/gui/GuiMEItemInputBus.java @@ -31,83 +31,29 @@ public class GuiMEItemInputBus extends GuiMEItemBus { private static final ResourceLocation TEXTURES_INPUT_BUS = new ResourceLocation(ModularMachinery.MODID, "textures/gui/meiteminputbus.png"); - private int invActionAmount = 0; - public GuiMEItemInputBus(final MEItemInputBus te, final EntityPlayer player) { super(new ContainerMEItemInputBus(te, player)); this.ySize = 204; } - private static int getAddAmount() { - int addAmount; - // SHIFT + CTRL + ALT 1000000 - // ALT + CTRL 100000 - // ALT + SHIFT 10000 - // SHIFT + CTRL 1000 - // CTRL 100 - // SHIFT 10 - if (isShiftDown() && isControlDown() && isAltDown()) { - addAmount = 1_000_000; - } else if (isAltDown() && isControlDown()) { - addAmount = 100_000; - } else if (isAltDown() && isShiftDown()) { - addAmount = 10_000; - } else if (isShiftDown() && isControlDown()) { - addAmount = 1_000; - } else if (isControlDown()) { - addAmount = 100; - } else if (isShiftDown()) { - addAmount = 10; - } else { - addAmount = 1; - } - return addAmount; - } - private static List getAddActionInfo() { List tooltip = new ArrayList<>(); tooltip.add(TextFormatting.GRAY + I18n.format("gui.meiteminputbus.inv_action")); // Quite a sight, isn't it? - String addAmount = MiscUtils.formatDecimal(getAddAmount()); - if (isShiftDown() && isControlDown() && isAltDown()) { - tooltip.add(TextFormatting.GRAY + I18n.format("gui.meiteminputbus.inv_action.increase", - "SHIFT + CTRL + ALT", addAmount)); - tooltip.add(TextFormatting.GRAY + I18n.format("gui.meiteminputbus.inv_action.decrease", - "SHIFT + CTRL + ALT", addAmount)); - } else if (isAltDown() && isControlDown()) { - tooltip.add(TextFormatting.GRAY + I18n.format("gui.meiteminputbus.inv_action.increase", - "CTRL + ALT", addAmount)); - tooltip.add(TextFormatting.GRAY + I18n.format("gui.meiteminputbus.inv_action.decrease", - "CTRL + ALT", addAmount)); - } else if (isAltDown() && isShiftDown()) { - tooltip.add(TextFormatting.GRAY + I18n.format("gui.meiteminputbus.inv_action.increase", - "SHIFT + ALT", addAmount)); - tooltip.add(TextFormatting.GRAY + I18n.format("gui.meiteminputbus.inv_action.decrease", - "SHIFT + ALT", addAmount)); - } else if (isShiftDown() && isControlDown()) { - tooltip.add(TextFormatting.GRAY + I18n.format("gui.meiteminputbus.inv_action.increase", - "SHIFT + CTRL", addAmount)); - tooltip.add(TextFormatting.GRAY + I18n.format("gui.meiteminputbus.inv_action.decrease", - "SHIFT + CTRL", addAmount)); - } else if (isControlDown()) { - tooltip.add(TextFormatting.GRAY + I18n.format("gui.meiteminputbus.inv_action.increase", - "CTRL", addAmount)); - tooltip.add(TextFormatting.GRAY + I18n.format("gui.meiteminputbus.inv_action.decrease", - "CTRL", addAmount)); - } else if (isShiftDown()) { - tooltip.add(TextFormatting.GRAY + I18n.format("gui.meiteminputbus.inv_action.increase", - "SHIFT", addAmount)); - tooltip.add(TextFormatting.GRAY + I18n.format("gui.meiteminputbus.inv_action.decrease", - "SHIFT", addAmount)); + // It was truly a beautiful sight... + + if (isShiftDown() && isControlDown()) { + String keyCombination = "SHIFT + CTRL"; + tooltip.add(TextFormatting.GRAY + I18n.format("gui.meiteminputbus.inv_action.multiply", + keyCombination)); + tooltip.add(TextFormatting.GRAY + I18n.format("gui.meiteminputbus.inv_action.divide", + keyCombination)); } else { tooltip.add(TextFormatting.GRAY + I18n.format("gui.meiteminputbus.inv_action.increase.normal")); tooltip.add(TextFormatting.GRAY + I18n.format("gui.meiteminputbus.inv_action.decrease.normal")); } - return tooltip; - } - private static boolean isAltDown() { - return Keyboard.isKeyDown(Keyboard.KEY_LMENU) || Keyboard.isKeyDown(Keyboard.KEY_RMENU); + return tooltip; } private static boolean isControlDown() { @@ -146,29 +92,53 @@ protected void onMouseWheelEvent(final int x, final int y, final int wheel) { return; } - int amount = wheel < 0 ? -getAddAmount() : getAddAmount(); int stackCount = stack.getCount(); + int countToSend = getUpdatedCount(isScrollingUp(wheel), stackCount); - if (amount > 0) { - if (stackCount + amount > slot.getSlotStackLimit()) { + if (countToSend > 0) { + if (countToSend > slot.getSlotStackLimit()) { return; } - } else if (stackCount - amount <= 0) { - return; } - this.invActionAmount += amount; - ClientProxy.clientScheduler.addRunnable(() -> sendInvActionToServer(slot.slotNumber), 0); + ClientProxy.clientScheduler.addRunnable(() -> sendInvActionToServer(slot.slotNumber, countToSend), 0); + } + + private boolean isScrollingUp(int wheel) { + return wheel >= 0; + } + + private int getUpdatedCount(boolean isScrollingUp, int currentAmount) { + if (isShiftDown() && isControlDown()) { + if (isScrollingUp) { + // Overflow protection + if (currentAmount <= Integer.MAX_VALUE / 2) { + return 2 * currentAmount; + } + return Integer.MAX_VALUE; + } else { + return Math.max(1, currentAmount / 2); + } + } else { + if (isScrollingUp) { + // Overflow protection + if (currentAmount < Integer.MAX_VALUE) { + return 1 + currentAmount; + } + return Integer.MAX_VALUE; + } else { + return Math.max(1, currentAmount - 1); + } + } } - public void sendInvActionToServer(int slotNumber) { - if (invActionAmount == 0) { + public void sendInvActionToServer(int slotNumber, int amountToSend) { + if (amountToSend == 0) { return; } ModularMachinery.NET_CHANNEL.sendToServer(new PktMEInputBusInvAction( - invActionAmount, slotNumber + amountToSend, slotNumber )); - invActionAmount = 0; } @Override @@ -209,4 +179,4 @@ protected void renderToolTip(@Nonnull final ItemStack stack, final int x, final this.drawHoveringText(tooltip, x, y, (font == null ? fontRenderer : font)); GuiUtils.postItemToolTip(); } -} +} \ No newline at end of file diff --git a/src/main/java/github/kasuminova/mmce/client/gui/GuiMEItemOutputBusStackSize.java b/src/main/java/github/kasuminova/mmce/client/gui/GuiMEItemOutputBusStackSize.java index b009f15d..6d0a1ce4 100644 --- a/src/main/java/github/kasuminova/mmce/client/gui/GuiMEItemOutputBusStackSize.java +++ b/src/main/java/github/kasuminova/mmce/client/gui/GuiMEItemOutputBusStackSize.java @@ -1,28 +1,35 @@ package github.kasuminova.mmce.client.gui; import appeng.client.gui.AEBaseGui; -import appeng.client.gui.widgets.GuiNumberBox; +import appeng.client.gui.MathExpressionParser; import appeng.client.gui.widgets.GuiTabButton; +import appeng.core.localization.GuiText; import github.kasuminova.mmce.common.container.ContainerMEItemOutputBusStackSize; import github.kasuminova.mmce.common.network.PktMEOutputBusStackSizeChange; import github.kasuminova.mmce.common.network.PktSwitchGuiMEOutputBus; import github.kasuminova.mmce.common.tile.MEItemOutputBus; import hellfirepvp.modularmachinery.ModularMachinery; import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.gui.GuiTextField; +import net.minecraft.client.resources.I18n; import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; import org.lwjgl.input.Keyboard; import org.lwjgl.input.Mouse; import java.io.IOException; /** - * GUI for configuring the stack size limit of an ME Item Output Bus. + * GUI for configuring the stack size of an ME Item Output Bus. * This GUI mimics AE2's Priority GUI design but is adapted for stack size configuration. */ public class GuiMEItemOutputBusStackSize extends AEBaseGui { - private GuiNumberBox stackSizeBox; + private static final ResourceLocation TEXTURES = new ResourceLocation("modularmachinery", "textures/gui/stacksize.png"); + + private GuiTextField stackSizeBox; // Changed from GuiNumberBox to allow expressions private GuiTabButton originalGuiBtn; private final MEItemOutputBus outputBus; @@ -44,6 +51,7 @@ public GuiMEItemOutputBusStackSize(final InventoryPlayer inventoryPlayer, final @Override public void initGui() { + Keyboard.enableRepeatEvents(true); super.initGui(); // Create the +/- buttons (matching AE2's Priority GUI layout) @@ -66,22 +74,22 @@ public void initGui() { this.guiLeft + 154, this.guiTop, busIcon, - "ME Item Output Bus", + "ME Machinery Item Output Bus", // Fixed label this.itemRender )); } - // Create the number input box (centered, matching AE2's Priority GUI) - this.stackSizeBox = new GuiNumberBox( + // Create the number input box - using GuiTextField to allow math expressions + this.stackSizeBox = new GuiTextField( + 0, // componentId this.fontRenderer, this.guiLeft + 62, this.guiTop + 57, - 59, - this.fontRenderer.FONT_HEIGHT, - Integer.class + 75, + this.fontRenderer.FONT_HEIGHT ); this.stackSizeBox.setEnableBackgroundDrawing(false); - this.stackSizeBox.setMaxStringLength(10); // Max int is 10 digits + this.stackSizeBox.setMaxStringLength(32); // Longer to allow expressions like "(100+50)*2" this.stackSizeBox.setTextColor(0xFFFFFF); this.stackSizeBox.setVisible(true); this.stackSizeBox.setFocused(true); @@ -90,140 +98,158 @@ public void initGui() { this.stackSizeBox.setText(String.valueOf(container.getStackSize())); } - @Override - public void drawFG(final int offsetX, final int offsetY, final int mouseX, final int mouseY) { - // Draw title - this.fontRenderer.drawString("Stack Size", 8, 6, 4210752); - } - - @Override - public void drawBG(final int offsetX, final int offsetY, final int mouseX, final int mouseY) { - // Use AE2's priority.png texture - this.bindTexture("guis/priority.png"); - this.drawTexturedModalRect(offsetX, offsetY, 0, 0, this.xSize, this.ySize); - - // Draw the number box - this.stackSizeBox.drawTextBox(); - } - @Override protected void actionPerformed(final GuiButton btn) throws IOException { super.actionPerformed(btn); - // Handle return to main GUI button if (btn == this.originalGuiBtn) { - // Send packet to switch back to main Output Bus GUI + // Calculate and send before switching GUI + String text = this.stackSizeBox.getText(); + if (!text.isEmpty()) { + try { + long value = parseValue(text); + // Clamp to valid range + if (value > Integer.MAX_VALUE) { + value = Integer.MAX_VALUE; + } else if (value < 1) { + value = 1; + } + this.sendStackSizeToServer((int) value); + } catch (NumberFormatException e) { + // Ignore parsing errors + } + } + + // Switch back to main GUI ModularMachinery.NET_CHANNEL.sendToServer( new PktSwitchGuiMEOutputBus(this.outputBus.getPos(), 0) ); - return; } // Handle +/- buttons - if (btn == this.plus1) { - this.addQty(1); - } else if (btn == this.plus10) { - this.addQty(10); - } else if (btn == this.plus100) { - this.addQty(100); - } else if (btn == this.plus1000) { - this.addQty(1000); - } else if (btn == this.minus1) { - this.addQty(-1); - } else if (btn == this.minus10) { - this.addQty(-10); - } else if (btn == this.minus100) { - this.addQty(-100); - } else if (btn == this.minus1000) { - this.addQty(-1000); - } + if (btn == this.plus1) this.addQty(1); + else if (btn == this.plus10) this.addQty(10); + else if (btn == this.plus100) this.addQty(100); + else if (btn == this.plus1000) this.addQty(1000); + else if (btn == this.minus1) this.addQty(-1); + else if (btn == this.minus10) this.addQty(-10); + else if (btn == this.minus100) this.addQty(-100); + else if (btn == this.minus1000) this.addQty(-1000); } - /** - * Adds the specified amount to the current stack size value - */ private void addQty(final int amount) { try { String text = this.stackSizeBox.getText(); - // Remove leading zeros - boolean fixed = false; - while (text.startsWith("0") && text.length() > 1) { - text = text.substring(1); - fixed = true; - } - - if (fixed) { - this.stackSizeBox.setText(text); - } - - if (text.isEmpty()) { - text = "1"; // Minimum value is 1 - } - - int currentValue = Integer.parseInt(text); - int newValue = currentValue + amount; + // Allow empty field - treat as 0 for calculation + long currentValue = text.isEmpty() ? 0 : parseValue(text); + long newValue = currentValue + amount; - // Clamp to valid range (minimum 1, maximum Integer.MAX_VALUE) - if (newValue < 1) { - newValue = 1; - } - // Handle overflow - if (amount > 0 && newValue < currentValue) { + // Clamp to valid range - this now handles values > Integer.MAX_VALUE + if (newValue > Integer.MAX_VALUE) { newValue = Integer.MAX_VALUE; + } else if (newValue < 1) { + newValue = 1; } this.stackSizeBox.setText(String.valueOf(newValue)); - this.sendStackSizeToServer(newValue); + this.sendStackSizeToServer((int) newValue); } catch (final NumberFormatException e) { - // If parsing fails, reset to 1 + // If parsing fails, default to 1 this.stackSizeBox.setText("1"); this.sendStackSizeToServer(1); } } - /** - * Sends the new stack size value to the server - */ private void sendStackSizeToServer(int stackSize) { + System.out.println("GuiMEItemOutputBusStackSize: Sending stack size to server: " + stackSize); ModularMachinery.NET_CHANNEL.sendToServer( new PktMEOutputBusStackSizeChange(this.outputBus.getPos(), stackSize) ); } - @Override - protected void keyTyped(final char character, final int key) throws IOException { - if (!this.checkHotbarKeys(key)) { - // Allow typing numbers and navigation keys - if ((key == 211 || key == 205 || key == 203 || key == 14 || Character.isDigit(character)) - && this.stackSizeBox.textboxKeyTyped(character, key)) { - try { - String text = this.stackSizeBox.getText(); + /** + * Parses the value, supporting both plain integers and mathematical expressions. + * Returns a long to allow values > Integer.MAX_VALUE which will be clamped later. + * Examples: "500", "5*100", "1000/2", "250+250", "2^10", "9999999999999" + */ + private long parseValue(String text) { + // First try plain long parsing (fast path) + try { + return Long.parseLong(text); + } catch (NumberFormatException e) { + // If that fails, try mathematical expression parsing + try { + // Preprocess: Convert ^ (exponent) to power operations + // Example: "2^10" becomes a calculation + text = preprocessExponents(text); + + double result = MathExpressionParser.parse(text); + if (Double.isNaN(result) || Double.isInfinite(result)) { + throw new NumberFormatException("Invalid expression"); + } - // Remove leading zeros - boolean fixed = false; - while (text.startsWith("0") && text.length() > 1) { - text = text.substring(1); - fixed = true; - } + // Return as long - can exceed Integer.MAX_VALUE + return (long) Math.round(result); + } catch (Exception ex) { + throw new NumberFormatException("Invalid number or expression"); + } + } + } - if (fixed) { - this.stackSizeBox.setText(text); - } + /** + * Preprocesses the expression to handle ^ (exponent) operator. + * Converts expressions like "2^10" into "1024" by evaluating power operations. + */ + private String preprocessExponents(String expression) { + // Keep evaluating exponents until none remain + while (expression.contains("^")) { + // Find the first ^ operator + int caretIndex = expression.indexOf('^'); + + // Find the base (number before ^) + int baseStart = caretIndex - 1; + while (baseStart > 0 && (Character.isDigit(expression.charAt(baseStart - 1)) || expression.charAt(baseStart - 1) == '.')) { + baseStart--; + } - if (text.isEmpty()) { - text = "1"; - this.stackSizeBox.setText(text); - } + // Find the exponent (number after ^) + int expEnd = caretIndex + 2; + while (expEnd < expression.length() && (Character.isDigit(expression.charAt(expEnd)) || expression.charAt(expEnd) == '.')) { + expEnd++; + } - int value = Integer.parseInt(text); - value = Math.max(1, value); // Minimum 1 + // Extract base and exponent + String baseStr = expression.substring(baseStart, caretIndex); + String expStr = expression.substring(caretIndex + 1, expEnd); - this.sendStackSizeToServer(value); - } catch (final NumberFormatException e) { - this.stackSizeBox.setText("1"); - this.sendStackSizeToServer(1); - } + // Calculate the power + double base = Double.parseDouble(baseStr); + double exponent = Double.parseDouble(expStr); + double result = Math.pow(base, exponent); + + // Replace the expression with the result + expression = expression.substring(0, baseStart) + result + expression.substring(expEnd); + } + + return expression; + } + + @Override + protected void keyTyped(final char character, final int key) throws IOException { + if (!this.checkHotbarKeys(key)) { + // Allow digits, operators (including ^), decimal point, backspace, delete, and arrow keys + boolean isValidChar = Character.isDigit(character) || + character == '+' || character == '-' || + character == '*' || character == '/' || + character == '^' || // Added exponent operator + character == '(' || character == ')' || + character == '.' || character == 'E' || character == 'e'; + boolean isControlKey = key == 14 || key == 211 || key == 203 || key == 205; // backspace, delete, left, right + + if ((isValidChar || isControlKey) && this.stackSizeBox.textboxKeyTyped(character, key)) { + // Just let the user type - don't evaluate or send to server yet + // Evaluation happens when GUI closes or user presses ENTER } else { super.keyTyped(character, key); } @@ -243,7 +269,7 @@ public void handleMouseInput() throws IOException { // Check if mouse is over the number box int boxX = this.guiLeft + 62; int boxY = this.guiTop + 57; - int boxWidth = 59; + int boxWidth = 75; int boxHeight = this.fontRenderer.FONT_HEIGHT; if (x >= boxX && x <= boxX + boxWidth && y >= boxY && y <= boxY + boxHeight) { @@ -254,63 +280,95 @@ public void handleMouseInput() throws IOException { /** * Handles mouse wheel scrolling for the stack size value. - * Matches the behavior of GuiMEItemInputBus: - * - SHIFT+CTRL + scroll up = double - * - SHIFT+CTRL + scroll down = halve - * - SHIFT + scroll up = +1 - * - SHIFT + scroll down = -1 */ - private void onMouseWheelEvent(final int wheel) { - boolean shiftHeld = Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT); - boolean ctrlHeld = Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL); + private void onMouseWheelEvent(int wheel) { + boolean isShiftHeld = GuiScreen.isShiftKeyDown(); + boolean isCtrlHeld = GuiScreen.isCtrlKeyDown(); - // Only process if SHIFT is held (to match Input Bus behavior) - if (!shiftHeld) { - return; - } + String text = this.stackSizeBox.getText(); + long currentValue; try { - int currentValue = Integer.parseInt(this.stackSizeBox.getText()); - int newValue; - boolean isScrollingUp = wheel > 0; - - if (ctrlHeld) { - // SHIFT+CTRL: Double or halve - if (isScrollingUp) { - // Double (with overflow protection) - if (currentValue <= Integer.MAX_VALUE / 2) { - newValue = currentValue * 2; - } else { - newValue = Integer.MAX_VALUE; - } - } else { - // Halve - newValue = Math.max(1, currentValue / 2); - } + currentValue = text.isEmpty() ? 1 : parseValue(text); + } catch (NumberFormatException e) { + currentValue = 1; + } + + long newValue = currentValue; + + if (isShiftHeld && isCtrlHeld) { + // SHIFT + CTRL: Double or halve + if (wheel > 0) { + newValue = currentValue * 2; } else { - // SHIFT only: +1 or -1 - if (isScrollingUp) { - // +1 (with overflow protection) - if (currentValue < Integer.MAX_VALUE) { - newValue = currentValue + 1; - } else { - newValue = Integer.MAX_VALUE; - } - } else { - // -1 - newValue = Math.max(1, currentValue - 1); - } + newValue = currentValue / 2; + } + } else if (isShiftHeld) { + // SHIFT: +/- 1 + if (wheel > 0) { + newValue = currentValue + 1; + } else { + newValue = currentValue - 1; } + } - this.stackSizeBox.setText(String.valueOf(newValue)); - this.sendStackSizeToServer(newValue); - } catch (NumberFormatException e) { - this.stackSizeBox.setText("1"); - this.sendStackSizeToServer(1); + // Clamp to valid range - handles overflow + if (newValue > Integer.MAX_VALUE) { + newValue = Integer.MAX_VALUE; + } else if (newValue < 1) { + newValue = 1; } + + this.stackSizeBox.setText(String.valueOf(newValue)); + this.sendStackSizeToServer((int) newValue); + } + + @Override + public void drawFG(final int offsetX, final int offsetY, final int mouseX, final int mouseY) { + // FIX #1: Only draw "Stack Size" once (removed duplicate) + this.fontRenderer.drawString("Stack Size", 8, 6, 0x404040); + } + + @Override + public void drawBG(final int offsetX, final int offsetY, final int mouseX, final int mouseY) { + this.mc.getTextureManager().bindTexture(TEXTURES); // ← Use the constant you defined + this.drawTexturedModalRect(offsetX, offsetY, 0, 0, this.xSize, this.ySize); + + this.stackSizeBox.drawTextBox(); } - protected String getBackground() { - return "guis/priority.png"; + @Override + public void onGuiClosed() { + super.onGuiClosed(); + Keyboard.enableRepeatEvents(false); + + // Send the final stack size to server when GUI closes + String text = this.stackSizeBox.getText(); + if (!text.isEmpty()) { + try { + long value = parseValue(text); + // Clamp to valid range + int finalValue; + if (value > Integer.MAX_VALUE) { + finalValue = Integer.MAX_VALUE; + } else if (value < 1) { + finalValue = 1; + } else { + finalValue = (int) value; + } + + // Send to server + sendStackSizeToServer(finalValue); + + } catch (NumberFormatException e) { + // If parsing fails, try to get current value from container + try { + ContainerMEItemOutputBusStackSize container = (ContainerMEItemOutputBusStackSize) this.inventorySlots; + sendStackSizeToServer(container.getStackSize()); + } catch (Exception ex) { + // Last resort - do nothing, keep existing value + } + } + } } -} \ No newline at end of file +} // ← THIS CLOSING BRACE IS CRITICAL - it closes the CLASS \ No newline at end of file diff --git a/src/main/java/github/kasuminova/mmce/common/block/appeng/BlockMEItemOutputBus.java b/src/main/java/github/kasuminova/mmce/common/block/appeng/BlockMEItemOutputBus.java index 5fd4507b..339a4ab8 100644 --- a/src/main/java/github/kasuminova/mmce/common/block/appeng/BlockMEItemOutputBus.java +++ b/src/main/java/github/kasuminova/mmce/common/block/appeng/BlockMEItemOutputBus.java @@ -1,5 +1,6 @@ package github.kasuminova.mmce.common.block.appeng; +import appeng.api.implementations.items.IMemoryCard; import github.kasuminova.mmce.common.tile.MEItemOutputBus; import hellfirepvp.modularmachinery.ModularMachinery; import hellfirepvp.modularmachinery.common.CommonProxy; @@ -25,13 +26,24 @@ public class BlockMEItemOutputBus extends BlockMEItemBus { @Override public boolean onBlockActivated( - @Nonnull World worldIn, @Nonnull BlockPos pos, @Nonnull IBlockState state, - @Nonnull EntityPlayer playerIn, @Nonnull EnumHand hand, - @Nonnull EnumFacing facing, - float hitX, float hitY, float hitZ) { + @Nonnull World worldIn, @Nonnull BlockPos pos, @Nonnull IBlockState state, + @Nonnull EntityPlayer playerIn, @Nonnull EnumHand hand, + @Nonnull EnumFacing facing, + float hitX, float hitY, float hitZ) { if (!worldIn.isRemote) { TileEntity te = worldIn.getTileEntity(pos); - if (te instanceof MEItemOutputBus) { + if (te instanceof MEItemOutputBus outputBus) { + ItemStack heldItem = playerIn.getHeldItem(hand); + + // Check if player is holding a Memory Card + if (heldItem.getItem() instanceof IMemoryCard memoryCard) { + boolean handled = handleSettingsTransfer(outputBus, memoryCard, playerIn, heldItem); + if (handled) { + return true; + } + } + + // If not Memory Card or not handled, open the GUI playerIn.openGui(ModularMachinery.MODID, CommonProxy.GuiType.ME_ITEM_OUTPUT_BUS.ordinal(), worldIn, pos.getX(), pos.getY(), pos.getZ()); } } @@ -78,6 +90,9 @@ public void breakBlock(final World worldIn, IOInventory inventory = bus.getInternalInventory(); NBTTagCompound tag = new NBTTagCompound(); tag.setTag("inventory", inventory.writeNBT()); + // NOTE: Stack size is NOT saved here - it resets to max int when broken + // This allows Output Buses to stack in player inventory + dropped.setTagCompound(tag); for (int i = 0; i < inventory.getSlots(); i++) { @@ -99,8 +114,12 @@ public void onBlockPlacedBy(@Nonnull final World worldIn, TileEntity te = worldIn.getTileEntity(pos); NBTTagCompound tag = stack.getTagCompound(); - if (te instanceof MEItemOutputBus && tag != null && tag.hasKey("inventory")) { - ((MEItemOutputBus) te).readInventoryNBT(tag.getCompoundTag("inventory")); + if (te instanceof MEItemOutputBus bus && tag != null) { + if (tag.hasKey("inventory")) { + bus.readInventoryNBT(tag.getCompoundTag("inventory")); + } + // NOTE: Stack size is NOT restored from item NBT + // It will default to Integer.MAX_VALUE when placed } } -} +} \ No newline at end of file diff --git a/src/main/java/github/kasuminova/mmce/common/network/PktMEInputBusInvAction.java b/src/main/java/github/kasuminova/mmce/common/network/PktMEInputBusInvAction.java index 97e9e8b1..74c4cc2b 100644 --- a/src/main/java/github/kasuminova/mmce/common/network/PktMEInputBusInvAction.java +++ b/src/main/java/github/kasuminova/mmce/common/network/PktMEInputBusInvAction.java @@ -11,26 +11,26 @@ import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; public class PktMEInputBusInvAction implements IMessage, IMessageHandler { - private int addAmount = 0; + private int newAmount = 0; private int slotID = 0; public PktMEInputBusInvAction() { } - public PktMEInputBusInvAction(final int addAmount, final int slotID) { - this.addAmount = addAmount; + public PktMEInputBusInvAction(final int newAmount, final int slotID) { + this.newAmount = newAmount; this.slotID = slotID; } @Override public void fromBytes(final ByteBuf buf) { - this.addAmount = buf.readInt(); + this.newAmount = buf.readInt(); this.slotID = buf.readInt(); } @Override public void toBytes(final ByteBuf buf) { - buf.writeInt(addAmount); + buf.writeInt(newAmount); buf.writeInt(slotID); } @@ -51,21 +51,15 @@ public IMessage onMessage(final PktMEInputBusInvAction message, final MessageCon return null; } - int addAmount = message.addAmount; - if (addAmount == 0) { + int newAmount = message.newAmount; + if (newAmount == 0) { return null; } - int count = stack.getCount(); - if (addAmount > 0) { - stack.grow(Math.min(slot.getSlotStackLimit() - count, addAmount)); - slot.onSlotChanged(); - } else { - int decrAmount = -addAmount; - stack.shrink(Math.min(count - 1, decrAmount)); - slot.onSlotChanged(); - } + ItemStack newStack = stack.copy(); + newStack.setCount(newAmount); + slot.putStack(newStack); return null; } -} +} \ No newline at end of file diff --git a/src/main/java/github/kasuminova/mmce/common/network/PktMEOutputBusStackSizeChange.java b/src/main/java/github/kasuminova/mmce/common/network/PktMEOutputBusStackSizeChange.java index 05c4a251..cbe7590b 100644 --- a/src/main/java/github/kasuminova/mmce/common/network/PktMEOutputBusStackSizeChange.java +++ b/src/main/java/github/kasuminova/mmce/common/network/PktMEOutputBusStackSizeChange.java @@ -1,9 +1,9 @@ package github.kasuminova.mmce.common.network; -import github.kasuminova.mmce.common.container.ContainerMEItemOutputBusStackSize; +import github.kasuminova.mmce.common.tile.MEItemOutputBus; import io.netty.buffer.ByteBuf; import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraft.inventory.Container; +import net.minecraft.tileentity.TileEntity; import net.minecraft.util.math.BlockPos; import net.minecraftforge.fml.common.network.simpleimpl.IMessage; import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; @@ -11,8 +11,7 @@ /** * Packet sent from client to server when the player changes the stack size value in the GUI. - * Updates the CONTAINER's temporary stack size value, NOT the tile entity. - * The actual tile entity is only updated when the GUI is closed. + * Updates the tile entity's stack size configuration directly. */ public class PktMEOutputBusStackSizeChange implements IMessage, IMessageHandler { @@ -55,8 +54,7 @@ public void toBytes(final ByteBuf buf) { /** * Handles the packet on the server side. - * Updates the container's temporary stack size value. - * Does NOT update the tile entity directly. + * Updates the tile entity's stack size configuration directly. */ @Override public IMessage onMessage(final PktMEOutputBusStackSizeChange message, final MessageContext ctx) { @@ -64,22 +62,24 @@ public IMessage onMessage(final PktMEOutputBusStackSizeChange message, final Mes // Schedule the action on the server thread player.getServerWorld().addScheduledTask(() -> { - // Get the player's currently open container - Container container = player.openContainer; + // Get the tile entity at the specified position + TileEntity te = player.world.getTileEntity(message.pos); - // Verify it's the stack size container - if (!(container instanceof ContainerMEItemOutputBusStackSize)) { + // Verify it's an ME Item Output Bus + if (!(te instanceof MEItemOutputBus)) { return; } - ContainerMEItemOutputBusStackSize stackSizeContainer = (ContainerMEItemOutputBusStackSize) container; + MEItemOutputBus outputBus = (MEItemOutputBus) te; // Validate the stack size (minimum 1) int validatedStackSize = Math.max(1, message.stackSize); - // Update the container's temporary stack size value - // This will be synced to the client automatically via @GuiSync - stackSizeContainer.stackSize = validatedStackSize; + // Update the tile entity's stack size configuration + outputBus.setConfiguredStackSize(validatedStackSize); + + // Mark the tile entity as dirty to ensure it saves + outputBus.markDirty(); }); return null; diff --git a/src/main/java/github/kasuminova/mmce/common/tile/MEItemOutputBus.java b/src/main/java/github/kasuminova/mmce/common/tile/MEItemOutputBus.java index a904f95e..67189d00 100644 --- a/src/main/java/github/kasuminova/mmce/common/tile/MEItemOutputBus.java +++ b/src/main/java/github/kasuminova/mmce/common/tile/MEItemOutputBus.java @@ -8,6 +8,7 @@ import appeng.me.GridAccessException; import appeng.util.Platform; import github.kasuminova.mmce.common.tile.base.MEItemBus; +import github.kasuminova.mmce.common.tile.SettingsTransfer; import hellfirepvp.modularmachinery.common.lib.ItemsMM; import hellfirepvp.modularmachinery.common.machine.IOType; import hellfirepvp.modularmachinery.common.machine.MachineComponent; @@ -19,7 +20,7 @@ import javax.annotation.Nullable; import java.util.concurrent.locks.ReadWriteLock; -public class MEItemOutputBus extends MEItemBus { +public class MEItemOutputBus extends MEItemBus implements SettingsTransfer { // Stack size configuration field private int configuredStackSize = Integer.MAX_VALUE; @@ -192,4 +193,26 @@ public void writeCustomNBT(final NBTTagCompound compound) { // Write configured stack size to NBT compound.setInteger("configuredStackSize", this.configuredStackSize); } + // ==================== SettingsTransfer Interface ==================== // ADD FROM HERE + + @Override + public NBTTagCompound downloadSettings() { + NBTTagCompound tag = new NBTTagCompound(); + tag.setInteger("configuredStackSize", this.configuredStackSize); + return tag; + } + + @Override + public void uploadSettings(NBTTagCompound settings) { + if (settings.hasKey("configuredStackSize")) { + setConfiguredStackSize(settings.getInteger("configuredStackSize")); + + // Alert the ME network that settings changed + try { + proxy.getTick().alertDevice(proxy.getNode()); + } catch (GridAccessException e) { + // NO-OP + } + } + } // ADD TO HERE } \ No newline at end of file diff --git a/src/main/resources/assets/modularmachinery/lang/en_US.lang b/src/main/resources/assets/modularmachinery/lang/en_US.lang index b15f68e0..135a7146 100644 --- a/src/main/resources/assets/modularmachinery/lang/en_US.lang +++ b/src/main/resources/assets/modularmachinery/lang/en_US.lang @@ -57,13 +57,16 @@ gui.upgradebus.bounded=Bound %s machinery gui.upgradebus.incompatible=§eWarning: %s is not compatible with this machinery. gui.meitemoutputbus.title=ME Machinery Item Output Bus +gui.meitemoutputbus.stacksize.title=Stack Size gui.meiteminputbus.title=ME Machinery Item Input Bus -gui.meiteminputbus.inv_action=Use the scroll wheel and the SHIFT, CONTROL, ALT key combination to modify the number of marked items. +gui.meiteminputbus.inv_action=Use the scroll wheel and the SHIFT and CONTROL key combination to modify the number of marked items. gui.meiteminputbus.inv_action.increase.normal=Scroll the wheel up to increase the number of items by 1. gui.meiteminputbus.inv_action.decrease.normal=Scroll the wheel down or right-click on an item to decrease the number of items by 1. gui.meiteminputbus.inv_action.increase=Press the %s key combination to increase the number of %s items while the wheel is scrolling up. gui.meiteminputbus.inv_action.decrease=Press the %s key combination to decrease the number of %s items while the wheel is scrolling up. +gui.meiteminputbus.inv_action.multiply=Press the %s key combination to double the number of items while the wheel is scrolling up. +gui.meiteminputbus.inv_action.divide=Press the %s key combination to halve the number of items while the wheel is scrolling down. gui.meiteminputbus.items_marked=Items marked: %s gui.meitembus.item_cached=Items Cached: %s gui.meitembus.nbt_stored=Items have been stored internally. diff --git a/src/main/resources/assets/modularmachinery/textures/gui/stacksize.png b/src/main/resources/assets/modularmachinery/textures/gui/stacksize.png new file mode 100644 index 0000000000000000000000000000000000000000..1ee1fa1a22d38e4a4a58f40e9f9dd1a1463b116a GIT binary patch literal 736 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|G$6&2?&#~tz_78e=6B#^1_q|- zo-U3d6?5L+I+%Ogfx-1)>_O9y3fq?2MRfd{a4Jd9Oz20F`o_Z^`On-O+WDP+J21_8 zyu9{6@(g$W3bB0iqWk5~=N~tCE~E6p)Q``;|5@2?UjH@m$@};Z{H?Pu5vWPIz0L5L z#P!#u6+%C(m&fbN)MZ%KJ~BTrS%`r{c#xrL%c=wWx8>fxC@gnulTLE%^~LEQdW#q( z*4O9QmF-C z0=DH^R~-tjluSNj`MhrT-8(TImDNl$o`3%NK=VT-FdljgpIx+;yZc*uhx``iy6K1c gfoWo}fe*{;7^?mom<3FXhyuCI)78&qol`;+0JsmX00000 literal 0 HcmV?d00001 From 1e24436a143541355459450b1bedea338b2d795e Mon Sep 17 00:00:00 2001 From: ArshdipKhinda Date: Fri, 7 Nov 2025 19:19:19 -0800 Subject: [PATCH 4/5] Removed excessive comments and debug code. --- .../mmce/client/gui/GuiMEItemOutputBus.java | 15 +--- .../gui/GuiMEItemOutputBusStackSize.java | 77 +++---------------- .../block/appeng/BlockMEItemOutputBus.java | 15 +--- .../ContainerMEItemOutputBusStackSize.java | 34 -------- .../PktMEOutputBusStackSizeChange.java | 29 ------- .../network/PktSwitchGuiMEOutputBus.java | 40 +--------- .../mmce/common/tile/MEItemOutputBus.java | 25 +----- .../modularmachinery/client/ClientProxy.java | 25 +++--- .../modularmachinery/common/CommonProxy.java | 1 - 9 files changed, 26 insertions(+), 235 deletions(-) diff --git a/src/main/java/github/kasuminova/mmce/client/gui/GuiMEItemOutputBus.java b/src/main/java/github/kasuminova/mmce/client/gui/GuiMEItemOutputBus.java index c47a0928..c5d21109 100644 --- a/src/main/java/github/kasuminova/mmce/client/gui/GuiMEItemOutputBus.java +++ b/src/main/java/github/kasuminova/mmce/client/gui/GuiMEItemOutputBus.java @@ -13,12 +13,9 @@ import net.minecraft.client.resources.I18n; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.ResourceLocation; - import java.io.IOException; -import java.util.List; public class GuiMEItemOutputBus extends GuiMEItemBus { - // For convenience, the Sky Chest resource was used :P private static final ResourceLocation TEXTURES_OUTPUT_BUS = new ResourceLocation("appliedenergistics2", "textures/guis/skychest.png"); private CustomStackSizeButton stackSizeBtn; @@ -34,11 +31,9 @@ public GuiMEItemOutputBus(final MEItemOutputBus te, final EntityPlayer player) { public void initGui() { super.initGui(); - // Add wrench button for stack size configuration - // Position: Left side, matching AE2's Partition Storage button position this.stackSizeBtn = new CustomStackSizeButton( - this.guiLeft - 18, // Left side of GUI - this.guiTop + 8 // Top position + this.guiLeft - 18, + this.guiTop + 8 ); this.buttonList.add(this.stackSizeBtn); } @@ -48,7 +43,6 @@ protected void actionPerformed(final GuiButton btn) throws IOException { super.actionPerformed(btn); if (btn == this.stackSizeBtn) { - // Switch to stack size configuration GUI ModularMachinery.NET_CHANNEL.sendToServer( new PktSwitchGuiMEOutputBus(this.outputBus.getPos(), 1) ); @@ -68,9 +62,6 @@ public void drawBG(int offsetX, int offsetY, int mouseX, int mouseY) { this.drawTexturedModalRect(offsetX, offsetY, 0, 0, this.xSize, this.ySize); } - /** - * Custom button that extends GuiImgButton but overrides the tooltip message - */ private static class CustomStackSizeButton extends GuiImgButton { public CustomStackSizeButton(int x, int y) { super(x, y, Settings.ACTIONS, ActionItems.WRENCH); @@ -78,9 +69,7 @@ public CustomStackSizeButton(int x, int y) { @Override public String getMessage() { - // Return our custom tooltip instead of AE2's default return "Configure Stack Size"; } } - } \ No newline at end of file diff --git a/src/main/java/github/kasuminova/mmce/client/gui/GuiMEItemOutputBusStackSize.java b/src/main/java/github/kasuminova/mmce/client/gui/GuiMEItemOutputBusStackSize.java index 6d0a1ce4..523e2d92 100644 --- a/src/main/java/github/kasuminova/mmce/client/gui/GuiMEItemOutputBusStackSize.java +++ b/src/main/java/github/kasuminova/mmce/client/gui/GuiMEItemOutputBusStackSize.java @@ -3,7 +3,6 @@ import appeng.client.gui.AEBaseGui; import appeng.client.gui.MathExpressionParser; import appeng.client.gui.widgets.GuiTabButton; -import appeng.core.localization.GuiText; import github.kasuminova.mmce.common.container.ContainerMEItemOutputBusStackSize; import github.kasuminova.mmce.common.network.PktMEOutputBusStackSizeChange; import github.kasuminova.mmce.common.network.PktSwitchGuiMEOutputBus; @@ -12,28 +11,21 @@ import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.GuiTextField; -import net.minecraft.client.resources.I18n; import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.item.ItemStack; import net.minecraft.util.ResourceLocation; import org.lwjgl.input.Keyboard; import org.lwjgl.input.Mouse; - import java.io.IOException; -/** - * GUI for configuring the stack size of an ME Item Output Bus. - * This GUI mimics AE2's Priority GUI design but is adapted for stack size configuration. - */ public class GuiMEItemOutputBusStackSize extends AEBaseGui { private static final ResourceLocation TEXTURES = new ResourceLocation("modularmachinery", "textures/gui/stacksize.png"); - private GuiTextField stackSizeBox; // Changed from GuiNumberBox to allow expressions + private GuiTextField stackSizeBox; private GuiTabButton originalGuiBtn; private final MEItemOutputBus outputBus; - // Button references private GuiButton plus1; private GuiButton plus10; private GuiButton plus100; @@ -46,7 +38,7 @@ public class GuiMEItemOutputBusStackSize extends AEBaseGui { public GuiMEItemOutputBusStackSize(final InventoryPlayer inventoryPlayer, final MEItemOutputBus outputBus) { super(new ContainerMEItemOutputBusStackSize(inventoryPlayer, outputBus)); this.outputBus = outputBus; - this.ySize = 105; // Same height as AE2's Priority GUI + this.ySize = 105; } @Override @@ -54,7 +46,6 @@ public void initGui() { Keyboard.enableRepeatEvents(true); super.initGui(); - // Create the +/- buttons (matching AE2's Priority GUI layout) this.buttonList.add(this.plus1 = new GuiButton(0, this.guiLeft + 20, this.guiTop + 32, 22, 20, "+1")); this.buttonList.add(this.plus10 = new GuiButton(0, this.guiLeft + 48, this.guiTop + 32, 28, 20, "+10")); this.buttonList.add(this.plus100 = new GuiButton(0, this.guiLeft + 82, this.guiTop + 32, 32, 20, "+100")); @@ -65,7 +56,6 @@ public void initGui() { this.buttonList.add(this.minus100 = new GuiButton(0, this.guiLeft + 82, this.guiTop + 69, 32, 20, "-100")); this.buttonList.add(this.minus1000 = new GuiButton(0, this.guiLeft + 120, this.guiTop + 69, 38, 20, "-1000")); - // Create button to return to main Output Bus GUI final ContainerMEItemOutputBusStackSize container = (ContainerMEItemOutputBusStackSize) this.inventorySlots; final ItemStack busIcon = new ItemStack(this.outputBus.getBlockType()); @@ -74,14 +64,13 @@ public void initGui() { this.guiLeft + 154, this.guiTop, busIcon, - "ME Machinery Item Output Bus", // Fixed label + "ME Machinery Item Output Bus", this.itemRender )); } - // Create the number input box - using GuiTextField to allow math expressions this.stackSizeBox = new GuiTextField( - 0, // componentId + 0, this.fontRenderer, this.guiLeft + 62, this.guiTop + 57, @@ -89,12 +78,11 @@ public void initGui() { this.fontRenderer.FONT_HEIGHT ); this.stackSizeBox.setEnableBackgroundDrawing(false); - this.stackSizeBox.setMaxStringLength(32); // Longer to allow expressions like "(100+50)*2" + this.stackSizeBox.setMaxStringLength(32); this.stackSizeBox.setTextColor(0xFFFFFF); this.stackSizeBox.setVisible(true); this.stackSizeBox.setFocused(true); - // Set initial value from container this.stackSizeBox.setText(String.valueOf(container.getStackSize())); } @@ -103,12 +91,10 @@ protected void actionPerformed(final GuiButton btn) throws IOException { super.actionPerformed(btn); if (btn == this.originalGuiBtn) { - // Calculate and send before switching GUI String text = this.stackSizeBox.getText(); if (!text.isEmpty()) { try { long value = parseValue(text); - // Clamp to valid range if (value > Integer.MAX_VALUE) { value = Integer.MAX_VALUE; } else if (value < 1) { @@ -116,17 +102,14 @@ protected void actionPerformed(final GuiButton btn) throws IOException { } this.sendStackSizeToServer((int) value); } catch (NumberFormatException e) { - // Ignore parsing errors } } - // Switch back to main GUI ModularMachinery.NET_CHANNEL.sendToServer( new PktSwitchGuiMEOutputBus(this.outputBus.getPos(), 0) ); } - // Handle +/- buttons if (btn == this.plus1) this.addQty(1); else if (btn == this.plus10) this.addQty(10); else if (btn == this.plus100) this.addQty(100); @@ -141,11 +124,9 @@ private void addQty(final int amount) { try { String text = this.stackSizeBox.getText(); - // Allow empty field - treat as 0 for calculation long currentValue = text.isEmpty() ? 0 : parseValue(text); long newValue = currentValue + amount; - // Clamp to valid range - this now handles values > Integer.MAX_VALUE if (newValue > Integer.MAX_VALUE) { newValue = Integer.MAX_VALUE; } else if (newValue < 1) { @@ -155,33 +136,22 @@ private void addQty(final int amount) { this.stackSizeBox.setText(String.valueOf(newValue)); this.sendStackSizeToServer((int) newValue); } catch (final NumberFormatException e) { - // If parsing fails, default to 1 this.stackSizeBox.setText("1"); this.sendStackSizeToServer(1); } } private void sendStackSizeToServer(int stackSize) { - System.out.println("GuiMEItemOutputBusStackSize: Sending stack size to server: " + stackSize); ModularMachinery.NET_CHANNEL.sendToServer( new PktMEOutputBusStackSizeChange(this.outputBus.getPos(), stackSize) ); } - /** - * Parses the value, supporting both plain integers and mathematical expressions. - * Returns a long to allow values > Integer.MAX_VALUE which will be clamped later. - * Examples: "500", "5*100", "1000/2", "250+250", "2^10", "9999999999999" - */ private long parseValue(String text) { - // First try plain long parsing (fast path) try { return Long.parseLong(text); } catch (NumberFormatException e) { - // If that fails, try mathematical expression parsing try { - // Preprocess: Convert ^ (exponent) to power operations - // Example: "2^10" becomes a calculation text = preprocessExponents(text); double result = MathExpressionParser.parse(text); @@ -189,7 +159,6 @@ private long parseValue(String text) { throw new NumberFormatException("Invalid expression"); } - // Return as long - can exceed Integer.MAX_VALUE return (long) Math.round(result); } catch (Exception ex) { throw new NumberFormatException("Invalid number or expression"); @@ -197,38 +166,27 @@ private long parseValue(String text) { } } - /** - * Preprocesses the expression to handle ^ (exponent) operator. - * Converts expressions like "2^10" into "1024" by evaluating power operations. - */ private String preprocessExponents(String expression) { - // Keep evaluating exponents until none remain while (expression.contains("^")) { - // Find the first ^ operator int caretIndex = expression.indexOf('^'); - // Find the base (number before ^) int baseStart = caretIndex - 1; while (baseStart > 0 && (Character.isDigit(expression.charAt(baseStart - 1)) || expression.charAt(baseStart - 1) == '.')) { baseStart--; } - // Find the exponent (number after ^) int expEnd = caretIndex + 2; while (expEnd < expression.length() && (Character.isDigit(expression.charAt(expEnd)) || expression.charAt(expEnd) == '.')) { expEnd++; } - // Extract base and exponent String baseStr = expression.substring(baseStart, caretIndex); String expStr = expression.substring(caretIndex + 1, expEnd); - // Calculate the power double base = Double.parseDouble(baseStr); double exponent = Double.parseDouble(expStr); double result = Math.pow(base, exponent); - // Replace the expression with the result expression = expression.substring(0, baseStart) + result + expression.substring(expEnd); } @@ -238,18 +196,15 @@ private String preprocessExponents(String expression) { @Override protected void keyTyped(final char character, final int key) throws IOException { if (!this.checkHotbarKeys(key)) { - // Allow digits, operators (including ^), decimal point, backspace, delete, and arrow keys boolean isValidChar = Character.isDigit(character) || character == '+' || character == '-' || character == '*' || character == '/' || - character == '^' || // Added exponent operator + character == '^' || character == '(' || character == ')' || character == '.' || character == 'E' || character == 'e'; - boolean isControlKey = key == 14 || key == 211 || key == 203 || key == 205; // backspace, delete, left, right + boolean isControlKey = key == 14 || key == 211 || key == 203 || key == 205; if ((isValidChar || isControlKey) && this.stackSizeBox.textboxKeyTyped(character, key)) { - // Just let the user type - don't evaluate or send to server yet - // Evaluation happens when GUI closes or user presses ENTER } else { super.keyTyped(character, key); } @@ -262,11 +217,9 @@ public void handleMouseInput() throws IOException { final int wheel = Mouse.getEventDWheel(); if (wheel != 0) { - // Get mouse position final int x = Mouse.getEventX() * this.width / this.mc.displayWidth; final int y = this.height - Mouse.getEventY() * this.height / this.mc.displayHeight - 1; - // Check if mouse is over the number box int boxX = this.guiLeft + 62; int boxY = this.guiTop + 57; int boxWidth = 75; @@ -278,9 +231,6 @@ public void handleMouseInput() throws IOException { } } - /** - * Handles mouse wheel scrolling for the stack size value. - */ private void onMouseWheelEvent(int wheel) { boolean isShiftHeld = GuiScreen.isShiftKeyDown(); boolean isCtrlHeld = GuiScreen.isCtrlKeyDown(); @@ -297,14 +247,12 @@ private void onMouseWheelEvent(int wheel) { long newValue = currentValue; if (isShiftHeld && isCtrlHeld) { - // SHIFT + CTRL: Double or halve if (wheel > 0) { newValue = currentValue * 2; } else { newValue = currentValue / 2; } } else if (isShiftHeld) { - // SHIFT: +/- 1 if (wheel > 0) { newValue = currentValue + 1; } else { @@ -312,7 +260,6 @@ private void onMouseWheelEvent(int wheel) { } } - // Clamp to valid range - handles overflow if (newValue > Integer.MAX_VALUE) { newValue = Integer.MAX_VALUE; } else if (newValue < 1) { @@ -325,13 +272,12 @@ private void onMouseWheelEvent(int wheel) { @Override public void drawFG(final int offsetX, final int offsetY, final int mouseX, final int mouseY) { - // FIX #1: Only draw "Stack Size" once (removed duplicate) this.fontRenderer.drawString("Stack Size", 8, 6, 0x404040); } @Override public void drawBG(final int offsetX, final int offsetY, final int mouseX, final int mouseY) { - this.mc.getTextureManager().bindTexture(TEXTURES); // ← Use the constant you defined + this.mc.getTextureManager().bindTexture(TEXTURES); this.drawTexturedModalRect(offsetX, offsetY, 0, 0, this.xSize, this.ySize); this.stackSizeBox.drawTextBox(); @@ -342,12 +288,10 @@ public void onGuiClosed() { super.onGuiClosed(); Keyboard.enableRepeatEvents(false); - // Send the final stack size to server when GUI closes String text = this.stackSizeBox.getText(); if (!text.isEmpty()) { try { long value = parseValue(text); - // Clamp to valid range int finalValue; if (value > Integer.MAX_VALUE) { finalValue = Integer.MAX_VALUE; @@ -357,18 +301,15 @@ public void onGuiClosed() { finalValue = (int) value; } - // Send to server sendStackSizeToServer(finalValue); } catch (NumberFormatException e) { - // If parsing fails, try to get current value from container try { ContainerMEItemOutputBusStackSize container = (ContainerMEItemOutputBusStackSize) this.inventorySlots; sendStackSizeToServer(container.getStackSize()); } catch (Exception ex) { - // Last resort - do nothing, keep existing value } } } } -} // ← THIS CLOSING BRACE IS CRITICAL - it closes the CLASS \ No newline at end of file +} \ No newline at end of file diff --git a/src/main/java/github/kasuminova/mmce/common/block/appeng/BlockMEItemOutputBus.java b/src/main/java/github/kasuminova/mmce/common/block/appeng/BlockMEItemOutputBus.java index 339a4ab8..abebcb84 100644 --- a/src/main/java/github/kasuminova/mmce/common/block/appeng/BlockMEItemOutputBus.java +++ b/src/main/java/github/kasuminova/mmce/common/block/appeng/BlockMEItemOutputBus.java @@ -23,7 +23,6 @@ import javax.annotation.Nullable; public class BlockMEItemOutputBus extends BlockMEItemBus { - @Override public boolean onBlockActivated( @Nonnull World worldIn, @Nonnull BlockPos pos, @Nonnull IBlockState state, @@ -34,8 +33,6 @@ public boolean onBlockActivated( TileEntity te = worldIn.getTileEntity(pos); if (te instanceof MEItemOutputBus outputBus) { ItemStack heldItem = playerIn.getHeldItem(hand); - - // Check if player is holding a Memory Card if (heldItem.getItem() instanceof IMemoryCard memoryCard) { boolean handled = handleSettingsTransfer(outputBus, memoryCard, playerIn, heldItem); if (handled) { @@ -43,7 +40,6 @@ public boolean onBlockActivated( } } - // If not Memory Card or not handled, open the GUI playerIn.openGui(ModularMachinery.MODID, CommonProxy.GuiType.ME_ITEM_OUTPUT_BUS.ordinal(), worldIn, pos.getX(), pos.getY(), pos.getZ()); } } @@ -90,9 +86,6 @@ public void breakBlock(final World worldIn, IOInventory inventory = bus.getInternalInventory(); NBTTagCompound tag = new NBTTagCompound(); tag.setTag("inventory", inventory.writeNBT()); - // NOTE: Stack size is NOT saved here - it resets to max int when broken - // This allows Output Buses to stack in player inventory - dropped.setTagCompound(tag); for (int i = 0; i < inventory.getSlots(); i++) { @@ -114,12 +107,8 @@ public void onBlockPlacedBy(@Nonnull final World worldIn, TileEntity te = worldIn.getTileEntity(pos); NBTTagCompound tag = stack.getTagCompound(); - if (te instanceof MEItemOutputBus bus && tag != null) { - if (tag.hasKey("inventory")) { - bus.readInventoryNBT(tag.getCompoundTag("inventory")); - } - // NOTE: Stack size is NOT restored from item NBT - // It will default to Integer.MAX_VALUE when placed + if (te instanceof MEItemOutputBus && tag != null && tag.hasKey("inventory")) { + ((MEItemOutputBus) te).readInventoryNBT(tag.getCompoundTag("inventory")); } } } \ No newline at end of file diff --git a/src/main/java/github/kasuminova/mmce/common/container/ContainerMEItemOutputBusStackSize.java b/src/main/java/github/kasuminova/mmce/common/container/ContainerMEItemOutputBusStackSize.java index a0aa7c1c..bf4dbc55 100644 --- a/src/main/java/github/kasuminova/mmce/common/container/ContainerMEItemOutputBusStackSize.java +++ b/src/main/java/github/kasuminova/mmce/common/container/ContainerMEItemOutputBusStackSize.java @@ -6,22 +6,10 @@ import github.kasuminova.mmce.common.tile.MEItemOutputBus; import net.minecraft.entity.player.InventoryPlayer; -/** - * Container for the ME Item Output Bus Stack Size configuration GUI. - * Handles synchronization of the stack size value between client and server. - * - * NOTE: This container does NOT apply changes to the tile entity in real-time. - * Changes are only applied when the GUI is closed via onContainerClosed(). - */ public class ContainerMEItemOutputBusStackSize extends AEBaseContainer { private final MEItemOutputBus outputBus; - /** - * The stack size value displayed and edited in the GUI. - * Synced from server to client automatically via @GuiSync. - * This is a TEMPORARY value that gets applied when the GUI closes. - */ @GuiSync(0) public int stackSize = Integer.MAX_VALUE; @@ -29,51 +17,29 @@ public ContainerMEItemOutputBusStackSize(final InventoryPlayer inventoryPlayer, super(inventoryPlayer, outputBus); this.outputBus = outputBus; - // Initialize with the current value from the tile entity - // This must be done in the constructor, not in detectAndSendChanges, - // to ensure the value is set before the GUI tries to read it this.stackSize = outputBus.getConfiguredStackSize(); } - /** - * Returns the current stack size value being displayed/edited in the GUI. - * This is NOT necessarily the actual stack size in the tile entity. - */ public int getStackSize() { return this.stackSize; } - /** - * Returns the Output Bus tile entity. - */ public MEItemOutputBus getOwner() { return this.outputBus; } - /** - * Called periodically on the server to detect changes and sync to client. - * We don't read from the tile entity here to avoid overwriting user edits. - */ @Override public void detectAndSendChanges() { this.verifyPermissions(SecurityPermissions.BUILD, false); - // Let AE2's @GuiSync system handle synchronization - // Don't read from tile entity - we want to preserve user edits super.detectAndSendChanges(); } - /** - * Called when the container is closed (player closes the GUI). - * This is where we apply the configured stack size to the tile entity. - */ @Override public void onContainerClosed(net.minecraft.entity.player.EntityPlayer playerIn) { super.onContainerClosed(playerIn); - // Only apply on server side if (!playerIn.world.isRemote) { - // Apply the configured stack size to the tile entity this.outputBus.setConfiguredStackSize(this.stackSize); } } diff --git a/src/main/java/github/kasuminova/mmce/common/network/PktMEOutputBusStackSizeChange.java b/src/main/java/github/kasuminova/mmce/common/network/PktMEOutputBusStackSizeChange.java index cbe7590b..73a253d1 100644 --- a/src/main/java/github/kasuminova/mmce/common/network/PktMEOutputBusStackSizeChange.java +++ b/src/main/java/github/kasuminova/mmce/common/network/PktMEOutputBusStackSizeChange.java @@ -9,76 +9,47 @@ import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; -/** - * Packet sent from client to server when the player changes the stack size value in the GUI. - * Updates the tile entity's stack size configuration directly. - */ public class PktMEOutputBusStackSizeChange implements IMessage, IMessageHandler { - private BlockPos pos = BlockPos.ORIGIN; private int stackSize = Integer.MAX_VALUE; - /** - * Default constructor required by Forge's packet system - */ public PktMEOutputBusStackSizeChange() { } - /** - * Constructor for creating a packet to send - * @param pos The position of the Output Bus tile entity - * @param stackSize The new stack size value - */ public PktMEOutputBusStackSizeChange(final BlockPos pos, final int stackSize) { this.pos = pos; this.stackSize = stackSize; } - /** - * Reads packet data from the byte buffer (client -> server) - */ @Override public void fromBytes(final ByteBuf buf) { this.pos = BlockPos.fromLong(buf.readLong()); this.stackSize = buf.readInt(); } - /** - * Writes packet data to the byte buffer (client -> server) - */ @Override public void toBytes(final ByteBuf buf) { buf.writeLong(this.pos.toLong()); buf.writeInt(this.stackSize); } - /** - * Handles the packet on the server side. - * Updates the tile entity's stack size configuration directly. - */ @Override public IMessage onMessage(final PktMEOutputBusStackSizeChange message, final MessageContext ctx) { EntityPlayerMP player = ctx.getServerHandler().player; - // Schedule the action on the server thread player.getServerWorld().addScheduledTask(() -> { - // Get the tile entity at the specified position TileEntity te = player.world.getTileEntity(message.pos); - // Verify it's an ME Item Output Bus if (!(te instanceof MEItemOutputBus)) { return; } MEItemOutputBus outputBus = (MEItemOutputBus) te; - // Validate the stack size (minimum 1) int validatedStackSize = Math.max(1, message.stackSize); - // Update the tile entity's stack size configuration outputBus.setConfiguredStackSize(validatedStackSize); - // Mark the tile entity as dirty to ensure it saves outputBus.markDirty(); }); diff --git a/src/main/java/github/kasuminova/mmce/common/network/PktSwitchGuiMEOutputBus.java b/src/main/java/github/kasuminova/mmce/common/network/PktSwitchGuiMEOutputBus.java index c9d8ec86..b3745127 100644 --- a/src/main/java/github/kasuminova/mmce/common/network/PktSwitchGuiMEOutputBus.java +++ b/src/main/java/github/kasuminova/mmce/common/network/PktSwitchGuiMEOutputBus.java @@ -11,77 +11,44 @@ import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; -/** - * Packet for switching between the main ME Item Output Bus GUI and the Stack Size configuration GUI. - * Sent from client to server when the player clicks the wrench button or return button. - * - * GUI Type: 0 = Main Output Bus GUI, 1 = Stack Size Configuration GUI - */ public class PktSwitchGuiMEOutputBus implements IMessage, IMessageHandler { - private BlockPos pos = BlockPos.ORIGIN; - private int guiType = 0; // 0 = main GUI, 1 = stack size GUI + private int guiType = 0; - /** - * Default constructor required by Forge's packet system - */ public PktSwitchGuiMEOutputBus() { } - /** - * Constructor for creating a packet to send - * @param pos The position of the Output Bus tile entity - * @param guiType The GUI type to open (0 = main, 1 = stack size) - */ public PktSwitchGuiMEOutputBus(final BlockPos pos, final int guiType) { this.pos = pos; this.guiType = guiType; } - /** - * Reads packet data from the byte buffer (client -> server) - */ @Override public void fromBytes(final ByteBuf buf) { this.pos = BlockPos.fromLong(buf.readLong()); this.guiType = buf.readInt(); } - /** - * Writes packet data to the byte buffer (client -> server) - */ @Override public void toBytes(final ByteBuf buf) { buf.writeLong(this.pos.toLong()); buf.writeInt(this.guiType); } - /** - * Handles the packet on the server side - */ @Override public IMessage onMessage(final PktSwitchGuiMEOutputBus message, final MessageContext ctx) { EntityPlayerMP player = ctx.getServerHandler().player; - System.out.println("PktSwitchGuiMEOutputBus received! GUI Type: " + message.guiType + ", Pos: " + message.pos); - - // Schedule the action on the server thread player.getServerWorld().addScheduledTask(() -> { TileEntity te = player.world.getTileEntity(message.pos); - System.out.println("Tile entity: " + (te != null ? te.getClass().getSimpleName() : "null")); - - // Verify it's an ME Item Output Bus if (!(te instanceof MEItemOutputBus)) { return; } - // Close current GUI player.closeScreen(); - // Open the requested GUI if (message.guiType == 0) { - // Open main Output Bus GUI player.openGui( ModularMachinery.MODID, GuiType.ME_ITEM_OUTPUT_BUS.ordinal(), @@ -91,11 +58,6 @@ public IMessage onMessage(final PktSwitchGuiMEOutputBus message, final MessageCo message.pos.getZ() ); } else if (message.guiType == 1) { - - System.out.println("Opening stack size GUI with ID: " + GuiType.ME_ITEM_OUTPUT_BUS_STACK_SIZE.ordinal()); - - - // Open stack size configuration GUI player.openGui( ModularMachinery.MODID, GuiType.ME_ITEM_OUTPUT_BUS_STACK_SIZE.ordinal(), diff --git a/src/main/java/github/kasuminova/mmce/common/tile/MEItemOutputBus.java b/src/main/java/github/kasuminova/mmce/common/tile/MEItemOutputBus.java index 67189d00..bbf47907 100644 --- a/src/main/java/github/kasuminova/mmce/common/tile/MEItemOutputBus.java +++ b/src/main/java/github/kasuminova/mmce/common/tile/MEItemOutputBus.java @@ -8,7 +8,6 @@ import appeng.me.GridAccessException; import appeng.util.Platform; import github.kasuminova.mmce.common.tile.base.MEItemBus; -import github.kasuminova.mmce.common.tile.SettingsTransfer; import hellfirepvp.modularmachinery.common.lib.ItemsMM; import hellfirepvp.modularmachinery.common.machine.IOType; import hellfirepvp.modularmachinery.common.machine.MachineComponent; @@ -22,7 +21,6 @@ public class MEItemOutputBus extends MEItemBus implements SettingsTransfer { - // Stack size configuration field private int configuredStackSize = Integer.MAX_VALUE; @Override @@ -137,30 +135,16 @@ public void markNoUpdate() { super.markNoUpdate(); } - // ==================== Stack Size Configuration Methods ==================== - - /** - * Gets the currently configured stack size limit for this Output Bus - * @return the configured stack size (minimum 1, maximum Integer.MAX_VALUE) - */ public int getConfiguredStackSize() { return this.configuredStackSize; } - /** - * Sets the stack size limit for all slots in this Output Bus - * @param size the new stack size limit (will be clamped to minimum 1) - */ public void setConfiguredStackSize(int size) { - // Clamp to valid range (minimum 1) this.configuredStackSize = Math.max(1, size); this.applyStackSizeToInventory(); this.markForUpdate(); } - /** - * Applies the configured stack size to the inventory - */ private void applyStackSizeToInventory() { if (this.inventory != null) { int[] slotIDs = new int[this.inventory.getSlots()]; @@ -171,18 +155,14 @@ private void applyStackSizeToInventory() { } } - // ==================== NBT Serialization ==================== - @Override public void readCustomNBT(final NBTTagCompound compound) { super.readCustomNBT(compound); - // Read configured stack size from NBT if (compound.hasKey("configuredStackSize")) { this.configuredStackSize = compound.getInteger("configuredStackSize"); } - // Apply stack size after reading this.applyStackSizeToInventory(); } @@ -190,10 +170,8 @@ public void readCustomNBT(final NBTTagCompound compound) { public void writeCustomNBT(final NBTTagCompound compound) { super.writeCustomNBT(compound); - // Write configured stack size to NBT compound.setInteger("configuredStackSize", this.configuredStackSize); } - // ==================== SettingsTransfer Interface ==================== // ADD FROM HERE @Override public NBTTagCompound downloadSettings() { @@ -207,12 +185,11 @@ public void uploadSettings(NBTTagCompound settings) { if (settings.hasKey("configuredStackSize")) { setConfiguredStackSize(settings.getInteger("configuredStackSize")); - // Alert the ME network that settings changed try { proxy.getTick().alertDevice(proxy.getNode()); } catch (GridAccessException e) { // NO-OP } } - } // ADD TO HERE + } } \ No newline at end of file diff --git a/src/main/java/hellfirepvp/modularmachinery/client/ClientProxy.java b/src/main/java/hellfirepvp/modularmachinery/client/ClientProxy.java index 00de56be..59b1e0e3 100644 --- a/src/main/java/hellfirepvp/modularmachinery/client/ClientProxy.java +++ b/src/main/java/hellfirepvp/modularmachinery/client/ClientProxy.java @@ -19,7 +19,6 @@ import github.kasuminova.mmce.common.tile.MEItemInputBus; import github.kasuminova.mmce.common.tile.MEItemOutputBus; import github.kasuminova.mmce.common.tile.MEPatternProvider; -import github.kasuminova.mmce.client.gui.GuiMEItemOutputBusStackSize; import hellfirepvp.modularmachinery.ModularMachinery; import hellfirepvp.modularmachinery.client.gui.GuiContainerEnergyHatch; import hellfirepvp.modularmachinery.client.gui.GuiContainerFluidHatch; @@ -113,13 +112,13 @@ private static void registerPendingIBlockColorBlocks() { colors.registerBlockColorHandler(dynamicColor::getColorMultiplier, (Block) dynamicColor); } BlockController.MACHINE_CONTROLLERS.values().forEach(block -> - colors.registerBlockColorHandler(block::getColorMultiplier, block) + colors.registerBlockColorHandler(block::getColorMultiplier, block) ); BlockController.MOC_MACHINE_CONTROLLERS.values().forEach(block -> - colors.registerBlockColorHandler(block::getColorMultiplier, block) + colors.registerBlockColorHandler(block::getColorMultiplier, block) ); BlockFactoryController.FACTORY_CONTROLLERS.values().forEach(block -> - colors.registerBlockColorHandler(block::getColorMultiplier, block) + colors.registerBlockColorHandler(block::getColorMultiplier, block) ); } @@ -129,13 +128,13 @@ private static void registerPendingIItemColorItems() { colors.registerItemColorHandler(dynamicColor::getColorFromItemstack, (Item) dynamicColor); } BlockController.MACHINE_CONTROLLERS.values().forEach(block -> - colors.registerItemColorHandler(block::getColorFromItemstack, block) + colors.registerItemColorHandler(block::getColorFromItemstack, block) ); BlockController.MOC_MACHINE_CONTROLLERS.values().forEach(block -> - colors.registerItemColorHandler(block::getColorFromItemstack, block) + colors.registerItemColorHandler(block::getColorFromItemstack, block) ); BlockFactoryController.FACTORY_CONTROLLERS.values().forEach(block -> - colors.registerItemColorHandler(block::getColorFromItemstack, block) + colors.registerItemColorHandler(block::getColorFromItemstack, block) ); } @@ -145,11 +144,11 @@ private static void registryItemModel(final Item item, final String name) { if (!list.isEmpty()) { for (ItemStack i : list) { ModelLoader.setCustomModelResourceLocation(item, i.getItemDamage(), - new ModelResourceLocation(ModularMachinery.MODID + ":" + name, "inventory")); + new ModelResourceLocation(ModularMachinery.MODID + ":" + name, "inventory")); } } else { ModelLoader.setCustomModelResourceLocation(item, 0, - new ModelResourceLocation(ModularMachinery.MODID + ":" + name, "inventory")); + new ModelResourceLocation(ModularMachinery.MODID + ":" + name, "inventory")); } } @@ -194,12 +193,12 @@ private void registerModels() { String name = unlocName + "_" + ((BlockVariants) block).getBlockStateName(state); ModelBakery.registerItemVariants(i, new ResourceLocation(ModularMachinery.MODID, name)); ModelLoader.setCustomModelResourceLocation(i, block.getMetaFromState(state), - new ModelResourceLocation(ModularMachinery.MODID + ":" + name, "inventory")); + new ModelResourceLocation(ModularMachinery.MODID + ":" + name, "inventory")); } } else { ModelBakery.registerItemVariants(i, new ResourceLocation(ModularMachinery.MODID, block.getClass().getSimpleName().toLowerCase())); ModelLoader.setCustomModelResourceLocation(i, 0, - new ModelResourceLocation(ModularMachinery.MODID + ":" + block.getClass().getSimpleName().toLowerCase(), "inventory")); + new ModelResourceLocation(ModularMachinery.MODID + ":" + block.getClass().getSimpleName().toLowerCase(), "inventory")); } } for (Item item : itemModelsToRegister) { @@ -359,8 +358,6 @@ public Object getClientGuiElement(int ID, EntityPlayer player, World world, int return new GuiContainerLifeEssence((TileLifeEssenceProvider) present, player); } } - return null; } - -} +} \ No newline at end of file diff --git a/src/main/java/hellfirepvp/modularmachinery/common/CommonProxy.java b/src/main/java/hellfirepvp/modularmachinery/common/CommonProxy.java index 213813df..b64c0619 100644 --- a/src/main/java/hellfirepvp/modularmachinery/common/CommonProxy.java +++ b/src/main/java/hellfirepvp/modularmachinery/common/CommonProxy.java @@ -32,7 +32,6 @@ import github.kasuminova.mmce.common.tile.MEPatternProvider; import github.kasuminova.mmce.common.util.concurrent.Action; import github.kasuminova.mmce.common.world.MMWorldEventListener; -import github.kasuminova.mmce.client.gui.GuiMEItemOutputBusStackSize; import hellfirepvp.modularmachinery.ModularMachinery; import hellfirepvp.modularmachinery.common.base.Mods; import hellfirepvp.modularmachinery.common.container.ContainerController; From e8573e4b72ede9308f45881b1d846bc913c1e6b3 Mon Sep 17 00:00:00 2001 From: ArshdipKhinda Date: Sat, 8 Nov 2025 12:30:26 -0800 Subject: [PATCH 5/5] Reverted changes that were borrowed from PR #168 "Changed the interaction with the configured items in machinery item hatches" --- .../mmce/client/gui/GuiMEItemInputBus.java | 118 +++++++++++------- .../network/PktMEInputBusInvAction.java | 26 ++-- .../assets/modularmachinery/lang/en_US.lang | 5 +- 3 files changed, 91 insertions(+), 58 deletions(-) diff --git a/src/main/java/github/kasuminova/mmce/client/gui/GuiMEItemInputBus.java b/src/main/java/github/kasuminova/mmce/client/gui/GuiMEItemInputBus.java index 6c4f89ad..2b7bff62 100644 --- a/src/main/java/github/kasuminova/mmce/client/gui/GuiMEItemInputBus.java +++ b/src/main/java/github/kasuminova/mmce/client/gui/GuiMEItemInputBus.java @@ -31,31 +31,85 @@ public class GuiMEItemInputBus extends GuiMEItemBus { private static final ResourceLocation TEXTURES_INPUT_BUS = new ResourceLocation(ModularMachinery.MODID, "textures/gui/meiteminputbus.png"); + private int invActionAmount = 0; + public GuiMEItemInputBus(final MEItemInputBus te, final EntityPlayer player) { super(new ContainerMEItemInputBus(te, player)); this.ySize = 204; } + private static int getAddAmount() { + int addAmount; + // SHIFT + CTRL + ALT 1000000 + // ALT + CTRL 100000 + // ALT + SHIFT 10000 + // SHIFT + CTRL 1000 + // CTRL 100 + // SHIFT 10 + if (isShiftDown() && isControlDown() && isAltDown()) { + addAmount = 1_000_000; + } else if (isAltDown() && isControlDown()) { + addAmount = 100_000; + } else if (isAltDown() && isShiftDown()) { + addAmount = 10_000; + } else if (isShiftDown() && isControlDown()) { + addAmount = 1_000; + } else if (isControlDown()) { + addAmount = 100; + } else if (isShiftDown()) { + addAmount = 10; + } else { + addAmount = 1; + } + return addAmount; + } + private static List getAddActionInfo() { List tooltip = new ArrayList<>(); tooltip.add(TextFormatting.GRAY + I18n.format("gui.meiteminputbus.inv_action")); // Quite a sight, isn't it? - // It was truly a beautiful sight... - - if (isShiftDown() && isControlDown()) { - String keyCombination = "SHIFT + CTRL"; - tooltip.add(TextFormatting.GRAY + I18n.format("gui.meiteminputbus.inv_action.multiply", - keyCombination)); - tooltip.add(TextFormatting.GRAY + I18n.format("gui.meiteminputbus.inv_action.divide", - keyCombination)); + String addAmount = MiscUtils.formatDecimal(getAddAmount()); + if (isShiftDown() && isControlDown() && isAltDown()) { + tooltip.add(TextFormatting.GRAY + I18n.format("gui.meiteminputbus.inv_action.increase", + "SHIFT + CTRL + ALT", addAmount)); + tooltip.add(TextFormatting.GRAY + I18n.format("gui.meiteminputbus.inv_action.decrease", + "SHIFT + CTRL + ALT", addAmount)); + } else if (isAltDown() && isControlDown()) { + tooltip.add(TextFormatting.GRAY + I18n.format("gui.meiteminputbus.inv_action.increase", + "CTRL + ALT", addAmount)); + tooltip.add(TextFormatting.GRAY + I18n.format("gui.meiteminputbus.inv_action.decrease", + "CTRL + ALT", addAmount)); + } else if (isAltDown() && isShiftDown()) { + tooltip.add(TextFormatting.GRAY + I18n.format("gui.meiteminputbus.inv_action.increase", + "SHIFT + ALT", addAmount)); + tooltip.add(TextFormatting.GRAY + I18n.format("gui.meiteminputbus.inv_action.decrease", + "SHIFT + ALT", addAmount)); + } else if (isShiftDown() && isControlDown()) { + tooltip.add(TextFormatting.GRAY + I18n.format("gui.meiteminputbus.inv_action.increase", + "SHIFT + CTRL", addAmount)); + tooltip.add(TextFormatting.GRAY + I18n.format("gui.meiteminputbus.inv_action.decrease", + "SHIFT + CTRL", addAmount)); + } else if (isControlDown()) { + tooltip.add(TextFormatting.GRAY + I18n.format("gui.meiteminputbus.inv_action.increase", + "CTRL", addAmount)); + tooltip.add(TextFormatting.GRAY + I18n.format("gui.meiteminputbus.inv_action.decrease", + "CTRL", addAmount)); + } else if (isShiftDown()) { + tooltip.add(TextFormatting.GRAY + I18n.format("gui.meiteminputbus.inv_action.increase", + "SHIFT", addAmount)); + tooltip.add(TextFormatting.GRAY + I18n.format("gui.meiteminputbus.inv_action.decrease", + "SHIFT", addAmount)); } else { tooltip.add(TextFormatting.GRAY + I18n.format("gui.meiteminputbus.inv_action.increase.normal")); tooltip.add(TextFormatting.GRAY + I18n.format("gui.meiteminputbus.inv_action.decrease.normal")); } - return tooltip; } + private static boolean isAltDown() { + return Keyboard.isKeyDown(Keyboard.KEY_LMENU) || Keyboard.isKeyDown(Keyboard.KEY_RMENU); + } + private static boolean isControlDown() { return Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL); } @@ -92,53 +146,29 @@ protected void onMouseWheelEvent(final int x, final int y, final int wheel) { return; } + int amount = wheel < 0 ? -getAddAmount() : getAddAmount(); int stackCount = stack.getCount(); - int countToSend = getUpdatedCount(isScrollingUp(wheel), stackCount); - if (countToSend > 0) { - if (countToSend > slot.getSlotStackLimit()) { + if (amount > 0) { + if (stackCount + amount > slot.getSlotStackLimit()) { return; } + } else if (stackCount - amount <= 0) { + return; } - ClientProxy.clientScheduler.addRunnable(() -> sendInvActionToServer(slot.slotNumber, countToSend), 0); - } - - private boolean isScrollingUp(int wheel) { - return wheel >= 0; - } - - private int getUpdatedCount(boolean isScrollingUp, int currentAmount) { - if (isShiftDown() && isControlDown()) { - if (isScrollingUp) { - // Overflow protection - if (currentAmount <= Integer.MAX_VALUE / 2) { - return 2 * currentAmount; - } - return Integer.MAX_VALUE; - } else { - return Math.max(1, currentAmount / 2); - } - } else { - if (isScrollingUp) { - // Overflow protection - if (currentAmount < Integer.MAX_VALUE) { - return 1 + currentAmount; - } - return Integer.MAX_VALUE; - } else { - return Math.max(1, currentAmount - 1); - } - } + this.invActionAmount += amount; + ClientProxy.clientScheduler.addRunnable(() -> sendInvActionToServer(slot.slotNumber), 0); } - public void sendInvActionToServer(int slotNumber, int amountToSend) { - if (amountToSend == 0) { + public void sendInvActionToServer(int slotNumber) { + if (invActionAmount == 0) { return; } ModularMachinery.NET_CHANNEL.sendToServer(new PktMEInputBusInvAction( - amountToSend, slotNumber + invActionAmount, slotNumber )); + invActionAmount = 0; } @Override diff --git a/src/main/java/github/kasuminova/mmce/common/network/PktMEInputBusInvAction.java b/src/main/java/github/kasuminova/mmce/common/network/PktMEInputBusInvAction.java index 74c4cc2b..c710b968 100644 --- a/src/main/java/github/kasuminova/mmce/common/network/PktMEInputBusInvAction.java +++ b/src/main/java/github/kasuminova/mmce/common/network/PktMEInputBusInvAction.java @@ -11,26 +11,26 @@ import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; public class PktMEInputBusInvAction implements IMessage, IMessageHandler { - private int newAmount = 0; + private int addAmount = 0; private int slotID = 0; public PktMEInputBusInvAction() { } - public PktMEInputBusInvAction(final int newAmount, final int slotID) { - this.newAmount = newAmount; + public PktMEInputBusInvAction(final int addAmount, final int slotID) { + this.addAmount = addAmount; this.slotID = slotID; } @Override public void fromBytes(final ByteBuf buf) { - this.newAmount = buf.readInt(); + this.addAmount = buf.readInt(); this.slotID = buf.readInt(); } @Override public void toBytes(final ByteBuf buf) { - buf.writeInt(newAmount); + buf.writeInt(addAmount); buf.writeInt(slotID); } @@ -51,14 +51,20 @@ public IMessage onMessage(final PktMEInputBusInvAction message, final MessageCon return null; } - int newAmount = message.newAmount; - if (newAmount == 0) { + int addAmount = message.addAmount; + if (addAmount == 0) { return null; } - ItemStack newStack = stack.copy(); - newStack.setCount(newAmount); - slot.putStack(newStack); + int count = stack.getCount(); + if (addAmount > 0) { + stack.grow(Math.min(slot.getSlotStackLimit() - count, addAmount)); + slot.onSlotChanged(); + } else { + int decrAmount = -addAmount; + stack.shrink(Math.min(count - 1, decrAmount)); + slot.onSlotChanged(); + } return null; } diff --git a/src/main/resources/assets/modularmachinery/lang/en_US.lang b/src/main/resources/assets/modularmachinery/lang/en_US.lang index 135a7146..b15f68e0 100644 --- a/src/main/resources/assets/modularmachinery/lang/en_US.lang +++ b/src/main/resources/assets/modularmachinery/lang/en_US.lang @@ -57,16 +57,13 @@ gui.upgradebus.bounded=Bound %s machinery gui.upgradebus.incompatible=§eWarning: %s is not compatible with this machinery. gui.meitemoutputbus.title=ME Machinery Item Output Bus -gui.meitemoutputbus.stacksize.title=Stack Size gui.meiteminputbus.title=ME Machinery Item Input Bus -gui.meiteminputbus.inv_action=Use the scroll wheel and the SHIFT and CONTROL key combination to modify the number of marked items. +gui.meiteminputbus.inv_action=Use the scroll wheel and the SHIFT, CONTROL, ALT key combination to modify the number of marked items. gui.meiteminputbus.inv_action.increase.normal=Scroll the wheel up to increase the number of items by 1. gui.meiteminputbus.inv_action.decrease.normal=Scroll the wheel down or right-click on an item to decrease the number of items by 1. gui.meiteminputbus.inv_action.increase=Press the %s key combination to increase the number of %s items while the wheel is scrolling up. gui.meiteminputbus.inv_action.decrease=Press the %s key combination to decrease the number of %s items while the wheel is scrolling up. -gui.meiteminputbus.inv_action.multiply=Press the %s key combination to double the number of items while the wheel is scrolling up. -gui.meiteminputbus.inv_action.divide=Press the %s key combination to halve the number of items while the wheel is scrolling down. gui.meiteminputbus.items_marked=Items marked: %s gui.meitembus.item_cached=Items Cached: %s gui.meitembus.nbt_stored=Items have been stored internally.