From 0be3b4ebfad149841b52823b7d5159bc4eca0d9e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 15 Feb 2026 16:18:22 +0000 Subject: [PATCH 1/7] Initial plan From 942234d229e22277508a8cbe81c7dcb43f38f382 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 15 Feb 2026 16:24:48 +0000 Subject: [PATCH 2/7] Add Ender Chest tab implementation Co-authored-by: rubensworks <440384+rubensworks@users.noreply.github.com> --- .../TerminalStorageTabEnderChest.java | 44 +++++ .../TerminalStorageTabEnderChestClient.java | 185 ++++++++++++++++++ .../TerminalStorageTabEnderChestCommon.java | 67 +++++++ .../TerminalStorageTabEnderChestServer.java | 40 ++++ .../terminalstorage/TerminalStorageTabs.java | 3 + .../integratedterminals/lang/en_us.json | 1 + 6 files changed, 340 insertions(+) create mode 100644 src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabEnderChest.java create mode 100644 src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabEnderChestClient.java create mode 100644 src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabEnderChestCommon.java create mode 100644 src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabEnderChestServer.java diff --git a/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabEnderChest.java b/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabEnderChest.java new file mode 100644 index 000000000..4cbe5e85b --- /dev/null +++ b/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabEnderChest.java @@ -0,0 +1,44 @@ +package org.cyclops.integratedterminals.core.terminalstorage; + +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.player.Player; +import org.cyclops.integrateddynamics.api.network.INetwork; +import org.cyclops.integratedterminals.IntegratedTerminals; +import org.cyclops.integratedterminals.api.terminalstorage.ITerminalStorageTab; +import org.cyclops.integratedterminals.api.terminalstorage.ITerminalStorageTabClient; +import org.cyclops.integratedterminals.api.terminalstorage.ITerminalStorageTabCommon; +import org.cyclops.integratedterminals.api.terminalstorage.ITerminalStorageTabServer; +import org.cyclops.integratedterminals.inventory.container.ContainerTerminalStorageBase; + +import javax.annotation.Nullable; + +/** + * Terminal storage tab for Ender Chest. + * @author rubensworks + */ +public class TerminalStorageTabEnderChest implements ITerminalStorageTab { + + public static ResourceLocation NAME = new ResourceLocation(IntegratedTerminals.MOD_ID, "ender_chest"); + + @Override + public ResourceLocation getName() { + return NAME; + } + + @Override + public ITerminalStorageTabClient createClientTab(ContainerTerminalStorageBase container, Player player) { + return new TerminalStorageTabEnderChestClient(container, getName()); + } + + @Override + public ITerminalStorageTabServer createServerTab(ContainerTerminalStorageBase container, Player player, INetwork network) { + return new TerminalStorageTabEnderChestServer(getName(), (ServerPlayer) player); + } + + @Nullable + @Override + public ITerminalStorageTabCommon createCommonTab(ContainerTerminalStorageBase container, Player player) { + return new TerminalStorageTabEnderChestCommon(container, getName()); + } +} diff --git a/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabEnderChestClient.java b/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabEnderChestClient.java new file mode 100644 index 000000000..6404e0aa8 --- /dev/null +++ b/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabEnderChestClient.java @@ -0,0 +1,185 @@ +package org.cyclops.integratedterminals.core.terminalstorage; + +import com.google.common.collect.Lists; +import com.mojang.blaze3d.vertex.PoseStack; +import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.Blocks; +import org.cyclops.integratedterminals.api.terminalstorage.ITerminalButton; +import org.cyclops.integratedterminals.api.terminalstorage.ITerminalRowColumnProvider; +import org.cyclops.integratedterminals.api.terminalstorage.ITerminalStorageSlot; +import org.cyclops.integratedterminals.api.terminalstorage.ITerminalStorageTabClient; +import org.cyclops.integratedterminals.api.terminalstorage.ITerminalStorageTabCommon; +import org.cyclops.integratedterminals.client.gui.container.ContainerScreenTerminalStorage; +import org.cyclops.integratedterminals.inventory.container.ContainerTerminalStorageBase; + +import java.util.Collections; +import java.util.List; +import java.util.Set; + +/** + * A client-side storage terminal tab for Ender Chest. + * @author rubensworks + */ +public class TerminalStorageTabEnderChestClient implements ITerminalStorageTabClient { + + private final ResourceLocation name; + private final ItemStack icon; + protected final ContainerTerminalStorageBase container; + private final ITerminalRowColumnProvider rowColumnProvider; + + public TerminalStorageTabEnderChestClient(ContainerTerminalStorageBase container, ResourceLocation name) { + this.name = name; + this.icon = new ItemStack(Blocks.ENDER_CHEST); + this.container = container; + this.rowColumnProvider = () -> new ITerminalRowColumnProvider.RowsColumns(5, 9); + } + + @Override + public void onSelect(int channel) { + // No action needed on select + } + + @Override + public void onDeselect(int channel) { + // No action needed on deselect + } + + @Override + public ResourceLocation getName() { + return this.name; + } + + @Override + public ItemStack getIcon() { + return this.icon; + } + + @Override + public List getTooltip() { + return Lists.newArrayList(Component.translatable("gui.integratedterminals.terminal_storage.ender_chest")); + } + + @Override + public String getInstanceFilter(int channel) { + return ""; + } + + @Override + public void setInstanceFilter(int channel, String filter) { + // Ender Chest doesn't support filtering + } + + @Override + public List getSlots(int channel, int offset, int limit) { + // Ender Chest inventory is handled by regular container slots + return Collections.emptyList(); + } + + @Override + public ITerminalRowColumnProvider getRowColumnProvider() { + return rowColumnProvider; + } + + @Override + public boolean isEnabled() { + return true; + } + + @Override + public int getSlotCount(int channel) { + return 27; // Ender Chest has 27 slots + } + + @Override + public String getStatus(int channel) { + return ""; + } + + @Override + public int[] getChannels() { + return new int[]{0}; // Single channel + } + + @Override + public void resetActiveSlot() { + // No active slot for Ender Chest + } + + @Override + public boolean handleClick(AbstractContainerMenu container, int channel, int hoveringStorageSlot, int mouseButton, + boolean hasClickedOutside, boolean hasClickedInStorage, int hoveredContainerSlot, + boolean isQuickMove) { + // Let default container handling take care of clicks + return false; + } + + @Override + public boolean handleScroll(AbstractContainerMenu container, int channel, int hoveringStorageSlot, double delta, + boolean hasClickedOutside, boolean hasClickedInStorage, int hoveredContainerSlot) { + // No scroll handling needed + return false; + } + + @Override + public int getActiveSlotId() { + return -1; + } + + @Override + public int getActiveSlotQuantity() { + return 0; + } + + @Override + public void setActiveSlotQuantity(int quantity) { + // No active slot for Ender Chest + } + + @Override + public List> getButtons() { + return Collections.emptyList(); + } + + @Override + public int getSlotOffsetX() { + return 32; + } + + @Override + public int getSlotOffsetY() { + return 58; // Adjusted to position the Ender Chest slots properly + } + + @Override + public int getSlotVisibleRows() { + return 3; // Ender Chest has 3 rows + } + + @Override + public int getSlotRowLength() { + return 9; // 9 columns + } + + @Override + public boolean isSlotValidForDraggingInto(int channel, Slot slot) { + // Allow dragging into Ender Chest slots + return true; + } + + @Override + public int computeDraggingQuantity(Set dragSlots, int dragMode, ItemStack stack, int quantity) { + // Use default dragging behavior + return quantity / Math.max(1, dragSlots.size()); + } + + @Override + public int dragIntoSlot(AbstractContainerMenu container, int channel, Slot slot, int quantity, boolean simulate) { + // Use default container behavior + return 0; + } +} diff --git a/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabEnderChestCommon.java b/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabEnderChestCommon.java new file mode 100644 index 000000000..957a17a32 --- /dev/null +++ b/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabEnderChestCommon.java @@ -0,0 +1,67 @@ +package org.cyclops.integratedterminals.core.terminalstorage; + +import com.google.common.collect.Lists; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.Slot; +import org.apache.commons.lang3.tuple.Pair; +import org.cyclops.integratedterminals.IntegratedTerminals; +import org.cyclops.integratedterminals.api.terminalstorage.ITerminalStorageTabCommon; +import org.cyclops.integratedterminals.inventory.container.ContainerTerminalStorageBase; + +import java.util.List; +import java.util.Optional; + +/** + * A common storage terminal tab for Ender Chest. + * @author rubensworks + */ +public class TerminalStorageTabEnderChestCommon implements ITerminalStorageTabCommon { + + private final ContainerTerminalStorageBase containerTerminalStorage; + private final ResourceLocation name; + + public TerminalStorageTabEnderChestCommon(ContainerTerminalStorageBase containerTerminalStorage, + ResourceLocation name) { + this.containerTerminalStorage = containerTerminalStorage; + this.name = name; + } + + @Override + public ResourceLocation getName() { + return this.name; + } + + @Override + public List> loadSlots(AbstractContainerMenu container, int startIndex, Player player, + Optional variableInventoryOptional) { + List> slots = Lists.newArrayList(); + + // Add Ender Chest slots (27 slots in 3 rows of 9) + for (int row = 0; row < 3; row++) { + for (int col = 0; col < 9; col++) { + int slotIndex = col + row * 9; + int finalRow = row; + int finalCol = col; + + Slot slot = new Slot(player.getEnderChestInventory(), slotIndex, 0, 0); + ISlotPositionCallback positionCallback = (factors) -> { + int x = factors.offsetX() + finalCol * 18; + int y = factors.offsetY() + finalRow * 18 + 18; // Add offset to position below tab area + return Pair.of(x, y); + }; + + slots.add(Pair.of(slot, positionCallback)); + } + } + + return slots; + } + + @Override + public void onUpdate(AbstractContainerMenu container, Player player, + Optional variableInventory) { + // No special update logic needed for Ender Chest + } +} diff --git a/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabEnderChestServer.java b/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabEnderChestServer.java new file mode 100644 index 000000000..588a6a184 --- /dev/null +++ b/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabEnderChestServer.java @@ -0,0 +1,40 @@ +package org.cyclops.integratedterminals.core.terminalstorage; + +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerPlayer; +import org.cyclops.integratedterminals.api.terminalstorage.ITerminalStorageTabServer; + +/** + * A server-side storage terminal tab for Ender Chest. + * @author rubensworks + */ +public class TerminalStorageTabEnderChestServer implements ITerminalStorageTabServer { + + private final ResourceLocation name; + private final ServerPlayer player; + + public TerminalStorageTabEnderChestServer(ResourceLocation name, ServerPlayer player) { + this.name = name; + this.player = player; + } + + @Override + public ResourceLocation getName() { + return this.name; + } + + @Override + public void init() { + // No initialization needed + } + + @Override + public void deInit() { + // No cleanup needed + } + + @Override + public void updateActive() { + // No active updates needed - Minecraft handles Ender Chest inventory updates automatically + } +} diff --git a/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabs.java b/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabs.java index 60f80bbf6..71deadfc9 100644 --- a/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabs.java +++ b/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabs.java @@ -40,6 +40,9 @@ public static void afterIngredientComponentsRegistration(RegisterEvent event) { && ingredientComponentItemStack.getCapability(PositionedAddonsNetworkIngredientsHandlerConfig.CAPABILITY).isPresent()) { TerminalStorageTabs.REGISTRY.register(new TerminalStorageTabIngredientComponentItemStackCrafting(ingredientComponentItemStack)); } + + // Add Ender Chest tab + TerminalStorageTabs.REGISTRY.register(new TerminalStorageTabEnderChest()); } } diff --git a/src/main/resources/assets/integratedterminals/lang/en_us.json b/src/main/resources/assets/integratedterminals/lang/en_us.json index 9dbbd48d4..af0eb3c51 100644 --- a/src/main/resources/assets/integratedterminals/lang/en_us.json +++ b/src/main/resources/assets/integratedterminals/lang/en_us.json @@ -11,6 +11,7 @@ "gui.integratedterminals.terminal_storage.tooltip.fluid.amount": "%s mB", "gui.integratedterminals.terminal_storage.storage_name": "%s Storage", "gui.integratedterminals.terminal_storage.crafting_name": "%s Crafting", + "gui.integratedterminals.terminal_storage.ender_chest": "Ender Chest", "gui.integratedterminals.terminal_storage.channel": "Chan:", "gui.integratedterminals.terminal_storage.craft": "craft", "gui.integratedterminals.terminal_storage.tooltip.requirements": "Crafting Requirements:", From 1674895fb9be8f63e758d3ac77e9aff02b23746d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 15 Feb 2026 16:44:22 +0000 Subject: [PATCH 3/7] Fix compilation issues: use Reference.MOD_ID and remove RowsColumns overkill Co-authored-by: rubensworks <440384+rubensworks@users.noreply.github.com> --- .../terminalstorage/TerminalStorageTabEnderChest.java | 4 ++-- .../TerminalStorageTabEnderChestClient.java | 8 -------- .../TerminalStorageTabEnderChestCommon.java | 1 - 3 files changed, 2 insertions(+), 11 deletions(-) diff --git a/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabEnderChest.java b/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabEnderChest.java index 4cbe5e85b..64b48a293 100644 --- a/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabEnderChest.java +++ b/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabEnderChest.java @@ -4,7 +4,7 @@ import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Player; import org.cyclops.integrateddynamics.api.network.INetwork; -import org.cyclops.integratedterminals.IntegratedTerminals; +import org.cyclops.integratedterminals.Reference; import org.cyclops.integratedterminals.api.terminalstorage.ITerminalStorageTab; import org.cyclops.integratedterminals.api.terminalstorage.ITerminalStorageTabClient; import org.cyclops.integratedterminals.api.terminalstorage.ITerminalStorageTabCommon; @@ -19,7 +19,7 @@ */ public class TerminalStorageTabEnderChest implements ITerminalStorageTab { - public static ResourceLocation NAME = new ResourceLocation(IntegratedTerminals.MOD_ID, "ender_chest"); + public static ResourceLocation NAME = new ResourceLocation(Reference.MOD_ID, "ender_chest"); @Override public ResourceLocation getName() { diff --git a/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabEnderChestClient.java b/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabEnderChestClient.java index 6404e0aa8..6222c002f 100644 --- a/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabEnderChestClient.java +++ b/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabEnderChestClient.java @@ -10,7 +10,6 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.Blocks; import org.cyclops.integratedterminals.api.terminalstorage.ITerminalButton; -import org.cyclops.integratedterminals.api.terminalstorage.ITerminalRowColumnProvider; import org.cyclops.integratedterminals.api.terminalstorage.ITerminalStorageSlot; import org.cyclops.integratedterminals.api.terminalstorage.ITerminalStorageTabClient; import org.cyclops.integratedterminals.api.terminalstorage.ITerminalStorageTabCommon; @@ -30,13 +29,11 @@ public class TerminalStorageTabEnderChestClient implements ITerminalStorageTabCl private final ResourceLocation name; private final ItemStack icon; protected final ContainerTerminalStorageBase container; - private final ITerminalRowColumnProvider rowColumnProvider; public TerminalStorageTabEnderChestClient(ContainerTerminalStorageBase container, ResourceLocation name) { this.name = name; this.icon = new ItemStack(Blocks.ENDER_CHEST); this.container = container; - this.rowColumnProvider = () -> new ITerminalRowColumnProvider.RowsColumns(5, 9); } @Override @@ -80,11 +77,6 @@ public List getSlots(int channel, int offset, int limit) { return Collections.emptyList(); } - @Override - public ITerminalRowColumnProvider getRowColumnProvider() { - return rowColumnProvider; - } - @Override public boolean isEnabled() { return true; diff --git a/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabEnderChestCommon.java b/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabEnderChestCommon.java index 957a17a32..07da6b6de 100644 --- a/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabEnderChestCommon.java +++ b/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabEnderChestCommon.java @@ -6,7 +6,6 @@ import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.Slot; import org.apache.commons.lang3.tuple.Pair; -import org.cyclops.integratedterminals.IntegratedTerminals; import org.cyclops.integratedterminals.api.terminalstorage.ITerminalStorageTabCommon; import org.cyclops.integratedterminals.inventory.container.ContainerTerminalStorageBase; From 86227d987bb65fc7972c6b29a66ff24d0f7ca068 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 15 Feb 2026 18:23:21 +0000 Subject: [PATCH 4/7] Fix CI build failure: add getRowColumnProvider() implementation Co-authored-by: rubensworks <440384+rubensworks@users.noreply.github.com> --- .../TerminalStorageTabEnderChestClient.java | 20 ++++++------------- .../TerminalStorageTabEnderChestCommon.java | 4 ++-- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabEnderChestClient.java b/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabEnderChestClient.java index 6222c002f..a07c52137 100644 --- a/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabEnderChestClient.java +++ b/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabEnderChestClient.java @@ -1,8 +1,6 @@ package org.cyclops.integratedterminals.core.terminalstorage; import com.google.common.collect.Lists; -import com.mojang.blaze3d.vertex.PoseStack; -import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.inventory.AbstractContainerMenu; @@ -10,10 +8,9 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.Blocks; import org.cyclops.integratedterminals.api.terminalstorage.ITerminalButton; +import org.cyclops.integratedterminals.api.terminalstorage.ITerminalRowColumnProvider; import org.cyclops.integratedterminals.api.terminalstorage.ITerminalStorageSlot; import org.cyclops.integratedterminals.api.terminalstorage.ITerminalStorageTabClient; -import org.cyclops.integratedterminals.api.terminalstorage.ITerminalStorageTabCommon; -import org.cyclops.integratedterminals.client.gui.container.ContainerScreenTerminalStorage; import org.cyclops.integratedterminals.inventory.container.ContainerTerminalStorageBase; import java.util.Collections; @@ -77,6 +74,11 @@ public List getSlots(int channel, int offset, int limit) { return Collections.emptyList(); } + @Override + public ITerminalRowColumnProvider getRowColumnProvider() { + return () -> new ITerminalRowColumnProvider.RowsAndColumns(3, 9); + } + @Override public boolean isEnabled() { return true; @@ -147,16 +149,6 @@ public int getSlotOffsetY() { return 58; // Adjusted to position the Ender Chest slots properly } - @Override - public int getSlotVisibleRows() { - return 3; // Ender Chest has 3 rows - } - - @Override - public int getSlotRowLength() { - return 9; // 9 columns - } - @Override public boolean isSlotValidForDraggingInto(int channel, Slot slot) { // Allow dragging into Ender Chest slots diff --git a/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabEnderChestCommon.java b/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabEnderChestCommon.java index 07da6b6de..5a5ff60a3 100644 --- a/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabEnderChestCommon.java +++ b/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabEnderChestCommon.java @@ -43,14 +43,14 @@ public List> loadSlots(AbstractContainerMenu c int slotIndex = col + row * 9; int finalRow = row; int finalCol = col; - + Slot slot = new Slot(player.getEnderChestInventory(), slotIndex, 0, 0); ISlotPositionCallback positionCallback = (factors) -> { int x = factors.offsetX() + finalCol * 18; int y = factors.offsetY() + finalRow * 18 + 18; // Add offset to position below tab area return Pair.of(x, y); }; - + slots.add(Pair.of(slot, positionCallback)); } } From a93613d2f3a0ba62158f65036d89db3928485572 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 15 Feb 2026 18:52:00 +0000 Subject: [PATCH 5/7] Fix slot alignment, add config option, and update translation - Fix slot positioning: Remove extra Y offset so slots align with GUI borders - Add config option terminalStorageTabEnderChestEnabled to allow disabling the tab - Change translation from "Ender Chest" to "Ender Storage" Co-authored-by: rubensworks <440384+rubensworks@users.noreply.github.com> --- .../org/cyclops/integratedterminals/GeneralConfig.java | 2 ++ .../TerminalStorageTabEnderChestClient.java | 10 ---------- .../TerminalStorageTabEnderChestCommon.java | 2 +- .../core/terminalstorage/TerminalStorageTabs.java | 5 ++++- .../assets/integratedterminals/lang/en_us.json | 2 +- 5 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/main/java/org/cyclops/integratedterminals/GeneralConfig.java b/src/main/java/org/cyclops/integratedterminals/GeneralConfig.java index c00d50ee6..a100bb03a 100644 --- a/src/main/java/org/cyclops/integratedterminals/GeneralConfig.java +++ b/src/main/java/org/cyclops/integratedterminals/GeneralConfig.java @@ -90,6 +90,8 @@ public class GeneralConfig extends DummyConfig { public static int guiStorageScaleMaxColumns = 32; @ConfigurableProperty(category = "general", comment = "If the crafting grid should always be shown centrally, and not be responsive based on screen size.", isCommandable = true, configLocation = ModConfig.Type.CLIENT) public static boolean guiStorageForceCraftingGridCenter = false; + @ConfigurableProperty(category = "general", comment = "If the Ender Chest tab should be enabled in the storage terminal.", isCommandable = true, configLocation = ModConfig.Type.COMMON) + public static boolean terminalStorageTabEnderChestEnabled = true; public GeneralConfig() { super(IntegratedTerminals._instance, "general"); diff --git a/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabEnderChestClient.java b/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabEnderChestClient.java index a07c52137..7ebb07d2c 100644 --- a/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabEnderChestClient.java +++ b/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabEnderChestClient.java @@ -139,16 +139,6 @@ public void setActiveSlotQuantity(int quantity) { return Collections.emptyList(); } - @Override - public int getSlotOffsetX() { - return 32; - } - - @Override - public int getSlotOffsetY() { - return 58; // Adjusted to position the Ender Chest slots properly - } - @Override public boolean isSlotValidForDraggingInto(int channel, Slot slot) { // Allow dragging into Ender Chest slots diff --git a/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabEnderChestCommon.java b/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabEnderChestCommon.java index 5a5ff60a3..0c0d7077f 100644 --- a/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabEnderChestCommon.java +++ b/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabEnderChestCommon.java @@ -47,7 +47,7 @@ public List> loadSlots(AbstractContainerMenu c Slot slot = new Slot(player.getEnderChestInventory(), slotIndex, 0, 0); ISlotPositionCallback positionCallback = (factors) -> { int x = factors.offsetX() + finalCol * 18; - int y = factors.offsetY() + finalRow * 18 + 18; // Add offset to position below tab area + int y = factors.offsetY() + finalRow * 18; return Pair.of(x, y); }; diff --git a/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabs.java b/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabs.java index 71deadfc9..a1ed3e4ac 100644 --- a/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabs.java +++ b/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabs.java @@ -8,6 +8,7 @@ import net.minecraftforge.registries.RegisterEvent; import org.cyclops.commoncapabilities.api.ingredient.IngredientComponent; import org.cyclops.integrateddynamics.capability.network.PositionedAddonsNetworkIngredientsHandlerConfig; +import org.cyclops.integratedterminals.GeneralConfig; import org.cyclops.integratedterminals.IntegratedTerminals; import org.cyclops.integratedterminals.api.terminalstorage.ITerminalStorageTabRegistry; @@ -42,7 +43,9 @@ public static void afterIngredientComponentsRegistration(RegisterEvent event) { } // Add Ender Chest tab - TerminalStorageTabs.REGISTRY.register(new TerminalStorageTabEnderChest()); + if (GeneralConfig.terminalStorageTabEnderChestEnabled) { + TerminalStorageTabs.REGISTRY.register(new TerminalStorageTabEnderChest()); + } } } diff --git a/src/main/resources/assets/integratedterminals/lang/en_us.json b/src/main/resources/assets/integratedterminals/lang/en_us.json index af0eb3c51..428506531 100644 --- a/src/main/resources/assets/integratedterminals/lang/en_us.json +++ b/src/main/resources/assets/integratedterminals/lang/en_us.json @@ -11,7 +11,7 @@ "gui.integratedterminals.terminal_storage.tooltip.fluid.amount": "%s mB", "gui.integratedterminals.terminal_storage.storage_name": "%s Storage", "gui.integratedterminals.terminal_storage.crafting_name": "%s Crafting", - "gui.integratedterminals.terminal_storage.ender_chest": "Ender Chest", + "gui.integratedterminals.terminal_storage.ender_chest": "Ender Storage", "gui.integratedterminals.terminal_storage.channel": "Chan:", "gui.integratedterminals.terminal_storage.craft": "craft", "gui.integratedterminals.terminal_storage.tooltip.requirements": "Crafting Requirements:", From 0212260fa904a1b0016119d448bdd6a5255c98a8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 15 Feb 2026 18:54:30 +0000 Subject: [PATCH 6/7] Implement shift-click support for Ender Chest slots Add custom shift-click handling in handleClick method to move items between Ender Chest and player inventory. Implements proper item merging and empty slot filling logic. Co-authored-by: rubensworks <440384+rubensworks@users.noreply.github.com> --- .../TerminalStorageTabEnderChestClient.java | 89 ++++++++++++++++++- 1 file changed, 88 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabEnderChestClient.java b/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabEnderChestClient.java index 7ebb07d2c..51ab2b29c 100644 --- a/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabEnderChestClient.java +++ b/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabEnderChestClient.java @@ -7,10 +7,12 @@ import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.Blocks; +import org.apache.commons.lang3.tuple.Pair; import org.cyclops.integratedterminals.api.terminalstorage.ITerminalButton; import org.cyclops.integratedterminals.api.terminalstorage.ITerminalRowColumnProvider; import org.cyclops.integratedterminals.api.terminalstorage.ITerminalStorageSlot; import org.cyclops.integratedterminals.api.terminalstorage.ITerminalStorageTabClient; +import org.cyclops.integratedterminals.api.terminalstorage.ITerminalStorageTabCommon; import org.cyclops.integratedterminals.inventory.container.ContainerTerminalStorageBase; import java.util.Collections; @@ -108,10 +110,95 @@ public void resetActiveSlot() { public boolean handleClick(AbstractContainerMenu container, int channel, int hoveringStorageSlot, int mouseButton, boolean hasClickedOutside, boolean hasClickedInStorage, int hoveredContainerSlot, boolean isQuickMove) { - // Let default container handling take care of clicks + // Handle shift-clicking for Ender Chest slots + if (isQuickMove && hoveredContainerSlot >= 0 && container instanceof ContainerTerminalStorageBase) { + ContainerTerminalStorageBase terminalContainer = (ContainerTerminalStorageBase) container; + + // Get the Ender Chest slots for this tab + List> enderSlots = + terminalContainer.getTabSlots(getName().toString()); + + if (!enderSlots.isEmpty()) { + // Find the start and end indices of Ender Chest slots + int startIndex = Integer.MAX_VALUE; + int endIndex = Integer.MIN_VALUE; + for (Pair slotPair : enderSlots) { + int index = slotPair.getLeft().index; + startIndex = Math.min(startIndex, index); + endIndex = Math.max(endIndex, index); + } + + boolean isEnderSlot = hoveredContainerSlot >= startIndex && hoveredContainerSlot <= endIndex; + Slot slot = container.getSlot(hoveredContainerSlot); + ItemStack stackInSlot = slot.getItem().copy(); + + if (!stackInSlot.isEmpty()) { + // Try to move items + if (isEnderSlot) { + // Moving from Ender Chest to player inventory (slots 0-35) + if (moveItems(container, stackInSlot, 0, 36)) { + slot.set(stackInSlot.isEmpty() ? ItemStack.EMPTY : stackInSlot); + slot.setChanged(); + return true; + } + } else { + // Moving from player inventory to Ender Chest + if (moveItems(container, stackInSlot, startIndex, endIndex + 1)) { + slot.set(stackInSlot.isEmpty() ? ItemStack.EMPTY : stackInSlot); + slot.setChanged(); + return true; + } + } + } + } + } + + // Let default container handling take care of other clicks return false; } + private boolean moveItems(AbstractContainerMenu container, ItemStack stack, int startIndex, int endIndex) { + boolean moved = false; + int originalCount = stack.getCount(); + + // Try to merge with existing stacks first + for (int i = startIndex; i < endIndex && !stack.isEmpty(); i++) { + Slot targetSlot = container.getSlot(i); + ItemStack targetStack = targetSlot.getItem(); + + if (!targetStack.isEmpty() && ItemStack.isSameItemSameTags(stack, targetStack)) { + int maxSize = Math.min(targetSlot.getMaxStackSize(), targetStack.getMaxStackSize()); + int toTransfer = Math.min(stack.getCount(), maxSize - targetStack.getCount()); + + if (toTransfer > 0) { + targetStack.grow(toTransfer); + stack.shrink(toTransfer); + targetSlot.setChanged(); + moved = true; + } + } + } + + // Then try to put in empty slots + for (int i = startIndex; i < endIndex && !stack.isEmpty(); i++) { + Slot targetSlot = container.getSlot(i); + + if (!targetSlot.mayPlace(stack)) { + continue; + } + + ItemStack targetStack = targetSlot.getItem(); + if (targetStack.isEmpty()) { + int toTransfer = Math.min(stack.getCount(), targetSlot.getMaxStackSize()); + targetSlot.set(stack.split(toTransfer)); + targetSlot.setChanged(); + moved = true; + } + } + + return moved && stack.getCount() < originalCount; + } + @Override public boolean handleScroll(AbstractContainerMenu container, int channel, int hoveringStorageSlot, double delta, boolean hasClickedOutside, boolean hasClickedInStorage, int hoveredContainerSlot) { From ac0c549cde5fb32de7e231530f538a321a430a0d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 15 Feb 2026 19:19:07 +0000 Subject: [PATCH 7/7] Implement ender upgrade system for terminal storage - Add enderUpgraded boolean to PartTypeTerminalStorage.State with NBT persistence - Add right-click handler for Eye of Ender to upgrade terminal - Conditionally load ender chest tab based on upgrade state - Drop Eye of Ender when upgraded terminal is broken (upgrade not persisted) - Remove config option in favor of upgrade-based system Co-authored-by: rubensworks <440384+rubensworks@users.noreply.github.com> --- .../integratedterminals/GeneralConfig.java | 2 - .../terminalstorage/TerminalStorageTabs.java | 7 +-- .../ContainerTerminalStorageBase.java | 12 +++++ .../part/PartTypeTerminalStorage.java | 52 +++++++++++++++++++ 4 files changed, 66 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/cyclops/integratedterminals/GeneralConfig.java b/src/main/java/org/cyclops/integratedterminals/GeneralConfig.java index a100bb03a..c00d50ee6 100644 --- a/src/main/java/org/cyclops/integratedterminals/GeneralConfig.java +++ b/src/main/java/org/cyclops/integratedterminals/GeneralConfig.java @@ -90,8 +90,6 @@ public class GeneralConfig extends DummyConfig { public static int guiStorageScaleMaxColumns = 32; @ConfigurableProperty(category = "general", comment = "If the crafting grid should always be shown centrally, and not be responsive based on screen size.", isCommandable = true, configLocation = ModConfig.Type.CLIENT) public static boolean guiStorageForceCraftingGridCenter = false; - @ConfigurableProperty(category = "general", comment = "If the Ender Chest tab should be enabled in the storage terminal.", isCommandable = true, configLocation = ModConfig.Type.COMMON) - public static boolean terminalStorageTabEnderChestEnabled = true; public GeneralConfig() { super(IntegratedTerminals._instance, "general"); diff --git a/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabs.java b/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabs.java index a1ed3e4ac..6026ee20c 100644 --- a/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabs.java +++ b/src/main/java/org/cyclops/integratedterminals/core/terminalstorage/TerminalStorageTabs.java @@ -8,7 +8,6 @@ import net.minecraftforge.registries.RegisterEvent; import org.cyclops.commoncapabilities.api.ingredient.IngredientComponent; import org.cyclops.integrateddynamics.capability.network.PositionedAddonsNetworkIngredientsHandlerConfig; -import org.cyclops.integratedterminals.GeneralConfig; import org.cyclops.integratedterminals.IntegratedTerminals; import org.cyclops.integratedterminals.api.terminalstorage.ITerminalStorageTabRegistry; @@ -42,10 +41,8 @@ public static void afterIngredientComponentsRegistration(RegisterEvent event) { TerminalStorageTabs.REGISTRY.register(new TerminalStorageTabIngredientComponentItemStackCrafting(ingredientComponentItemStack)); } - // Add Ender Chest tab - if (GeneralConfig.terminalStorageTabEnderChestEnabled) { - TerminalStorageTabs.REGISTRY.register(new TerminalStorageTabEnderChest()); - } + // Add Ender Chest tab (conditionally loaded per-terminal based on upgrade state) + TerminalStorageTabs.REGISTRY.register(new TerminalStorageTabEnderChest()); } } diff --git a/src/main/java/org/cyclops/integratedterminals/inventory/container/ContainerTerminalStorageBase.java b/src/main/java/org/cyclops/integratedterminals/inventory/container/ContainerTerminalStorageBase.java index 4f02593f0..a0c5f9774 100644 --- a/src/main/java/org/cyclops/integratedterminals/inventory/container/ContainerTerminalStorageBase.java +++ b/src/main/java/org/cyclops/integratedterminals/inventory/container/ContainerTerminalStorageBase.java @@ -100,6 +100,18 @@ public ContainerTerminalStorageBase(@Nullable MenuType type, int id, Inventor // Add all tabs from the registry for (ITerminalStorageTab tab : TerminalStorageTabs.REGISTRY.getTabs()) { String tabId = tab.getName().toString(); + + // Skip ender chest tab if terminal is not upgraded + if (tabId.equals("integratedterminals:ender_chest")) { + if (variableInventory.isPresent() && variableInventory.get() instanceof org.cyclops.integratedterminals.part.PartTypeTerminalStorage.State) { + org.cyclops.integratedterminals.part.PartTypeTerminalStorage.State partState = + (org.cyclops.integratedterminals.part.PartTypeTerminalStorage.State) variableInventory.get(); + if (!partState.isEnderUpgraded()) { + continue; // Skip this tab + } + } + } + if (this.getWorld().isClientSide()) { this.tabsClient.put(tabId, tab.createClientTab(this, player)); } else { diff --git a/src/main/java/org/cyclops/integratedterminals/part/PartTypeTerminalStorage.java b/src/main/java/org/cyclops/integratedterminals/part/PartTypeTerminalStorage.java index dcdcf274d..7ba67ff81 100644 --- a/src/main/java/org/cyclops/integratedterminals/part/PartTypeTerminalStorage.java +++ b/src/main/java/org/cyclops/integratedterminals/part/PartTypeTerminalStorage.java @@ -8,6 +8,11 @@ import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.MenuProvider; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.InteractionHand; +import net.minecraft.core.BlockPos; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.level.Level; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; import net.minecraft.nbt.ListTag; @@ -54,6 +59,30 @@ protected PartTypeTerminalStorage.State constructDefaultState() { return new PartTypeTerminalStorage.State(); } + @Override + public InteractionResult onPartActivated(State partState, BlockPos pos, Level world, Player player, InteractionHand hand, ItemStack heldItem, BlockHitResult hit) { + // Check if player is holding an Eye of Ender and terminal is not yet upgraded + if (!partState.isEnderUpgraded() && heldItem.getItem() == net.minecraft.world.item.Items.ENDER_EYE) { + if (!world.isClientSide) { + // Upgrade the terminal + partState.setEnderUpgraded(true); + + // Consume the Eye of Ender + if (!player.isCreative()) { + heldItem.shrink(1); + } + + // Play sound + world.playSound(null, pos, net.minecraft.sounds.SoundEvents.END_PORTAL_FRAME_FILL, + net.minecraft.sounds.SoundSource.BLOCKS, 1.0F, 1.0F); + } + return InteractionResult.sidedSuccess(world.isClientSide); + } + + // Default behavior for opening GUI + return super.onPartActivated(partState, pos, world, player, hand, heldItem, hit); + } + @Override public Optional getContainerProvider(PartPos pos) { return Optional.of(new MenuProvider() { @@ -94,6 +123,12 @@ public void writeExtraGuiData(FriendlyByteBuf packetBuffer, PartPos pos, ServerP @Override public void addDrops(PartTarget target, State state, List itemStacks, boolean dropMainElement, boolean saveState) { + // If the terminal was ender-upgraded, drop an Eye of Ender and reset the upgrade + if (state.isEnderUpgraded() && dropMainElement) { + itemStacks.add(new ItemStack(net.minecraft.world.item.Items.ENDER_EYE)); + state.setEnderUpgraded(false); + } + for (Map.Entry> entry : state.getNamedInventories().entrySet()) { // TODO: for now hardcoded on crafting tab if (entry.getKey().equals(TerminalStorageTabIngredientComponentItemStackCrafting.NAME.toString())) { @@ -115,10 +150,21 @@ public static class State extends PartStateEmpty private final Map> namedInventories; private final Map playerStorageStates; + private boolean enderUpgraded; public State() { this.namedInventories = Maps.newHashMap(); this.playerStorageStates = Maps.newHashMap(); + this.enderUpgraded = false; + } + + public boolean isEnderUpgraded() { + return enderUpgraded; + } + + public void setEnderUpgraded(boolean enderUpgraded) { + this.enderUpgraded = enderUpgraded; + this.onDirty(); } @Override @@ -160,6 +206,9 @@ public TerminalStorageState getPlayerStorageState(Player player) { public void writeToNBT(CompoundTag tag) { super.writeToNBT(tag); + // Write enderUpgraded + tag.putBoolean("enderUpgraded", this.enderUpgraded); + // Write namedInventories ListTag namedInventoriesList = new ListTag(); for (Map.Entry> entry : this.namedInventories.entrySet()) { @@ -186,6 +235,9 @@ public void writeToNBT(CompoundTag tag) { public void readFromNBT(CompoundTag tag) { super.readFromNBT(tag); + // Read enderUpgraded + this.enderUpgraded = tag.getBoolean("enderUpgraded"); + // Read namedInventories for (Tag listEntry : tag.getList("namedInventories", Tag.TAG_COMPOUND)) { NonNullList list = NonNullList.withSize(((CompoundTag) listEntry).getInt("itemCount"), ItemStack.EMPTY);