Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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) {
Expand Down Expand Up @@ -120,6 +123,8 @@ private EntityPlayer toNMS(Player player) {
*/
private class AnvilContainer extends ContainerAnvil implements AnvilContainerWrapper {

private Function<String, ItemStack> renameVisitor;

public AnvilContainer(Player player, IChatBaseComponent guiTitle) {
super(
getRealNextContainerId(player),
Expand All @@ -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
Expand Down Expand Up @@ -171,9 +191,31 @@ public void setRenameText(String text) {
}
}

@Override
public void setRenameVisitor(Function<String, ItemStack> 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));
}
}
}
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -140,6 +142,13 @@ default String getRenameText() {
*/
default void setRenameText(String text) {}

default void setRenameVisitor(Function<String, ItemStack> 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
*
Expand Down
60 changes: 49 additions & 11 deletions api/src/main/java/net/wesjd/anvilgui/AnvilGUI.java
Original file line number Diff line number Diff line change
Expand Up @@ -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<StateSnapshot> closeListener;

private final BiFunction<String, StateSnapshot, ItemStack> 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 */
Expand Down Expand Up @@ -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,
Expand All @@ -147,6 +150,7 @@ private AnvilGUI(
boolean geyserCompatibility,
Set<Integer> interactableSlots,
Consumer<StateSnapshot> closeListener,
BiFunction<String, StateSnapshot, ItemStack> renameVisitor,
boolean concurrentClickHandlerExecution,
ClickHandler clickHandler) {
this.plugin = plugin;
Expand All @@ -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
*/
Expand All @@ -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.
Expand Down Expand Up @@ -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<StateSnapshot> closeListener;

private BiFunction<String, StateSnapshot, ItemStack> 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 */
Expand Down Expand Up @@ -495,6 +513,12 @@ public Builder onClose(Consumer<StateSnapshot> closeListener) {
return this;
}

public Builder onRename(BiFunction<String, StateSnapshot, ItemStack> renameVisitor) {
Validate.notNull(renameVisitor, "renameVisitor cannot be null");
this.renameVisitor = renameVisitor;
return this;
}

/**
* Do an action when a slot is clicked in the inventory
* <p>
Expand Down Expand Up @@ -679,6 +703,7 @@ public AnvilGUI open(Player player) {
geyserCompatibility,
interactableSlots,
closeListener,
renameVisitor,
concurrentClickHandlerExecution,
clickHandler);
anvilGUI.openInventory();
Expand Down Expand Up @@ -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
*/
Expand All @@ -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
*
Expand Down Expand Up @@ -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();
}
}
}