From 410065d68ccf14fc44f31fa949caf715f9a41271 Mon Sep 17 00:00:00 2001 From: Danil Tkach Date: Mon, 6 Apr 2026 20:20:19 +0300 Subject: [PATCH] add direct methods to change items, add renameVisitor to preprocess rename text --- .../anvilgui/version/Wrapper1_16_R3.java | 42 +++++++++++++ .../anvilgui/version/VersionWrapper.java | 9 +++ .../java/net/wesjd/anvilgui/AnvilGUI.java | 60 +++++++++++++++---- 3 files changed, 100 insertions(+), 11 deletions(-) diff --git a/1_16_R3/src/main/java/net/wesjd/anvilgui/version/Wrapper1_16_R3.java b/1_16_R3/src/main/java/net/wesjd/anvilgui/version/Wrapper1_16_R3.java index 33d645ec..0918e0ad 100644 --- a/1_16_R3/src/main/java/net/wesjd/anvilgui/version/Wrapper1_16_R3.java +++ b/1_16_R3/src/main/java/net/wesjd/anvilgui/version/Wrapper1_16_R3.java @@ -1,11 +1,14 @@ package net.wesjd.anvilgui.version; +import java.util.function.Function; import net.minecraft.server.v1_16_R3.*; import org.bukkit.craftbukkit.v1_16_R3.CraftWorld; import org.bukkit.craftbukkit.v1_16_R3.entity.CraftPlayer; import org.bukkit.craftbukkit.v1_16_R3.event.CraftEventFactory; +import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftItemStack; import org.bukkit.entity.Player; import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; public class Wrapper1_16_R3 implements VersionWrapper { private int getRealNextContainerId(Player player) { @@ -120,6 +123,8 @@ private EntityPlayer toNMS(Player player) { */ private class AnvilContainer extends ContainerAnvil implements AnvilContainerWrapper { + private Function renameVisitor; + public AnvilContainer(Player player, IChatBaseComponent guiTitle) { super( getRealNextContainerId(player), @@ -129,6 +134,21 @@ public AnvilContainer(Player player, IChatBaseComponent guiTitle) { setTitle(guiTitle); } + @Override + public void setLeftItem(ItemStack item) { + this.getSlot(0).set(CraftItemStack.asNMSCopy(item)); + } + + @Override + public void setMiddleItem(ItemStack item) { + this.getSlot(1).set(CraftItemStack.asNMSCopy(item)); + } + + @Override + public void setRightItem(ItemStack item) { + this.getSlot(2).set(CraftItemStack.asNMSCopy(item)); + } + @Override public void e() { // If the output is empty copy the left input into the output @@ -171,9 +191,31 @@ public void setRenameText(String text) { } } + @Override + public void setRenameVisitor(Function renameVisitor) { + this.renameVisitor = renameVisitor; + } + @Override public Inventory getBukkitInventory() { return getBukkitView().getTopInventory(); } + + @Override + public void a(String s) { + if (renameVisitor == null) { + super.a(s); + return; + } + + ItemStack item = renameVisitor.apply(s); + if (item == null) { + super.a(s); + return; + } + + this.renameText = s; + this.getSlot(2).set(CraftItemStack.asNMSCopy(item)); + } } } diff --git a/abstraction/src/main/java/net/wesjd/anvilgui/version/VersionWrapper.java b/abstraction/src/main/java/net/wesjd/anvilgui/version/VersionWrapper.java index 5efe2c56..f0d9ca0e 100644 --- a/abstraction/src/main/java/net/wesjd/anvilgui/version/VersionWrapper.java +++ b/abstraction/src/main/java/net/wesjd/anvilgui/version/VersionWrapper.java @@ -1,7 +1,9 @@ package net.wesjd.anvilgui.version; +import java.util.function.Function; import org.bukkit.entity.Player; import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; /** * Wraps versions to be able to easily use different NMS server versions @@ -140,6 +142,13 @@ default String getRenameText() { */ default void setRenameText(String text) {} + default void setRenameVisitor(Function renameVisitor) {} + + default void setLeftItem(ItemStack item) {} + + default void setMiddleItem(ItemStack item) {} + + default void setRightItem(ItemStack item) {} /** * Gets the {@link Inventory} wrapper of the NMS container * diff --git a/api/src/main/java/net/wesjd/anvilgui/AnvilGUI.java b/api/src/main/java/net/wesjd/anvilgui/AnvilGUI.java index 1aab4e5f..217fcbd0 100644 --- a/api/src/main/java/net/wesjd/anvilgui/AnvilGUI.java +++ b/api/src/main/java/net/wesjd/anvilgui/AnvilGUI.java @@ -94,6 +94,8 @@ private static ItemStack itemNotNull(ItemStack stack) { /** An {@link Consumer} that is called when the anvil GUI is close */ private final Consumer closeListener; + + private final BiFunction renameVisitor; /** A flag that decides whether the async click handler can be run concurrently */ private final boolean concurrentClickHandlerExecution; /** An {@link BiFunction} that is called when a slot is clicked */ @@ -126,16 +128,17 @@ private static ItemStack itemNotNull(ItemStack stack) { /** * Create an AnvilGUI * - * @param plugin A {@link org.bukkit.plugin.java.JavaPlugin} instance - * @param player The {@link Player} to open the inventory for - * @param mainThreadExecutor An {@link Executor} that executes on the main server thread - * @param titleComponent What to have the text already set to - * @param initialContents The initial contents of the inventory - * @param preventClose Whether to prevent the inventory from closing - * @param geyserCompatibility Whether to enable compatibility with Geyser software - * @param closeListener A {@link Consumer} when the inventory closes + * @param plugin A {@link org.bukkit.plugin.java.JavaPlugin} instance + * @param player The {@link Player} to open the inventory for + * @param mainThreadExecutor An {@link Executor} that executes on the main server thread + * @param titleComponent What to have the text already set to + * @param initialContents The initial contents of the inventory + * @param preventClose Whether to prevent the inventory from closing + * @param geyserCompatibility Whether to enable compatibility with Geyser software + * @param closeListener A {@link Consumer} when the inventory closes + * @param renameVisitor * @param concurrentClickHandlerExecution Flag to allow concurrent execution of the click handler - * @param clickHandler A {@link ClickHandler} that is called when the player clicks a slot + * @param clickHandler A {@link ClickHandler} that is called when the player clicks a slot */ private AnvilGUI( Plugin plugin, @@ -147,6 +150,7 @@ private AnvilGUI( boolean geyserCompatibility, Set interactableSlots, Consumer closeListener, + BiFunction renameVisitor, boolean concurrentClickHandlerExecution, ClickHandler clickHandler) { this.plugin = plugin; @@ -158,10 +162,15 @@ private AnvilGUI( this.geyserCompatibility = geyserCompatibility; this.interactableSlots = Collections.unmodifiableSet(interactableSlots); this.closeListener = closeListener; + this.renameVisitor = renameVisitor; this.concurrentClickHandlerExecution = concurrentClickHandlerExecution; this.clickHandler = clickHandler; } + public VersionWrapper.AnvilContainerWrapper getContainer() { + return container; + } + /** * Opens the anvil GUI */ @@ -170,6 +179,13 @@ private void openInventory() { container = WRAPPER.newContainerAnvil(player, titleComponent); + if (renameVisitor != null) { + container.setRenameVisitor(s -> { + StateSnapshot stateSnapshot = StateSnapshot.fromAnvilGUI(this); + return renameVisitor.apply(s, stateSnapshot); + }); + } + inventory = container.getBukkitInventory(); // We need to use setItem instead of setContents because a Minecraft ContainerAnvil // contains two separate inventories: the result inventory and the ingredients inventory. @@ -412,6 +428,8 @@ public static class Builder { private Executor mainThreadExecutor; /** An {@link Consumer} that is called when the anvil GUI is close */ private Consumer closeListener; + + private BiFunction renameVisitor; /** A flag that decides whether the async click handler can be run concurrently */ private boolean concurrentClickHandlerExecution = false; /** An {@link Function} that is called when a slot in the inventory has been clicked */ @@ -495,6 +513,12 @@ public Builder onClose(Consumer closeListener) { return this; } + public Builder onRename(BiFunction renameVisitor) { + Validate.notNull(renameVisitor, "renameVisitor cannot be null"); + this.renameVisitor = renameVisitor; + return this; + } + /** * Do an action when a slot is clicked in the inventory *

@@ -679,6 +703,7 @@ public AnvilGUI open(Player player) { geyserCompatibility, interactableSlots, closeListener, + renameVisitor, concurrentClickHandlerExecution, clickHandler); anvilGUI.openInventory(); @@ -870,13 +895,16 @@ public static final class StateSnapshot { */ private static StateSnapshot fromAnvilGUI(AnvilGUI anvilGUI) { final Inventory inventory = anvilGUI.getInventory(); + return new StateSnapshot( + anvilGUI.container, itemNotNull(inventory.getItem(Slot.INPUT_LEFT)).clone(), itemNotNull(inventory.getItem(Slot.INPUT_RIGHT)).clone(), itemNotNull(inventory.getItem(Slot.OUTPUT)).clone(), anvilGUI.player); } + private final VersionWrapper.AnvilContainerWrapper container; /** * The {@link ItemStack} in the anvilGui slots */ @@ -894,13 +922,23 @@ private static StateSnapshot fromAnvilGUI(AnvilGUI anvilGUI) { * @param outputItem The item that would have been outputted, when the items would have been combined * @param player The player that clicked the output slot */ - public StateSnapshot(ItemStack leftItem, ItemStack rightItem, ItemStack outputItem, Player player) { + public StateSnapshot( + VersionWrapper.AnvilContainerWrapper container, + ItemStack leftItem, + ItemStack rightItem, + ItemStack outputItem, + Player player) { + this.container = container; this.leftItem = leftItem; this.rightItem = rightItem; this.outputItem = outputItem; this.player = player; } + public VersionWrapper.AnvilContainerWrapper getContainer() { + return container; + } + /** * It returns the item in the left combine slot of the gui * @@ -944,7 +982,7 @@ public Player getPlayer() { * @return The text of the rename field */ public String getText() { - return outputItem.hasItemMeta() ? outputItem.getItemMeta().getDisplayName() : ""; + return container.getRenameText(); } } }