diff --git a/ae2wtlib_api/src/main/java/de/mari_023/ae2wtlib/api/AE2wtlibAPI.java b/ae2wtlib_api/src/main/java/de/mari_023/ae2wtlib/api/AE2wtlibAPI.java index fef42983..e842fa82 100644 --- a/ae2wtlib_api/src/main/java/de/mari_023/ae2wtlib/api/AE2wtlibAPI.java +++ b/ae2wtlib_api/src/main/java/de/mari_023/ae2wtlib/api/AE2wtlibAPI.java @@ -16,6 +16,7 @@ import appeng.api.upgrades.IUpgradeInventory; import appeng.menu.locator.ItemMenuHostLocator; +import de.mari_023.ae2wtlib.api.registration.WTDefinition; import de.mari_023.ae2wtlib.api.terminal.ItemWUT; public class AE2wtlibAPI { @@ -62,6 +63,16 @@ public static void cycleTerminal(boolean isHandlingRightClick) { AE2wtlibAPIImpl.instance().cycleTerminal(isHandlingRightClick); } + @ApiStatus.Internal + public static void selectTerminal(WTDefinition terminal) { + AE2wtlibAPIImpl.instance().selectTerminal(terminal); + } + + @ApiStatus.Internal + public static boolean alwaysShowTerminalSelector() { + return AE2wtlibAPIImpl.instance().alwaysShowTerminalSelector(); + } + /** * Sends an update to the client about the current terminal. This is only relevant for Universal Terminals, and only * sent when ae2wtlib is present. diff --git a/ae2wtlib_api/src/main/java/de/mari_023/ae2wtlib/api/AE2wtlibAPIImpl.java b/ae2wtlib_api/src/main/java/de/mari_023/ae2wtlib/api/AE2wtlibAPIImpl.java index 95b9fc98..77fc5d60 100644 --- a/ae2wtlib_api/src/main/java/de/mari_023/ae2wtlib/api/AE2wtlibAPIImpl.java +++ b/ae2wtlib_api/src/main/java/de/mari_023/ae2wtlib/api/AE2wtlibAPIImpl.java @@ -14,6 +14,8 @@ import appeng.api.upgrades.IUpgradeInventory; import appeng.menu.locator.ItemMenuHostLocator; +import de.mari_023.ae2wtlib.api.registration.WTDefinition; + @ApiStatus.Internal public class AE2wtlibAPIImpl { @Nullable @@ -49,5 +51,13 @@ public Item getWUT() { @ApiStatus.Internal public void cycleTerminal(boolean isHandlingRightClick) {} + @ApiStatus.Internal + public void selectTerminal(WTDefinition terminal) {} + + @ApiStatus.Internal + public boolean alwaysShowTerminalSelector() { + return false; + } + public void updateClientTerminal(ServerPlayer player, ItemMenuHostLocator locator, ItemStack stack) {} } diff --git a/ae2wtlib_api/src/main/java/de/mari_023/ae2wtlib/api/TextConstants.java b/ae2wtlib_api/src/main/java/de/mari_023/ae2wtlib/api/TextConstants.java index 49be9ffe..0a946c7f 100644 --- a/ae2wtlib_api/src/main/java/de/mari_023/ae2wtlib/api/TextConstants.java +++ b/ae2wtlib_api/src/main/java/de/mari_023/ae2wtlib/api/TextConstants.java @@ -40,7 +40,12 @@ public static MutableComponent formatTerminalName(String terminal) { } public static final Component TERMINAL_EMPTY = Component - .literal("This terminal does not contain any other Terminals"); + .translatable("gui.ae2wtlib.terminal_empty"); + + public static Component currentTerminal(WTDefinition terminal) { + return Component.translatable("gui.ae2wtlib.current_terminal", + Component.translatable(terminal.translationKey()).withStyle(STYLE_GRAY)); + } public static Component cycleNext(WTDefinition terminal) { return Component.translatable("gui.ae2wtlib.cycle_terminal.desc", diff --git a/ae2wtlib_api/src/main/java/de/mari_023/ae2wtlib/api/terminal/IUniversalTerminalCapable.java b/ae2wtlib_api/src/main/java/de/mari_023/ae2wtlib/api/terminal/IUniversalTerminalCapable.java index d524cfb5..232c988c 100644 --- a/ae2wtlib_api/src/main/java/de/mari_023/ae2wtlib/api/terminal/IUniversalTerminalCapable.java +++ b/ae2wtlib_api/src/main/java/de/mari_023/ae2wtlib/api/terminal/IUniversalTerminalCapable.java @@ -1,7 +1,6 @@ package de.mari_023.ae2wtlib.api.terminal; import java.util.ArrayList; -import java.util.List; import org.jetbrains.annotations.Contract; @@ -14,7 +13,6 @@ import appeng.menu.SlotSemantics; import de.mari_023.ae2wtlib.api.AE2wtlibAPI; -import de.mari_023.ae2wtlib.api.TextConstants; import de.mari_023.ae2wtlib.api.gui.AE2wtlibSlotSemantics; import de.mari_023.ae2wtlib.api.gui.IconButton; import de.mari_023.ae2wtlib.api.gui.ScrollingUpgradesPanel; @@ -52,17 +50,14 @@ default boolean checkForTerminalKeys(int keyCode, int scanCode) { } /** - * creates the button that switches to the next terminal. you are responsible for adding this to the leftToolbar - * when appropriate - * - * @return CycleTerminalButton + * creates the button that opens the terminal selector. you are responsible for adding this to the leftToolbar when + * appropriate + * + * @return TerminalSelectionButton */ @Contract(value = "-> new", pure = true) default IconButton cycleTerminalButton() { - var next = WUTHandler.nextTerminal(getHost().getItemStack(), false); - var previous = WUTHandler.nextTerminal(getHost().getItemStack(), true); - return IconButton.withAE2Background(btn -> cycleTerminal(), next.icon()) - .withTooltip(List.of(TextConstants.cycleNext(next), TextConstants.cyclePrevious(previous))); + return new TerminalSelectionButton(getHost(), this::storeState); } /** diff --git a/ae2wtlib_api/src/main/java/de/mari_023/ae2wtlib/api/terminal/ItemWUT.java b/ae2wtlib_api/src/main/java/de/mari_023/ae2wtlib/api/terminal/ItemWUT.java index db37ecb3..efd3180a 100644 --- a/ae2wtlib_api/src/main/java/de/mari_023/ae2wtlib/api/terminal/ItemWUT.java +++ b/ae2wtlib_api/src/main/java/de/mari_023/ae2wtlib/api/terminal/ItemWUT.java @@ -64,6 +64,11 @@ public MenuType getMenuType(ItemMenuHostLocator locator, Player player) { @OnlyIn(Dist.CLIENT) public void appendHoverText(final ItemStack stack, final TooltipContext context, final List lines, final TooltipFlag advancedTooltips) { + var currentTerminal = WTDefinition.ofOrNull(stack); + if (currentTerminal != null) { + lines.add(TextConstants.currentTerminal(currentTerminal)); + lines.add(Component.empty()); + } lines.add(TextConstants.UNIVERSAL); for (var terminal : WTDefinition.wirelessTerminals()) { if (stack.get(terminal.componentType()) != null) diff --git a/ae2wtlib_api/src/main/java/de/mari_023/ae2wtlib/api/terminal/TerminalSelectionButton.java b/ae2wtlib_api/src/main/java/de/mari_023/ae2wtlib/api/terminal/TerminalSelectionButton.java new file mode 100644 index 00000000..02965d91 --- /dev/null +++ b/ae2wtlib_api/src/main/java/de/mari_023/ae2wtlib/api/terminal/TerminalSelectionButton.java @@ -0,0 +1,232 @@ +package de.mari_023.ae2wtlib.api.terminal; + +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.renderer.Rect2i; +import net.minecraft.network.chat.Component; + +import appeng.client.gui.style.BackgroundGenerator; + +import de.mari_023.ae2wtlib.api.AE2wtlibAPI; +import de.mari_023.ae2wtlib.api.TextConstants; +import de.mari_023.ae2wtlib.api.gui.Icon; +import de.mari_023.ae2wtlib.api.gui.IconButton; +import de.mari_023.ae2wtlib.api.registration.WTDefinition; + +/** + * Provides a button that opens a terminal selector panel for the wireless universal terminal. + */ +final class TerminalSelectionButton extends IconButton { + private static final int BUTTON_WIDTH = 18; + private static final int BUTTON_HEIGHT = 20; + private static final int MAX_ROWS = 3; + private static final int GAP = 2; + private static final int PANEL_GAP = 5; + private static final int ALWAYS_VISIBLE_PANEL_X_OFFSET = -15; + private static final int ALWAYS_VISIBLE_PANEL_Y_OFFSET = 3; + private static final int PANEL_PADDING = 3; + private static final int ICON_OFFSET = 1; + private static final int TOOLBAR_BUTTON_SPACING = 6; + + private final WTMenuHost host; + private final List terminals; + private final Runnable storeState; + private boolean menuOpen; + private List tooltip = List.of(); + + TerminalSelectionButton(WTMenuHost host, Runnable storeState) { + super(btn -> { + }, Icon.CRAFTING, Icon.TOOLBAR_BUTTON_BACKGROUND, Icon.TOOLBAR_BUTTON_BACKGROUND_HOVERED, + Icon.TOOLBAR_BUTTON_BACKGROUND_FOCUSED); + this.host = host; + this.storeState = storeState; + this.terminals = installedTerminals(host); + } + + @Override + public void renderWidget(GuiGraphics guiGraphics, int mouseX, int mouseY, float partial) { + if (!visible) + return; + + boolean alwaysVisible = alwaysVisible(); + tooltip = List.of(); + if (!alwaysVisible) { + super.renderWidget(guiGraphics, mouseX, mouseY, partial); + if (isHovered()) + tooltip = currentTooltip(); + } + + if (menuOpen || alwaysVisible) + renderMenu(guiGraphics, mouseX, mouseY); + } + + @Override + protected Icon getIcon() { + WTDefinition terminal = WTDefinition.ofOrNull(host.getItemStack()); + return terminal == null ? Icon.CRAFTING : terminal.icon(); + } + + @Override + public void onPress() { + if (!alwaysVisible() && !terminals.isEmpty()) + menuOpen = !menuOpen; + } + + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + boolean alwaysVisible = alwaysVisible(); + if ((menuOpen || alwaysVisible) && button == 0) { + WTDefinition terminal = terminalAt(mouseX, mouseY); + if (terminal != null) { + if (!alwaysVisible) + menuOpen = false; + storeState.run(); + AE2wtlibAPI.selectTerminal(terminal); + return true; + } + } + + if (alwaysVisible) + return false; + + if (super.mouseClicked(mouseX, mouseY, button)) + return true; + + if (menuOpen) { + menuOpen = false; + } + return false; + } + + @Override + public int getWidth() { + return alwaysVisible() ? 0 : super.getWidth(); + } + + @Override + public int getHeight() { + return alwaysVisible() ? -TOOLBAR_BUTTON_SPACING : super.getHeight(); + } + + @Override + public List getTooltipMessage() { + return tooltip; + } + + @Override + public Rect2i getTooltipArea() { + if (!menuOpen && !alwaysVisible()) + return super.getTooltipArea(); + + int x = panelX() - 1; + int y = panelY() - 1; + int right = Math.max(getX() + getWidth(), panelX() + panelWidth() + 1); + int bottom = Math.max(getY() + getHeight(), panelY() + panelHeight() + 1); + return new Rect2i(x, y, right - x, bottom - y); + } + + private static List installedTerminals(WTMenuHost host) { + List terminals = new ArrayList<>(); + for (var terminal : WTDefinition.wirelessTerminalList) { + if (WUTHandler.hasTerminal(host.getItemStack(), terminal)) + terminals.add(terminal); + } + return terminals; + } + + private boolean alwaysVisible() { + return AE2wtlibAPI.alwaysShowTerminalSelector() && !terminals.isEmpty(); + } + + private List currentTooltip() { + WTDefinition terminal = WTDefinition.ofOrNull(host.getItemStack()); + if (terminal == null) + return List.of(TextConstants.TERMINAL_EMPTY); + return List.of(TextConstants.currentTerminal(terminal)); + } + + private void renderMenu(GuiGraphics guiGraphics, int mouseX, int mouseY) { + int panelX = panelX(); + int panelY = panelY(); + int width = panelWidth(); + int height = panelHeight(); + WTDefinition currentTerminal = WTDefinition.ofOrNull(host.getItemStack()); + + BackgroundGenerator.draw(width, height, guiGraphics, panelX, panelY); + + for (int i = 0; i < terminals.size(); i++) { + WTDefinition terminal = terminals.get(i); + int x = buttonX(i); + int y = buttonY(i); + boolean selected = terminal.equals(currentTerminal); + boolean hovered = mouseX >= x && mouseY >= y && mouseX < x + BUTTON_WIDTH && mouseY < y + BUTTON_HEIGHT; + int yOffset = hovered ? 1 : 0; + Icon background = hovered ? Icon.TOOLBAR_BUTTON_BACKGROUND_HOVERED + : selected ? Icon.TOOLBAR_BUTTON_BACKGROUND_FOCUSED : Icon.TOOLBAR_BUTTON_BACKGROUND; + + background.getBlitter().dest(x, y + yOffset, background.width(), background.height()).zOffset(2) + .blit(guiGraphics); + terminal.icon().getBlitter().dest(x + ICON_OFFSET, y + ICON_OFFSET + yOffset).zOffset(3).blit(guiGraphics); + + if (hovered) + tooltip = List.of(terminal.formattedName()); + } + } + + private WTDefinition terminalAt(double mouseX, double mouseY) { + for (int i = 0; i < terminals.size(); i++) { + int x = buttonX(i); + int y = buttonY(i); + if (mouseX >= x && mouseY >= y && mouseX < x + BUTTON_WIDTH && mouseY < y + BUTTON_HEIGHT) + return terminals.get(i); + } + return null; + } + + private int panelX() { + int x = getX(); + int gap = PANEL_GAP; + if (alwaysVisible()) { + x -= super.getWidth(); + gap = ALWAYS_VISIBLE_PANEL_X_OFFSET; + } + return x - gap - panelWidth(); + } + + private int panelY() { + return getY() + (alwaysVisible() ? ALWAYS_VISIBLE_PANEL_Y_OFFSET : 0); + } + + private int panelWidth() { + return PANEL_PADDING * 2 + columns() * BUTTON_WIDTH + Math.max(0, columns() - 1) * GAP; + } + + private int panelHeight() { + return PANEL_PADDING * 2 + 2 + rows() * BUTTON_HEIGHT + Math.max(0, rows() - 1) * GAP; + } + + private int buttonX(int index) { + return panelX() + PANEL_PADDING + (index / rows()) * (BUTTON_WIDTH + GAP); + } + + private int buttonY(int index) { + return panelY() + PANEL_PADDING + (index % rows()) * (BUTTON_HEIGHT + GAP) + lastColumnYOffset(index); + } + + private int columns() { + return Math.max(1, (terminals.size() + rows() - 1) / rows()); + } + + private int rows() { + return Math.max(1, Math.min(MAX_ROWS, terminals.size())); + } + + private int lastColumnYOffset(int index) { + int entries = terminals.size() % rows(); + if (entries == 0 || index / rows() != columns() - 1) + return 0; + return (rows() - entries) * (BUTTON_HEIGHT + GAP) / 2; + } +} diff --git a/src/main/java/de/mari_023/ae2wtlib/AE2wtlibAPIImplementation.java b/src/main/java/de/mari_023/ae2wtlib/AE2wtlibAPIImplementation.java index 6e190736..47a97699 100644 --- a/src/main/java/de/mari_023/ae2wtlib/AE2wtlibAPIImplementation.java +++ b/src/main/java/de/mari_023/ae2wtlib/AE2wtlibAPIImplementation.java @@ -11,7 +11,9 @@ import appeng.menu.locator.ItemMenuHostLocator; import de.mari_023.ae2wtlib.api.AE2wtlibAPIImpl; +import de.mari_023.ae2wtlib.api.registration.WTDefinition; import de.mari_023.ae2wtlib.networking.CycleTerminalPacket; +import de.mari_023.ae2wtlib.networking.SelectTerminalPacket; import de.mari_023.ae2wtlib.networking.UpdateWUTPackage; public class AE2wtlibAPIImplementation extends AE2wtlibAPIImpl { @@ -30,6 +32,16 @@ public void cycleTerminal(boolean isHandlingRightClick) { PacketDistributor.sendToServer(new CycleTerminalPacket(isHandlingRightClick)); } + @Override + public void selectTerminal(WTDefinition terminal) { + PacketDistributor.sendToServer(new SelectTerminalPacket(terminal)); + } + + @Override + public boolean alwaysShowTerminalSelector() { + return AE2wtlibClientConfig.CONFIG.alwaysShowTerminalSelector(); + } + @Override public void updateClientTerminal(ServerPlayer player, ItemMenuHostLocator locator, ItemStack stack) { PacketDistributor.sendToPlayer(player, new UpdateWUTPackage(locator, stack)); diff --git a/src/main/java/de/mari_023/ae2wtlib/AE2wtlibClient.java b/src/main/java/de/mari_023/ae2wtlib/AE2wtlibClient.java index 2658b404..a358026d 100644 --- a/src/main/java/de/mari_023/ae2wtlib/AE2wtlibClient.java +++ b/src/main/java/de/mari_023/ae2wtlib/AE2wtlibClient.java @@ -1,19 +1,27 @@ package de.mari_023.ae2wtlib; import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screens.Screen; import net.neoforged.api.distmarker.Dist; import net.neoforged.bus.api.IEventBus; import net.neoforged.fml.ModContainer; import net.neoforged.fml.common.Mod; +import net.neoforged.fml.config.ModConfig; +import net.neoforged.neoforge.client.event.InputEvent; import net.neoforged.neoforge.client.gui.ConfigurationScreen; import net.neoforged.neoforge.client.gui.IConfigScreenFactory; +import net.neoforged.neoforge.network.PacketDistributor; import de.mari_023.ae2wtlib.api.AE2wtlibAPI; +import de.mari_023.ae2wtlib.api.terminal.ItemWUT; +import de.mari_023.ae2wtlib.networking.CycleTerminalPacket; import de.mari_023.ae2wtlib.wct.CraftingTerminalHandler; @Mod(value = AE2wtlibAPI.MOD_NAME, dist = Dist.CLIENT) public class AE2wtlibClient { public AE2wtlibClient(IEventBus modEventBus, ModContainer modContainer) { + modContainer.registerConfig(ModConfig.Type.CLIENT, AE2wtlibClientConfig.SPEC, + AE2wtlibAPI.MOD_NAME + "-client.toml"); modContainer.registerExtensionPoint(IConfigScreenFactory.class, ConfigurationScreen::new); } @@ -22,4 +30,18 @@ public static void clientTick() { return; CraftingTerminalHandler.getCraftingTerminalHandler(Minecraft.getInstance().player).checkTerminal(); } + + public static void mouseScroll(InputEvent.MouseScrollingEvent event) { + var minecraft = Minecraft.getInstance(); + var player = minecraft.player; + if (player == null || minecraft.screen != null || !Screen.hasShiftDown() || event.getScrollDeltaY() == 0) + return; + + if (!(player.getMainHandItem().getItem() instanceof ItemWUT) + && !(player.getOffhandItem().getItem() instanceof ItemWUT)) + return; + + PacketDistributor.sendToServer(new CycleTerminalPacket(event.getScrollDeltaY() < 0)); + event.setCanceled(true); + } } diff --git a/src/main/java/de/mari_023/ae2wtlib/AE2wtlibClientConfig.java b/src/main/java/de/mari_023/ae2wtlib/AE2wtlibClientConfig.java new file mode 100644 index 00000000..0bcbd490 --- /dev/null +++ b/src/main/java/de/mari_023/ae2wtlib/AE2wtlibClientConfig.java @@ -0,0 +1,25 @@ +package de.mari_023.ae2wtlib; + +import org.apache.commons.lang3.tuple.Pair; + +import net.neoforged.neoforge.common.ModConfigSpec; + +public record AE2wtlibClientConfig(ModConfigSpec.BooleanValue alwaysShowTerminalSelectorValue) { + public static final AE2wtlibClientConfig CONFIG; + public static final ModConfigSpec SPEC; + + static { + Pair pair = new ModConfigSpec.Builder() + .configure(AE2wtlibClientConfig::new); + CONFIG = pair.getLeft(); + SPEC = pair.getRight(); + } + + AE2wtlibClientConfig(ModConfigSpec.Builder builder) { + this(builder.define("always_show_terminal_selector", false)); + } + + public boolean alwaysShowTerminalSelector() { + return alwaysShowTerminalSelectorValue().get(); + } +} diff --git a/src/main/java/de/mari_023/ae2wtlib/AE2wtlibForge.java b/src/main/java/de/mari_023/ae2wtlib/AE2wtlibForge.java index 8d2d9b65..c668979c 100644 --- a/src/main/java/de/mari_023/ae2wtlib/AE2wtlibForge.java +++ b/src/main/java/de/mari_023/ae2wtlib/AE2wtlibForge.java @@ -16,6 +16,7 @@ import net.neoforged.neoforge.capabilities.Capabilities; import net.neoforged.neoforge.capabilities.RegisterCapabilitiesEvent; import net.neoforged.neoforge.client.event.ClientTickEvent; +import net.neoforged.neoforge.client.event.InputEvent; import net.neoforged.neoforge.event.BuildCreativeModeTabContentsEvent; import net.neoforged.neoforge.event.entity.living.LivingEntityUseItemEvent; import net.neoforged.neoforge.event.entity.player.ArrowLooseEvent; @@ -54,6 +55,7 @@ public AE2wtlibForge(IEventBus modEventBus, ModContainer modContainer) { modEventBus.addListener((RegisterPayloadHandlersEvent event) -> { PayloadRegistrar registrar = event.registrar(AE2wtlibAPI.MOD_NAME); registerPacket(registrar, CycleTerminalPacket.ID, CycleTerminalPacket.STREAM_CODEC); + registerPacket(registrar, SelectTerminalPacket.ID, SelectTerminalPacket.STREAM_CODEC); registerPacket(registrar, PickBlockPacket.ID, PickBlockPacket.STREAM_CODEC); registerPacket(registrar, TerminalSettingsPacket.ID, TerminalSettingsPacket.STREAM_CODEC); registerPacket(registrar, UpdateWUTPackage.ID, UpdateWUTPackage.STREAM_CODEC); @@ -149,4 +151,9 @@ public static void handle(ArrowLooseEvent event) { public static void handle(ClientTickEvent.Post event) { AE2wtlibClient.clientTick(); } + + @SubscribeEvent + public static void handle(InputEvent.MouseScrollingEvent event) { + AE2wtlibClient.mouseScroll(event); + } } diff --git a/src/main/java/de/mari_023/ae2wtlib/networking/CycleTerminalPacket.java b/src/main/java/de/mari_023/ae2wtlib/networking/CycleTerminalPacket.java index 114e516a..9b0fb419 100644 --- a/src/main/java/de/mari_023/ae2wtlib/networking/CycleTerminalPacket.java +++ b/src/main/java/de/mari_023/ae2wtlib/networking/CycleTerminalPacket.java @@ -5,14 +5,18 @@ import net.minecraft.network.codec.ByteBufCodecs; import net.minecraft.network.codec.StreamCodec; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; +import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.item.ItemStack; import appeng.menu.AEBaseMenu; import appeng.menu.locator.ItemMenuHostLocator; +import appeng.menu.locator.MenuLocators; import de.mari_023.ae2wtlib.api.AE2wtlibAPI; +import de.mari_023.ae2wtlib.api.AE2wtlibComponents; +import de.mari_023.ae2wtlib.api.TextConstants; import de.mari_023.ae2wtlib.api.terminal.ItemWUT; import de.mari_023.ae2wtlib.api.terminal.WUTHandler; @@ -24,8 +28,10 @@ public record CycleTerminalPacket(boolean isRightClick) implements AE2wtlibPacke public void processPacketData(Player player) { final AbstractContainerMenu containerMenu = player.containerMenu; - if (!(containerMenu instanceof AEBaseMenu aeMenu)) + if (!(containerMenu instanceof AEBaseMenu aeMenu)) { + cycleHeldUniversalTerminal(player); return; + } if (!(aeMenu.getLocator() instanceof ItemMenuHostLocator locator)) return; @@ -39,6 +45,31 @@ public void processPacketData(Player player) { WUTHandler.open(player, locator, true); } + private void cycleHeldUniversalTerminal(Player player) { + ItemMenuHostLocator locator = getHeldUniversalTerminalLocator(player); + if (locator == null) + return; + + ItemStack item = locator.locateItem(player); + + if (!(item.getItem() instanceof ItemWUT)) + return; + + WUTHandler.cycle(player, locator, item, isRightClick()); + + var terminal = item.get(AE2wtlibComponents.CURRENT_TERMINAL); + if (terminal != null) + player.displayClientMessage(TextConstants.currentTerminal(terminal), true); + } + + private static ItemMenuHostLocator getHeldUniversalTerminalLocator(Player player) { + if (player.getMainHandItem().getItem() instanceof ItemWUT) + return MenuLocators.forInventorySlot(player.getInventory().selected); + if (player.getOffhandItem().getItem() instanceof ItemWUT) + return MenuLocators.forInventorySlot(Inventory.SLOT_OFFHAND); + return null; + } + @Override public Type type() { return ID; diff --git a/src/main/java/de/mari_023/ae2wtlib/networking/SelectTerminalPacket.java b/src/main/java/de/mari_023/ae2wtlib/networking/SelectTerminalPacket.java new file mode 100644 index 00000000..9bab023b --- /dev/null +++ b/src/main/java/de/mari_023/ae2wtlib/networking/SelectTerminalPacket.java @@ -0,0 +1,47 @@ +package de.mari_023.ae2wtlib.networking; + +import io.netty.buffer.ByteBuf; + +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.item.ItemStack; + +import appeng.menu.AEBaseMenu; +import appeng.menu.locator.ItemMenuHostLocator; + +import de.mari_023.ae2wtlib.api.AE2wtlibAPI; +import de.mari_023.ae2wtlib.api.registration.WTDefinition; +import de.mari_023.ae2wtlib.api.terminal.ItemWUT; +import de.mari_023.ae2wtlib.api.terminal.WUTHandler; + +public record SelectTerminalPacket(WTDefinition terminal) implements AE2wtlibPacket { + public static final Type ID = new Type<>(AE2wtlibAPI.id("select_terminal")); + public static final StreamCodec STREAM_CODEC = WTDefinition.STREAM_CODEC + .map(SelectTerminalPacket::new, SelectTerminalPacket::terminal); + + public void processPacketData(Player player) { + final AbstractContainerMenu containerMenu = player.containerMenu; + + if (!(containerMenu instanceof AEBaseMenu aeMenu)) + return; + + if (!(aeMenu.getLocator() instanceof ItemMenuHostLocator locator)) + return; + + ItemStack item = locator.locateItem(player); + if (!(item.getItem() instanceof ItemWUT)) + return; + if (!WUTHandler.hasTerminal(item, terminal())) + return; + + WUTHandler.setCurrentTerminal(player, locator, item, terminal()); + WUTHandler.open(player, locator, true); + } + + @Override + public Type type() { + return ID; + } +} diff --git a/src/main/resources/assets/ae2wtlib/lang/en_us.json b/src/main/resources/assets/ae2wtlib/lang/en_us.json index 82a59e85..9e4e9fe4 100644 --- a/src/main/resources/assets/ae2wtlib/lang/en_us.json +++ b/src/main/resources/assets/ae2wtlib/lang/en_us.json @@ -15,6 +15,8 @@ "gui.ae2wtlib.magnetcard.desc.me_no_magnet": "Magnet Off, Pickup to ME", "gui.ae2wtlib.cycle_terminal.desc": "Open %s", "gui.ae2wtlib.cycle_terminal.desc1": "Right click to open %s", + "gui.ae2wtlib.current_terminal": "Current Terminal: %s", + "gui.ae2wtlib.terminal_empty": "This terminal does not contain any other terminals", "gui.ae2wtlib.magnetcard.hotkey": "Magnet Card: %s", "gui.ae2wtlib.restock": "Restock: %s", "gui.ae2wtlib.off": "Off", @@ -49,5 +51,6 @@ "key.ae2.ae2wtlib_magnet": "Toggle Magnet Card", "key.ae2.ae2wtlib_stow": "Stow stack in hand into ME System", - "ae2wtlib.configuration.magnet_card_range": "Magnet Card Range" + "ae2wtlib.configuration.magnet_card_range": "Magnet Card Range", + "ae2wtlib.configuration.always_show_terminal_selector": "Always Show Universal Terminal Selector" } diff --git a/src/main/resources/assets/ae2wtlib/lang/es_es.json b/src/main/resources/assets/ae2wtlib/lang/es_es.json index 6d39544a..be7247f9 100644 --- a/src/main/resources/assets/ae2wtlib/lang/es_es.json +++ b/src/main/resources/assets/ae2wtlib/lang/es_es.json @@ -15,6 +15,8 @@ "gui.ae2wtlib.magnetcard.desc.me_no_magnet": "Imán apagado, recoger a ME", "gui.ae2wtlib.cycle_terminal.desc": "Abrir %s", "gui.ae2wtlib.cycle_terminal.desc1": "Haz clic derecho para abrir %s", + "gui.ae2wtlib.current_terminal": "Terminal actual: %s", + "gui.ae2wtlib.terminal_empty": "Esta terminal no contiene otras terminales", "gui.ae2wtlib.magnetcard.hotkey": "Tarjeta de imán: %s", "gui.ae2wtlib.restock": "Reabastecer: %s", "gui.ae2wtlib.off": "Apagado", @@ -48,5 +50,6 @@ "key.ae2.ae2wtlib_magnet": "Alternar tarjeta de imán", "key.ae2.ae2wtlib_stow": "Guardar stack en mano en el sistema ME", - "ae2wtlib.configuration.magnet_card_range": "Rango de tarjeta de imán" + "ae2wtlib.configuration.magnet_card_range": "Rango de tarjeta de imán", + "ae2wtlib.configuration.always_show_terminal_selector": "Mostrar siempre el selector de terminal universal" } diff --git a/src/main/resources/assets/ae2wtlib/lang/es_mx.json b/src/main/resources/assets/ae2wtlib/lang/es_mx.json index 6d39544a..be7247f9 100644 --- a/src/main/resources/assets/ae2wtlib/lang/es_mx.json +++ b/src/main/resources/assets/ae2wtlib/lang/es_mx.json @@ -15,6 +15,8 @@ "gui.ae2wtlib.magnetcard.desc.me_no_magnet": "Imán apagado, recoger a ME", "gui.ae2wtlib.cycle_terminal.desc": "Abrir %s", "gui.ae2wtlib.cycle_terminal.desc1": "Haz clic derecho para abrir %s", + "gui.ae2wtlib.current_terminal": "Terminal actual: %s", + "gui.ae2wtlib.terminal_empty": "Esta terminal no contiene otras terminales", "gui.ae2wtlib.magnetcard.hotkey": "Tarjeta de imán: %s", "gui.ae2wtlib.restock": "Reabastecer: %s", "gui.ae2wtlib.off": "Apagado", @@ -48,5 +50,6 @@ "key.ae2.ae2wtlib_magnet": "Alternar tarjeta de imán", "key.ae2.ae2wtlib_stow": "Guardar stack en mano en el sistema ME", - "ae2wtlib.configuration.magnet_card_range": "Rango de tarjeta de imán" + "ae2wtlib.configuration.magnet_card_range": "Rango de tarjeta de imán", + "ae2wtlib.configuration.always_show_terminal_selector": "Mostrar siempre el selector de terminal universal" }