items, @NotNull ItemStack item) {
- ItemMeta meta = item.getItemMeta();
- if (meta == null) {
- return null;
- }
-
- UUID uuid = meta.getPersistentDataContainer().get(GuiItem.KEY_UUID, UUIDTagType.INSTANCE);
- if (uuid == null) {
- return null;
+ for (T guiItem : items) {
+ if (matchesItem(guiItem, item)) {
+ return guiItem;
+ }
}
- return items.stream()
- .filter(guiItem -> guiItem.getUUID().equals(uuid))
- .findAny().orElse(null);
+ return null;
}
/**
@@ -615,7 +711,6 @@ public void setOnClick(@Nullable Consumer onClick) {
/**
* Calls the consumer (if it's not null) that was specified using {@link #setOnClick(Consumer)},
* so the consumer that should be called whenever this pane is clicked in.
- * Catches and logs all exceptions the consumer might throw.
*
* @param event the event to handle
* @since 0.6.0
@@ -624,17 +719,93 @@ protected void callOnClick(@NotNull InventoryClickEvent event) {
if (onClick == null) {
return;
}
-
+
+
try {
onClick.accept(event);
} catch (Throwable t) {
- Logger logger = JavaPlugin.getProvidingPlugin(getClass()).getLogger();
- logger.log(Level.SEVERE, "Exception while handling click event in inventory '"
- + event.getView().getTitle() + "', slot=" + event.getSlot() + ", for "
- + getClass().getSimpleName() + ", x=" + x + ", y=" + y + ", length=" + length + ", height=" + height, t);
+ throw new RuntimeException(
+ "Exception while handling click event in inventory '"
+ + InventoryViewUtil.getInstance().getTitle(event.getView()) + "', slot=" + event.getSlot() +
+ ", for " + getClass().getSimpleName() + ", x=" + getX() + ", y=" + getY()
+ + ", length=" + length + ", height=" + height,
+ t
+ );
}
}
+ /**
+ * Creates a pane which displays as a border around the outside of the pane consisting of the provided item. The
+ * slot, length and height parameters are used for the respective properties of the pane. If either the length or
+ * height is negative an {@link IllegalArgumentException} will be thrown.
+ *
+ * @param slot the slot of the pane
+ * @param length the length of the pane
+ * @param height the height of the pane
+ * @param item the item of which the border is made
+ * @return the created pane which displays a border
+ * @since 0.10.8
+ * @throws IllegalArgumentException if length or height is negative
+ */
+ @NotNull
+ @Contract(pure = true)
+ public static Pane createBorder(Slot slot, int length, int height, @NotNull GuiItem item) {
+ if (length < 0) {
+ throw new IllegalArgumentException("Length should be non-negative");
+ }
+
+ if (height < 0) {
+ throw new IllegalArgumentException("Height should be non-negative");
+ }
+
+ String[] mask = new String[height];
+
+ if (height > 0) {
+ mask[0] = createLine(length);
+ }
+
+ if (height > 1) {
+ mask[height - 1] = createLine(length);
+ }
+
+ for (int yIndex = 1; yIndex < height - 1; yIndex++) {
+ StringBuilder builder = new StringBuilder("1");
+
+ for (int i = 0; i < length - 2; i++) {
+ builder.append('0');
+ }
+
+ mask[yIndex] = builder.append('1').toString();
+ }
+
+ OutlinePane pane = new OutlinePane(slot, length, height);
+ pane.applyMask(new Mask(mask));
+ pane.addItem(item);
+ pane.setRepeat(true);
+
+ return pane;
+ }
+
+ /**
+ * Creates a pane which displays as a border around the outside of the pane consisting of the provided item. The x,
+ * y, length and height parameters are used for the respective properties of the pane. If either the length or
+ * height is negative an {@link IllegalArgumentException} will be thrown.
+ *
+ * @param x the x coordinate of the pane
+ * @param y the y coordinate of the pane
+ * @param length the length of the pane
+ * @param height the height of the pane
+ * @param item the item of which the border is made
+ * @return the created pane which displays a border
+ * @since 0.10.7
+ * @throws IllegalArgumentException if length or height is negative
+ */
+ @NotNull
+ @Contract(pure = true)
+ public static Pane createBorder(int x, int y, int length, int height, @NotNull GuiItem item) {
+ return createBorder(Slot.fromXY(x, y), length, height, item);
+ }
+
/**
* Registers a property that can be used inside an XML file to add additional new properties.
* The use of {@link Gui#registerProperty(String, Function)} is preferred over this method.
@@ -653,6 +824,31 @@ public static void registerProperty(@NotNull String attributeName, @NotNull Func
PROPERTY_MAPPINGS.put(attributeName, function);
}
+ /**
+ * Creates a string containing the character '1' repeated length amount of times. If the provided length is negative
+ * an {@link IllegalArgumentException} will be thrown.
+ *
+ * @param length the length of the string
+ * @return the string containing '1's
+ * @since 0.10.7
+ * @throws IllegalArgumentException if length is negative
+ */
+ @NotNull
+ @Contract(pure = true)
+ private static String createLine(int length) {
+ if (length < 0) {
+ throw new IllegalArgumentException("Length should be non-negative");
+ }
+
+ StringBuilder builder = new StringBuilder();
+
+ for (int i = 0; i < length; i++) {
+ builder.append('1');
+ }
+
+ return builder.toString();
+ }
+
/**
* An enum representing the rendering priorities for the panes. Uses a similar system to Bukkit's
* {@link org.bukkit.event.EventPriority} system
diff --git a/IF/src/main/java/com/github/stefvanschie/inventoryframework/pane/PatternPane.java b/IF/src/main/java/com/github/stefvanschie/inventoryframework/pane/PatternPane.java
index 4adde932e..86a02db3a 100644
--- a/IF/src/main/java/com/github/stefvanschie/inventoryframework/pane/PatternPane.java
+++ b/IF/src/main/java/com/github/stefvanschie/inventoryframework/pane/PatternPane.java
@@ -5,9 +5,12 @@
import com.github.stefvanschie.inventoryframework.gui.InventoryComponent;
import com.github.stefvanschie.inventoryframework.gui.type.util.Gui;
import com.github.stefvanschie.inventoryframework.pane.util.Pattern;
+import com.github.stefvanschie.inventoryframework.pane.util.Slot;
import com.github.stefvanschie.inventoryframework.util.GeometryUtil;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.ItemStack;
+import org.bukkit.plugin.Plugin;
+import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.w3c.dom.Element;
@@ -54,27 +57,42 @@ public class PatternPane extends Pane implements Flippable, Rotatable {
/**
* Constructs a new pattern pane.
*
- * @param x the upper left x coordinate of the pane
- * @param y the upper left y coordinate of the pane
+ * @param slot the slot of the pane
* @param length the length of the pane
* @param height the height of the pane
* @param priority the priority of the pane
* @param pattern the pattern of the pane
* @throws IllegalArgumentException when the pane and pattern dimensions don't match
- * @since 0.9.8
+ * @since 0.10.8
*/
- public PatternPane(int x, int y, int length, int height, @NotNull Priority priority, @NotNull Pattern pattern) {
- super(x, y, length, height, priority);
+ public PatternPane(@NotNull Slot slot, int length, int height, @NotNull Priority priority, @NotNull Pattern pattern) {
+ super(slot, length, height, priority);
if (pattern.getLength() != length || pattern.getHeight() != height) {
throw new IllegalArgumentException(
- "Dimensions of the provided pattern do not match the dimensions of the pane"
+ "Dimensions of the provided pattern do not match the dimensions of the pane"
);
}
this.pattern = pattern;
}
+ /**
+ * Constructs a new pattern pane.
+ *
+ * @param x the upper left x coordinate of the pane
+ * @param y the upper left y coordinate of the pane
+ * @param length the length of the pane
+ * @param height the height of the pane
+ * @param priority the priority of the pane
+ * @param pattern the pattern of the pane
+ * @throws IllegalArgumentException when the pane and pattern dimensions don't match
+ * @since 0.9.8
+ */
+ public PatternPane(int x, int y, int length, int height, @NotNull Priority priority, @NotNull Pattern pattern) {
+ this(Slot.fromXY(x, y), length, height, priority, pattern);
+ }
+
/**
* Constructs a new pattern pane, with no position.
*
@@ -88,6 +106,20 @@ public PatternPane(int length, int height, @NotNull Pattern pattern) {
this(0, 0, length, height, pattern);
}
+ /**
+ * Constructs a new pattern pane.
+ *
+ * @param slot the slot of the pane
+ * @param length the length of the pane
+ * @param height the height of the pane
+ * @param pattern the pattern of the pane
+ * @throws IllegalArgumentException when the pane and pattern dimensions don't match
+ * @since 0.10.8
+ */
+ public PatternPane(@NotNull Slot slot, int length, int height, @NotNull Pattern pattern) {
+ this(slot, length, height, Priority.NORMAL, pattern);
+ }
+
/**
* Constructs a new pattern pane.
*
@@ -133,8 +165,10 @@ public void display(@NotNull InventoryComponent inventoryComponent, int paneOffs
newX = coordinates.getKey();
newY = coordinates.getValue();
- int finalRow = getY() + newY + paneOffsetY;
- int finalColumn = getX() + newX + paneOffsetX;
+ Slot slot = getSlot();
+
+ int finalRow = slot.getY(maxLength) + newY + paneOffsetY;
+ int finalColumn = slot.getX(maxLength) + newX + paneOffsetX;
inventoryComponent.setItem(item, finalColumn, finalRow);
}
@@ -148,10 +182,17 @@ public boolean click(@NotNull Gui gui, @NotNull InventoryComponent inventoryComp
int length = Math.min(this.length, maxLength);
int height = Math.min(this.height, maxHeight);
- int adjustedSlot = slot - (getX() + paneOffsetX) - inventoryComponent.getLength() * (getY() + paneOffsetY);
+ Slot paneSlot = getSlot();
+
+ int xPosition = paneSlot.getX(maxLength);
+ int yPosition = paneSlot.getY(maxLength);
+
+ int totalLength = inventoryComponent.getLength();
+
+ int adjustedSlot = slot - (xPosition + paneOffsetX) - totalLength * (yPosition + paneOffsetY);
- int x = adjustedSlot % inventoryComponent.getLength();
- int y = adjustedSlot / inventoryComponent.getLength();
+ int x = adjustedSlot % totalLength;
+ int y = adjustedSlot / totalLength;
//this isn't our item
if (x < 0 || x >= length || y < 0 || y >= height) {
@@ -181,16 +222,16 @@ public boolean click(@NotNull Gui gui, @NotNull InventoryComponent inventoryComp
@Contract(pure = true)
@Override
public PatternPane copy() {
- PatternPane patternPane = new PatternPane(getX(), getY(), getLength(), getHeight(), getPriority(), getPattern());
+ PatternPane patternPane = new PatternPane(getSlot(), getLength(), getHeight(), getPriority(), getPattern());
patternPane.setVisible(isVisible());
patternPane.onClick = onClick;
patternPane.uuid = uuid;
- patternPane.setRotation(getRotation());
- patternPane.flipHorizontally(isFlippedHorizontally());
- patternPane.flipVertically(isFlippedVertically());
+ patternPane.rotation = rotation;
+ patternPane.flippedHorizontally = flippedHorizontally;
+ patternPane.flippedVertically = flippedVertically;
return patternPane;
}
@@ -339,11 +380,13 @@ public int getRotation() {
* Loads a pattern pane from a given element
*
* @param instance the instance class
- * @param element the element
+ * @param element the element
+ * @param plugin the plugin that will own the underlying items
* @return the pattern pane
+ * @since 0.10.8
*/
@NotNull
- public static PatternPane load(@NotNull Object instance, @NotNull Element element) {
+ public static PatternPane load(@NotNull Object instance, @NotNull Element element, @NotNull Plugin plugin) {
try {
NodeList childNodes = element.getChildNodes();
@@ -387,7 +430,7 @@ public static PatternPane load(@NotNull Object instance, @NotNull Element elemen
throw new XMLLoadException("Binding has multiple inner tags, one expected");
}
- guiItem = Pane.loadItem(instance, (Element) guiItemNode);
+ guiItem = Pane.loadItem(instance, (Element) guiItemNode, plugin);
}
//guaranteed to only be a single code point
@@ -422,4 +465,19 @@ public static PatternPane load(@NotNull Object instance, @NotNull Element elemen
throw new XMLLoadException(exception);
}
}
+
+ /**
+ * Loads a pattern pane from a given element
+ *
+ * @param instance the instance class
+ * @param element the element
+ * @return the pattern pane
+ * @deprecated this method is no longer used internally and has been superseded by
+ * {@link #load(Object, Element, Plugin)}
+ */
+ @NotNull
+ @Deprecated
+ public static PatternPane load(@NotNull Object instance, @NotNull Element element) {
+ return load(instance, element, JavaPlugin.getProvidingPlugin(PatternPane.class));
+ }
}
diff --git a/IF/src/main/java/com/github/stefvanschie/inventoryframework/pane/StaticPane.java b/IF/src/main/java/com/github/stefvanschie/inventoryframework/pane/StaticPane.java
index b77249f35..1661708a0 100644
--- a/IF/src/main/java/com/github/stefvanschie/inventoryframework/pane/StaticPane.java
+++ b/IF/src/main/java/com/github/stefvanschie/inventoryframework/pane/StaticPane.java
@@ -4,9 +4,12 @@
import com.github.stefvanschie.inventoryframework.gui.type.util.Gui;
import com.github.stefvanschie.inventoryframework.gui.GuiItem;
import com.github.stefvanschie.inventoryframework.exception.XMLLoadException;
+import com.github.stefvanschie.inventoryframework.pane.util.Slot;
import com.github.stefvanschie.inventoryframework.util.GeometryUtil;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.ItemStack;
+import org.bukkit.plugin.Plugin;
+import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -19,6 +22,12 @@
/**
* A pane for static items and stuff. All items will have to be specified a slot, or will be added in the next position.
+ *
+ * This pane allows you to specify the positions of the items either in the form of an x and y coordinate pair or as an
+ * index, in which case the indexing starts from the top left and continues to the right and bottom, with the horizontal
+ * axis taking priority. There are nuances at play with regard to mixing these two types of positioning systems within
+ * the same pane. It's recommended to only use one of these systems per pane and to not mix them.
+ *
*/
public class StaticPane extends Pane implements Flippable, Rotatable {
@@ -27,7 +36,7 @@ public class StaticPane extends Pane implements Flippable, Rotatable {
* the key and the y coordinate is the value.
*/
@NotNull
- private final Map, GuiItem> items;
+ private final Map items;
/**
* The clockwise rotation of this pane in degrees
@@ -39,12 +48,37 @@ public class StaticPane extends Pane implements Flippable, Rotatable {
*/
private boolean flipHorizontally, flipVertically;
- public StaticPane(int x, int y, int length, int height, @NotNull Priority priority) {
- super(x, y, length, height, priority);
+ /**
+ * Creates a new static pane.
+ *
+ * @param slot the slot of the pane
+ * @param length the length of the pane
+ * @param height the height of the pane
+ * @param priority the priority of the pane
+ * @since 0.10.8
+ */
+ public StaticPane(Slot slot, int length, int height, @NotNull Priority priority) {
+ super(slot, length, height, priority);
this.items = new HashMap<>(length * height);
}
+ public StaticPane(int x, int y, int length, int height, @NotNull Priority priority) {
+ this(Slot.fromXY(x, y), length, height, priority);
+ }
+
+ /**
+ * Creates a new static pane.
+ *
+ * @param slot the slot of the pane
+ * @param length the length of the pane
+ * @param height the height of the pane
+ * @since 0.10.8
+ */
+ public StaticPane(Slot slot, int length, int height) {
+ this(slot, length, height, Priority.NORMAL);
+ }
+
public StaticPane(int x, int y, int length, int height) {
this(x, y, length, height, Priority.NORMAL);
}
@@ -53,6 +87,18 @@ public StaticPane(int length, int height) {
this(0, 0, length, height);
}
+ /**
+ * {@inheritDoc}
+ *
+ * If there are multiple items in the same position when displaying the items, either one of those items may be
+ * shown. In particular, there is no guarantee that a specific item will be shown.
+ *
+ * @param inventoryComponent {@inheritDoc}
+ * @param paneOffsetX {@inheritDoc}
+ * @param paneOffsetY {@inheritDoc}
+ * @param maxLength {@inheritDoc}
+ * @param maxHeight {@inheritDoc}
+ */
@Override
public void display(@NotNull InventoryComponent inventoryComponent, int paneOffsetX, int paneOffsetY, int maxLength,
int maxHeight) {
@@ -60,9 +106,10 @@ public void display(@NotNull InventoryComponent inventoryComponent, int paneOffs
int height = Math.min(this.height, maxHeight);
items.entrySet().stream().filter(entry -> entry.getValue().isVisible()).forEach(entry -> {
- Map.Entry location = entry.getKey();
+ Slot location = entry.getKey();
- int x = location.getKey(), y = location.getValue();
+ int x = location.getX(getLength());
+ int y = location.getY(getLength());
if (flipHorizontally)
x = length - x - 1;
@@ -82,27 +129,41 @@ public void display(@NotNull InventoryComponent inventoryComponent, int paneOffs
GuiItem item = entry.getValue();
- int finalRow = getY() + y + paneOffsetY;
- int finalColumn = getX() + x + paneOffsetX;
+ Slot slot = getSlot();
+ int finalRow = slot.getY(maxLength) + y + paneOffsetY;
+ int finalColumn = slot.getX(maxLength) + x + paneOffsetX;
inventoryComponent.setItem(item, finalColumn, finalRow);
});
}
/**
- * Adds a gui item at the specific spot in the pane. If the coordinates as specified by the x and y parameters is
- * already occupied, that item will be replaced by the item parameter.
+ * Adds a gui item at the specific spot in the pane. If there is another item specified in terms of x and y
+ * coordinates that are equal to the coordinates of this item, the old item will be overwritten by this item.
*
* @param item the item to set
* @param x the x coordinate of the position of the item
* @param y the y coordinate of the position of the item
*/
public void addItem(@NotNull GuiItem item, int x, int y) {
- items.keySet().removeIf(entry -> entry.getKey() == x && entry.getValue() == y);
-
- items.put(new AbstractMap.SimpleEntry<>(x, y), item);
+ addItem(item, Slot.fromXY(x, y));
}
+ /**
+ * Adds a gui item at the specific spot in the pane. If the slot is specified in terms of an x and y coordinate pair
+ * and this pane contains another item whose position is specified as such and these positions are equal, the old
+ * item will be overwritten by this item. If the slot is specified in terms of an index and this pane contains
+ * another item whose position is specified as such and these positions are equal, the old item will be overwritten
+ * by this item.
+ *
+ * @param item the item to set
+ * @param slot the position of the item
+ * @since 0.10.8
+ */
+ public void addItem(@NotNull GuiItem item, Slot slot) {
+ this.items.put(slot, item);
+ }
+
/**
* Removes the specified item from the pane
*
@@ -113,6 +174,29 @@ public void removeItem(@NotNull GuiItem item) {
items.values().removeIf(guiItem -> guiItem.equals(item));
}
+ /**
+ * Removes the specified item from the pane. This will only remove items whose slot was specified in terms of an x
+ * and y coordinate pair which matches the coordinate specified.
+ *
+ * @param x the x coordinate of the item to remove
+ * @param y the y coordinate of the item to remove
+ * @since 0.10.0
+ */
+ public void removeItem(int x, int y) {
+ this.items.remove(Slot.fromXY(x, y));
+ }
+
+ /**
+ * Removes the specified item from the pane. This will only remove items whose slot was specified in the same way as
+ * the original slot and whose slot positions match.
+ *
+ * @param slot the slot of the item to remove
+ * @since 0.10.8
+ */
+ public void removeItem(@NotNull Slot slot) {
+ this.items.remove(slot);
+ }
+
@Override
public boolean click(@NotNull Gui gui, @NotNull InventoryComponent inventoryComponent,
@NotNull InventoryClickEvent event, int slot, int paneOffsetX, int paneOffsetY, int maxLength,
@@ -120,10 +204,17 @@ public boolean click(@NotNull Gui gui, @NotNull InventoryComponent inventoryComp
int length = Math.min(this.length, maxLength);
int height = Math.min(this.height, maxHeight);
- int adjustedSlot = slot - (getX() + paneOffsetX) - inventoryComponent.getLength() * (getY() + paneOffsetY);
+ Slot paneSlot = getSlot();
+
+ int xPosition = paneSlot.getX(maxLength);
+ int yPosition = paneSlot.getY(maxLength);
+
+ int totalLength = inventoryComponent.getLength();
- int x = adjustedSlot % inventoryComponent.getLength();
- int y = adjustedSlot / inventoryComponent.getLength();
+ int adjustedSlot = slot - (xPosition + paneOffsetX) - totalLength * (yPosition + paneOffsetY);
+
+ int x = adjustedSlot % totalLength;
+ int y = adjustedSlot / totalLength;
//this isn't our item
if (x < 0 || x >= length || y < 0 || y >= height) {
@@ -153,12 +244,10 @@ public boolean click(@NotNull Gui gui, @NotNull InventoryComponent inventoryComp
@Contract(pure = true)
@Override
public StaticPane copy() {
- StaticPane staticPane = new StaticPane(x, y, length, height, getPriority());
-
- for (Map.Entry, GuiItem> entry : items.entrySet()) {
- Map.Entry coordinates = entry.getKey();
+ StaticPane staticPane = new StaticPane(getSlot(), length, height, getPriority());
- staticPane.addItem(entry.getValue().copy(), coordinates.getKey(), coordinates.getValue());
+ for (Map.Entry entry : items.entrySet()) {
+ staticPane.addItem(entry.getValue().copy(), entry.getKey());
}
staticPane.setVisible(isVisible());
@@ -189,31 +278,45 @@ public void setRotation(int rotation) {
* Fills all empty space in the pane with the given {@code itemStack} and adds the given action
*
* @param itemStack The {@link ItemStack} to fill the empty space with
- * @param action The action called whenever an interaction with the item happens
- * @since 0.5.9
+ * @param action The action called whenever an interaction with the item happens
+ * @param plugin the plugin that will be the owner of the created items
+ * @see #fillWith(ItemStack, Consumer)
+ * @since 0.10.8
*/
- public void fillWith(@NotNull ItemStack itemStack, @Nullable Consumer action) {
+ public void fillWith(@NotNull ItemStack itemStack, @Nullable Consumer action,
+ @NotNull Plugin plugin) {
//The non empty spots
- Set> locations = this.items.keySet();
+ Set locations = this.items.keySet();
for (int y = 0; y < this.getHeight(); y++) {
for (int x = 0; x < this.getLength(); x++) {
boolean found = false;
- for (Map.Entry location : locations) {
- if (location.getKey() == x && location.getValue() == y) {
+ for (Slot location : locations) {
+ if (location.getX(getLength()) == x && location.getY(getLength()) == y) {
found = true;
break;
}
}
if (!found) {
- this.addItem(new GuiItem(itemStack, action), x, y);
+ this.addItem(new GuiItem(itemStack, action, plugin), x, y);
}
}
}
}
+ /**
+ * Fills all empty space in the pane with the given {@code itemStack} and adds the given action
+ *
+ * @param itemStack The {@link ItemStack} to fill the empty space with
+ * @param action The action called whenever an interaction with the item happens
+ * @since 0.5.9
+ */
+ public void fillWith(@NotNull ItemStack itemStack, @Nullable Consumer action) {
+ fillWith(itemStack, action, JavaPlugin.getProvidingPlugin(StaticPane.class));
+ }
+
/**
* Fills all empty space in the pane with the given {@code itemStack}
*
@@ -275,11 +378,13 @@ public boolean isFlippedVertically() {
* Loads an outline pane from a given element
*
* @param instance the instance class
- * @param element the element
+ * @param element the element
+ * @param plugin the plugin that will be the owner of the udnerlying items
* @return the outline pane
+ * @since 0.10.8
*/
@NotNull
- public static StaticPane load(@NotNull Object instance, @NotNull Element element) {
+ public static StaticPane load(@NotNull Object instance, @NotNull Element element, @NotNull Plugin plugin) {
try {
StaticPane staticPane = new StaticPane(
Integer.parseInt(element.getAttribute("length")),
@@ -303,8 +408,7 @@ public static StaticPane load(@NotNull Object instance, @NotNull Element element
Element child = (Element) item;
- staticPane.addItem(Pane.loadItem(instance, child), Integer.parseInt(child.getAttribute("x")),
- Integer.parseInt(child.getAttribute("y")));
+ staticPane.addItem(Pane.loadItem(instance, child, plugin), Slot.deserialize(child));
}
return staticPane;
@@ -312,4 +416,19 @@ public static StaticPane load(@NotNull Object instance, @NotNull Element element
throw new XMLLoadException(exception);
}
}
+
+ /**
+ * Loads an outline pane from a given element
+ *
+ * @param instance the instance class
+ * @param element the element
+ * @return the outline pane
+ * @deprecated this method is no longer used internally and has been superseded by
+ * {@link #load(Object, Element, Plugin)}
+ */
+ @NotNull
+ @Deprecated
+ public static StaticPane load(@NotNull Object instance, @NotNull Element element) {
+ return load(instance, element, JavaPlugin.getProvidingPlugin(StaticPane.class));
+ }
}
diff --git a/IF/src/main/java/com/github/stefvanschie/inventoryframework/pane/component/CycleButton.java b/IF/src/main/java/com/github/stefvanschie/inventoryframework/pane/component/CycleButton.java
index 709d70284..dbe60c9e9 100644
--- a/IF/src/main/java/com/github/stefvanschie/inventoryframework/pane/component/CycleButton.java
+++ b/IF/src/main/java/com/github/stefvanschie/inventoryframework/pane/component/CycleButton.java
@@ -5,7 +5,10 @@
import com.github.stefvanschie.inventoryframework.gui.GuiItem;
import com.github.stefvanschie.inventoryframework.exception.XMLLoadException;
import com.github.stefvanschie.inventoryframework.pane.Pane;
+import com.github.stefvanschie.inventoryframework.pane.util.Slot;
import org.bukkit.event.inventory.InventoryClickEvent;
+import org.bukkit.plugin.Plugin;
+import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.w3c.dom.Element;
@@ -32,10 +35,35 @@ public class CycleButton extends Pane {
*/
private int position = 0;
+ /**
+ * Creates a new cycle button
+ *
+ * @param slot the slot of the button
+ * @param length the length of the button
+ * @param height the height of the button
+ * @param priority the priority of the button
+ * @since 0.10.8
+ */
+ public CycleButton(@NotNull Slot slot, int length, int height, @NotNull Priority priority) {
+ super(slot, length, height, priority);
+ }
+
public CycleButton(int x, int y, int length, int height, @NotNull Priority priority) {
super(x, y, length, height, priority);
}
+ /**
+ * Creates a new cycle button
+ *
+ * @param slot the slot of the button
+ * @param length the length of the button
+ * @param height the height of the button
+ * @since 0.10.8
+ */
+ public CycleButton(@NotNull Slot slot, int length, int height) {
+ super(slot, length, height);
+ }
+
public CycleButton(int x, int y, int length, int height) {
super(x, y, length, height);
}
@@ -51,16 +79,25 @@ public boolean click(@NotNull Gui gui, @NotNull InventoryComponent inventoryComp
int length = Math.min(this.length, maxLength);
int height = Math.min(this.height, maxHeight);
- int adjustedSlot = slot - (getX() + paneOffsetX) - inventoryComponent.getLength() * (getY() + paneOffsetY);
+ Slot paneSlot = getSlot();
+
+ int xPosition = paneSlot.getX(maxLength);
+ int yPosition = paneSlot.getY(maxLength);
+
+ int totalLength = inventoryComponent.getLength();
- int x = adjustedSlot % inventoryComponent.getLength();
- int y = adjustedSlot / inventoryComponent.getLength();
+ int adjustedSlot = slot - (xPosition + paneOffsetX) - totalLength * (yPosition + paneOffsetY);
+
+ int x = adjustedSlot % totalLength;
+ int y = adjustedSlot / totalLength;
//this isn't our item
if (x < 0 || x >= length || y < 0 || y >= height) {
return false;
}
+ int previousPosition = position;
+
position++;
if (position == panes.size()) {
@@ -69,7 +106,8 @@ public boolean click(@NotNull Gui gui, @NotNull InventoryComponent inventoryComp
callOnClick(event);
- Pane pane = panes.get(position);
+ //use the previous position, since that will have the pane we clicked on
+ Pane pane = panes.get(previousPosition);
pane.click(gui, inventoryComponent, event, slot, paneOffsetX + x, paneOffsetY + y,
length, height);
@@ -81,8 +119,10 @@ public boolean click(@NotNull Gui gui, @NotNull InventoryComponent inventoryComp
@Override
public void display(@NotNull InventoryComponent inventoryComponent, int paneOffsetX, int paneOffsetY, int maxLength,
int maxHeight) {
- int newX = paneOffsetX + x;
- int newY = paneOffsetY + y;
+ Slot slot = getSlot();
+
+ int newX = paneOffsetX + slot.getX(maxLength);
+ int newY = paneOffsetY + slot.getY(maxLength);
int newMaxLength = Math.min(maxLength, length);
int newMaxHeight = Math.min(maxHeight, height);
@@ -94,7 +134,7 @@ public void display(@NotNull InventoryComponent inventoryComponent, int paneOffs
@Contract(pure = true)
@Override
public CycleButton copy() {
- CycleButton cycleButton = new CycleButton(x, y, length, height, getPriority());
+ CycleButton cycleButton = new CycleButton(getSlot(), length, height, getPriority());
for (Pane pane : panes) {
cycleButton.addPane(pane);
@@ -162,11 +202,12 @@ public void cycle() {
*
* @param instance the instance class
* @param element the element
+ * @param plugin the plugin that will be the owner of the underlying items
* @return the cycle button
- * @since 0.5.0
+ * @since 0.10.8
*/
@NotNull
- public static CycleButton load(@NotNull Object instance, @NotNull Element element) {
+ public static CycleButton load(@NotNull Object instance, @NotNull Element element, @NotNull Plugin plugin) {
int length;
int height;
@@ -194,9 +235,25 @@ public static CycleButton load(@NotNull Object instance, @NotNull Element elemen
continue;
}
- cycleButton.addPane(Gui.loadPane(instance, pane));
+ cycleButton.addPane(Gui.loadPane(instance, pane, plugin));
}
return cycleButton;
}
+
+ /**
+ * Loads a cycle button from a given element
+ *
+ * @param instance the instance class
+ * @param element the element
+ * @return the cycle button
+ * @since 0.5.0
+ * @deprecated this method is no longer used internally and has been superseded by
+ * {@link #load(Object, Element, Plugin)}
+ */
+ @NotNull
+ @Deprecated
+ public static CycleButton load(@NotNull Object instance, @NotNull Element element) {
+ return load(instance, element, JavaPlugin.getProvidingPlugin(CycleButton.class));
+ }
}
diff --git a/IF/src/main/java/com/github/stefvanschie/inventoryframework/pane/component/Label.java b/IF/src/main/java/com/github/stefvanschie/inventoryframework/pane/component/Label.java
index 205315ad2..fda4a04df 100644
--- a/IF/src/main/java/com/github/stefvanschie/inventoryframework/pane/component/Label.java
+++ b/IF/src/main/java/com/github/stefvanschie/inventoryframework/pane/component/Label.java
@@ -6,12 +6,17 @@
import com.github.stefvanschie.inventoryframework.exception.XMLLoadException;
import com.github.stefvanschie.inventoryframework.font.util.Font;
import com.github.stefvanschie.inventoryframework.pane.*;
+import com.github.stefvanschie.inventoryframework.pane.util.Slot;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.ItemStack;
+import org.bukkit.plugin.Plugin;
+import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.w3c.dom.Element;
+import java.util.function.BiFunction;
+
/**
* A label for displaying text.
*
@@ -31,6 +36,113 @@ public class Label extends OutlinePane {
@NotNull
private String text;
+ /**
+ * The plugin to be sed for creating items
+ */
+ @NotNull
+ private final Plugin plugin;
+
+ /**
+ * Creates a new label
+ *
+ * @param slot the slot
+ * @param length the length
+ * @param height the height
+ * @param priority the priority
+ * @param font the character set
+ * @param plugin the plugin that will be the owner for this label's items
+ * @see #Label(int, int, int, int, Priority, Font)
+ * @since 0.10.8
+ */
+ public Label(@NotNull Slot slot, int length, int height, @NotNull Priority priority, @NotNull Font font,
+ @NotNull Plugin plugin) {
+ super(slot, length, height);
+
+ this.font = font;
+ this.text = "";
+
+ this.plugin = plugin;
+
+ setPriority(priority);
+ }
+
+ /**
+ * Creates a new label
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param length the length
+ * @param height the height
+ * @param priority the priority
+ * @param font the character set
+ * @param plugin the plugin that will be the owner for this label's items
+ * @see #Label(int, int, int, int, Priority, Font)
+ * @since 0.10.8
+ */
+ public Label(int x, int y, int length, int height, @NotNull Priority priority, @NotNull Font font,
+ @NotNull Plugin plugin) {
+ this(Slot.fromXY(x, y), length, height, priority, font, plugin);
+ }
+
+ /**
+ * Creates a new label
+ *
+ * @param slot the slot
+ * @param length the length
+ * @param height the height
+ * @param font the character set
+ * @param plugin the plugin that will be the owner for this label's items
+ * @see #Label(int, int, int, int, Font)
+ * @since 0.10.8
+ */
+ public Label(@NotNull Slot slot, int length, int height, @NotNull Font font, @NotNull Plugin plugin) {
+ this(slot, length, height, Priority.NORMAL, font, plugin);
+ }
+
+ /**
+ * Creates a new label
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param length the length
+ * @param height the height
+ * @param font the character set
+ * @param plugin the plugin that will be the owner for this label's items
+ * @see #Label(int, int, int, int, Font)
+ * @since 0.10.8
+ */
+ public Label(int x, int y, int length, int height, @NotNull Font font, @NotNull Plugin plugin) {
+ this(x, y, length, height, Priority.NORMAL, font, plugin);
+ }
+
+ /**
+ * Creates a new label
+ *
+ * @param length the length
+ * @param height the height
+ * @param font the character set
+ * @param plugin the plugin that will be the owner for this label's items
+ * @see #Label(int, int, Font)
+ * @since 0.10.8
+ */
+ public Label(int length, int height, @NotNull Font font, @NotNull Plugin plugin) {
+ this(0, 0, length, height, font, plugin);
+ }
+
+ /**
+ * Creates a new label
+ *
+ * @param slot the slot
+ * @param length the length
+ * @param height the height
+ * @param priority the priority
+ * @param font the character set
+ * @since 0.10.8
+ */
+ public Label(@NotNull Slot slot, int length, int height, @NotNull Priority priority, @NotNull Font font) {
+ this(slot, length, height, priority, font, JavaPlugin.getProvidingPlugin(Label.class));
+ }
+
/**
* Creates a new label
*
@@ -43,9 +155,20 @@ public class Label extends OutlinePane {
* @since 0.5.0
*/
public Label(int x, int y, int length, int height, @NotNull Priority priority, @NotNull Font font) {
- this(x, y, length, height, font);
+ this(x, y, length, height, priority, font, JavaPlugin.getProvidingPlugin(Label.class));
+ }
- setPriority(priority);
+ /**
+ * Creates a new label
+ *
+ * @param slot the slot
+ * @param length the length
+ * @param height the height
+ * @param font the character set
+ * @since 0.10.8
+ */
+ public Label(@NotNull Slot slot, int length, int height, @NotNull Font font) {
+ this(slot, length, height, Priority.NORMAL, font);
}
/**
@@ -59,10 +182,7 @@ public Label(int x, int y, int length, int height, @NotNull Priority priority, @
* @since 0.5.0
*/
public Label(int x, int y, int length, int height, @NotNull Font font) {
- this(length, height, font);
-
- this.x = x;
- this.y = y;
+ this(x, y, length, height, Priority.NORMAL, font);
}
/**
@@ -74,19 +194,22 @@ public Label(int x, int y, int length, int height, @NotNull Font font) {
* @since 0.5.0
*/
public Label(int length, int height, @NotNull Font font) {
- super(length, height);
-
- this.font = font;
- this.text = "";
+ this(0, 0, length, height, font);
}
/**
- * Sets the text to be displayed in this label
+ * Sets the text to be displayed in this label. If this label already had text, this text will be overwritten. The
+ * specified processor will be called for each character that is part of the specified text. The provided character
+ * will be the original character that was attempted to be shown - it is not subject to any transformations that may
+ * be applied for finding a valid item corresponding to this character, such as capitalization changes.
*
* @param text the new text
- * @since 0.5.0
+ * @param processor processes each character before using them
+ * @since 0.10.4
*/
- public void setText(@NotNull String text) {
+ public void setText(@NotNull String text,
+ @NotNull BiFunction super @NotNull Character, ? super @NotNull ItemStack,
+ ? extends @NotNull GuiItem> processor) {
this.text = text;
clear();
@@ -106,15 +229,26 @@ public void setText(@NotNull String text) {
item = font.getDefaultItem();
}
- addItem(new GuiItem(item));
+ addItem(processor.apply(character, item.clone()));
}
}
+ /**
+ * Sets the text to be displayed in this label. If this label already had text, this text will be overwritten.
+ *
+ * @param text the new text
+ * @see #setText(String, BiFunction)
+ * @since 0.5.0
+ */
+ public void setText(@NotNull String text) {
+ setText(text, (character, item) -> new GuiItem(item, this.plugin));
+ }
+
@NotNull
@Contract(pure = true)
@Override
public Label copy() {
- Label label = new Label(x, y, length, height, getPriority(), font);
+ Label label = new Label(getSlot(), length, height, getPriority(), font, this.plugin);
for (GuiItem item : getItems()) {
label.addItem(item.copy());
@@ -174,12 +308,14 @@ public Font getFont() {
* Loads a label from a given element
*
* @param instance the instance class
- * @param element the element
+ * @param element the element
+ * @param plugin the plugin that will be the owner of the underlying items
* @return the percentage bar
+ * @since 0.10.8
*/
@NotNull
@Contract(pure = true)
- public static Label load(@NotNull Object instance, @NotNull Element element) {
+ public static Label load(@NotNull Object instance, @NotNull Element element, @NotNull Plugin plugin) {
int length;
int height;
@@ -200,7 +336,7 @@ public static Label load(@NotNull Object instance, @NotNull Element element) {
throw new XMLLoadException("Incorrect font specified for label");
}
- Label label = new Label(length, height, font);
+ Label label = new Label(length, height, font, plugin);
Pane.load(label, instance, element);
Orientable.load(label, element);
@@ -217,4 +353,20 @@ public static Label load(@NotNull Object instance, @NotNull Element element) {
return label;
}
+
+ /**
+ * Loads a label from a given element
+ *
+ * @param instance the instance class
+ * @param element the element
+ * @return the percentage bar
+ * @deprecated this method is no longer used internally and has been superseded by
+ * {@link #load(Object, Element, Plugin)}
+ */
+ @NotNull
+ @Contract(pure = true)
+ @Deprecated
+ public static Label load(@NotNull Object instance, @NotNull Element element) {
+ return load(instance, element, JavaPlugin.getProvidingPlugin(Label.class));
+ }
}
diff --git a/IF/src/main/java/com/github/stefvanschie/inventoryframework/pane/component/PagingButtons.java b/IF/src/main/java/com/github/stefvanschie/inventoryframework/pane/component/PagingButtons.java
new file mode 100644
index 000000000..7458b5999
--- /dev/null
+++ b/IF/src/main/java/com/github/stefvanschie/inventoryframework/pane/component/PagingButtons.java
@@ -0,0 +1,395 @@
+package com.github.stefvanschie.inventoryframework.pane.component;
+
+import com.github.stefvanschie.inventoryframework.exception.XMLLoadException;
+import com.github.stefvanschie.inventoryframework.gui.GuiItem;
+import com.github.stefvanschie.inventoryframework.gui.InventoryComponent;
+import com.github.stefvanschie.inventoryframework.gui.type.util.Gui;
+import com.github.stefvanschie.inventoryframework.pane.PaginatedPane;
+import com.github.stefvanschie.inventoryframework.pane.Pane;
+import com.github.stefvanschie.inventoryframework.pane.util.Slot;
+import org.bukkit.Material;
+import org.bukkit.event.inventory.InventoryClickEvent;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.plugin.Plugin;
+import org.bukkit.plugin.java.JavaPlugin;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.w3c.dom.Element;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+
+/**
+ * An interface for interacting with {@link PaginatedPane}s. This gives two buttons for navigating backwards and
+ * forwards through the pages of the {@link PaginatedPane}. The backward button will be displayed at (0, 0) of this pane
+ * and the forward button will be displayed at (length - 1, 0) of this pane. If the paginated pane is at the first page
+ * or the last page, the backwards respectively the forward button will not show. This does not display the
+ * {@link PaginatedPane} itself, but is merely an interface for interacting with it.
+ *
+ * @since 0.10.14
+ */
+public class PagingButtons extends Pane {
+
+ /**
+ * The paginated pane.
+ */
+ @NotNull
+ private final PaginatedPane pages;
+
+ /**
+ * The backwards button.
+ */
+ @NotNull
+ private GuiItem backwardButton;
+
+ /**
+ * The forwards button.
+ */
+ @NotNull
+ private GuiItem forwardButton;
+
+ /**
+ * The plugin with which the items were created.
+ */
+ @NotNull
+ private final Plugin plugin;
+
+ /**
+ * Creates a new PagingButtons instance, which controls the provided {@link PaginatedPane}. The backward and forward
+ * item will be an arrow. If the length provided is less than 2, this will throw an
+ * {@link IllegalArgumentException}.
+ *
+ * @param slot the position of this interface
+ * @param length the length of this interface
+ * @param priority the priority of this interface
+ * @param pages the pages to interact with
+ * @param plugin the plugin that will be the owner of this interface's items
+ * @since 0.10.14
+ * @throws IllegalArgumentException if the length is less than 2
+ */
+ public PagingButtons(
+ @NotNull Slot slot,
+ int length,
+ @NotNull Priority priority,
+ @NotNull PaginatedPane pages,
+ @NotNull Plugin plugin
+ ) {
+ super(slot, length, 1, priority);
+
+ if (length < 2) {
+ throw new IllegalArgumentException("Length of paging buttons must be at least 2");
+ }
+
+ this.pages = pages;
+ this.plugin = plugin;
+
+ this.backwardButton = new GuiItem(new ItemStack(Material.ARROW), plugin);
+ this.forwardButton = new GuiItem(new ItemStack(Material.ARROW), plugin);
+ }
+
+ /**
+ * Creates a new PagingButtons instance, which controls the provided {@link PaginatedPane}. The backward and forward
+ * item will be an arrow. If the length provided is less than 2, this will throw an
+ * {@link IllegalArgumentException}.
+ *
+ * @param slot the position of this interface
+ * @param length the length of this interface
+ * @param priority the priority of this interface
+ * @param pages the pages to interact with
+ * @since 0.10.14
+ * @throws IllegalArgumentException if the length is less than 2
+ */
+ public PagingButtons(@NotNull Slot slot, int length, @NotNull Priority priority, @NotNull PaginatedPane pages) {
+ this(slot, length, priority, pages, JavaPlugin.getProvidingPlugin(PagingButtons.class));
+ }
+
+ /**
+ * Creates a new PagingButtons instance, which controls the provided {@link PaginatedPane}. The backward and forward
+ * item will be an arrow. If the length provided is less than 2, this will throw an
+ * {@link IllegalArgumentException}.
+ *
+ * @param slot the position of this interface
+ * @param length the length of this interface
+ * @param pages the pages to interact with
+ * @param plugin the plugin that will be the owner of this interface's items
+ * @since 0.10.14
+ * @throws IllegalArgumentException if the length is less than 2
+ */
+ public PagingButtons(@NotNull Slot slot, int length, @NotNull PaginatedPane pages, @NotNull Plugin plugin) {
+ this(slot, length, Priority.NORMAL, pages, plugin);
+ }
+
+ /**
+ * Creates a new PagingButtons instance, which controls the provided {@link PaginatedPane}. The backward and forward
+ * item will be an arrow. If the length provided is less than 2, this will throw an
+ * {@link IllegalArgumentException}.
+ *
+ * @param slot the position of this interface
+ * @param length the length of this interface
+ * @param pages the pages to interact with
+ * @since 0.10.14
+ * @throws IllegalArgumentException if the length is less than 2
+ */
+ public PagingButtons(@NotNull Slot slot, int length, @NotNull PaginatedPane pages) {
+ this(slot, length, Priority.NORMAL, pages);
+ }
+
+ /**
+ * Creates a new PagingButtons instance, which controls the provided {@link PaginatedPane}. The backward and forward
+ * item will be an arrow. If the length provided is less than 2, this will throw an
+ * {@link IllegalArgumentException}.
+ *
+ * @param length the length of this interface
+ * @param priority the priority of this interface
+ * @param pages the pages to interact with
+ * @param plugin the plugin that will be the owner of this interface's items
+ * @since 0.10.14
+ * @throws IllegalArgumentException if the length is less than 2
+ */
+ public PagingButtons(int length, @NotNull Priority priority, @NotNull PaginatedPane pages, @NotNull Plugin plugin) {
+ this(Slot.fromXY(0, 0), length, priority, pages, plugin);
+ }
+
+ /**
+ * Creates a new PagingButtons instance, which controls the provided {@link PaginatedPane}. The backward and forward
+ * item will be an arrow. If the length provided is less than 2, this will throw an
+ * {@link IllegalArgumentException}.
+ *
+ * @param length the length of this interface
+ * @param priority the priority of this interface
+ * @param pages the pages to interact with
+ * @since 0.10.14
+ * @throws IllegalArgumentException if the length is less than 2
+ */
+ public PagingButtons(int length, @NotNull Priority priority, @NotNull PaginatedPane pages) {
+ this(Slot.fromXY(0, 0), length, priority, pages, JavaPlugin.getProvidingPlugin(PagingButtons.class));
+ }
+
+ /**
+ * Creates a new PagingButtons instance, which controls the provided {@link PaginatedPane}. The backward and forward
+ * item will be an arrow. If the length provided is less than 2, this will throw an
+ * {@link IllegalArgumentException}.
+ *
+ * @param length the length of this interface
+ * @param pages the pages to interact with
+ * @param plugin the plugin that will be the owner of this interface's items
+ * @since 0.10.14
+ * @throws IllegalArgumentException if the length is less than 2
+ */
+ public PagingButtons(int length, @NotNull PaginatedPane pages, @NotNull Plugin plugin) {
+ this(Slot.fromXY(0, 0), length, Priority.NORMAL, pages, plugin);
+ }
+
+ /**
+ * Creates a new PagingButtons instance, which controls the provided {@link PaginatedPane}. The backward and forward
+ * item will be an arrow. If the length provided is less than 2, this will throw an
+ * {@link IllegalArgumentException}.
+ *
+ * @param length the length of this interface
+ * @param pages the pages to interact with
+ * @since 0.10.14
+ * @throws IllegalArgumentException if the length is less than 2
+ */
+ public PagingButtons(int length, @NotNull PaginatedPane pages) {
+ this(Slot.fromXY(0, 0), length, Priority.NORMAL, pages);
+ }
+
+ @Override
+ public boolean click(
+ @NotNull Gui gui,
+ @NotNull InventoryComponent inventoryComponent,
+ @NotNull InventoryClickEvent event,
+ int slot,
+ int paneOffsetX,
+ int paneOffsetY,
+ int maxLength,
+ int maxHeight
+ ) {
+ int length = Math.min(this.length, maxLength);
+ int height = Math.min(this.height, maxHeight);
+
+ Slot paneSlot = getSlot();
+
+ int xPosition = paneSlot.getX(maxLength);
+ int yPosition = paneSlot.getY(maxLength);
+
+ int totalLength = inventoryComponent.getLength();
+
+ int adjustedSlot = slot - (xPosition + paneOffsetX) - totalLength * (yPosition + paneOffsetY);
+
+ int x = adjustedSlot % totalLength;
+ int y = adjustedSlot / totalLength;
+
+ //this isn't our item
+ if (x < 0 || x >= length || y < 0 || y >= height) {
+ return false;
+ }
+
+ callOnClick(event);
+
+ ItemStack itemStack = event.getCurrentItem();
+
+ if (itemStack == null) {
+ return false;
+ }
+
+ if (matchesItem(this.backwardButton, itemStack)) {
+ this.pages.setPage(this.pages.getPage() - 1);
+
+ this.backwardButton.callAction(event);
+
+ gui.update();
+
+ return true;
+ }
+
+ if (matchesItem(this.forwardButton, itemStack)) {
+ this.pages.setPage(this.pages.getPage() + 1);
+
+ this.forwardButton.callAction(event);
+
+ gui.update();
+
+ return true;
+ }
+
+ return false;
+ }
+
+ @Override
+ public void display(
+ @NotNull InventoryComponent inventoryComponent,
+ int paneOffsetX,
+ int paneOffsetY,
+ int maxLength,
+ int maxHeight
+ ) {
+ int length = Math.min(getLength(), maxLength);
+
+ int x = super.slot.getX(length) + paneOffsetX;
+ int y = super.slot.getY(length) + paneOffsetY;
+
+ if (this.pages.getPage() > 0) {
+ inventoryComponent.setItem(this.backwardButton, x, y);
+ }
+
+ if (this.pages.getPage() < this.pages.getPages() - 1) {
+ inventoryComponent.setItem(this.forwardButton, x + length - 1, y);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * This does not make a copy of the {@link PaginatedPane} that is being controlled by this interface.
+ */
+ @NotNull
+ @Contract(pure = true)
+ @Override
+ public PagingButtons copy() {
+ PagingButtons pagingButtons = new PagingButtons(getSlot(), getLength(), getPriority(), this.pages, this.plugin);
+
+ pagingButtons.setVisible(isVisible());
+ pagingButtons.onClick = super.onClick;
+
+ pagingButtons.uuid = super.uuid;
+
+ pagingButtons.backwardButton = this.backwardButton.copy();
+ pagingButtons.forwardButton = this.forwardButton.copy();
+
+ return pagingButtons;
+ }
+
+ @NotNull
+ @Contract(pure = true)
+ @Override
+ public Collection getItems() {
+ Collection items = new HashSet<>();
+
+ items.add(this.backwardButton);
+ items.add(this.forwardButton);
+
+ return Collections.unmodifiableCollection(items);
+ }
+
+ /**
+ * Sets the item to be used for navigating backwards. If an event is attached to the item, this event will be called
+ * after the page has been changed.
+ *
+ * @param item the new backward item
+ * @since 0.10.14
+ */
+ public void setBackwardButton(@NotNull GuiItem item) {
+ this.backwardButton = item;
+ }
+
+ /**
+ * Sets the item to be used for navigating forwards. If an event is attached to the item, this event will be called
+ * after the page has been changed.
+ *
+ * @param item the new forward item
+ * @since 0.10.14
+ */
+ public void setForwardButton(@NotNull GuiItem item) {
+ this.forwardButton = item;
+ }
+
+ @NotNull
+ @Contract(pure = true)
+ @Override
+ public Collection getPanes() {
+ return Collections.emptySet();
+ }
+
+ /**
+ * This is a no-op.
+ *
+ * @since 0.10.14
+ */
+ @Override
+ public void clear() {}
+
+ /**
+ * Loads a paging buttons pane from an XML element.
+ *
+ * @param instance the instance class
+ * @param element the element
+ * @param plugin the plugin that will be the owner of the underlying items
+ * @return the paging buttons pane
+ * @since 0.10.14
+ */
+ @NotNull
+ @Contract(pure = true)
+ public static PagingButtons load(@NotNull Object instance, @NotNull Element element, @NotNull Plugin plugin) {
+ int length;
+
+ try {
+ length = Integer.parseInt(element.getAttribute("length"));
+ } catch (NumberFormatException exception) {
+ throw new XMLLoadException(exception);
+ }
+
+ if (!element.hasAttribute("pages")) {
+ throw new XMLLoadException("Paging buttons does not have pages attribute");
+ }
+
+ Element paginatedPaneElement = element.getOwnerDocument().getElementById(element.getAttribute("pages"));
+
+ if (paginatedPaneElement == null) {
+ throw new XMLLoadException("Paging buttons pages reference is invalid");
+ }
+
+ Object paginatedPane = paginatedPaneElement.getUserData("pane");
+
+ if (!(paginatedPane instanceof PaginatedPane)) {
+ throw new XMLLoadException("Retrieved data is not a paginated pane");
+ }
+
+ PagingButtons pagingButtons = new PagingButtons(length, (PaginatedPane) paginatedPane);
+
+ Pane.load(pagingButtons, instance, element);
+
+ return pagingButtons;
+ }
+}
diff --git a/IF/src/main/java/com/github/stefvanschie/inventoryframework/pane/component/PercentageBar.java b/IF/src/main/java/com/github/stefvanschie/inventoryframework/pane/component/PercentageBar.java
index 49340a8cd..b4729c885 100644
--- a/IF/src/main/java/com/github/stefvanschie/inventoryframework/pane/component/PercentageBar.java
+++ b/IF/src/main/java/com/github/stefvanschie/inventoryframework/pane/component/PercentageBar.java
@@ -7,7 +7,10 @@
import com.github.stefvanschie.inventoryframework.pane.Orientable;
import com.github.stefvanschie.inventoryframework.pane.Pane;
import com.github.stefvanschie.inventoryframework.pane.component.util.VariableBar;
+import com.github.stefvanschie.inventoryframework.pane.util.Slot;
import org.bukkit.event.inventory.InventoryClickEvent;
+import org.bukkit.plugin.Plugin;
+import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.w3c.dom.Element;
@@ -19,10 +22,104 @@
*/
public class PercentageBar extends VariableBar {
+ /**
+ * Creates a new percentage bar
+ *
+ * @param slot the slot of the bar
+ * @param length the length of the bar
+ * @param height the height of the bar
+ * @param priority the priority of the bar
+ * @param plugin the plugin that will be the owner for this percentage bar's items
+ * @since 0.10.8
+ */
+ public PercentageBar(@NotNull Slot slot, int length, int height, @NotNull Priority priority,
+ @NotNull Plugin plugin) {
+ super(slot, length, height, priority, plugin);
+ }
+
+ /**
+ * Creates a new percentage bar
+ *
+ * @param x the x coordinate of the bar
+ * @param y the y coordinate of the bar
+ * @param length the length of the bar
+ * @param height the height of the bar
+ * @param priority the priority of the bar
+ * @param plugin the plugin that will be the owner for this percentage bar's items
+ * @since 0.10.8
+ */
+ public PercentageBar(int x, int y, int length, int height, @NotNull Priority priority, @NotNull Plugin plugin) {
+ super(x, y, length, height, priority, plugin);
+ }
+
+ /**
+ * Creates a new percentage bar
+ *
+ * @param slot the slot of the bar
+ * @param length the length of the bar
+ * @param height the height of the bar
+ * @param plugin the plugin that will be the owner for this percentage bar's items
+ * @since 0.10.8
+ */
+ public PercentageBar(@NotNull Slot slot, int length, int height, @NotNull Plugin plugin) {
+ super(slot, length, height, plugin);
+ }
+
+ /**
+ * Creates a new percentage bar
+ *
+ * @param x the x coordinate of the bar
+ * @param y the y coordinate of the bar
+ * @param length the length of the bar
+ * @param height the height of the bar
+ * @param plugin the plugin that will be the owner for this percentage bar's items
+ * @since 0.10.8
+ */
+ public PercentageBar(int x, int y, int length, int height, @NotNull Plugin plugin) {
+ super(x, y, length, height, plugin);
+ }
+
+ /**
+ * Creates a new percentage bar
+ *
+ * @param length the length of the bar
+ * @param height the height of the bar
+ * @param plugin the plugin that will be the owner for this percentage bar's items
+ * @since 0.10.8
+ */
+ public PercentageBar(int length, int height, @NotNull Plugin plugin) {
+ super(length, height, plugin);
+ }
+
+ /**
+ * Creates a new percentage bar
+ *
+ * @param slot the slot of the bar
+ * @param length the length of the bar
+ * @param height the height of the bar
+ * @param priority the priority of the bar
+ * @since 0.10.8
+ */
+ public PercentageBar(@NotNull Slot slot, int length, int height, @NotNull Priority priority) {
+ super(slot, length, height, priority);
+ }
+
public PercentageBar(int x, int y, int length, int height, @NotNull Priority priority) {
super(x, y, length, height, priority);
}
+ /**
+ * Creates a new percentage bar
+ *
+ * @param slot the slot of the bar
+ * @param length the length of the bar
+ * @param height the height of the bar
+ * @since 0.10.8
+ */
+ public PercentageBar(@NotNull Slot slot, int length, int height) {
+ super(slot, length, height);
+ }
+
public PercentageBar(int x, int y, int length, int height) {
super(x, y, length, height);
}
@@ -38,10 +135,17 @@ public boolean click(@NotNull Gui gui, @NotNull InventoryComponent inventoryComp
int length = Math.min(this.length, maxLength);
int height = Math.min(this.height, maxHeight);
- int adjustedSlot = slot - (getX() + paneOffsetX) - inventoryComponent.getLength() * (getY() + paneOffsetY);
+ Slot paneSlot = getSlot();
+
+ int xPosition = paneSlot.getX(maxLength);
+ int yPosition = paneSlot.getY(maxLength);
+
+ int totalLength = inventoryComponent.getLength();
+
+ int adjustedSlot = slot - (xPosition + paneOffsetX) - totalLength * (yPosition + paneOffsetY);
- int x = adjustedSlot % inventoryComponent.getLength();
- int y = adjustedSlot / inventoryComponent.getLength();
+ int x = adjustedSlot % totalLength;
+ int y = adjustedSlot / totalLength;
if (x < 0 || x >= length || y < 0 || y >= height) {
return false;
@@ -51,8 +155,8 @@ public boolean click(@NotNull Gui gui, @NotNull InventoryComponent inventoryComp
event.setCancelled(true);
- int newPaneOffsetX = paneOffsetX + getX();
- int newPaneOffsetY = paneOffsetY + getY();
+ int newPaneOffsetX = paneOffsetX + xPosition;
+ int newPaneOffsetY = paneOffsetY + yPosition;
return this.fillPane.click(
@@ -79,7 +183,7 @@ public void setPercentage(float percentage) {
@Contract(pure = true)
@Override
public PercentageBar copy() {
- PercentageBar percentageBar = new PercentageBar(x, y, length, height, getPriority());
+ PercentageBar percentageBar = new PercentageBar(getSlot(), length, height, getPriority());
applyContents(percentageBar);
@@ -100,12 +204,14 @@ public float getPercentage() {
* Loads a percentage bar from a given element
*
* @param instance the instance class
- * @param element the element
+ * @param element the element
+ * @param plugin the plugin that will be the owner of the underlying items
* @return the percentage bar
+ * @since 0.10.8
*/
@NotNull
@Contract(pure = true)
- public static PercentageBar load(@NotNull Object instance, @NotNull Element element) {
+ public static PercentageBar load(@NotNull Object instance, @NotNull Element element, @NotNull Plugin plugin) {
int length;
int height;
@@ -116,7 +222,7 @@ public static PercentageBar load(@NotNull Object instance, @NotNull Element elem
throw new XMLLoadException(exception);
}
- PercentageBar percentageBar = new PercentageBar(length, height);
+ PercentageBar percentageBar = new PercentageBar(length, height, plugin);
Pane.load(percentageBar, instance, element);
Orientable.load(percentageBar, element);
@@ -136,4 +242,20 @@ public static PercentageBar load(@NotNull Object instance, @NotNull Element elem
return percentageBar;
}
+
+ /**
+ * Loads a percentage bar from a given element
+ *
+ * @param instance the instance class
+ * @param element the element
+ * @return the percentage bar
+ * @deprecated this method is no longer used internally and has been superseded by
+ * {@link #load(Object, Element, Plugin)}
+ */
+ @NotNull
+ @Contract(pure = true)
+ @Deprecated
+ public static PercentageBar load(@NotNull Object instance, @NotNull Element element) {
+ return load(instance, element, JavaPlugin.getProvidingPlugin(PercentageBar.class));
+ }
}
diff --git a/IF/src/main/java/com/github/stefvanschie/inventoryframework/pane/component/Slider.java b/IF/src/main/java/com/github/stefvanschie/inventoryframework/pane/component/Slider.java
index 17e873ff7..26c74e3d2 100644
--- a/IF/src/main/java/com/github/stefvanschie/inventoryframework/pane/component/Slider.java
+++ b/IF/src/main/java/com/github/stefvanschie/inventoryframework/pane/component/Slider.java
@@ -7,7 +7,10 @@
import com.github.stefvanschie.inventoryframework.pane.Orientable;
import com.github.stefvanschie.inventoryframework.pane.Pane;
import com.github.stefvanschie.inventoryframework.pane.component.util.VariableBar;
+import com.github.stefvanschie.inventoryframework.pane.util.Slot;
import org.bukkit.event.inventory.InventoryClickEvent;
+import org.bukkit.plugin.Plugin;
+import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.w3c.dom.Element;
@@ -19,10 +22,103 @@
*/
public class Slider extends VariableBar {
+ /**
+ * Creates a new slider
+ *
+ * @param slot the slot of the slider
+ * @param length the length of the slider
+ * @param height the height of the slider
+ * @param priority the priority of the slider
+ * @param plugin the plugin that will be the owner of the slider's items
+ * @since 0.10.8
+ */
+ public Slider(@NotNull Slot slot, int length, int height, @NotNull Priority priority, @NotNull Plugin plugin) {
+ super(slot, length, height, priority, plugin);
+ }
+
+ /**
+ * Creates a new slider
+ *
+ * @param x the x coordinate of the slider
+ * @param y the y coordinate of the slier
+ * @param length the length of the slider
+ * @param height the height of the slider
+ * @param priority the priority of the slider
+ * @param plugin the plugin that will be the owner of the slider's items
+ * @since 0.10.8
+ */
+ public Slider(int x, int y, int length, int height, @NotNull Priority priority, @NotNull Plugin plugin) {
+ super(x, y, length, height, priority, plugin);
+ }
+
+ /**
+ * Creates a new slider
+ *
+ * @param slot the slot of the slider
+ * @param length the length of the slider
+ * @param height the height of the slider
+ * @param plugin the plugin that will be the owner of the slider's items
+ * @since 0.10.8
+ */
+ public Slider(@NotNull Slot slot, int length, int height, @NotNull Plugin plugin) {
+ super(slot, length, height, plugin);
+ }
+
+ /**
+ * Creates a new slider
+ *
+ * @param x the x coordinate of the slider
+ * @param y the y coordinate of the slier
+ * @param length the length of the slider
+ * @param height the height of the slider
+ * @param plugin the plugin that will be the owner of the slider's items
+ * @since 0.10.8
+ */
+ public Slider(int x, int y, int length, int height, @NotNull Plugin plugin) {
+ super(x, y, length, height, plugin);
+ }
+
+ /**
+ * Creates a new slider
+ *
+ * @param length the length of the slider
+ * @param height the height of the slider
+ * @param plugin the plugin that will be the owner of the slider's items
+ * @since 0.10.8
+ */
+ public Slider(int length, int height, @NotNull Plugin plugin) {
+ super(length, height, plugin);
+ }
+
+ /**
+ * Creates a new slider
+ *
+ * @param slot the slot of the slider
+ * @param length the length of the slider
+ * @param height the height of the slider
+ * @param priority the priority of the slider
+ * @since 0.10.8
+ */
+ public Slider(@NotNull Slot slot, int length, int height, @NotNull Priority priority) {
+ super(slot, length, height, priority);
+ }
+
public Slider(int x, int y, int length, int height, @NotNull Priority priority) {
super(x, y, length, height, priority);
}
+ /**
+ * Creates a new slider
+ *
+ * @param slot the slot of the slider
+ * @param length the length of the slider
+ * @param height the height of the slider
+ * @since 0.10.8
+ */
+ public Slider(@NotNull Slot slot, int length, int height) {
+ super(slot, length, height);
+ }
+
public Slider(int x, int y, int length, int height) {
super(x, y, length, height);
}
@@ -38,10 +134,17 @@ public boolean click(@NotNull Gui gui, @NotNull InventoryComponent inventoryComp
int length = Math.min(this.length, maxLength);
int height = Math.min(this.height, maxHeight);
- int adjustedSlot = slot - (getX() + paneOffsetX) - inventoryComponent.getLength() * (getY() + paneOffsetY);
+ Slot paneSlot = getSlot();
+
+ int xPosition = paneSlot.getX(maxLength);
+ int yPosition = paneSlot.getY(maxLength);
+
+ int totalLength = inventoryComponent.getLength();
+
+ int adjustedSlot = slot - (xPosition + paneOffsetX) - totalLength * (yPosition + paneOffsetY);
- int x = adjustedSlot % inventoryComponent.getLength();
- int y = adjustedSlot / inventoryComponent.getLength();
+ int x = adjustedSlot % totalLength;
+ int y = adjustedSlot / totalLength;
if (x < 0 || x >= length || y < 0 || y >= height) {
return false;
@@ -57,8 +160,8 @@ public boolean click(@NotNull Gui gui, @NotNull InventoryComponent inventoryComp
callOnClick(event);
- int newPaneOffsetX = paneOffsetX + getX();
- int newPaneOffsetY = paneOffsetY + getY();
+ int newPaneOffsetX = paneOffsetX + xPosition;
+ int newPaneOffsetY = paneOffsetY + yPosition;
boolean success = this.fillPane.click(
gui, inventoryComponent, event, slot, newPaneOffsetX, newPaneOffsetY, length, height
@@ -88,7 +191,7 @@ public void setValue(float value) {
@Contract(pure = true)
@Override
public Slider copy() {
- Slider slider = new Slider(x, y, length, height, getPriority());
+ Slider slider = new Slider(getSlot(), length, height, getPriority());
applyContents(slider);
@@ -109,12 +212,14 @@ public float getValue() {
* Loads a percentage bar from a given element
*
* @param instance the instance class
- * @param element the element
+ * @param element the element
+ * @param plugin the plugin that will be the owner of the udnerlying items
* @return the percentage bar
+ * @since 0.10.8
*/
@NotNull
@Contract(pure = true)
- public static Slider load(@NotNull Object instance, @NotNull Element element) {
+ public static Slider load(@NotNull Object instance, @NotNull Element element, @NotNull Plugin plugin) {
int length;
int height;
@@ -125,7 +230,7 @@ public static Slider load(@NotNull Object instance, @NotNull Element element) {
throw new XMLLoadException(exception);
}
- Slider slider = new Slider(length, height);
+ Slider slider = new Slider(length, height, plugin);
Pane.load(slider, instance, element);
Orientable.load(slider, element);
@@ -145,4 +250,20 @@ public static Slider load(@NotNull Object instance, @NotNull Element element) {
return slider;
}
+
+ /**
+ * Loads a percentage bar from a given element
+ *
+ * @param instance the instance class
+ * @param element the element
+ * @return the percentage bar
+ * @deprecated this method is no longer used internally and has been superseded by
+ * {@link #load(Object, Element, Plugin)}
+ */
+ @NotNull
+ @Contract(pure = true)
+ @Deprecated
+ public static Slider load(@NotNull Object instance, @NotNull Element element) {
+ return load(instance, element, JavaPlugin.getProvidingPlugin(Slider.class));
+ }
}
diff --git a/IF/src/main/java/com/github/stefvanschie/inventoryframework/pane/component/ToggleButton.java b/IF/src/main/java/com/github/stefvanschie/inventoryframework/pane/component/ToggleButton.java
index da25e0435..6ff5bd43a 100644
--- a/IF/src/main/java/com/github/stefvanschie/inventoryframework/pane/component/ToggleButton.java
+++ b/IF/src/main/java/com/github/stefvanschie/inventoryframework/pane/component/ToggleButton.java
@@ -1,221 +1,499 @@
-package com.github.stefvanschie.inventoryframework.pane.component;
-
-import com.github.stefvanschie.inventoryframework.gui.InventoryComponent;
-import com.github.stefvanschie.inventoryframework.gui.type.util.Gui;
-import com.github.stefvanschie.inventoryframework.gui.GuiItem;
-import com.github.stefvanschie.inventoryframework.exception.XMLLoadException;
-import com.github.stefvanschie.inventoryframework.pane.OutlinePane;
-import com.github.stefvanschie.inventoryframework.pane.Pane;
-import org.bukkit.Material;
-import org.bukkit.event.inventory.InventoryClickEvent;
-import org.bukkit.inventory.ItemStack;
-import org.jetbrains.annotations.Contract;
-import org.jetbrains.annotations.NotNull;
-import org.w3c.dom.Element;
-
-import java.util.Collection;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-/**
- * A button that toggles between an enabled and disabled state.
- *
- * @since 0.5.0
- */
-public class ToggleButton extends Pane {
-
- /**
- * The panes used for showing the enabled and disabled states
- */
- private final OutlinePane enabledPane, disabledPane;
-
- /**
- * Whether the button is enabled or disabled
- */
- private boolean enabled = false;
-
- public ToggleButton(int x, int y, int length, int height, @NotNull Priority priority) {
- this(x, y, length, height);
-
- setPriority(priority);
- }
-
- public ToggleButton(int length, int height) {
- super(length, height);
-
- this.enabledPane = new OutlinePane(0, 0, length, height);
- this.enabledPane.addItem(new GuiItem(new ItemStack(Material.GREEN_STAINED_GLASS_PANE)));
- this.enabledPane.setRepeat(true);
-
- this.disabledPane = new OutlinePane(0, 0, length, height);
- this.disabledPane.addItem(new GuiItem(new ItemStack(Material.RED_STAINED_GLASS_PANE)));
- this.disabledPane.setRepeat(true);
- }
-
- public ToggleButton(int x, int y, int length, int height) {
- this(length, height);
-
- setX(x);
- setY(y);
- }
-
- @Override
- public void display(@NotNull InventoryComponent inventoryComponent, int paneOffsetX, int paneOffsetY, int maxLength,
- int maxHeight) {
- int newX = paneOffsetX + x;
- int newY = paneOffsetY + y;
-
- int newMaxLength = Math.min(maxLength, length);
- int newMaxHeight = Math.min(maxHeight, height);
-
- if (enabled) {
- enabledPane.display(inventoryComponent, newX, newY, newMaxLength, newMaxHeight);
- } else {
- disabledPane.display(inventoryComponent, newX, newY, newMaxLength, newMaxHeight);
- }
- }
-
- @Override
- public boolean click(@NotNull Gui gui, @NotNull InventoryComponent inventoryComponent,
- @NotNull InventoryClickEvent event, int slot, int paneOffsetX, int paneOffsetY, int maxLength,
- int maxHeight) {
- int length = Math.min(this.length, maxLength);
- int height = Math.min(this.height, maxHeight);
-
- int adjustedSlot = slot - (getX() + paneOffsetX) - inventoryComponent.getLength() * (getY() + paneOffsetY);
-
- int x = adjustedSlot % inventoryComponent.getLength();
- int y = adjustedSlot / inventoryComponent.getLength();
-
- //this isn't our item
- if (x < 0 || x >= length || y < 0 || y >= height) {
- return false;
- }
-
- toggle();
-
- callOnClick(event);
-
- int newX = paneOffsetX + x;
- int newY = paneOffsetY + y;
-
- if (enabled) {
- enabledPane.click(gui, inventoryComponent, event, slot, newX, newY, length, height);
- } else {
- disabledPane.click(gui, inventoryComponent, event, slot, newX, newY, length, height);
- }
-
- gui.update();
-
- return true;
- }
-
- @NotNull
- @Contract(pure = true)
- @Override
- public ToggleButton copy() {
- ToggleButton toggleButton = new ToggleButton(x, y, length, height, getPriority());
-
- toggleButton.setVisible(isVisible());
- toggleButton.onClick = onClick;
-
- toggleButton.uuid = uuid;
-
- toggleButton.setEnabledItem(enabledPane.getItems().get(0).copy());
- toggleButton.setDisabledItem(disabledPane.getItems().get(0).copy());
-
- toggleButton.enabled = enabled;
-
- return toggleButton;
- }
-
- /**
- * Sets the item to use when the button is set to disabled
- *
- * @param item the disabled item
- * @since 0.5.0
- */
- public void setDisabledItem(@NotNull GuiItem item) {
- disabledPane.clear();
-
- disabledPane.addItem(item);
- }
-
- /**
- * Sets the item to use when the button is set to enabled
- *
- * @param item the enabled item
- * @since 0.5.0
- */
- public void setEnabledItem(@NotNull GuiItem item) {
- enabledPane.clear();
-
- enabledPane.addItem(item);
- }
-
- @NotNull
- @Override
- public Collection getItems() {
- return getPanes().stream().flatMap(pane -> pane.getItems().stream()).collect(Collectors.toSet());
- }
-
- @NotNull
- @Override
- public Collection getPanes() {
- return Stream.of(enabledPane, disabledPane).collect(Collectors.toSet());
- }
-
- /**
- * Gets whether this toggle button is currently enabled or disabled.
- *
- * @return whether the button is enabled or disabled
- * @since 0.9.6
- */
- @Contract(pure = true)
- public boolean isEnabled() {
- return enabled;
- }
-
- /**
- * Toggles between the enabled and disabled states
- *
- * @since 0.5.0
- */
- public void toggle() {
- enabled = !enabled;
- }
-
- @Override
- public void clear() {}
-
- /**
- * Loads a toggle button from an XML element
- *
- * @param instance the instance class
- * @param element the element
- * @return the toggle button
- * @since 0.5.0
- */
- @NotNull
- @Contract(pure = true)
- public static ToggleButton load(@NotNull Object instance, @NotNull Element element) {
- int length, height;
-
- try {
- length = Integer.parseInt(element.getAttribute("length"));
- height = Integer.parseInt(element.getAttribute("height"));
- } catch (NumberFormatException exception) {
- throw new XMLLoadException(exception);
- }
-
- ToggleButton toggleButton = new ToggleButton(length, height);
-
- Pane.load(toggleButton, instance, element);
-
- if (element.hasAttribute("enabled") && Boolean.parseBoolean(element.getAttribute("enabled"))) {
- toggleButton.toggle();
- }
-
- return toggleButton;
- }
-}
+package com.github.stefvanschie.inventoryframework.pane.component;
+
+import com.github.stefvanschie.inventoryframework.gui.InventoryComponent;
+import com.github.stefvanschie.inventoryframework.gui.type.util.Gui;
+import com.github.stefvanschie.inventoryframework.gui.GuiItem;
+import com.github.stefvanschie.inventoryframework.exception.XMLLoadException;
+import com.github.stefvanschie.inventoryframework.pane.OutlinePane;
+import com.github.stefvanschie.inventoryframework.pane.Pane;
+import com.github.stefvanschie.inventoryframework.pane.util.Slot;
+import org.bukkit.Material;
+import org.bukkit.event.inventory.InventoryClickEvent;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.plugin.Plugin;
+import org.bukkit.plugin.java.JavaPlugin;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.w3c.dom.Element;
+
+import java.util.Collection;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * A button that toggles between an enabled and disabled state.
+ *
+ * @since 0.5.0
+ */
+public class ToggleButton extends Pane {
+
+ /**
+ * The panes used for showing the enabled and disabled states
+ */
+ private final OutlinePane enabledPane, disabledPane;
+
+ /**
+ * Whether the button is enabled or disabled
+ */
+ private boolean enabled;
+
+ /**
+ * Whether this button can be toggled by a player
+ */
+ private boolean allowToggle = true;
+
+ /**
+ * Creates a new toggle button
+ *
+ * @param slot the slot
+ * @param length the length
+ * @param height the height
+ * @param priority the priority
+ * @param enabled whether the button should start in its enabled or disabled state
+ * @param plugin the plugin that will be the owner of this button's items
+ * @see #ToggleButton(int, int, int, int, Priority, boolean)
+ * @since 0.10.8
+ */
+ public ToggleButton(@NotNull Slot slot, int length, int height, @NotNull Priority priority, boolean enabled,
+ @NotNull Plugin plugin) {
+ super(slot, length, height, priority);
+
+ this.enabled = enabled;
+
+ this.enabledPane = new OutlinePane(length, height);
+ this.enabledPane.addItem(new GuiItem(new ItemStack(Material.GREEN_STAINED_GLASS_PANE), plugin));
+ this.enabledPane.setRepeat(true);
+
+ this.disabledPane = new OutlinePane(length, height);
+ this.disabledPane.addItem(new GuiItem(new ItemStack(Material.RED_STAINED_GLASS_PANE), plugin));
+ this.disabledPane.setRepeat(true);
+ }
+
+ /**
+ * Creates a new toggle button
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param length the length
+ * @param height the height
+ * @param priority the priority
+ * @param enabled whether the button should start in its enabled or disabled state
+ * @param plugin the plugin that will be the owner of this button's items
+ * @see #ToggleButton(int, int, int, int, Priority, boolean)
+ * @since 0.10.8
+ */
+ public ToggleButton(int x, int y, int length, int height, @NotNull Priority priority, boolean enabled,
+ @NotNull Plugin plugin) {
+ this(Slot.fromXY(x, y), length, height, priority, enabled, plugin);
+ }
+
+ /**
+ * Creates a new toggle button
+ *
+ * @param slot the slot
+ * @param length the length
+ * @param height the height
+ * @param priority the priority
+ * @param plugin the plugin that will be the owner of this button's items
+ * @see #ToggleButton(Slot, int, int, Priority)
+ * @since 0.10.8
+ */
+ public ToggleButton(@NotNull Slot slot, int length, int height, @NotNull Priority priority,
+ @NotNull Plugin plugin) {
+ this(slot, length, height, priority, false, plugin);
+ }
+
+ /**
+ * Creates a new toggle button
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param length the length
+ * @param height the height
+ * @param priority the priority
+ * @param plugin the plugin that will be the owner of this button's items
+ * @see #ToggleButton(int, int, int, int, Priority)
+ * @since 0.10.8
+ */
+ public ToggleButton(int x, int y, int length, int height, @NotNull Priority priority, @NotNull Plugin plugin) {
+ this(x, y, length, height, priority, false, plugin);
+ }
+
+ /**
+ * Creates a new toggle button
+ *
+ * @param slot the slot
+ * @param length the length
+ * @param height the height
+ * @param enabled whether the button should start in its enabled or disabled state
+ * @param plugin the plugin that will be the owner of this button's items
+ * @see #ToggleButton(Slot, int, int, boolean)
+ * @since 0.10.8
+ */
+ public ToggleButton(@NotNull Slot slot, int length, int height, boolean enabled, @NotNull Plugin plugin) {
+ this(slot, length, height, Priority.NORMAL, enabled, plugin);
+ }
+
+ /**
+ * Creates a new toggle button
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param length the length
+ * @param height the height
+ * @param enabled whether the button should start in its enabled or disabled state
+ * @param plugin the plugin that will be the owner of this button's items
+ * @see #ToggleButton(int, int, int, int, boolean)
+ * @since 0.10.8
+ */
+ public ToggleButton(int x, int y, int length, int height, boolean enabled, @NotNull Plugin plugin) {
+ this(x, y, length, height, Priority.NORMAL, enabled, plugin);
+ }
+
+ /**
+ * Creates a new toggle button
+ *
+ * @param slot the slot
+ * @param length the length
+ * @param height the height
+ * @param plugin the plugin that will be the owner of this button's items
+ * @see #ToggleButton(Slot, int, int)
+ * @since 0.10.8
+ */
+ public ToggleButton(@NotNull Slot slot, int length, int height, @NotNull Plugin plugin) {
+ this(slot, length, height, false, plugin);
+ }
+
+ /**
+ * Creates a new toggle button
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param length the length
+ * @param height the height
+ * @param plugin the plugin that will be the owner of this button's items
+ * @see #ToggleButton(int, int, int, int)
+ * @since 0.10.8
+ */
+ public ToggleButton(int x, int y, int length, int height, @NotNull Plugin plugin) {
+ this(x, y, length, height, false, plugin);
+ }
+
+ /**
+ * Creates a new toggle button
+ *
+ * @param length the length
+ * @param height the height
+ * @param enabled whether the button should start in its enabled or disabled state
+ * @param plugin the plugin that will be the owner of this button's items
+ * @see #ToggleButton(int, int, boolean)
+ * @since 0.10.8
+ */
+ public ToggleButton(int length, int height, boolean enabled, @NotNull Plugin plugin) {
+ this(0, 0, length, height, enabled);
+ }
+
+ /**
+ * Creates a new toggle button
+ *
+ * @param length the length
+ * @param height the height
+ * @param plugin the plugin that will be the owner of this button's items
+ * @see #ToggleButton(int, int)
+ * @since 0.10.8
+ */
+ public ToggleButton(int length, int height, @NotNull Plugin plugin) {
+ this(length, height, false);
+ }
+
+ /**
+ * Creates a new toggle button
+ *
+ * @param slot the slot
+ * @param length the length
+ * @param height the height
+ * @param priority the priority
+ * @param enabled whether the button should start in its enabled or disabled state
+ * @since 0.10.8
+ */
+ public ToggleButton(@NotNull Slot slot, int length, int height, @NotNull Priority priority, boolean enabled) {
+ this(slot, length, height, priority, enabled, JavaPlugin.getProvidingPlugin(ToggleButton.class));
+ }
+
+ public ToggleButton(int x, int y, int length, int height, @NotNull Priority priority, boolean enabled) {
+ this(x, y, length, height, priority, enabled, JavaPlugin.getProvidingPlugin(ToggleButton.class));
+ }
+
+ /**
+ * Creates a new toggle button
+ *
+ * @param slot the slot
+ * @param length the length
+ * @param height the height
+ * @param priority the priority
+ * @since 0.10.8
+ */
+ public ToggleButton(@NotNull Slot slot, int length, int height, @NotNull Priority priority) {
+ this(slot, length, height, priority, false);
+ }
+
+ public ToggleButton(int x, int y, int length, int height, @NotNull Priority priority) {
+ this(x, y, length, height, priority, false);
+ }
+
+ /**
+ * Creates a new toggle button
+ *
+ * @param slot the slot
+ * @param length the length
+ * @param height the height
+ * @param enabled whether the button should start in its enabled or disabled state
+ * @since 0.10.8
+ */
+ public ToggleButton(@NotNull Slot slot, int length, int height, boolean enabled) {
+ this(slot, length, height, Priority.NORMAL, enabled);
+ }
+
+ public ToggleButton(int x, int y, int length, int height, boolean enabled) {
+ this(x, y, length, height, Priority.NORMAL, enabled);
+ }
+
+ /**
+ * Creates a new toggle button
+ *
+ * @param slot the slot
+ * @param length the length
+ * @param height the height
+ * @since 0.10.8
+ */
+ public ToggleButton(@NotNull Slot slot, int length, int height) {
+ this(slot, length, height, false);
+ }
+
+ public ToggleButton(int x, int y, int length, int height) {
+ this(x, y, length, height, false);
+ }
+
+ public ToggleButton(int length, int height, boolean enabled) {
+ this(0, 0, length, height, enabled);
+ }
+
+ public ToggleButton(int length, int height) {
+ this(length, height, false);
+ }
+
+ @Override
+ public void display(@NotNull InventoryComponent inventoryComponent, int paneOffsetX, int paneOffsetY, int maxLength,
+ int maxHeight) {
+ int newMaxLength = Math.min(maxLength, length);
+ int newMaxHeight = Math.min(maxHeight, height);
+
+ int newPaneOffsetX = this.slot.getX(newMaxLength) + paneOffsetX;
+ int newPaneOffsetY = this.slot.getY(newMaxHeight) + paneOffsetY;
+
+ if (enabled) {
+ this.enabledPane.display(inventoryComponent, newPaneOffsetX, newPaneOffsetY, newMaxLength, newMaxHeight);
+ } else {
+ this.disabledPane.display(inventoryComponent, newPaneOffsetX, newPaneOffsetY, newMaxLength, newMaxHeight);
+ }
+ }
+
+ @Override
+ public boolean click(@NotNull Gui gui, @NotNull InventoryComponent inventoryComponent,
+ @NotNull InventoryClickEvent event, int slot, int paneOffsetX, int paneOffsetY, int maxLength,
+ int maxHeight) {
+ int length = Math.min(this.length, maxLength);
+ int height = Math.min(this.height, maxHeight);
+
+ Slot paneSlot = getSlot();
+
+ int xPosition = paneSlot.getX(maxLength);
+ int yPosition = paneSlot.getY(maxLength);
+
+ int totalLength = inventoryComponent.getLength();
+
+ int adjustedSlot = slot - (xPosition + paneOffsetX) - totalLength * (yPosition + paneOffsetY);
+
+ int x = adjustedSlot % totalLength;
+ int y = adjustedSlot / totalLength;
+
+ //this isn't our item
+ if (x < 0 || x >= length || y < 0 || y >= height) {
+ return false;
+ }
+
+ if (this.allowToggle) {
+ toggle();
+ }
+
+ callOnClick(event);
+
+ int newX = paneOffsetX + xPosition;
+ int newY = paneOffsetY + yPosition;
+
+ /*
+ Since we've toggled before, the click for the panes should be swapped around. If we haven't toggled due to
+ allowToggle being false, then we should click the pane corresponding to the current state. An XOR achieves this.
+ */
+ if (enabled == this.allowToggle) {
+ disabledPane.click(gui, inventoryComponent, event, slot, newX, newY, length, height);
+ } else {
+ enabledPane.click(gui, inventoryComponent, event, slot, newX, newY, length, height);
+ }
+
+ gui.update();
+
+ return true;
+ }
+
+ @NotNull
+ @Contract(pure = true)
+ @Override
+ public ToggleButton copy() {
+ ToggleButton toggleButton = new ToggleButton(getSlot(), length, height, getPriority(), enabled);
+
+ toggleButton.allowToggle = this.allowToggle;
+
+ toggleButton.setVisible(isVisible());
+ toggleButton.onClick = onClick;
+
+ toggleButton.uuid = uuid;
+
+ toggleButton.setEnabledItem(enabledPane.getItems().get(0).copy());
+ toggleButton.setDisabledItem(disabledPane.getItems().get(0).copy());
+
+ return toggleButton;
+ }
+
+ @Override
+ public void setLength(int length) {
+ super.setLength(length);
+
+ this.disabledPane.setLength(length);
+ this.enabledPane.setLength(length);
+ }
+
+ @Override
+ public void setHeight(int height) {
+ super.setHeight(height);
+
+ this.disabledPane.setHeight(height);
+ this.enabledPane.setHeight(height);
+ }
+
+ /**
+ * Sets the item to use when the button is set to disabled
+ *
+ * @param item the disabled item
+ * @since 0.5.0
+ */
+ public void setDisabledItem(@NotNull GuiItem item) {
+ disabledPane.clear();
+
+ disabledPane.addItem(item);
+ }
+
+ /**
+ * Sets the item to use when the button is set to enabled
+ *
+ * @param item the enabled item
+ * @since 0.5.0
+ */
+ public void setEnabledItem(@NotNull GuiItem item) {
+ enabledPane.clear();
+
+ enabledPane.addItem(item);
+ }
+
+ @NotNull
+ @Override
+ public Collection getItems() {
+ return getPanes().stream().flatMap(pane -> pane.getItems().stream()).collect(Collectors.toSet());
+ }
+
+ @NotNull
+ @Override
+ public Collection getPanes() {
+ return Stream.of(enabledPane, disabledPane).collect(Collectors.toSet());
+ }
+
+ /**
+ * Sets whether this toggle button can be toggled. This only prevents players from toggling the button and does not
+ * prevent toggling the button programmatically with methods such as {@link #toggle()}.
+ *
+ * @param allowToggle whether this button can be toggled
+ * @since 0.10.8
+ */
+ public void allowToggle(boolean allowToggle) {
+ this.allowToggle = allowToggle;
+ }
+
+ /**
+ * Gets whether this toggle button is currently enabled or disabled.
+ *
+ * @return whether the button is enabled or disabled
+ * @since 0.9.6
+ */
+ @Contract(pure = true)
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ /**
+ * Toggles between the enabled and disabled states
+ *
+ * @since 0.5.0
+ */
+ public void toggle() {
+ enabled = !enabled;
+ }
+
+ @Override
+ public void clear() {}
+
+ /**
+ * Loads a toggle button from an XML element
+ *
+ * @param instance the instance class
+ * @param element the element
+ * @param plugin the plugin that will be the owner of the underlying items
+ * @return the toggle button
+ * @since 0.10.8
+ */
+ @NotNull
+ @Contract(pure = true)
+ public static ToggleButton load(@NotNull Object instance, @NotNull Element element, @NotNull Plugin plugin) {
+ int length, height;
+
+ try {
+ length = Integer.parseInt(element.getAttribute("length"));
+ height = Integer.parseInt(element.getAttribute("height"));
+ } catch (NumberFormatException exception) {
+ throw new XMLLoadException(exception);
+ }
+
+ boolean enabled = element.hasAttribute("enabled") && Boolean.parseBoolean(element.getAttribute("enabled"));
+ ToggleButton toggleButton = new ToggleButton(length, height, enabled, plugin);
+
+ Pane.load(toggleButton, instance, element);
+
+ return toggleButton;
+ }
+
+ /**
+ * Loads a toggle button from an XML element
+ *
+ * @param instance the instance class
+ * @param element the element
+ * @return the toggle button
+ * @since 0.5.0
+ * @deprecated this method is no longer used internally and has been superseded by
+ * {@link #load(Object, Element, Plugin)}
+ */
+ @NotNull
+ @Contract(pure = true)
+ @Deprecated
+ public static ToggleButton load(@NotNull Object instance, @NotNull Element element) {
+ return load(instance, element, JavaPlugin.getProvidingPlugin(ToggleButton.class));
+ }
+}
diff --git a/IF/src/main/java/com/github/stefvanschie/inventoryframework/pane/component/util/VariableBar.java b/IF/src/main/java/com/github/stefvanschie/inventoryframework/pane/component/util/VariableBar.java
index 1b07921fe..e3a2d0507 100644
--- a/IF/src/main/java/com/github/stefvanschie/inventoryframework/pane/component/util/VariableBar.java
+++ b/IF/src/main/java/com/github/stefvanschie/inventoryframework/pane/component/util/VariableBar.java
@@ -6,8 +6,11 @@
import com.github.stefvanschie.inventoryframework.pane.Orientable;
import com.github.stefvanschie.inventoryframework.pane.OutlinePane;
import com.github.stefvanschie.inventoryframework.pane.Pane;
+import com.github.stefvanschie.inventoryframework.pane.util.Slot;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
+import org.bukkit.plugin.Plugin;
+import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
@@ -43,8 +46,33 @@ public abstract class VariableBar extends Pane implements Orientable, Flippable
*/
protected boolean flipHorizontally, flipVertically;
- protected VariableBar(int length, int height) {
- super(length, height);
+ /**
+ * Creates a new variable bar
+ *
+ * @param length the length of the bar
+ * @param height the height of the bar
+ * @param plugin the plugin that will be the owner for this variable bar's items
+ * @see #VariableBar(int, int)
+ * @since 0.10.8
+ */
+ protected VariableBar(int length, int height, @NotNull Plugin plugin) {
+ this(0, 0, length, height, plugin);
+ }
+
+ /**
+ * Creates a new variable bar
+ *
+ * @param slot the slot of the bar
+ * @param length the length of the bar
+ * @param height the height of the bar
+ * @param priority the priority of the bar
+ * @param plugin the plugin that will be the owner for this variable bar's items
+ * @see #VariableBar(Slot, int, int, Priority)
+ * @since 0.10.8
+ */
+ protected VariableBar(@NotNull Slot slot, int length, int height, @NotNull Priority priority,
+ @NotNull Plugin plugin) {
+ super(slot, length, height);
this.value = 0F;
this.orientation = Orientation.HORIZONTAL;
@@ -53,23 +81,94 @@ protected VariableBar(int length, int height) {
this.backgroundPane = new OutlinePane(0, 0, length, height);
this.fillPane.addItem(new GuiItem(new ItemStack(Material.GREEN_STAINED_GLASS_PANE),
- event -> event.setCancelled(true)));
+ event -> event.setCancelled(true), plugin));
this.backgroundPane.addItem(new GuiItem(new ItemStack(Material.RED_STAINED_GLASS_PANE),
- event -> event.setCancelled(true)));
+ event -> event.setCancelled(true), plugin));
this.fillPane.setRepeat(true);
this.backgroundPane.setRepeat(true);
this.fillPane.setVisible(false);
+
+ setPriority(priority);
}
- protected VariableBar(int x, int y, int length, int height, @NotNull Priority priority) {
- this(length, height);
+ /**
+ * Creates a new variable bar
+ *
+ * @param x the x coordinate of the bar
+ * @param y the y coordinate of the bar
+ * @param length the length of the bar
+ * @param height the height of the bar
+ * @param priority the priority of the bar
+ * @param plugin the plugin that will be the owner for this variable bar's items
+ * @see #VariableBar(int, int)
+ * @since 0.10.8
+ */
+ protected VariableBar(int x, int y, int length, int height, @NotNull Priority priority, @NotNull Plugin plugin) {
+ this(Slot.fromXY(x, y), length, height, priority, plugin);
+ }
- setX(x);
- setY(y);
+ /**
+ * Creates a new variable bar
+ *
+ * @param slot the slot of the bar
+ * @param length the length of the bar
+ * @param height the height of the bar
+ * @param plugin the plugin that will be the owner for this variable bar's items
+ * @see #VariableBar(Slot, int, int)
+ * @since 0.10.8
+ */
+ protected VariableBar(@NotNull Slot slot, int length, int height, @NotNull Plugin plugin) {
+ this(slot, length, height, Priority.NORMAL, plugin);
+ }
- setPriority(priority);
+ /**
+ * Creates a new variable bar
+ *
+ * @param x the x coordinate of the bar
+ * @param y the y coordinate of the bar
+ * @param length the length of the bar
+ * @param height the height of the bar
+ * @param plugin the plugin that will be the owner for this variable bar's items
+ * @see #VariableBar(int, int)
+ * @since 0.10.8
+ */
+ protected VariableBar(int x, int y, int length, int height, @NotNull Plugin plugin) {
+ this(x, y, length, height, Priority.NORMAL, plugin);
+ }
+
+ protected VariableBar(int length, int height) {
+ this(0, 0, length, height);
+ }
+
+ /**
+ * Creates a new variable bar
+ *
+ * @param slot the slot of the bar
+ * @param length the length of the bar
+ * @param height the height of the bar
+ * @param priority the priority of the bar
+ * @since 0.10.8
+ */
+ protected VariableBar(@NotNull Slot slot, int length, int height, @NotNull Priority priority) {
+ this(slot, length, height, priority, JavaPlugin.getProvidingPlugin(VariableBar.class));
+ }
+
+ protected VariableBar(int x, int y, int length, int height, @NotNull Priority priority) {
+ this(x, y, length, height, priority, JavaPlugin.getProvidingPlugin(VariableBar.class));
+ }
+
+ /**
+ * Creates a new variable bar
+ *
+ * @param slot the slot of the bar
+ * @param length the length of the bar
+ * @param height the height of the bar
+ * @since 0.10.8
+ */
+ protected VariableBar(@NotNull Slot slot, int length, int height) {
+ this(slot, length, height, Priority.NORMAL);
}
protected VariableBar(int x, int y, int length, int height) {
@@ -184,6 +283,7 @@ public void setHeight(int height) {
protected void applyContents(@NotNull VariableBar copy) {
copy.x = x;
copy.y = y;
+ copy.slot = slot;
copy.length = length;
copy.height = height;
copy.setPriority(getPriority());
@@ -236,13 +336,20 @@ public void setOrientation(@NotNull Orientation orientation) {
@Override
public void display(@NotNull InventoryComponent inventoryComponent, int paneOffsetX, int paneOffsetY, int maxLength,
int maxHeight) {
- int newPaneOffsetX = paneOffsetX + getX();
- int newPaneOffsetY = paneOffsetY + getY();
+ Slot slot = getSlot();
+
+ int newPaneOffsetX = paneOffsetX + slot.getX(maxLength);
+ int newPaneOffsetY = paneOffsetY + slot.getY(maxLength);
int newMaxLength = Math.min(maxLength, getLength());
int newMaxHeight = Math.min(maxHeight, getHeight());
- this.backgroundPane.display(inventoryComponent, newPaneOffsetX, newPaneOffsetY, newMaxLength, newMaxHeight);
- this.fillPane.display(inventoryComponent, newPaneOffsetX, newPaneOffsetY, newMaxLength, newMaxHeight);
+ if (this.backgroundPane.isVisible()) {
+ this.backgroundPane.display(inventoryComponent, newPaneOffsetX, newPaneOffsetY, newMaxLength, newMaxHeight);
+ }
+
+ if (this.fillPane.isVisible()) {
+ this.fillPane.display(inventoryComponent, newPaneOffsetX, newPaneOffsetY, newMaxLength, newMaxHeight);
+ }
}
/**
diff --git a/IF/src/main/java/com/github/stefvanschie/inventoryframework/pane/util/Mask.java b/IF/src/main/java/com/github/stefvanschie/inventoryframework/pane/util/Mask.java
index 55bce832f..901d854a4 100644
--- a/IF/src/main/java/com/github/stefvanschie/inventoryframework/pane/util/Mask.java
+++ b/IF/src/main/java/com/github/stefvanschie/inventoryframework/pane/util/Mask.java
@@ -154,7 +154,7 @@ public int amountOfEnabledSlots() {
* @since 0.5.16
*/
public boolean[] getColumn(int index) {
- boolean[] column = new boolean[mask[0].length];
+ boolean[] column = new boolean[mask.length];
for (int i = 0; i < getHeight(); i++) {
column[i] = mask[i][index];
diff --git a/IF/src/main/java/com/github/stefvanschie/inventoryframework/pane/util/Slot.java b/IF/src/main/java/com/github/stefvanschie/inventoryframework/pane/util/Slot.java
new file mode 100644
index 000000000..d1306fe42
--- /dev/null
+++ b/IF/src/main/java/com/github/stefvanschie/inventoryframework/pane/util/Slot.java
@@ -0,0 +1,249 @@
+package com.github.stefvanschie.inventoryframework.pane.util;
+
+import com.github.stefvanschie.inventoryframework.exception.XMLLoadException;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.w3c.dom.Element;
+
+import java.util.Objects;
+
+/**
+ * A slot represents a position in some type of container. Implementors of this class represent slots in different ways.
+ *
+ * @since 0.10.8
+ */
+public interface Slot {
+
+ /**
+ * Gets the x coordinate of this slot.
+ *
+ * @param length the length of the parent container
+ * @return the x coordinate of this slot
+ * @since 0.10.8
+ */
+ @Contract(pure = true)
+ int getX(int length);
+
+ /**
+ * Gets the y coordinate of this slot.
+ *
+ * @param length the length of the parent container
+ * @return the y coordinate of this slot
+ * @since 0.10.8
+ */
+ @Contract(pure = true)
+ int getY(int length);
+
+ /**
+ * Deserializes the slot from an element. The slot may either be provided as an (x, y) coordinate pair via the "x"
+ * and "y" attributes; or as an index via the "index" attribute. If both forms are present, an
+ * {@link XMLLoadException} will be thrown. If only the "x" or the "y" attribute is present, but not both, an
+ * {@link XMLLoadException} will be thrown. If none of the aforementioned attributes appear, an
+ * {@link XMLLoadException} will be thrown. If any of these attributes contain a value that is not an integer, an
+ * {@link XMLLoadException} will be thrown. Otherwise, this will return a slot based on the present attributes.
+ *
+ * @param element the element from which to retrieve the attributes for the slot
+ * @return the deserialized slot
+ * @throws XMLLoadException if "x", "y", and "index" attributes are present; if only an "x" attribute is present; if
+ * only a "y" attribute is present; if no "x", "y", or "index" attribute is present; or if
+ * the "x", "y", or "index" attribute contain a value that is not an integer.
+ */
+ @NotNull
+ @Contract(value = "_ -> new", pure = true)
+ static Slot deserialize(@NotNull Element element) {
+ boolean hasX = element.hasAttribute("x");
+ boolean hasY = element.hasAttribute("y");
+ boolean hasIndex = element.hasAttribute("index");
+
+ if (hasX && hasY && !hasIndex) {
+ int x, y;
+
+ try {
+ x = Integer.parseInt(element.getAttribute("x"));
+ y = Integer.parseInt(element.getAttribute("y"));
+ } catch (NumberFormatException exception) {
+ throw new XMLLoadException("The x or y attribute does not have an integer as value");
+ }
+
+ return Slot.fromXY(x, y);
+ }
+
+ if (hasIndex && !hasX && !hasY) {
+ int index;
+
+ try {
+ index = Integer.parseInt(element.getAttribute("index"));
+ } catch (NumberFormatException exception) {
+ throw new XMLLoadException("The index attribute does not have an integer as value");
+ }
+
+ return Slot.fromIndex(index);
+ }
+
+ throw new XMLLoadException("The combination of x, y and index attributes is invalid");
+ }
+
+ /**
+ * Creates a new slot based on an (x, y) coordinate pair.
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @return the slot representing this position
+ * @since 0.10.8
+ */
+ @NotNull
+ @Contract(value = "_, _ -> new", pure = true)
+ static Slot fromXY(int x, int y) {
+ return new XY(x, y);
+ }
+
+ /**
+ * Creates a new slot based on an index. This index is relative to the parent container this slot will be used in.
+ *
+ * @param index the index
+ * @return the slot representing this relative position
+ * @since 0.10.8
+ */
+ @NotNull
+ @Contract("_ -> new")
+ static Slot fromIndex(int index) {
+ return new Indexed(index);
+ }
+
+ /**
+ * A class representing a slot based on an (x, y) coordinate pair.
+ *
+ * @since 0.10.8
+ */
+ class XY implements Slot {
+
+ /**
+ * The (x, y) coordinate pair
+ */
+ private final int x, y;
+
+ /**
+ * Creates a new slot based on an (x, y) coordinate pair.
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @since 0.10.8
+ */
+ private XY(int x, int y) {
+ this.x = x;
+ this.y = y;
+ }
+
+ @Override
+ public int getX(int length) {
+ return this.x;
+ }
+
+ @Override
+ public int getY(int length) {
+ return this.y;
+ }
+
+ @Override
+ public boolean equals(@Nullable Object object) {
+ if (this == object) {
+ return true;
+ }
+
+ if (object == null || getClass() != object.getClass()) {
+ return false;
+ }
+
+ XY xy = (XY) object;
+
+ return x == xy.x && y == xy.y;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(x, y);
+ }
+ }
+
+ /**
+ * A class representing a slot based on an index.
+ *
+ * @since 0.10.8
+ */
+ class Indexed implements Slot {
+
+ /**
+ * The index of this slot.
+ */
+ private final int index;
+
+ /**
+ * Creates a new slot based on an index.
+ *
+ * @param index the index of this slot
+ * @since 0.10.8
+ */
+ private Indexed(int index) {
+ this.index = index;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * If {@code length} is zero, this will throw an {@link IllegalArgumentException}.
+ *
+ * @param length {@inheritDoc}
+ * @return {@inheritDoc}
+ * @throws IllegalArgumentException when {@code length} is zero
+ */
+ @Override
+ @Contract(pure = true)
+ public int getX(int length) {
+ if (length == 0) {
+ throw new IllegalArgumentException("Length may not be zero");
+ }
+
+ return this.index % length;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * If {@code length} is zero, this will throw an {@link IllegalArgumentException}.
+ *
+ * @param length {@inheritDoc}
+ * @return {@inheritDoc}
+ * @throws IllegalArgumentException when {@code length} is zero
+ */
+ @Override
+ @Contract(pure = true)
+ public int getY(int length) {
+ if (length == 0) {
+ throw new IllegalArgumentException("Length may not be zero");
+ }
+
+ return this.index / length;
+ }
+
+ @Override
+ public boolean equals(@Nullable Object object) {
+ if (this == object) {
+ return true;
+ }
+
+ if (object == null || getClass() != object.getClass()) {
+ return false;
+ }
+
+ Indexed indexed = (Indexed) object;
+
+ return index == indexed.index;
+ }
+
+ @Override
+ public int hashCode() {
+ return index;
+ }
+ }
+}
diff --git a/IF/src/main/java/com/github/stefvanschie/inventoryframework/util/CSVUtil.java b/IF/src/main/java/com/github/stefvanschie/inventoryframework/util/CSVUtil.java
index 1f2b75797..89d05da5f 100644
--- a/IF/src/main/java/com/github/stefvanschie/inventoryframework/util/CSVUtil.java
+++ b/IF/src/main/java/com/github/stefvanschie/inventoryframework/util/CSVUtil.java
@@ -1,6 +1,5 @@
package com.github.stefvanschie.inventoryframework.util;
-import org.apache.commons.lang.StringUtils;
import org.jetbrains.annotations.NotNull;
import java.io.BufferedReader;
@@ -72,9 +71,7 @@ public static List readAll(@NotNull InputStream inputStream) throws IO
array[i] = array[i].substring(1, array[i].length() - 1);
}
- array[i] = StringUtils.replace(array[i], "\"\"", "\"");
- //Restore original code (array[i] = array[i].replace("\"\"", "\""))
- //once we update to Java 11, where it receives the current, faster implementation
+ array[i] = array[i].replace("\"\"", "\"");
//replace unicode characters
Matcher matcher = UNICODE_CHARACTER_PATTERN.matcher(array[i]);
diff --git a/IF/src/main/java/com/github/stefvanschie/inventoryframework/util/InventoryViewUtil.java b/IF/src/main/java/com/github/stefvanschie/inventoryframework/util/InventoryViewUtil.java
new file mode 100644
index 000000000..8d6327e69
--- /dev/null
+++ b/IF/src/main/java/com/github/stefvanschie/inventoryframework/util/InventoryViewUtil.java
@@ -0,0 +1,42 @@
+package com.github.stefvanschie.inventoryframework.util;
+
+import com.github.stefvanschie.inventoryframework.inventoryview.abstraction.AbstractInventoryViewUtil;
+import com.github.stefvanschie.inventoryframework.util.version.Version;
+import org.bukkit.inventory.InventoryView;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * A utility class for working with {@link InventoryView}s across different definitions.
+ *
+ * @since 0.10.16
+ */
+public class InventoryViewUtil {
+
+ /**
+ * The underlying implementation.
+ */
+ @Nullable
+ private static AbstractInventoryViewUtil IMPLEMENTATION;
+
+ /**
+ * Gets the instance of this class to use for the current version.
+ *
+ * @return an instance of a utility class
+ * @since 0.10.16
+ */
+ @NotNull
+ @Contract(pure = true)
+ public static AbstractInventoryViewUtil getInstance() {
+ if (IMPLEMENTATION == null) {
+ if (Version.getVersion().isInventoryViewInterface()) {
+ IMPLEMENTATION = com.github.stefvanschie.inventoryframework.inventoryview.interface_.InventoryViewUtil.getInstance();
+ } else {
+ IMPLEMENTATION = com.github.stefvanschie.inventoryframework.inventoryview.abstractclass.InventoryViewUtil.getInstance();
+ }
+ }
+
+ return IMPLEMENTATION;
+ }
+}
diff --git a/IF/src/main/java/com/github/stefvanschie/inventoryframework/util/SkullUtil.java b/IF/src/main/java/com/github/stefvanschie/inventoryframework/util/SkullUtil.java
index b28b82bc4..1537767dc 100644
--- a/IF/src/main/java/com/github/stefvanschie/inventoryframework/util/SkullUtil.java
+++ b/IF/src/main/java/com/github/stefvanschie/inventoryframework/util/SkullUtil.java
@@ -8,6 +8,8 @@
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
import java.util.Base64;
import java.util.Objects;
import java.util.UUID;
@@ -51,17 +53,27 @@ public static ItemStack getSkull(@NotNull String id) {
* @param id the skull id
*/
public static void setSkull(@NotNull ItemMeta meta, @NotNull String id) {
- GameProfile profile = new GameProfile(UUID.randomUUID(), null);
+ GameProfile profile = new GameProfile(UUID.randomUUID(), "");
byte[] encodedData = Base64.getEncoder().encode(String.format("{textures:{SKIN:{url:\"%s\"}}}",
"http://textures.minecraft.net/texture/" + id).getBytes());
profile.getProperties().put("textures", new Property("textures", new String(encodedData)));
+ String itemDisplayName = meta.getDisplayName();
try {
Field profileField = meta.getClass().getDeclaredField("profile");
profileField.setAccessible(true);
profileField.set(meta, profile);
- } catch (NoSuchFieldException | SecurityException | IllegalAccessException e) {
+
+ meta.setDisplayName(itemDisplayName);
+
+ // Sets serializedProfile field on meta
+ // If it does throw NoSuchMethodException this stops, and meta is correct.
+ // Else it has profile and will set the field.
+ Method setProfile = meta.getClass().getDeclaredMethod("setProfile", GameProfile.class);
+ setProfile.setAccessible(true);
+ setProfile.invoke(meta, profile);
+ } catch (NoSuchFieldException | SecurityException | IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
- }
+ } catch (NoSuchMethodException ignored) {}
}
}
diff --git a/IF/src/main/java/com/github/stefvanschie/inventoryframework/util/TriFunction.java b/IF/src/main/java/com/github/stefvanschie/inventoryframework/util/TriFunction.java
new file mode 100644
index 000000000..7ce718ca8
--- /dev/null
+++ b/IF/src/main/java/com/github/stefvanschie/inventoryframework/util/TriFunction.java
@@ -0,0 +1,25 @@
+package com.github.stefvanschie.inventoryframework.util;
+
+/**
+ * A function that takes three arguments and returns a result.
+ *
+ * @param the type of the first argument
+ * @param the type of the second argument
+ * @param the type of the third argument
+ * @param the type of the result
+ * @since 0.10.8
+ */
+@FunctionalInterface
+public interface TriFunction {
+
+ /**
+ * Applies this function to the given arguments.
+ *
+ * @param a the first argument
+ * @param b the second argument
+ * @param c the third argument
+ * @return the result value
+ * @since 0.10.8
+ */
+ R apply(A a, B b, C c);
+}
diff --git a/IF/src/main/java/com/github/stefvanschie/inventoryframework/util/XMLUtil.java b/IF/src/main/java/com/github/stefvanschie/inventoryframework/util/XMLUtil.java
index ede880dbc..1f3586bc9 100644
--- a/IF/src/main/java/com/github/stefvanschie/inventoryframework/util/XMLUtil.java
+++ b/IF/src/main/java/com/github/stefvanschie/inventoryframework/util/XMLUtil.java
@@ -62,6 +62,30 @@ public static Consumer loadOnEventAttribute(@NotNull Object
return null;
}
+ /**
+ * Invokes the method by the given name on the given instance with the provided argument. The method should have
+ * the exact name specified and the exact parameter as specified. If the method cannot be accessed or found, this
+ * will throw an {@link XMLLoadException}.
+ *
+ * @param instance the instance on which to call the method
+ * @param methodName the name of the method to invoke
+ * @param argument the argument to provide for the invocation
+ * @param parameter the parameter of the method
+ * @since 0.10.3
+ * @throws XMLLoadException if the method cannot be accessed or found
+ */
+ public static void invokeMethod(@NotNull Object instance, @NotNull String methodName, @NotNull Object argument,
+ @NotNull Class> parameter) {
+ try {
+ Method method = instance.getClass().getMethod(methodName, parameter);
+
+ method.setAccessible(true);
+ method.invoke(instance, argument);
+ } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException exception) {
+ throw new XMLLoadException(exception);
+ }
+ }
+
/**
* Sets a field from the given instance and element to the specified value
*
diff --git a/IF/src/main/java/com/github/stefvanschie/inventoryframework/util/version/Version.java b/IF/src/main/java/com/github/stefvanschie/inventoryframework/util/version/Version.java
index aa2a2edca..93ddce445 100644
--- a/IF/src/main/java/com/github/stefvanschie/inventoryframework/util/version/Version.java
+++ b/IF/src/main/java/com/github/stefvanschie/inventoryframework/util/version/Version.java
@@ -2,9 +2,13 @@
import com.github.stefvanschie.inventoryframework.exception.UnsupportedVersionException;
import org.bukkit.Bukkit;
+import org.bukkit.inventory.InventoryView;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
+import java.util.Collection;
+import java.util.EnumSet;
+
/**
* The different supported NMS versions
*
@@ -13,39 +17,234 @@
public enum Version {
/**
- * Version 1.14 R1
+ * Version 1.14
*
- * @since 0.8.0
+ * @since 0.10.0
*/
- V1_14_R1,
+ V1_14,
/**
- * Version 1.15 R1
+ * Version 1.15
*
- * @since 0.8.0
+ * @since 0.10.0
*/
- V1_15_R1,
+ V1_15,
/**
- * Version 1.16 R1
+ * Version 1.16.1
*
- * @since 0.8.0
+ * @since 0.10.0
*/
- V1_16_R1,
+ V1_16_1,
/**
- * Version 1.16 R2
+ * Version 1.16.2 - 1.16.3
*
- * @since 0.8.0
+ * @since 0.10.0
*/
- V1_16_R2,
+ V1_16_2_3,
/**
- * Version 1.16 R3
+ * Version 1.16.4 - 1.16.5
*
- * @since 0.8.0
+ * @since 0.10.0
+ */
+ V1_16_4_5,
+
+ /**
+ * Version 1.17
+ *
+ * @since 0.10.0
+ */
+ V1_17_0,
+
+ /**
+ * Version 1.17.1
+ *
+ * @since 0.10.0
+ */
+ V1_17_1,
+
+ /**
+ * Version 1.18.0
+ *
+ * @since 0.10.4
+ */
+ V1_18_0,
+
+ /**
+ * Version 1.18.1
+ *
+ * @since 0.10.4
+ */
+ V1_18_1,
+
+ /**
+ * Version 1.18.2
+ *
+ * @since 0.10.5
+ */
+ V1_18_2,
+
+ /**
+ * Version 1.19.0
+ *
+ * @since 0.10.6
+ */
+ V1_19_0,
+
+ /**
+ * Version 1.19.1
+ *
+ * @since 0.10.7
+ */
+ V1_19_1,
+
+ /**
+ * Version 1.19.2
+ *
+ * @since 0.10.7
+ */
+ V1_19_2,
+
+ /**
+ * Version 1.19.3
+ *
+ * @since 0.10.8
*/
- V1_16_R3;
+ V1_19_3,
+
+ /**
+ * Version 1.19.4
+ *
+ * @since 0.10.9
+ */
+ V1_19_4,
+
+ /**
+ * Version 1.20.0
+ *
+ * @since 0.10.14
+ */
+ V1_20_0,
+
+ /**
+ * Version 1.20.1
+ *
+ * @since 0.10.14
+ */
+ V1_20_1,
+
+ /**
+ * Version 1.20.2
+ *
+ * @since 0.10.12
+ */
+ V1_20_2,
+
+ /**
+ * Version 1.20.3 - 1.20.4
+ *
+ * @since 0.10.13
+ */
+ V1_20_3_4,
+
+ /**
+ * Version 1.20.5
+ *
+ * @since 0.10.14
+ */
+ V1_20_5,
+
+ /**
+ * Version 1.20.6
+ *
+ * @since 0.10.14
+ */
+ V1_20_6,
+
+ /**
+ * Version 1.21.0
+ *
+ * @since 0.10.18
+ */
+ V1_21_0,
+
+ /**
+ * Version 1.21.1
+ *
+ * @since 0.10.18
+ */
+ V1_21_1,
+
+ /**
+ * Version 1.21.2 - 1.21.3
+ *
+ * @since 0.10.18
+ */
+ V1_21_2_3;
+
+ /**
+ * A collection of versions on which modern smithing tables are available.
+ */
+ private static final Collection MODERN_SMITHING_TABLE_VERSIONS = EnumSet.of(
+ V1_19_4,
+ V1_20_0, V1_20_1, V1_20_2, V1_20_3_4, V1_20_5, V1_20_6,
+ V1_21_0, V1_21_1, V1_21_2_3
+ );
+
+ /**
+ * A collection of versions on which legacy smithing tables ae available.
+ */
+ @NotNull
+ private static final Collection<@NotNull Version> LEGACY_SMITHING_TABLE_VERSIONS = EnumSet.of(
+ V1_14,
+ V1_15,
+ V1_16_1, V1_16_2_3, V1_16_4_5,
+ V1_17_0, V1_17_1,
+ V1_18_0, V1_18_1, V1_18_2,
+ V1_19_0, V1_19_1, V1_19_2, V1_19_3, V1_19_4
+ );
+
+ /**
+ * A collection of versions on which {@link InventoryView} is an interface.
+ */
+ @NotNull
+ private static final Collection<@NotNull Version> INTERFACE_INVENTORY_VIEW = EnumSet.of(
+ V1_21_0, V1_21_1, V1_21_2_3
+ );
+
+ /**
+ * Checks whether the {@link InventoryView} class is an interface on this version.
+ *
+ * @return true if the class is an interface, false otherwise
+ * @since 0.10.16
+ */
+ @Contract(pure = true)
+ public boolean isInventoryViewInterface() {
+ return INTERFACE_INVENTORY_VIEW.contains(this);
+ }
+
+ /**
+ * Checks whether modern smithing tables exist on this version. Returns true if they do, otherwise false.
+ *
+ * @return true if modern smithing tables are available
+ * @since 0.10.10
+ */
+ boolean existsModernSmithingTable() {
+ return MODERN_SMITHING_TABLE_VERSIONS.contains(this);
+ }
+
+ /**
+ * Checks whether legacy smithing tables exist on this version. Returns true if they do, otherwise false.
+ *
+ * @return true if legacy smithing tables are available
+ * @since 0.10.10
+ */
+ @Contract(pure = true)
+ boolean existsLegacySmithingTable() {
+ return LEGACY_SMITHING_TABLE_VERSIONS.contains(this);
+ }
/**
* Gets the version currently being used. If the used version is not supported, an
@@ -57,19 +256,67 @@ public enum Version {
@NotNull
@Contract(pure = true)
public static Version getVersion() {
- String version = Bukkit.getServer().getClass().getPackage().getName();
-
- switch (version.substring(version.lastIndexOf('.') + 1)) {
- case "v1_14_R1":
- return V1_14_R1;
- case "v1_15_R1":
- return V1_15_R1;
- case "v1_16_R1":
- return V1_16_R1;
- case "v1_16_R2":
- return V1_16_R2;
- case "v1_16_R3":
- return V1_16_R3;
+ String version = Bukkit.getBukkitVersion().split("-")[0];
+
+ switch (version) {
+ case "1.14":
+ case "1.14.1":
+ case "1.14.2":
+ case "1.14.3":
+ case "1.14.4":
+ return V1_14;
+ case "1.15":
+ case "1.15.1":
+ case "1.15.2":
+ return V1_15;
+ case "1.16.1":
+ return V1_16_1;
+ case "1.16.2":
+ case "1.16.3":
+ return V1_16_2_3;
+ case "1.16.4":
+ case "1.16.5":
+ return V1_16_4_5;
+ case "1.17":
+ return V1_17_0;
+ case "1.17.1":
+ return V1_17_1;
+ case "1.18":
+ return V1_18_0;
+ case "1.18.1":
+ return V1_18_1;
+ case "1.18.2":
+ return V1_18_2;
+ case "1.19":
+ return V1_19_0;
+ case "1.19.1":
+ return V1_19_1;
+ case "1.19.2":
+ return V1_19_2;
+ case "1.19.3":
+ return V1_19_3;
+ case "1.19.4":
+ return V1_19_4;
+ case "1.20":
+ return V1_20_0;
+ case "1.20.1":
+ return V1_20_1;
+ case "1.20.2":
+ return V1_20_2;
+ case "1.20.3":
+ case "1.20.4":
+ return V1_20_3_4;
+ case "1.20.5":
+ return V1_20_5;
+ case "1.20.6":
+ return V1_20_6;
+ case "1.21":
+ return V1_21_0;
+ case "1.21.1":
+ return V1_21_1;
+ case "1.21.2":
+ case "1.21.3":
+ return V1_21_2_3;
default:
throw new UnsupportedVersionException("The server version provided is not supported");
}
diff --git a/IF/src/main/java/com/github/stefvanschie/inventoryframework/util/version/VersionMatcher.java b/IF/src/main/java/com/github/stefvanschie/inventoryframework/util/version/VersionMatcher.java
index c4f108e10..5ef836807 100644
--- a/IF/src/main/java/com/github/stefvanschie/inventoryframework/util/version/VersionMatcher.java
+++ b/IF/src/main/java/com/github/stefvanschie/inventoryframework/util/version/VersionMatcher.java
@@ -2,6 +2,7 @@
import com.github.stefvanschie.inventoryframework.abstraction.*;
import com.github.stefvanschie.inventoryframework.exception.UnsupportedVersionException;
+import com.github.stefvanschie.inventoryframework.nms.v1_19_4.LegacySmithingTableInventoryImpl;
import org.bukkit.inventory.InventoryHolder;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
@@ -41,11 +42,21 @@ public class VersionMatcher {
*/
private static final EnumMap> GRINDSTONE_INVENTORIES;
+ /**
+ * The different merchant inventories for different versions
+ */
+ private static final EnumMap> MERCHANT_INVENTORIES;
+
/**
* The different smithing table inventories for different versions
*/
private static final EnumMap> SMITHING_TABLE_INVENTORIES;
+ /**
+ * The different legacy smithing table inventories for different versions
+ */
+ private static final EnumMap> LEGACY_SMITHING_TABLE_INVENTORIES;
+
/**
* The different stonecutter inventories for different versions
*/
@@ -156,6 +167,24 @@ public static GrindstoneInventory newGrindstoneInventory(@NotNull Version versio
}
}
+ /**
+ * Gets a new merchant inventory for the specified version.
+ *
+ * @param version the version to get the inventory of
+ * @return the merchant inventory
+ * @since 0.10.1
+ */
+ @NotNull
+ @Contract(pure = true)
+ public static MerchantInventory newMerchantInventory(@NotNull Version version) {
+ try {
+ return MERCHANT_INVENTORIES.get(version).getConstructor().newInstance();
+ } catch (InstantiationException | IllegalAccessException | InvocationTargetException |
+ NoSuchMethodException exception) {
+ throw new IllegalStateException(exception);
+ }
+ }
+
/**
* Gets a new smithing table inventory for the specified version of the specified inventory holder. If a smithing
* table is requested for a version that does not have smithing tables, an {@link UnsupportedVersionException} is
@@ -164,17 +193,21 @@ public static GrindstoneInventory newGrindstoneInventory(@NotNull Version versio
* @param version the version to get the inventory of
* @param inventoryHolder the inventory holder
* @return the smithing table inventory
- * @since 0.8.0
+ * @since 0.10.9
* @throws UnsupportedVersionException when a smithing table is requested on a version without smithing tables
*/
@NotNull
@Contract(pure = true)
- public static SmithingTableInventory newSmithingTableInventory(@NotNull Version version,
- @NotNull InventoryHolder inventoryHolder) {
- if (version == Version.V1_14_R1 || version == Version.V1_15_R1) {
+ public static SmithingTableInventory newModernSmithingTableInventory(@NotNull Version version,
+ @NotNull InventoryHolder inventoryHolder) {
+ if (!version.existsModernSmithingTable() && !version.existsLegacySmithingTable()) {
throw new UnsupportedVersionException("Smithing tables didn't exist in version " + version);
}
+ if (!version.existsModernSmithingTable()) {
+ throw new UnsupportedVersionException("Modern smithing tables didn't exist in version " + version);
+ }
+
try {
Class extends SmithingTableInventory> clazz = SMITHING_TABLE_INVENTORIES.get(version);
@@ -185,6 +218,39 @@ public static SmithingTableInventory newSmithingTableInventory(@NotNull Version
}
}
+ /**
+ * Gets a new legacy smithing table inventory for the specified version of the specified inventory holder. If a
+ * smithing table is requested for a version that does not have smithing tables, an
+ * {@link UnsupportedVersionException} is thrown.
+ *
+ * @param version the version to get the inventory of
+ * @param inventoryHolder the inventory holder
+ * @return the smithing table inventory
+ * @since 0.8.0
+ * @throws UnsupportedVersionException when a smithing table is requested on a version without smithing tables
+ */
+ @NotNull
+ @Contract(pure = true)
+ public static SmithingTableInventory newSmithingTableInventory(@NotNull Version version,
+ @NotNull InventoryHolder inventoryHolder) {
+ if (!version.existsModernSmithingTable() && !version.existsLegacySmithingTable()) {
+ throw new UnsupportedVersionException("Smithing tables didn't exist in version " + version);
+ }
+
+ if (!version.existsLegacySmithingTable()) {
+ throw new UnsupportedVersionException("Legacy smithing tables don't exist in version " + version);
+ }
+
+ try {
+ Class extends SmithingTableInventory> clazz = LEGACY_SMITHING_TABLE_INVENTORIES.get(version);
+
+ return clazz.getConstructor(InventoryHolder.class).newInstance(inventoryHolder);
+ } catch (InstantiationException | IllegalAccessException | InvocationTargetException |
+ NoSuchMethodException exception) {
+ throw new IllegalStateException(exception);
+ }
+ }
+
/**
* Gets a new stonecutter inventory for the specified version of the specified inventory holder.
*
@@ -209,83 +275,403 @@ public static StonecutterInventory newStonecutterInventory(@NotNull Version vers
static {
ANVIL_INVENTORIES = new EnumMap<>(Version.class);
- ANVIL_INVENTORIES.put(Version.V1_14_R1,
- com.github.stefvanschie.inventoryframework.nms.v1_14_R1.AnvilInventoryImpl.class);
- ANVIL_INVENTORIES.put(Version.V1_15_R1,
- com.github.stefvanschie.inventoryframework.nms.v1_15_R1.AnvilInventoryImpl.class);
- ANVIL_INVENTORIES.put(Version.V1_16_R1,
- com.github.stefvanschie.inventoryframework.nms.v1_16_R1.AnvilInventoryImpl.class);
- ANVIL_INVENTORIES.put(Version.V1_16_R2,
- com.github.stefvanschie.inventoryframework.nms.v1_16_R2.AnvilInventoryImpl.class);
- ANVIL_INVENTORIES.put(Version.V1_16_R3,
- com.github.stefvanschie.inventoryframework.nms.v1_16_R3.AnvilInventoryImpl.class);
+ ANVIL_INVENTORIES.put(Version.V1_14,
+ com.github.stefvanschie.inventoryframework.nms.v1_14.AnvilInventoryImpl.class);
+ ANVIL_INVENTORIES.put(Version.V1_15,
+ com.github.stefvanschie.inventoryframework.nms.v1_15.AnvilInventoryImpl.class);
+ ANVIL_INVENTORIES.put(Version.V1_16_1,
+ com.github.stefvanschie.inventoryframework.nms.v1_16_1.AnvilInventoryImpl.class);
+ ANVIL_INVENTORIES.put(Version.V1_16_2_3,
+ com.github.stefvanschie.inventoryframework.nms.v1_16_2_3.AnvilInventoryImpl.class);
+ ANVIL_INVENTORIES.put(Version.V1_16_4_5,
+ com.github.stefvanschie.inventoryframework.nms.v1_16_4_5.AnvilInventoryImpl.class);
+ ANVIL_INVENTORIES.put(Version.V1_17_0,
+ com.github.stefvanschie.inventoryframework.nms.v1_17_0.AnvilInventoryImpl.class);
+ ANVIL_INVENTORIES.put(Version.V1_17_1,
+ com.github.stefvanschie.inventoryframework.nms.v1_17_1.AnvilInventoryImpl.class);
+ ANVIL_INVENTORIES.put(Version.V1_18_0,
+ com.github.stefvanschie.inventoryframework.nms.v1_18_0.AnvilInventoryImpl.class);
+ ANVIL_INVENTORIES.put(Version.V1_18_1,
+ com.github.stefvanschie.inventoryframework.nms.v1_18_1.AnvilInventoryImpl.class);
+ ANVIL_INVENTORIES.put(Version.V1_18_2,
+ com.github.stefvanschie.inventoryframework.nms.v1_18_2.AnvilInventoryImpl.class);
+ ANVIL_INVENTORIES.put(Version.V1_19_0,
+ com.github.stefvanschie.inventoryframework.nms.v1_19_0.AnvilInventoryImpl.class);
+ ANVIL_INVENTORIES.put(Version.V1_19_1,
+ com.github.stefvanschie.inventoryframework.nms.v1_19_1.AnvilInventoryImpl.class);
+ ANVIL_INVENTORIES.put(Version.V1_19_2,
+ com.github.stefvanschie.inventoryframework.nms.v1_19_2.AnvilInventoryImpl.class);
+ ANVIL_INVENTORIES.put(Version.V1_19_3,
+ com.github.stefvanschie.inventoryframework.nms.v1_19_3.AnvilInventoryImpl.class);
+ ANVIL_INVENTORIES.put(Version.V1_19_4,
+ com.github.stefvanschie.inventoryframework.nms.v1_19_4.AnvilInventoryImpl.class);
+ ANVIL_INVENTORIES.put(Version.V1_20_0,
+ com.github.stefvanschie.inventoryframework.nms.v1_20_0.AnvilInventoryImpl.class);
+ ANVIL_INVENTORIES.put(Version.V1_20_1,
+ com.github.stefvanschie.inventoryframework.nms.v1_20_1.AnvilInventoryImpl.class);
+ ANVIL_INVENTORIES.put(Version.V1_20_2,
+ com.github.stefvanschie.inventoryframework.nms.v1_20_2.AnvilInventoryImpl.class);
+ ANVIL_INVENTORIES.put(Version.V1_20_3_4,
+ com.github.stefvanschie.inventoryframework.nms.v1_20_3.AnvilInventoryImpl.class);
+ ANVIL_INVENTORIES.put(Version.V1_20_5,
+ com.github.stefvanschie.inventoryframework.nms.v1_20_5.AnvilInventoryImpl.class);
+ ANVIL_INVENTORIES.put(Version.V1_20_6,
+ com.github.stefvanschie.inventoryframework.nms.v1_20_6.AnvilInventoryImpl.class);
+ ANVIL_INVENTORIES.put(Version.V1_21_0,
+ com.github.stefvanschie.inventoryframework.nms.v1_21_0.AnvilInventoryImpl.class);
+ ANVIL_INVENTORIES.put(Version.V1_21_1,
+ com.github.stefvanschie.inventoryframework.nms.v1_21_1.AnvilInventoryImpl.class);
+ ANVIL_INVENTORIES.put(Version.V1_21_2_3,
+ com.github.stefvanschie.inventoryframework.nms.v1_21_2_3.AnvilInventoryImpl.class);
BEACON_INVENTORIES = new EnumMap<>(Version.class);
- BEACON_INVENTORIES.put(Version.V1_14_R1,
- com.github.stefvanschie.inventoryframework.nms.v1_14_R1.BeaconInventoryImpl.class);
- BEACON_INVENTORIES.put(Version.V1_15_R1,
- com.github.stefvanschie.inventoryframework.nms.v1_15_R1.BeaconInventoryImpl.class);
- BEACON_INVENTORIES.put(Version.V1_16_R1,
- com.github.stefvanschie.inventoryframework.nms.v1_16_R1.BeaconInventoryImpl.class);
- BEACON_INVENTORIES.put(Version.V1_16_R2,
- com.github.stefvanschie.inventoryframework.nms.v1_16_R2.BeaconInventoryImpl.class);
- BEACON_INVENTORIES.put(Version.V1_16_R3,
- com.github.stefvanschie.inventoryframework.nms.v1_16_R3.BeaconInventoryImpl.class);
+ BEACON_INVENTORIES.put(Version.V1_14,
+ com.github.stefvanschie.inventoryframework.nms.v1_14.BeaconInventoryImpl.class);
+ BEACON_INVENTORIES.put(Version.V1_15,
+ com.github.stefvanschie.inventoryframework.nms.v1_15.BeaconInventoryImpl.class);
+ BEACON_INVENTORIES.put(Version.V1_16_1,
+ com.github.stefvanschie.inventoryframework.nms.v1_16_1.BeaconInventoryImpl.class);
+ BEACON_INVENTORIES.put(Version.V1_16_2_3,
+ com.github.stefvanschie.inventoryframework.nms.v1_16_2_3.BeaconInventoryImpl.class);
+ BEACON_INVENTORIES.put(Version.V1_16_4_5,
+ com.github.stefvanschie.inventoryframework.nms.v1_16_4_5.BeaconInventoryImpl.class);
+ BEACON_INVENTORIES.put(Version.V1_17_0,
+ com.github.stefvanschie.inventoryframework.nms.v1_17_0.BeaconInventoryImpl.class);
+ BEACON_INVENTORIES.put(Version.V1_17_1,
+ com.github.stefvanschie.inventoryframework.nms.v1_17_1.BeaconInventoryImpl.class);
+ BEACON_INVENTORIES.put(Version.V1_18_0,
+ com.github.stefvanschie.inventoryframework.nms.v1_18_0.BeaconInventoryImpl.class);
+ BEACON_INVENTORIES.put(Version.V1_18_1,
+ com.github.stefvanschie.inventoryframework.nms.v1_18_1.BeaconInventoryImpl.class);
+ BEACON_INVENTORIES.put(Version.V1_18_2,
+ com.github.stefvanschie.inventoryframework.nms.v1_18_2.BeaconInventoryImpl.class);
+ BEACON_INVENTORIES.put(Version.V1_19_0,
+ com.github.stefvanschie.inventoryframework.nms.v1_19_0.BeaconInventoryImpl.class);
+ BEACON_INVENTORIES.put(Version.V1_19_1,
+ com.github.stefvanschie.inventoryframework.nms.v1_19_1.BeaconInventoryImpl.class);
+ BEACON_INVENTORIES.put(Version.V1_19_2,
+ com.github.stefvanschie.inventoryframework.nms.v1_19_2.BeaconInventoryImpl.class);
+ BEACON_INVENTORIES.put(Version.V1_19_3,
+ com.github.stefvanschie.inventoryframework.nms.v1_19_3.BeaconInventoryImpl.class);
+ BEACON_INVENTORIES.put(Version.V1_19_4,
+ com.github.stefvanschie.inventoryframework.nms.v1_19_4.BeaconInventoryImpl.class);
+ BEACON_INVENTORIES.put(Version.V1_20_0,
+ com.github.stefvanschie.inventoryframework.nms.v1_20_0.BeaconInventoryImpl.class);
+ BEACON_INVENTORIES.put(Version.V1_20_1,
+ com.github.stefvanschie.inventoryframework.nms.v1_20_1.BeaconInventoryImpl.class);
+ BEACON_INVENTORIES.put(Version.V1_20_2,
+ com.github.stefvanschie.inventoryframework.nms.v1_20_2.BeaconInventoryImpl.class);
+ BEACON_INVENTORIES.put(Version.V1_20_3_4,
+ com.github.stefvanschie.inventoryframework.nms.v1_20_3.BeaconInventoryImpl.class);
+ BEACON_INVENTORIES.put(Version.V1_20_5,
+ com.github.stefvanschie.inventoryframework.nms.v1_20_5.BeaconInventoryImpl.class);
+ BEACON_INVENTORIES.put(Version.V1_20_6,
+ com.github.stefvanschie.inventoryframework.nms.v1_20_6.BeaconInventoryImpl.class);
+ BEACON_INVENTORIES.put(Version.V1_21_0,
+ com.github.stefvanschie.inventoryframework.nms.v1_21_0.BeaconInventoryImpl.class);
+ BEACON_INVENTORIES.put(Version.V1_21_1,
+ com.github.stefvanschie.inventoryframework.nms.v1_21_1.BeaconInventoryImpl.class);
+ BEACON_INVENTORIES.put(Version.V1_21_2_3,
+ com.github.stefvanschie.inventoryframework.nms.v1_21_2_3.BeaconInventoryImpl.class);
CARTOGRAPHY_TABLE_INVENTORIES = new EnumMap<>(Version.class);
- CARTOGRAPHY_TABLE_INVENTORIES.put(Version.V1_14_R1,
- com.github.stefvanschie.inventoryframework.nms.v1_14_R1.CartographyTableInventoryImpl.class);
- CARTOGRAPHY_TABLE_INVENTORIES.put(Version.V1_15_R1,
- com.github.stefvanschie.inventoryframework.nms.v1_15_R1.CartographyTableInventoryImpl.class);
- CARTOGRAPHY_TABLE_INVENTORIES.put(Version.V1_16_R1,
- com.github.stefvanschie.inventoryframework.nms.v1_16_R1.CartographyTableInventoryImpl.class);
- CARTOGRAPHY_TABLE_INVENTORIES.put(Version.V1_16_R2,
- com.github.stefvanschie.inventoryframework.nms.v1_16_R2.CartographyTableInventoryImpl.class);
- CARTOGRAPHY_TABLE_INVENTORIES.put(Version.V1_16_R3,
- com.github.stefvanschie.inventoryframework.nms.v1_16_R3.CartographyTableInventoryImpl.class);
+ CARTOGRAPHY_TABLE_INVENTORIES.put(Version.V1_14,
+ com.github.stefvanschie.inventoryframework.nms.v1_14.CartographyTableInventoryImpl.class);
+ CARTOGRAPHY_TABLE_INVENTORIES.put(Version.V1_15,
+ com.github.stefvanschie.inventoryframework.nms.v1_15.CartographyTableInventoryImpl.class);
+ CARTOGRAPHY_TABLE_INVENTORIES.put(Version.V1_16_1,
+ com.github.stefvanschie.inventoryframework.nms.v1_16_1.CartographyTableInventoryImpl.class);
+ CARTOGRAPHY_TABLE_INVENTORIES.put(Version.V1_16_2_3,
+ com.github.stefvanschie.inventoryframework.nms.v1_16_2_3.CartographyTableInventoryImpl.class);
+ CARTOGRAPHY_TABLE_INVENTORIES.put(Version.V1_16_4_5,
+ com.github.stefvanschie.inventoryframework.nms.v1_16_4_5.CartographyTableInventoryImpl.class);
+ CARTOGRAPHY_TABLE_INVENTORIES.put(Version.V1_17_0,
+ com.github.stefvanschie.inventoryframework.nms.v1_17_0.CartographyTableInventoryImpl.class);
+ CARTOGRAPHY_TABLE_INVENTORIES.put(Version.V1_17_1,
+ com.github.stefvanschie.inventoryframework.nms.v1_17_1.CartographyTableInventoryImpl.class);
+ CARTOGRAPHY_TABLE_INVENTORIES.put(Version.V1_18_0,
+ com.github.stefvanschie.inventoryframework.nms.v1_18_0.CartographyTableInventoryImpl.class);
+ CARTOGRAPHY_TABLE_INVENTORIES.put(Version.V1_18_1,
+ com.github.stefvanschie.inventoryframework.nms.v1_18_1.CartographyTableInventoryImpl.class);
+ CARTOGRAPHY_TABLE_INVENTORIES.put(Version.V1_18_2,
+ com.github.stefvanschie.inventoryframework.nms.v1_18_2.CartographyTableInventoryImpl.class);
+ CARTOGRAPHY_TABLE_INVENTORIES.put(Version.V1_19_0,
+ com.github.stefvanschie.inventoryframework.nms.v1_19_0.CartographyTableInventoryImpl.class);
+ CARTOGRAPHY_TABLE_INVENTORIES.put(Version.V1_19_1,
+ com.github.stefvanschie.inventoryframework.nms.v1_19_1.CartographyTableInventoryImpl.class);
+ CARTOGRAPHY_TABLE_INVENTORIES.put(Version.V1_19_2,
+ com.github.stefvanschie.inventoryframework.nms.v1_19_2.CartographyTableInventoryImpl.class);
+ CARTOGRAPHY_TABLE_INVENTORIES.put(Version.V1_19_3,
+ com.github.stefvanschie.inventoryframework.nms.v1_19_3.CartographyTableInventoryImpl.class);
+ CARTOGRAPHY_TABLE_INVENTORIES.put(Version.V1_19_4,
+ com.github.stefvanschie.inventoryframework.nms.v1_19_4.CartographyTableInventoryImpl.class);
+ CARTOGRAPHY_TABLE_INVENTORIES.put(Version.V1_20_0,
+ com.github.stefvanschie.inventoryframework.nms.v1_20_0.CartographyTableInventoryImpl.class);
+ CARTOGRAPHY_TABLE_INVENTORIES.put(Version.V1_20_1,
+ com.github.stefvanschie.inventoryframework.nms.v1_20_1.CartographyTableInventoryImpl.class);
+ CARTOGRAPHY_TABLE_INVENTORIES.put(Version.V1_20_2,
+ com.github.stefvanschie.inventoryframework.nms.v1_20_2.CartographyTableInventoryImpl.class);
+ CARTOGRAPHY_TABLE_INVENTORIES.put(Version.V1_20_3_4,
+ com.github.stefvanschie.inventoryframework.nms.v1_20_3.CartographyTableInventoryImpl.class);
+ CARTOGRAPHY_TABLE_INVENTORIES.put(Version.V1_20_5,
+ com.github.stefvanschie.inventoryframework.nms.v1_20_5.CartographyTableInventoryImpl.class);
+ CARTOGRAPHY_TABLE_INVENTORIES.put(Version.V1_20_6,
+ com.github.stefvanschie.inventoryframework.nms.v1_20_6.CartographyTableInventoryImpl.class);
+ CARTOGRAPHY_TABLE_INVENTORIES.put(Version.V1_21_0,
+ com.github.stefvanschie.inventoryframework.nms.v1_21_0.CartographyTableInventoryImpl.class);
+ CARTOGRAPHY_TABLE_INVENTORIES.put(Version.V1_21_1,
+ com.github.stefvanschie.inventoryframework.nms.v1_21_1.CartographyTableInventoryImpl.class);
+ CARTOGRAPHY_TABLE_INVENTORIES.put(Version.V1_21_2_3,
+ com.github.stefvanschie.inventoryframework.nms.v1_21_2_3.CartographyTableInventoryImpl.class);
ENCHANTING_TABLE_INVENTORIES = new EnumMap<>(Version.class);
- ENCHANTING_TABLE_INVENTORIES.put(Version.V1_14_R1,
- com.github.stefvanschie.inventoryframework.nms.v1_14_R1.EnchantingTableInventoryImpl.class);
- ENCHANTING_TABLE_INVENTORIES.put(Version.V1_15_R1,
- com.github.stefvanschie.inventoryframework.nms.v1_15_R1.EnchantingTableInventoryImpl.class);
- ENCHANTING_TABLE_INVENTORIES.put(Version.V1_16_R1,
- com.github.stefvanschie.inventoryframework.nms.v1_16_R1.EnchantingTableInventoryImpl.class);
- ENCHANTING_TABLE_INVENTORIES.put(Version.V1_16_R2,
- com.github.stefvanschie.inventoryframework.nms.v1_16_R2.EnchantingTableInventoryImpl.class);
- ENCHANTING_TABLE_INVENTORIES.put(Version.V1_16_R3,
- com.github.stefvanschie.inventoryframework.nms.v1_16_R3.EnchantingTableInventoryImpl.class);
+ ENCHANTING_TABLE_INVENTORIES.put(Version.V1_14,
+ com.github.stefvanschie.inventoryframework.nms.v1_14.EnchantingTableInventoryImpl.class);
+ ENCHANTING_TABLE_INVENTORIES.put(Version.V1_15,
+ com.github.stefvanschie.inventoryframework.nms.v1_15.EnchantingTableInventoryImpl.class);
+ ENCHANTING_TABLE_INVENTORIES.put(Version.V1_16_1,
+ com.github.stefvanschie.inventoryframework.nms.v1_16_1.EnchantingTableInventoryImpl.class);
+ ENCHANTING_TABLE_INVENTORIES.put(Version.V1_16_2_3,
+ com.github.stefvanschie.inventoryframework.nms.v1_16_2_3.EnchantingTableInventoryImpl.class);
+ ENCHANTING_TABLE_INVENTORIES.put(Version.V1_16_4_5,
+ com.github.stefvanschie.inventoryframework.nms.v1_16_4_5.EnchantingTableInventoryImpl.class);
+ ENCHANTING_TABLE_INVENTORIES.put(Version.V1_17_0,
+ com.github.stefvanschie.inventoryframework.nms.v1_17_0.EnchantingTableInventoryImpl.class);
+ ENCHANTING_TABLE_INVENTORIES.put(Version.V1_17_1,
+ com.github.stefvanschie.inventoryframework.nms.v1_17_1.EnchantingTableInventoryImpl.class);
+ ENCHANTING_TABLE_INVENTORIES.put(Version.V1_18_0,
+ com.github.stefvanschie.inventoryframework.nms.v1_18_0.EnchantingTableInventoryImpl.class);
+ ENCHANTING_TABLE_INVENTORIES.put(Version.V1_18_1,
+ com.github.stefvanschie.inventoryframework.nms.v1_18_1.EnchantingTableInventoryImpl.class);
+ ENCHANTING_TABLE_INVENTORIES.put(Version.V1_18_2,
+ com.github.stefvanschie.inventoryframework.nms.v1_18_2.EnchantingTableInventoryImpl.class);
+ ENCHANTING_TABLE_INVENTORIES.put(Version.V1_19_0,
+ com.github.stefvanschie.inventoryframework.nms.v1_19_0.EnchantingTableInventoryImpl.class);
+ ENCHANTING_TABLE_INVENTORIES.put(Version.V1_19_1,
+ com.github.stefvanschie.inventoryframework.nms.v1_19_1.EnchantingTableInventoryImpl.class);
+ ENCHANTING_TABLE_INVENTORIES.put(Version.V1_19_2,
+ com.github.stefvanschie.inventoryframework.nms.v1_19_2.EnchantingTableInventoryImpl.class);
+ ENCHANTING_TABLE_INVENTORIES.put(Version.V1_19_3,
+ com.github.stefvanschie.inventoryframework.nms.v1_19_3.EnchantingTableInventoryImpl.class);
+ ENCHANTING_TABLE_INVENTORIES.put(Version.V1_19_4,
+ com.github.stefvanschie.inventoryframework.nms.v1_19_4.EnchantingTableInventoryImpl.class);
+ ENCHANTING_TABLE_INVENTORIES.put(Version.V1_20_0,
+ com.github.stefvanschie.inventoryframework.nms.v1_20_0.EnchantingTableInventoryImpl.class);
+ ENCHANTING_TABLE_INVENTORIES.put(Version.V1_20_1,
+ com.github.stefvanschie.inventoryframework.nms.v1_20_1.EnchantingTableInventoryImpl.class);
+ ENCHANTING_TABLE_INVENTORIES.put(Version.V1_20_2,
+ com.github.stefvanschie.inventoryframework.nms.v1_20_2.EnchantingTableInventoryImpl.class);
+ ENCHANTING_TABLE_INVENTORIES.put(Version.V1_20_3_4,
+ com.github.stefvanschie.inventoryframework.nms.v1_20_3.EnchantingTableInventoryImpl.class);
+ ENCHANTING_TABLE_INVENTORIES.put(Version.V1_20_5,
+ com.github.stefvanschie.inventoryframework.nms.v1_20_5.EnchantingTableInventoryImpl.class);
+ ENCHANTING_TABLE_INVENTORIES.put(Version.V1_20_6,
+ com.github.stefvanschie.inventoryframework.nms.v1_20_6.EnchantingTableInventoryImpl.class);
+ ENCHANTING_TABLE_INVENTORIES.put(Version.V1_21_0,
+ com.github.stefvanschie.inventoryframework.nms.v1_21_0.EnchantingTableInventoryImpl.class);
+ ENCHANTING_TABLE_INVENTORIES.put(Version.V1_21_1,
+ com.github.stefvanschie.inventoryframework.nms.v1_21_1.EnchantingTableInventoryImpl.class);
+ ENCHANTING_TABLE_INVENTORIES.put(Version.V1_21_2_3,
+ com.github.stefvanschie.inventoryframework.nms.v1_21_2_3.EnchantingTableInventoryImpl.class);
GRINDSTONE_INVENTORIES = new EnumMap<>(Version.class);
- GRINDSTONE_INVENTORIES.put(Version.V1_14_R1,
- com.github.stefvanschie.inventoryframework.nms.v1_14_R1.GrindstoneInventoryImpl.class);
- GRINDSTONE_INVENTORIES.put(Version.V1_15_R1,
- com.github.stefvanschie.inventoryframework.nms.v1_15_R1.GrindstoneInventoryImpl.class);
- GRINDSTONE_INVENTORIES.put(Version.V1_16_R1,
- com.github.stefvanschie.inventoryframework.nms.v1_16_R1.GrindstoneInventoryImpl.class);
- GRINDSTONE_INVENTORIES.put(Version.V1_16_R2,
- com.github.stefvanschie.inventoryframework.nms.v1_16_R2.GrindstoneInventoryImpl.class);
- GRINDSTONE_INVENTORIES.put(Version.V1_16_R3,
- com.github.stefvanschie.inventoryframework.nms.v1_16_R3.GrindstoneInventoryImpl.class);
+ GRINDSTONE_INVENTORIES.put(Version.V1_14,
+ com.github.stefvanschie.inventoryframework.nms.v1_14.GrindstoneInventoryImpl.class);
+ GRINDSTONE_INVENTORIES.put(Version.V1_15,
+ com.github.stefvanschie.inventoryframework.nms.v1_15.GrindstoneInventoryImpl.class);
+ GRINDSTONE_INVENTORIES.put(Version.V1_16_1,
+ com.github.stefvanschie.inventoryframework.nms.v1_16_1.GrindstoneInventoryImpl.class);
+ GRINDSTONE_INVENTORIES.put(Version.V1_16_2_3,
+ com.github.stefvanschie.inventoryframework.nms.v1_16_2_3.GrindstoneInventoryImpl.class);
+ GRINDSTONE_INVENTORIES.put(Version.V1_16_4_5,
+ com.github.stefvanschie.inventoryframework.nms.v1_16_4_5.GrindstoneInventoryImpl.class);
+ GRINDSTONE_INVENTORIES.put(Version.V1_17_0,
+ com.github.stefvanschie.inventoryframework.nms.v1_17_0.GrindstoneInventoryImpl.class);
+ GRINDSTONE_INVENTORIES.put(Version.V1_17_1,
+ com.github.stefvanschie.inventoryframework.nms.v1_17_1.GrindstoneInventoryImpl.class);
+ GRINDSTONE_INVENTORIES.put(Version.V1_18_0,
+ com.github.stefvanschie.inventoryframework.nms.v1_18_0.GrindstoneInventoryImpl.class);
+ GRINDSTONE_INVENTORIES.put(Version.V1_18_1,
+ com.github.stefvanschie.inventoryframework.nms.v1_18_1.GrindstoneInventoryImpl.class);
+ GRINDSTONE_INVENTORIES.put(Version.V1_18_2,
+ com.github.stefvanschie.inventoryframework.nms.v1_18_2.GrindstoneInventoryImpl.class);
+ GRINDSTONE_INVENTORIES.put(Version.V1_19_0,
+ com.github.stefvanschie.inventoryframework.nms.v1_19_0.GrindstoneInventoryImpl.class);
+ GRINDSTONE_INVENTORIES.put(Version.V1_19_1,
+ com.github.stefvanschie.inventoryframework.nms.v1_19_1.GrindstoneInventoryImpl.class);
+ GRINDSTONE_INVENTORIES.put(Version.V1_19_2,
+ com.github.stefvanschie.inventoryframework.nms.v1_19_2.GrindstoneInventoryImpl.class);
+ GRINDSTONE_INVENTORIES.put(Version.V1_19_3,
+ com.github.stefvanschie.inventoryframework.nms.v1_19_3.GrindstoneInventoryImpl.class);
+ GRINDSTONE_INVENTORIES.put(Version.V1_19_4,
+ com.github.stefvanschie.inventoryframework.nms.v1_19_4.GrindstoneInventoryImpl.class);
+ GRINDSTONE_INVENTORIES.put(Version.V1_20_0,
+ com.github.stefvanschie.inventoryframework.nms.v1_20_0.GrindstoneInventoryImpl.class);
+ GRINDSTONE_INVENTORIES.put(Version.V1_20_1,
+ com.github.stefvanschie.inventoryframework.nms.v1_20_1.GrindstoneInventoryImpl.class);
+ GRINDSTONE_INVENTORIES.put(Version.V1_20_2,
+ com.github.stefvanschie.inventoryframework.nms.v1_20_2.GrindstoneInventoryImpl.class);
+ GRINDSTONE_INVENTORIES.put(Version.V1_20_3_4,
+ com.github.stefvanschie.inventoryframework.nms.v1_20_3.GrindstoneInventoryImpl.class);
+ GRINDSTONE_INVENTORIES.put(Version.V1_20_5,
+ com.github.stefvanschie.inventoryframework.nms.v1_20_5.GrindstoneInventoryImpl.class);
+ GRINDSTONE_INVENTORIES.put(Version.V1_20_6,
+ com.github.stefvanschie.inventoryframework.nms.v1_20_6.GrindstoneInventoryImpl.class);
+ GRINDSTONE_INVENTORIES.put(Version.V1_21_0,
+ com.github.stefvanschie.inventoryframework.nms.v1_21_0.GrindstoneInventoryImpl.class);
+ GRINDSTONE_INVENTORIES.put(Version.V1_21_1,
+ com.github.stefvanschie.inventoryframework.nms.v1_21_1.GrindstoneInventoryImpl.class);
+ GRINDSTONE_INVENTORIES.put(Version.V1_21_2_3,
+ com.github.stefvanschie.inventoryframework.nms.v1_21_2_3.GrindstoneInventoryImpl.class);
+
+ MERCHANT_INVENTORIES = new EnumMap<>(Version.class);
+ MERCHANT_INVENTORIES.put(Version.V1_14,
+ com.github.stefvanschie.inventoryframework.nms.v1_14.MerchantInventoryImpl.class);
+ MERCHANT_INVENTORIES.put(Version.V1_15,
+ com.github.stefvanschie.inventoryframework.nms.v1_15.MerchantInventoryImpl.class);
+ MERCHANT_INVENTORIES.put(Version.V1_16_1,
+ com.github.stefvanschie.inventoryframework.nms.v1_16_1.MerchantInventoryImpl.class);
+ MERCHANT_INVENTORIES.put(Version.V1_16_2_3,
+ com.github.stefvanschie.inventoryframework.nms.v1_16_2_3.MerchantInventoryImpl.class);
+ MERCHANT_INVENTORIES.put(Version.V1_16_4_5,
+ com.github.stefvanschie.inventoryframework.nms.v1_16_4_5.MerchantInventoryImpl.class);
+ MERCHANT_INVENTORIES.put(Version.V1_17_0,
+ com.github.stefvanschie.inventoryframework.nms.v1_17_0.MerchantInventoryImpl.class);
+ MERCHANT_INVENTORIES.put(Version.V1_17_1,
+ com.github.stefvanschie.inventoryframework.nms.v1_17_1.MerchantInventoryImpl.class);
+ MERCHANT_INVENTORIES.put(Version.V1_18_0,
+ com.github.stefvanschie.inventoryframework.nms.v1_18_0.MerchantInventoryImpl.class);
+ MERCHANT_INVENTORIES.put(Version.V1_18_1,
+ com.github.stefvanschie.inventoryframework.nms.v1_18_1.MerchantInventoryImpl.class);
+ MERCHANT_INVENTORIES.put(Version.V1_18_2,
+ com.github.stefvanschie.inventoryframework.nms.v1_18_2.MerchantInventoryImpl.class);
+ MERCHANT_INVENTORIES.put(Version.V1_19_0,
+ com.github.stefvanschie.inventoryframework.nms.v1_19_0.MerchantInventoryImpl.class);
+ MERCHANT_INVENTORIES.put(Version.V1_19_1,
+ com.github.stefvanschie.inventoryframework.nms.v1_19_1.MerchantInventoryImpl.class);
+ MERCHANT_INVENTORIES.put(Version.V1_19_2,
+ com.github.stefvanschie.inventoryframework.nms.v1_19_2.MerchantInventoryImpl.class);
+ MERCHANT_INVENTORIES.put(Version.V1_19_3,
+ com.github.stefvanschie.inventoryframework.nms.v1_19_3.MerchantInventoryImpl.class);
+ MERCHANT_INVENTORIES.put(Version.V1_19_4,
+ com.github.stefvanschie.inventoryframework.nms.v1_19_4.MerchantInventoryImpl.class);
+ MERCHANT_INVENTORIES.put(Version.V1_20_0,
+ com.github.stefvanschie.inventoryframework.nms.v1_20_0.MerchantInventoryImpl.class);
+ MERCHANT_INVENTORIES.put(Version.V1_20_1,
+ com.github.stefvanschie.inventoryframework.nms.v1_20_1.MerchantInventoryImpl.class);
+ MERCHANT_INVENTORIES.put(Version.V1_20_2,
+ com.github.stefvanschie.inventoryframework.nms.v1_20_2.MerchantInventoryImpl.class);
+ MERCHANT_INVENTORIES.put(Version.V1_20_3_4,
+ com.github.stefvanschie.inventoryframework.nms.v1_20_3.MerchantInventoryImpl.class);
+ MERCHANT_INVENTORIES.put(Version.V1_20_5,
+ com.github.stefvanschie.inventoryframework.nms.v1_20_5.MerchantInventoryImpl.class);
+ MERCHANT_INVENTORIES.put(Version.V1_20_6,
+ com.github.stefvanschie.inventoryframework.nms.v1_20_6.MerchantInventoryImpl.class);
+ MERCHANT_INVENTORIES.put(Version.V1_21_0,
+ com.github.stefvanschie.inventoryframework.nms.v1_21_0.MerchantInventoryImpl.class);
+ MERCHANT_INVENTORIES.put(Version.V1_21_1,
+ com.github.stefvanschie.inventoryframework.nms.v1_21_1.MerchantInventoryImpl.class);
+ MERCHANT_INVENTORIES.put(Version.V1_21_2_3,
+ com.github.stefvanschie.inventoryframework.nms.v1_21_2_3.MerchantInventoryImpl.class);
SMITHING_TABLE_INVENTORIES = new EnumMap<>(Version.class);
- SMITHING_TABLE_INVENTORIES.put(Version.V1_16_R1,
- com.github.stefvanschie.inventoryframework.nms.v1_16_R1.SmithingTableInventoryImpl.class);
- SMITHING_TABLE_INVENTORIES.put(Version.V1_16_R2,
- com.github.stefvanschie.inventoryframework.nms.v1_16_R2.SmithingTableInventoryImpl.class);
- SMITHING_TABLE_INVENTORIES.put(Version.V1_16_R3,
- com.github.stefvanschie.inventoryframework.nms.v1_16_R3.SmithingTableInventoryImpl.class);
+ SMITHING_TABLE_INVENTORIES.put(Version.V1_19_4,
+ com.github.stefvanschie.inventoryframework.nms.v1_19_4.SmithingTableInventoryImpl.class);
+ SMITHING_TABLE_INVENTORIES.put(Version.V1_20_0,
+ com.github.stefvanschie.inventoryframework.nms.v1_20_0.SmithingTableInventoryImpl.class);
+ SMITHING_TABLE_INVENTORIES.put(Version.V1_20_1,
+ com.github.stefvanschie.inventoryframework.nms.v1_20_1.SmithingTableInventoryImpl.class);
+ SMITHING_TABLE_INVENTORIES.put(Version.V1_20_2,
+ com.github.stefvanschie.inventoryframework.nms.v1_20_2.SmithingTableInventoryImpl.class);
+ SMITHING_TABLE_INVENTORIES.put(Version.V1_20_3_4,
+ com.github.stefvanschie.inventoryframework.nms.v1_20_3.SmithingTableInventoryImpl.class);
+ SMITHING_TABLE_INVENTORIES.put(Version.V1_20_5,
+ com.github.stefvanschie.inventoryframework.nms.v1_20_5.SmithingTableInventoryImpl.class);
+ SMITHING_TABLE_INVENTORIES.put(Version.V1_20_6,
+ com.github.stefvanschie.inventoryframework.nms.v1_20_6.SmithingTableInventoryImpl.class);
+ SMITHING_TABLE_INVENTORIES.put(Version.V1_21_0,
+ com.github.stefvanschie.inventoryframework.nms.v1_21_0.SmithingTableInventoryImpl.class);
+ SMITHING_TABLE_INVENTORIES.put(Version.V1_21_1,
+ com.github.stefvanschie.inventoryframework.nms.v1_21_1.SmithingTableInventoryImpl.class);
+ SMITHING_TABLE_INVENTORIES.put(Version.V1_21_2_3,
+ com.github.stefvanschie.inventoryframework.nms.v1_21_2_3.SmithingTableInventoryImpl.class);
+
+ LEGACY_SMITHING_TABLE_INVENTORIES = new EnumMap<>(Version.class);
+ LEGACY_SMITHING_TABLE_INVENTORIES.put(Version.V1_16_1,
+ com.github.stefvanschie.inventoryframework.nms.v1_16_1.SmithingTableInventoryImpl.class);
+ LEGACY_SMITHING_TABLE_INVENTORIES.put(Version.V1_16_2_3,
+ com.github.stefvanschie.inventoryframework.nms.v1_16_2_3.SmithingTableInventoryImpl.class);
+ LEGACY_SMITHING_TABLE_INVENTORIES.put(Version.V1_16_4_5,
+ com.github.stefvanschie.inventoryframework.nms.v1_16_4_5.SmithingTableInventoryImpl.class);
+ LEGACY_SMITHING_TABLE_INVENTORIES.put(Version.V1_17_0,
+ com.github.stefvanschie.inventoryframework.nms.v1_17_0.SmithingTableInventoryImpl.class);
+ LEGACY_SMITHING_TABLE_INVENTORIES.put(Version.V1_17_1,
+ com.github.stefvanschie.inventoryframework.nms.v1_17_1.SmithingTableInventoryImpl.class);
+ LEGACY_SMITHING_TABLE_INVENTORIES.put(Version.V1_18_0,
+ com.github.stefvanschie.inventoryframework.nms.v1_18_0.SmithingTableInventoryImpl.class);
+ LEGACY_SMITHING_TABLE_INVENTORIES.put(Version.V1_18_1,
+ com.github.stefvanschie.inventoryframework.nms.v1_18_1.SmithingTableInventoryImpl.class);
+ LEGACY_SMITHING_TABLE_INVENTORIES.put(Version.V1_18_2,
+ com.github.stefvanschie.inventoryframework.nms.v1_18_2.SmithingTableInventoryImpl.class);
+ LEGACY_SMITHING_TABLE_INVENTORIES.put(Version.V1_19_0,
+ com.github.stefvanschie.inventoryframework.nms.v1_19_0.SmithingTableInventoryImpl.class);
+ LEGACY_SMITHING_TABLE_INVENTORIES.put(Version.V1_19_1,
+ com.github.stefvanschie.inventoryframework.nms.v1_19_1.SmithingTableInventoryImpl.class);
+ LEGACY_SMITHING_TABLE_INVENTORIES.put(Version.V1_19_2,
+ com.github.stefvanschie.inventoryframework.nms.v1_19_2.SmithingTableInventoryImpl.class);
+ LEGACY_SMITHING_TABLE_INVENTORIES.put(Version.V1_19_3,
+ com.github.stefvanschie.inventoryframework.nms.v1_19_3.SmithingTableInventoryImpl.class);
+ LEGACY_SMITHING_TABLE_INVENTORIES.put(Version.V1_19_4,
+ LegacySmithingTableInventoryImpl.class);
STONECUTTER_INVENTORIES = new EnumMap<>(Version.class);
- STONECUTTER_INVENTORIES.put(Version.V1_14_R1,
- com.github.stefvanschie.inventoryframework.nms.v1_14_R1.StonecutterInventoryImpl.class);
- STONECUTTER_INVENTORIES.put(Version.V1_15_R1,
- com.github.stefvanschie.inventoryframework.nms.v1_15_R1.StonecutterInventoryImpl.class);
- STONECUTTER_INVENTORIES.put(Version.V1_16_R1,
- com.github.stefvanschie.inventoryframework.nms.v1_16_R1.StonecutterInventoryImpl.class);
- STONECUTTER_INVENTORIES.put(Version.V1_16_R2,
- com.github.stefvanschie.inventoryframework.nms.v1_16_R2.StonecutterInventoryImpl.class);
- STONECUTTER_INVENTORIES.put(Version.V1_16_R3,
- com.github.stefvanschie.inventoryframework.nms.v1_16_R3.StonecutterInventoryImpl.class);
+ STONECUTTER_INVENTORIES.put(Version.V1_14,
+ com.github.stefvanschie.inventoryframework.nms.v1_14.StonecutterInventoryImpl.class);
+ STONECUTTER_INVENTORIES.put(Version.V1_15,
+ com.github.stefvanschie.inventoryframework.nms.v1_15.StonecutterInventoryImpl.class);
+ STONECUTTER_INVENTORIES.put(Version.V1_16_1,
+ com.github.stefvanschie.inventoryframework.nms.v1_16_1.StonecutterInventoryImpl.class);
+ STONECUTTER_INVENTORIES.put(Version.V1_16_2_3,
+ com.github.stefvanschie.inventoryframework.nms.v1_16_2_3.StonecutterInventoryImpl.class);
+ STONECUTTER_INVENTORIES.put(Version.V1_16_4_5,
+ com.github.stefvanschie.inventoryframework.nms.v1_16_4_5.StonecutterInventoryImpl.class);
+ STONECUTTER_INVENTORIES.put(Version.V1_17_0,
+ com.github.stefvanschie.inventoryframework.nms.v1_17_0.StonecutterInventoryImpl.class);
+ STONECUTTER_INVENTORIES.put(Version.V1_17_1,
+ com.github.stefvanschie.inventoryframework.nms.v1_17_1.StonecutterInventoryImpl.class);
+ STONECUTTER_INVENTORIES.put(Version.V1_18_0,
+ com.github.stefvanschie.inventoryframework.nms.v1_18_0.StonecutterInventoryImpl.class);
+ STONECUTTER_INVENTORIES.put(Version.V1_18_1,
+ com.github.stefvanschie.inventoryframework.nms.v1_18_1.StonecutterInventoryImpl.class);
+ STONECUTTER_INVENTORIES.put(Version.V1_18_2,
+ com.github.stefvanschie.inventoryframework.nms.v1_18_2.StonecutterInventoryImpl.class);
+ STONECUTTER_INVENTORIES.put(Version.V1_19_0,
+ com.github.stefvanschie.inventoryframework.nms.v1_19_0.StonecutterInventoryImpl.class);
+ STONECUTTER_INVENTORIES.put(Version.V1_19_1,
+ com.github.stefvanschie.inventoryframework.nms.v1_19_1.StonecutterInventoryImpl.class);
+ STONECUTTER_INVENTORIES.put(Version.V1_19_2,
+ com.github.stefvanschie.inventoryframework.nms.v1_19_2.StonecutterInventoryImpl.class);
+ STONECUTTER_INVENTORIES.put(Version.V1_19_3,
+ com.github.stefvanschie.inventoryframework.nms.v1_19_3.StonecutterInventoryImpl.class);
+ STONECUTTER_INVENTORIES.put(Version.V1_19_4,
+ com.github.stefvanschie.inventoryframework.nms.v1_19_4.StonecutterInventoryImpl.class);
+ STONECUTTER_INVENTORIES.put(Version.V1_20_0,
+ com.github.stefvanschie.inventoryframework.nms.v1_20_0.StonecutterInventoryImpl.class);
+ STONECUTTER_INVENTORIES.put(Version.V1_20_1,
+ com.github.stefvanschie.inventoryframework.nms.v1_20_1.StonecutterInventoryImpl.class);
+ STONECUTTER_INVENTORIES.put(Version.V1_20_2,
+ com.github.stefvanschie.inventoryframework.nms.v1_20_2.StonecutterInventoryImpl.class);
+ STONECUTTER_INVENTORIES.put(Version.V1_20_3_4,
+ com.github.stefvanschie.inventoryframework.nms.v1_20_3.StonecutterInventoryImpl.class);
+ STONECUTTER_INVENTORIES.put(Version.V1_20_5,
+ com.github.stefvanschie.inventoryframework.nms.v1_20_5.StonecutterInventoryImpl.class);
+ STONECUTTER_INVENTORIES.put(Version.V1_20_6,
+ com.github.stefvanschie.inventoryframework.nms.v1_20_6.StonecutterInventoryImpl.class);
+ STONECUTTER_INVENTORIES.put(Version.V1_21_0,
+ com.github.stefvanschie.inventoryframework.nms.v1_21_0.StonecutterInventoryImpl.class);
+ STONECUTTER_INVENTORIES.put(Version.V1_21_1,
+ com.github.stefvanschie.inventoryframework.nms.v1_21_1.StonecutterInventoryImpl.class);
+ STONECUTTER_INVENTORIES.put(Version.V1_21_2_3,
+ com.github.stefvanschie.inventoryframework.nms.v1_21_2_3.StonecutterInventoryImpl.class);
}
}
diff --git a/IF/src/test/java/com/github/stefvanschie/inventoryframework/pane/OutlinePaneTest.java b/IF/src/test/java/com/github/stefvanschie/inventoryframework/pane/OutlinePaneTest.java
index 3522c1185..29f0a4411 100644
--- a/IF/src/test/java/com/github/stefvanschie/inventoryframework/pane/OutlinePaneTest.java
+++ b/IF/src/test/java/com/github/stefvanschie/inventoryframework/pane/OutlinePaneTest.java
@@ -24,6 +24,7 @@ void testCopy() {
original.flipHorizontally(true);
original.flipVertically(true);
original.applyMask(new Mask("0"));
+ original.align(OutlinePane.Alignment.CENTER);
OutlinePane copy = original.copy();
@@ -42,6 +43,7 @@ void testCopy() {
assertEquals(original.isFlippedHorizontally(), copy.isFlippedHorizontally());
assertEquals(original.isFlippedVertically(), copy.isFlippedVertically());
assertEquals(original.getMask(), copy.getMask());
+ assertEquals(original.getAlignment(), copy.getAlignment());
assertEquals(original.getUUID(), copy.getUUID());
}
}
diff --git a/IF/src/test/java/com/github/stefvanschie/inventoryframework/pane/PaginatedPaneTest.java b/IF/src/test/java/com/github/stefvanschie/inventoryframework/pane/PaginatedPaneTest.java
index 6be43125d..af2c6b54e 100644
--- a/IF/src/test/java/com/github/stefvanschie/inventoryframework/pane/PaginatedPaneTest.java
+++ b/IF/src/test/java/com/github/stefvanschie/inventoryframework/pane/PaginatedPaneTest.java
@@ -1,15 +1,60 @@
package com.github.stefvanschie.inventoryframework.pane;
-import com.github.stefvanschie.inventoryframework.font.util.Font;
-import com.github.stefvanschie.inventoryframework.pane.component.Label;
-import com.github.stefvanschie.inventoryframework.pane.component.PercentageBar;
-import com.github.stefvanschie.inventoryframework.pane.component.ToggleButton;
import org.junit.jupiter.api.Test;
+import java.util.Collection;
+
import static org.junit.jupiter.api.Assertions.*;
public class PaginatedPaneTest {
+ @Test
+ void testAddPageEmpty() {
+ PaginatedPane paginatedPane = new PaginatedPane(0, 0, 1, 1);
+
+ StaticPane staticPane = new StaticPane(0, 0, 1, 1);
+
+ assertDoesNotThrow(() -> {
+ paginatedPane.addPage(staticPane);
+
+ Collection panes = paginatedPane.getPanes(0);
+
+ assertEquals(1, panes.size());
+ assertSame(staticPane, panes.iterator().next());
+ });
+ }
+
+ @Test
+ void testAddPageNotEmpty() {
+ PaginatedPane paginatedPane = new PaginatedPane(0, 0, 1, 1);
+
+ StaticPane staticPane1 = new StaticPane(0, 0, 1, 1);
+ StaticPane staticPane2 = new StaticPane(0, 0, 1, 1);
+
+ paginatedPane.addPane(0, staticPane1);
+
+ assertDoesNotThrow(() -> {
+ paginatedPane.addPage(staticPane2);
+
+ Collection panes = paginatedPane.getPanes(1);
+
+ assertEquals(1, panes.size());
+ assertSame(staticPane2, panes.iterator().next());
+ });
+ }
+
+ @Test
+ void testAddPageException() {
+ PaginatedPane paginatedPane = new PaginatedPane(0, 0, 1, 1);
+
+ StaticPane staticPane1 = new StaticPane(0, 0, 1, 1);
+ StaticPane staticPane2 = new StaticPane(0, 0, 1, 1);
+
+ paginatedPane.addPane(Integer.MAX_VALUE, staticPane1);
+
+ assertThrows(ArithmeticException.class, () -> paginatedPane.addPage(staticPane2));
+ }
+
@Test
void testCopy() {
PaginatedPane original = new PaginatedPane(5, 5, 4, 1, Pane.Priority.NORMAL);
@@ -37,4 +82,37 @@ void testCopy() {
assertEquals(original.getPages(), copy.getPages());
assertEquals(original.getUUID(), copy.getUUID());
}
+
+ @Test
+ void testDeletePageExists() {
+ PaginatedPane pane = new PaginatedPane(0, 0, 1, 1);
+
+ StaticPane staticPane = new StaticPane(0, 0, 1, 1);
+
+ pane.addPane(0, new StaticPane(0, 0, 1, 1));
+ pane.addPane(1, staticPane);
+
+ pane.deletePage(0);
+
+ assertEquals(1, pane.getPages());
+ assertEquals(1, pane.getPanes(0).size());
+ assertSame(staticPane, pane.getPanes(0).toArray(new Pane[0])[0]);
+ }
+
+ @Test
+ void testDeletePageNotExists() {
+ PaginatedPane pane = new PaginatedPane(0, 0, 1, 1);
+
+ StaticPane staticPane1 = new StaticPane(0, 0, 1, 1);
+ StaticPane staticPane2 = new StaticPane(0, 0, 1, 1);
+
+ pane.addPane(0, staticPane1);
+ pane.addPane(1, staticPane2);
+
+ pane.deletePage(2);
+
+ assertEquals(2, pane.getPages());
+ assertSame(staticPane1, pane.getPanes(0).toArray(new Pane[0])[0]);
+ assertSame(staticPane2, pane.getPanes(1).toArray(new Pane[0])[0]);
+ }
}
diff --git a/IF/src/test/java/com/github/stefvanschie/inventoryframework/pane/util/MaskTest.java b/IF/src/test/java/com/github/stefvanschie/inventoryframework/pane/util/MaskTest.java
index 3545e05ab..189af67ef 100644
--- a/IF/src/test/java/com/github/stefvanschie/inventoryframework/pane/util/MaskTest.java
+++ b/IF/src/test/java/com/github/stefvanschie/inventoryframework/pane/util/MaskTest.java
@@ -39,6 +39,11 @@ void testGetColumn() {
"10",
"00"
).getColumn(0));
+
+ assertArrayEquals(new boolean[] {true, false}, new Mask(
+ "1",
+ "0"
+ ).getColumn(0));
}
@Test
diff --git a/IF/src/test/java/com/github/stefvanschie/inventoryframework/pane/util/SlotTest.java b/IF/src/test/java/com/github/stefvanschie/inventoryframework/pane/util/SlotTest.java
new file mode 100644
index 000000000..2ad037ef8
--- /dev/null
+++ b/IF/src/test/java/com/github/stefvanschie/inventoryframework/pane/util/SlotTest.java
@@ -0,0 +1,23 @@
+package com.github.stefvanschie.inventoryframework.pane.util;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+public class SlotTest {
+
+ @Test
+ void testEquals() {
+ assertEquals(Slot.fromXY(0, 0), Slot.fromXY(0, 0));
+ assertNotEquals(Slot.fromXY(0, 1), Slot.fromXY(1, 0));
+
+ assertEquals(Slot.fromIndex(0), Slot.fromIndex(0));
+ assertNotEquals(Slot.fromIndex(0), Slot.fromIndex(1));
+ }
+
+ @Test
+ void testHashCode() {
+ assertEquals(Slot.fromXY(0, 0).hashCode(), Slot.fromXY(0, 0).hashCode());
+ assertEquals(Slot.fromIndex(0).hashCode(), Slot.fromIndex(0).hashCode());
+ }
+}
diff --git a/README.md b/README.md
index a6d6353e1..666872443 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# IF
-*This framework works for Minecraft versions 1.14-1.16*
+*This framework works for Minecraft versions 1.14-1.21*
An inventory framework for managing GUIs
@@ -14,7 +14,7 @@ To add this project as a dependency to your pom.xml, add the following to your p
com.github.stefvanschie.inventoryframework
IF
- 0.9.8
+ 0.10.18
```
The project is in the Central Repository, so specifying a repository is not needed.
@@ -24,7 +24,7 @@ Now in order to shade the project into your project, add the following to your p
org.apache.maven.plugins
maven-shade-plugin
- 3.2.2
+ 3.5.2
${project.build.directory}/dependency-reduced-pom.xml
@@ -50,7 +50,7 @@ Replace [YOUR PACKAGE] with the top-level package of your project.
To add this project as a dependency for your Gradle project, make sure your `dependencies` section of your build.gradle looks like the following:
```Groovy
dependencies {
- compile 'com.github.stefvanschie.inventoryframework:IF:0.9.8'
+ implementation 'com.github.stefvanschie.inventoryframework:IF:0.10.18'
// ...
}
```
@@ -63,7 +63,10 @@ repositories {
```
In order to include the project in your own project, you will need to use the `shadowJar` plugin. If you don't have it already, add the following to the top of your file:
```Groovy
-apply plugin: 'com.github.johnrengelman.shadow'
+plugins {
+ // ...
+ id "com.github.johnrengelman.shadow" version "7.1.2"
+}
```
To relocate the project's classes to your own namespace, add the following, with [YOUR PACKAGE] being the top-level package of your project:
```Groovy
@@ -72,11 +75,162 @@ shadowJar {
}
```
+## Dependency via plugin.yml
+IF does **not** support declaring the dependency via the libraries section in the plugin.yml. Please make use of a build tool as described above to use IF as a dependency.
+
## Building from source
-If you want to build this project from source, run the following from Git Bash:
+If you want to build this project from source, run the following:
git clone https://github.com/stefvanschie/IF.git
- cd IF
- mvn clean package
-The build can then be found in /IF/target/.
+This will clone this repository to your device. This project relies on NMS, for which the dependencies are not available online. Because of this, you'll need to follow additional steps to obtain all these dependencies locally.
+
+### Installing Paper manually
+For versions 1.14-1.16, we have to manually install Paper. Run the following scripts for each version to install the dependencies locally. Running these commands generate additional files in the folder where you execute them. To ensure that you don't accidentallly overwrite other files, execute this in an empty folder. The files that get created can be deleted afterwards (either after installing a single version or after installing all of them), since they're no longer necessary.
+
+#### 1.14.4
+```
+wget https://papermc.io/api/v2/projects/paper/versions/1.14.4/builds/243/downloads/paper-1.14.4-243.jar -O paperclip/paper-1.14.4.jar
+java -jar paper-1.14.4.jar
+mvn install:install-file -Dfile=cache/patched_1.14.4.jar -DgroupId="io.papermc" -DartifactId="paper" -Dversion="1.14.4-R0.1-SNAPSHOT" -Dpackaging="jar"
+```
+
+#### 1.15.2
+```
+wget https://papermc.io/api/v2/projects/paper/versions/1.15.2/builds/391/downloads/paper-1.15.2-391.jar -O paperclip/paper-1.15.2.jar
+java -jar paper-1.15.2.jar
+mvn install:install-file -Dfile=cache/patched_1.15.2.jar -DgroupId="io.papermc" -DartifactId="paper" -Dversion="1.15.2-R0.1-SNAPSHOT" -Dpackaging="jar"
+```
+
+#### 1.16.1
+```
+wget https://papermc.io/api/v2/projects/paper/versions/1.16.1/builds/138/downloads/paper-1.16.1-138.jar -O paperclip/paper-1.16.1.jar
+java -jar paper-1.16.1.jar
+mvn install:install-file -Dfile=cache/patched_1.16.1.jar -DgroupId="io.papermc" -DartifactId="paper" -Dversion="1.16.1-R0.1-SNAPSHOT" -Dpackaging="jar"
+```
+
+#### 1.16.3
+```
+wget https://papermc.io/api/v2/projects/paper/versions/1.16.3/builds/253/downloads/paper-1.16.3-253.jar -O paperclip/paper-1.16.3.jar
+java -jar paper-1.16.3.jar
+mvn install:install-file -Dfile=cache/patched_1.16.3.jar -DgroupId="io.papermc" -DartifactId="paper" -Dversion="1.16.3-R0.1-SNAPSHOT" -Dpackaging="jar"
+```
+
+#### 1.16.4
+```
+wget https://papermc.io/api/v2/projects/paper/versions/1.16.4/builds/416/downloads/paper-1.16.4-416.jar -O paperclip/paper-1.16.4.jar
+java -jar paper-1.16.4.jar
+mvn install:install-file -Dfile=cache/patched_1.16.4.jar -DgroupId="io.papermc" -DartifactId="paper" -Dversion="1.16.4-R0.1-SNAPSHOT" -Dpackaging="jar"
+```
+
+### Installing Paper via the maven plugin
+For versions 1.17-1.20.4, we use Paper via the [paper-nms-maven-plugin](https://github.com/Alvinn8/paper-nms-maven-plugin). To install these versions locally, we must run a few maven commands. These commands should be ran in the root directory of the project.
+```
+mvn paper-nms:init -pl nms/1_17_0
+mvn paper-nms:init -pl nms/1_17_1
+mvn paper-nms:init -pl nms/1_18_0
+mvn paper-nms:init -pl nms/1_18_1
+mvn paper-nms:init -pl nms/1_18_2
+mvn paper-nms:init -pl nms/1_19_0
+mvn paper-nms:init -pl nms/1_19_1
+mvn paper-nms:init -pl nms/1_19_2
+mvn paper-nms:init -pl nms/1_19_3
+mvn paper-nms:init -pl nms/1_19_4
+mvn paper-nms:init -pl nms/1_20_0-1
+mvn paper-nms:init -pl nms/1_20_2
+mvn paper-nms:init -pl nms/1_20_3-4
+```
+
+### Installing Spigot via BuildTools
+For versions 1.20.5-1.21.3, we use BuildTools. To install these versions, we run the following commands.
+```
+wget https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar -O BuildTools.jar
+
+git clone https://hub.spigotmc.org/stash/scm/spigot/bukkit.git Bukkit
+cd Bukkit
+git checkout 304e83eb384c338546aa96eea51388e0e8407e26
+cd ..
+
+git clone https://hub.spigotmc.org/stash/scm/spigot/craftbukkit.git CraftBukkit
+cd CraftBukkit
+git checkout 91b1fc3f1cf89e2591367dca1fa7362fe376f289
+cd ..
+
+git clone https://hub.spigotmc.org/stash/scm/spigot/spigot.git Spigot
+cd Spigot
+git checkout b698b49caf14f97a717afd67e13fd7ac59f51089
+cd ..
+
+git clone https://hub.spigotmc.org/stash/scm/spigot/builddata.git BuildData
+cd BuildData
+git checkout a7f7c2118b877fde4cf0f32f1f730ffcdee8e9ee
+cd ..
+
+java -jar BuildTools.jar --remapped --disable-java-check --dont-update
+java -jar BuildTools.jar --rev 1.20.6 --remapped --disable-java-check
+
+cd Bukkit
+git checkout 2ec53f498e32b3af989cb24672fc54dfab087154
+cd ..
+
+cd CraftBukkit
+git checkout 8ee6fd1b8db9896590aa321d0199453de1fc35db
+cd ..
+
+cd Spigot
+git checkout fb8fb722a327a2f9f097f2ded700ac5de8157408
+cd ..
+
+cd BuildData
+git checkout ae1e7b1e31cd3a3892bb05a6ccdcecc48c73c455
+cd ..
+
+java -jar BuildTools.jar --remapped --disable-java-check --dont-update
+java -jar BuildTools.jar --rev 1.21.1 --remapped --disable-java-check
+java -jar BuildTools.jar --rev 1.21.3 --remapped --disable-java-check
+```
+
+Your environment is now set up correctly. To create a build, run the following inside the root folder of the project.
+```
+mvn clean package
+```
+Your build is now available in the /IF/target folder.
+
+## Adventure support
+
+IF supports [Adventure](https://github.com/KyoriPowered/adventure), but does not shade it in itself.
+The use of Adventure `Component`s instead of legacy `String`s is completely optional.
+If you do not wish to use Adventure you can safely ignore all `TextHolder` related methods.
+
+### What is Adventure?
+
+Adventure is a library that adds proper modern text support to Minecraft.
+Modern text is represented using bungee-chat and `BaseComponent` instances in Spigot.
+Adventure is an alternative to bungee-chat and offers more features.
+
+### Using Adventure on 1.16.5+ Paper
+
+You don't need to import/shade anything for Adventure support in this case!
+
+*Note: Paper only supports Adventure on build 473 and above. If you aren't running months old builds, then you are fine.*
+
+### Using Adventure on Spigot and older Paper
+
+On Spigot Adventure isn't included in the server, therefore you have to shade and relocate it yourself.
+The following dependencies need to be imported and shaded:
+- adventure-api
+- adventure-platform-bukkit
+
+Please consult the [Adventure documentation](https://docs.adventure.kyori.net/) for more information.
+
+### How to use Adventure `Component`s
+
+Example of migration from legacy `String` to Adventure `Component`:
+ - legacy: `namedGui.setTitle("My Title!");`
+ - Adventure: `namedGui.setTitle(ComponentHolder.of(Component.text("My Title!")));`
+
+We apologize for the boilerplate (the `ComponentHolder.of(...)` call), but that was the only way to not make IF hard-depend on Adventure.
+
+Full Adventure support is only achieved when your server natively supports Adventure (it is running Paper) and your plugin depends on Paper (instead of Spigot).
+In other words, you won't benefit from Adventure as much if you use Spigot instead of Paper.
+This is because when Adventure is relocated we have to convert everything back to legacy `String`s before passing them to the Bukkit API.
diff --git a/adventure-support/pom.xml b/adventure-support/pom.xml
new file mode 100644
index 000000000..3d4bb888f
--- /dev/null
+++ b/adventure-support/pom.xml
@@ -0,0 +1,39 @@
+
+
+
+ IF-parent
+ com.github.stefvanschie.inventoryframework
+ 0.10.18
+
+ 4.0.0
+
+ adventure-support
+
+
+ true
+
+
+
+
+ papermc
+ https://papermc.io/repo/repository/maven-public/
+
+
+
+
+
+ com.destroystokyo.paper
+ paper-api
+ 1.16.5-R0.1-SNAPSHOT
+ provided
+
+
+ net.kyori
+ adventure-api
+ ${adventure.version}
+ provided
+
+
+
\ No newline at end of file
diff --git a/adventure-support/src/main/java/com/github/stefvanschie/inventoryframework/adventuresupport/ComponentHolder.java b/adventure-support/src/main/java/com/github/stefvanschie/inventoryframework/adventuresupport/ComponentHolder.java
new file mode 100644
index 000000000..3d6a4b587
--- /dev/null
+++ b/adventure-support/src/main/java/com/github/stefvanschie/inventoryframework/adventuresupport/ComponentHolder.java
@@ -0,0 +1,176 @@
+package com.github.stefvanschie.inventoryframework.adventuresupport;
+
+import com.google.gson.JsonElement;
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
+import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
+import org.apache.commons.lang.Validate;
+import org.bukkit.Material;
+import org.bukkit.event.inventory.InventoryType;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.ItemMeta;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Objects;
+
+/**
+ * Wrapper of an Adventure {@link Component}.
+ *
+ * @since 0.10.0
+ */
+public abstract class ComponentHolder extends TextHolder {
+
+ /**
+ * Whether the server platform natively supports Adventure.
+ * A null value indicates that we don't yet know this: it hasn't been determined yet.
+ * This field should not be used directly, use {@link #isNativeAdventureSupport()} instead.
+ */
+ @Nullable
+ private static Boolean nativeAdventureSupport;
+
+ /**
+ * The serializer to use when converting wrapped values to legacy strings.
+ * A null value indicates that we haven't created the serializer yet.
+ * This field should not be used directly, use {@link #getLegacySerializer()} instead.
+ */
+ @Nullable
+ private static LegacyComponentSerializer legacySerializer;
+
+ /**
+ * Wraps the specified Adventure component.
+ *
+ * @param value the value to wrap
+ * @return an instance that wraps the specified value
+ * @since 0.10.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ public static ComponentHolder of(@NotNull Component value) {
+ Validate.notNull(value, "value mustn't be null");
+ return isNativeAdventureSupport()
+ ? new NativeComponentHolder(value)
+ : new ForeignComponentHolder(value);
+ }
+
+ /**
+ * Gets whether the server platform natively supports Adventure.
+ * Native Adventure support means that eg. {@link ItemMeta#displayName(Component)}
+ * is a valid method.
+ *
+ * @return whether the server platform natively supports Adventure
+ * @since 0.10.0
+ */
+ private static boolean isNativeAdventureSupport() {
+ if (nativeAdventureSupport == null) {
+ try {
+ Component component = Component.text("test");
+ NativeComponentHolder holder = new NativeComponentHolder(component);
+
+ //If NoSuchMethodError or something is thrown we can assume that
+ //Adventure components are not natively supported by the server platform
+
+ //noinspection unused
+ Object ignored1 = holder.asInventoryTitle(null, 9);
+ //noinspection unused
+ Object ignored2 = holder.asInventoryTitle(null, InventoryType.HOPPER);
+
+ ItemMeta meta = new ItemStack(Material.STONE).getItemMeta();
+ holder.asItemDisplayName(meta);
+ holder.asItemLoreAtEnd(meta);
+
+ nativeAdventureSupport = true;
+ } catch (Throwable t) {
+ nativeAdventureSupport = false;
+ }
+ }
+ return nativeAdventureSupport;
+ }
+
+ /**
+ * Gets the serializer to use when converting wrapped values to legacy strings.
+ * Main use case being the implementation of {@link #asLegacyString()}.
+ *
+ * @return a serializer for converting wrapped values to legacy strings
+ * @since 0.10.0
+ */
+ private static LegacyComponentSerializer getLegacySerializer() {
+ if (legacySerializer == null) {
+ LegacyComponentSerializer.Builder builder = LegacyComponentSerializer.builder()
+ .character(LegacyComponentSerializer.SECTION_CHAR);
+ if (!net.md_5.bungee.api.ChatColor.class.isEnum()) {
+ //1.16+ Spigot (or Paper), hex colors are supported, no need to down sample them
+ builder.hexColors()
+ .useUnusualXRepeatedCharacterHexFormat();
+ }
+ legacySerializer = builder.build();
+ }
+ return legacySerializer;
+ }
+
+ /**
+ * The Adventure component this instance wraps.
+ */
+ @NotNull
+ protected final Component value;
+
+ /**
+ * Creates and initializes a new instance.
+ *
+ * @param value the Adventure component this instance should wrap
+ * @since 0.10.0
+ */
+ ComponentHolder(@NotNull Component value) {
+ this.value = value;
+ }
+
+ /**
+ * Gets the Adventure component this instance wraps.
+ *
+ * @return the contained Adventure component
+ * @since 0.10.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ public Component getComponent() {
+ return value;
+ }
+
+ /**
+ * Gets the wrapped Adventure component in a JSON representation.
+ *
+ * @return the contained Adventure component as JSON
+ * @since 0.10.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ public JsonElement asJson() {
+ return GsonComponentSerializer.gson().serializeToTree(value);
+ }
+
+ @NotNull
+ @Contract(pure = true)
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + "{" + value + "}";
+ }
+
+ @Override
+ public int hashCode() {
+ return value.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other != null && getClass() == other.getClass()
+ && Objects.equals(value, ((ComponentHolder) other).value);
+ }
+
+ @NotNull
+ @Contract(pure = true)
+ @Override
+ public String asLegacyString() {
+ return getLegacySerializer().serialize(value);
+ }
+}
diff --git a/adventure-support/src/main/java/com/github/stefvanschie/inventoryframework/adventuresupport/ForeignComponentHolder.java b/adventure-support/src/main/java/com/github/stefvanschie/inventoryframework/adventuresupport/ForeignComponentHolder.java
new file mode 100644
index 000000000..ddc7955e9
--- /dev/null
+++ b/adventure-support/src/main/java/com/github/stefvanschie/inventoryframework/adventuresupport/ForeignComponentHolder.java
@@ -0,0 +1,70 @@
+package com.github.stefvanschie.inventoryframework.adventuresupport;
+
+import net.kyori.adventure.text.Component;
+import org.bukkit.Bukkit;
+import org.bukkit.event.inventory.InventoryType;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.InventoryHolder;
+import org.bukkit.inventory.Merchant;
+import org.bukkit.inventory.meta.ItemMeta;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * A {@link ComponentHolder} implementation for platforms where Adventure isn't natively supported.
+ * Adventure components are converted to legacy Strings before passed to the Bukkit API.
+ *
+ * @see NativeComponentHolder
+ * @since 0.10.0
+ */
+class ForeignComponentHolder extends ComponentHolder {
+
+ /**
+ * A {@link StringHolder} wrapping {@link #asLegacyString()}.
+ * This class depends on {@link StringHolder} to reduce code duplication.
+ */
+ @NotNull
+ private final StringHolder legacy;
+
+ /**
+ * Creates and initializes a new instance.
+ *
+ * @param value the Adventure component this instance should wrap
+ * @since 0.10.0
+ */
+ ForeignComponentHolder(@NotNull Component value) {
+ super(value);
+ legacy = StringHolder.of(asLegacyString());
+ }
+
+ @NotNull
+ @Contract(pure = true)
+ @Override
+ public Inventory asInventoryTitle(InventoryHolder holder, InventoryType type) {
+ return legacy.asInventoryTitle(holder, type);
+ }
+
+ @NotNull
+ @Contract(pure = true)
+ @Override
+ public Inventory asInventoryTitle(InventoryHolder holder, int size) {
+ return legacy.asInventoryTitle(holder, size);
+ }
+
+ @NotNull
+ @Contract(pure = true)
+ @Override
+ public Merchant asMerchantTitle() {
+ return legacy.asMerchantTitle();
+ }
+
+ @Override
+ public void asItemDisplayName(ItemMeta meta) {
+ legacy.asItemDisplayName(meta);
+ }
+
+ @Override
+ public void asItemLoreAtEnd(ItemMeta meta) {
+ legacy.asItemLoreAtEnd(meta);
+ }
+}
diff --git a/adventure-support/src/main/java/com/github/stefvanschie/inventoryframework/adventuresupport/NativeComponentHolder.java b/adventure-support/src/main/java/com/github/stefvanschie/inventoryframework/adventuresupport/NativeComponentHolder.java
new file mode 100644
index 000000000..eaea94d11
--- /dev/null
+++ b/adventure-support/src/main/java/com/github/stefvanschie/inventoryframework/adventuresupport/NativeComponentHolder.java
@@ -0,0 +1,70 @@
+package com.github.stefvanschie.inventoryframework.adventuresupport;
+
+import net.kyori.adventure.text.Component;
+import org.bukkit.Bukkit;
+import org.bukkit.event.inventory.InventoryType;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.InventoryHolder;
+import org.bukkit.inventory.Merchant;
+import org.bukkit.inventory.meta.ItemMeta;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * A {@link ComponentHolder} implementation for platforms where Adventure is natively supported.
+ * Adventure components are directly passed to the Bukkit (Paper) API.
+ *
+ * @see ForeignComponentHolder
+ * @since 0.10.0
+ */
+class NativeComponentHolder extends ComponentHolder {
+
+ /**
+ * Creates and initializes a new instance.
+ *
+ * @param value the Adventure component this instance should wrap
+ * @since 0.10.0
+ */
+ NativeComponentHolder(@NotNull Component value) {
+ super(value);
+ }
+
+ @NotNull
+ @Contract(pure = true)
+ @Override
+ public Inventory asInventoryTitle(InventoryHolder holder, InventoryType type) {
+ return Bukkit.createInventory(holder, type, value);
+ }
+
+ @NotNull
+ @Contract(pure = true)
+ @Override
+ public Inventory asInventoryTitle(InventoryHolder holder, int size) {
+ return Bukkit.createInventory(holder, size, value);
+ }
+
+ @NotNull
+ @Contract(pure = true)
+ @Override
+ public Merchant asMerchantTitle() {
+ return Bukkit.createMerchant(value);
+ }
+
+ @Override
+ public void asItemDisplayName(ItemMeta meta) {
+ meta.displayName(value);
+ }
+
+ @Override
+ public void asItemLoreAtEnd(ItemMeta meta) {
+ List lore = meta.hasLore()
+ ? Objects.requireNonNull(meta.lore())
+ : new ArrayList<>();
+ lore.add(value);
+ meta.lore(lore);
+ }
+}
diff --git a/adventure-support/src/main/java/com/github/stefvanschie/inventoryframework/adventuresupport/StringHolder.java b/adventure-support/src/main/java/com/github/stefvanschie/inventoryframework/adventuresupport/StringHolder.java
new file mode 100644
index 000000000..cfbbb7aa6
--- /dev/null
+++ b/adventure-support/src/main/java/com/github/stefvanschie/inventoryframework/adventuresupport/StringHolder.java
@@ -0,0 +1,138 @@
+package com.github.stefvanschie.inventoryframework.adventuresupport;
+
+import org.apache.commons.lang.Validate;
+import org.bukkit.Bukkit;
+import org.bukkit.event.inventory.InventoryType;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.InventoryHolder;
+import org.bukkit.inventory.Merchant;
+import org.bukkit.inventory.meta.ItemMeta;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Wrapper of a legacy string value.
+ * {@link org.bukkit.ChatColor} based formatting is used.
+ *
+ * @since 0.10.0
+ */
+public final class StringHolder extends TextHolder {
+
+ /**
+ * Cached instance which wraps an empty {@link String}.
+ */
+ @NotNull
+ private static final StringHolder EMPTY = StringHolder.of("");
+
+ /**
+ * Wraps the specified legacy string.
+ *
+ * @param value the value to wrap
+ * @return an instance that wraps the specified value
+ * @since 0.10.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ public static StringHolder of(@NotNull String value) {
+ Validate.notNull(value, "value mustn't be null");
+ return new StringHolder(value);
+ }
+
+ /**
+ * Gets an instance that contains no characters.
+ *
+ * @return an instance without any characters
+ * @since 0.10.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ public static StringHolder empty() {
+ return EMPTY;
+ }
+
+ /**
+ * The legacy string this instance wraps.
+ */
+ @NotNull
+ private final String value;
+
+ /**
+ * Creates and initializes a new instance.
+ *
+ * @param value the legacy string this instance should wrap
+ * @since 0.10.0
+ */
+ private StringHolder(@NotNull String value) {
+ this.value = value;
+ }
+
+ @NotNull
+ @Contract(pure = true)
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + "{" + value + "}";
+ }
+
+ @Override
+ public int hashCode() {
+ return value.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other != null && getClass() == other.getClass()
+ && Objects.equals(value, ((StringHolder) other).value);
+ }
+
+ @NotNull
+ @Contract(pure = true)
+ @Override
+ public String asLegacyString() {
+ return value;
+ }
+
+ @NotNull
+ @Contract(pure = true)
+ @Override
+ public Inventory asInventoryTitle(InventoryHolder holder, InventoryType type) {
+ //noinspection deprecation
+ return Bukkit.createInventory(holder, type, value);
+ }
+
+ @NotNull
+ @Contract(pure = true)
+ @Override
+ public Inventory asInventoryTitle(InventoryHolder holder, int size) {
+ //noinspection deprecation
+ return Bukkit.createInventory(holder, size, value);
+ }
+
+ @NotNull
+ @Contract(pure = true)
+ @Override
+ public Merchant asMerchantTitle() {
+ //noinspection deprecation
+ return Bukkit.createMerchant(value);
+ }
+
+ @Override
+ public void asItemDisplayName(ItemMeta meta) {
+ //noinspection deprecation
+ meta.setDisplayName(value);
+ }
+
+ @Override
+ public void asItemLoreAtEnd(ItemMeta meta) {
+ //noinspection deprecation
+ List lore = meta.hasLore()
+ ? Objects.requireNonNull(meta.getLore())
+ : new ArrayList<>();
+ lore.add(value);
+ //noinspection deprecation
+ meta.setLore(lore);
+ }
+}
diff --git a/adventure-support/src/main/java/com/github/stefvanschie/inventoryframework/adventuresupport/TextHolder.java b/adventure-support/src/main/java/com/github/stefvanschie/inventoryframework/adventuresupport/TextHolder.java
new file mode 100644
index 000000000..dea4b8d72
--- /dev/null
+++ b/adventure-support/src/main/java/com/github/stefvanschie/inventoryframework/adventuresupport/TextHolder.java
@@ -0,0 +1,132 @@
+package com.github.stefvanschie.inventoryframework.adventuresupport;
+
+import net.kyori.adventure.text.Component;
+import org.bukkit.ChatColor;
+import org.bukkit.event.inventory.InventoryType;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.InventoryHolder;
+import org.bukkit.inventory.Merchant;
+import org.bukkit.inventory.meta.ItemMeta;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Immutable wrapper of a text-like value.
+ * Support for both Adventure and legacy strings is achieved through this class.
+ * To get an instance of this class please refer to either {@link StringHolder#of(String)}
+ * or {@link ComponentHolder#of(Component)}.
+ * Other methods like {@link #empty()} and {@link #deserialize(String)}
+ * also exist, but their use cases are very limited.
+ *
+ * @see StringHolder
+ * @see ComponentHolder
+ * @since 0.10.0
+ */
+public abstract class TextHolder {
+
+ /**
+ * Gets an instance that contains no characters and no formatting.
+ *
+ * @return an instance without any characters or formatting
+ * @since 0.10.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ public static TextHolder empty() {
+ return StringHolder.empty();
+ }
+
+ /**
+ * Deserializes the specified {@link String} as a {@link TextHolder}.
+ * This method is still WIP and may change drastically in the future:
+ *
+ * - Are we going to use MiniMessage if it's present?
+ * - Is MiniMessage going to be opt-in? If yes, how do we opt-in?
+ *
+ *
+ * @param string the raw data to deserialize
+ * @return an instance containing the text from the string
+ * @since 0.10.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ public static TextHolder deserialize(@NotNull String string) {
+ return StringHolder.of(ChatColor.translateAlternateColorCodes('&', string));
+ }
+
+ TextHolder() {
+ //package-private constructor to "seal" the class
+ }
+
+ @NotNull
+ @Contract(pure = true)
+ @Override
+ public abstract String toString();
+
+ @Override
+ public abstract int hashCode();
+
+ @Override
+ public abstract boolean equals(Object other);
+
+ /**
+ * Converts the text wrapped by this class instance to a legacy string,
+ * keeping the original formatting.
+ *
+ * @return the wrapped value represented as a legacy string
+ * @since 0.10.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ public abstract String asLegacyString();
+
+ /**
+ * Creates a new inventory with the wrapped value as the inventory's title.
+ *
+ * @param holder the holder to use for the new inventory
+ * @param type the type of inventory to create
+ * @return a newly created inventory with the wrapped value as its title
+ * @since 0.10.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ public abstract Inventory asInventoryTitle(InventoryHolder holder, InventoryType type);
+
+ /**
+ * Creates a new inventory with the wrapped value as the inventory's title.
+ *
+ * @param holder the holder to use for the new inventory
+ * @param size the count of slots the inventory should have (normal size restrictions apply)
+ * @return a newly created inventory with the wrapped value as its title
+ * @since 0.10.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ public abstract Inventory asInventoryTitle(InventoryHolder holder, int size);
+
+ /**
+ * Creates a new merchant with the wrapped value as the merchant's title.
+ *
+ * @return a newly created inventory with the wrapped value as its title
+ * @since 0.10.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ public abstract Merchant asMerchantTitle();
+
+ /**
+ * Modifies the specified meta: sets the display name to the wrapped value.
+ *
+ * @param meta the meta whose display name to set
+ * @since 0.10.0
+ */
+ public abstract void asItemDisplayName(ItemMeta meta);
+
+ /**
+ * Modifies the specified meta: adds the wrapped value as a new lore line at the end
+ *
+ * @param meta the meta whose lore to append to
+ * @since 0.10.0
+ */
+ public abstract void asItemLoreAtEnd(ItemMeta meta);
+}
diff --git a/inventory-view/iv-abstract-class/pom.xml b/inventory-view/iv-abstract-class/pom.xml
new file mode 100644
index 000000000..ea1a52a81
--- /dev/null
+++ b/inventory-view/iv-abstract-class/pom.xml
@@ -0,0 +1,47 @@
+
+
+ 4.0.0
+
+ com.github.stefvanschie.inventoryframework
+ IF-parent
+ 0.10.18
+ ../../pom.xml
+
+
+ iv-abstract-class
+
+
+ true
+
+
+
+
+ spigot-repo
+ https://hub.spigotmc.org/nexus/content/repositories/snapshots/
+
+
+
+
+
+ com.github.stefvanschie.inventoryframework
+ iv-abstraction
+ ${project.version}
+
+
+ org.spigotmc
+ spigot-api
+ 1.20.6-R0.1-SNAPSHOT
+ provided
+
+
+
+ org.apache.commons
+ commons-lang3
+
+
+
+
+
+
\ No newline at end of file
diff --git a/inventory-view/iv-abstract-class/src/main/java/com/github/stefvanschie/inventoryframework/inventoryview/abstractclass/InventoryViewUtil.java b/inventory-view/iv-abstract-class/src/main/java/com/github/stefvanschie/inventoryframework/inventoryview/abstractclass/InventoryViewUtil.java
new file mode 100644
index 000000000..eb8ec2084
--- /dev/null
+++ b/inventory-view/iv-abstract-class/src/main/java/com/github/stefvanschie/inventoryframework/inventoryview/abstractclass/InventoryViewUtil.java
@@ -0,0 +1,77 @@
+package com.github.stefvanschie.inventoryframework.inventoryview.abstractclass;
+
+import com.github.stefvanschie.inventoryframework.inventoryview.abstraction.AbstractInventoryViewUtil;
+import org.bukkit.event.inventory.InventoryType;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.InventoryView;
+import org.bukkit.inventory.ItemStack;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * A wrapper for {@link InventoryView} methods that apply when {@link InventoryView} was an abstract class.
+ *
+ * @since 0.10.16
+ */
+public class InventoryViewUtil implements AbstractInventoryViewUtil {
+
+ /**
+ * Instance of this singleton class.
+ */
+ @NotNull
+ private static final InventoryViewUtil INSTANCE = new InventoryViewUtil();
+
+ @NotNull
+ @Override
+ public Inventory getBottomInventory(@NotNull InventoryView view) {
+ return view.getBottomInventory();
+ }
+
+ @Nullable
+ @Override
+ public ItemStack getCursor(@NotNull InventoryView view) {
+ return view.getCursor();
+ }
+
+ @Override
+ public void setCursor(@NotNull InventoryView view, @Nullable ItemStack item) {
+ view.setCursor(item);
+ }
+
+ @Nullable
+ @Override
+ public Inventory getInventory(@NotNull InventoryView view, int slot) {
+ return view.getInventory(slot);
+ }
+
+ @NotNull
+ @Override
+ public InventoryType.SlotType getSlotType(@NotNull InventoryView view, int slot) {
+ return view.getSlotType(slot);
+ }
+
+ @NotNull
+ @Override
+ public String getTitle(@NotNull InventoryView view) {
+ return view.getTitle();
+ }
+
+ @NotNull
+ @Override
+ public Inventory getTopInventory(@NotNull InventoryView view) {
+ return view.getTopInventory();
+ }
+
+ /**
+ * Gets the singleton instance of this class.
+ *
+ * @return the instance of this class
+ * @since 0.10.16
+ */
+ @NotNull
+ @Contract(pure = true)
+ public static InventoryViewUtil getInstance() {
+ return INSTANCE;
+ }
+}
diff --git a/inventory-view/iv-abstraction/pom.xml b/inventory-view/iv-abstraction/pom.xml
new file mode 100644
index 000000000..c03fa67b7
--- /dev/null
+++ b/inventory-view/iv-abstraction/pom.xml
@@ -0,0 +1,42 @@
+
+
+ 4.0.0
+
+ com.github.stefvanschie.inventoryframework
+ IF-parent
+ 0.10.18
+ ../../pom.xml
+
+
+ iv-abstraction
+
+
+ true
+
+
+
+
+ spigot-repo
+ https://hub.spigotmc.org/nexus/content/repositories/snapshots/
+
+
+
+
+
+ org.spigotmc
+ spigot-api
+ 1.21-R0.1-SNAPSHOT
+ provided
+
+
+
+ org.apache.commons
+ commons-lang3
+
+
+
+
+
+
\ No newline at end of file
diff --git a/inventory-view/iv-abstraction/src/main/java/com/github/stefvanschie/inventoryframework/inventoryview/abstraction/AbstractInventoryViewUtil.java b/inventory-view/iv-abstraction/src/main/java/com/github/stefvanschie/inventoryframework/inventoryview/abstraction/AbstractInventoryViewUtil.java
new file mode 100644
index 000000000..8d7f0c6cc
--- /dev/null
+++ b/inventory-view/iv-abstraction/src/main/java/com/github/stefvanschie/inventoryframework/inventoryview/abstraction/AbstractInventoryViewUtil.java
@@ -0,0 +1,87 @@
+package com.github.stefvanschie.inventoryframework.inventoryview.abstraction;
+
+import org.bukkit.event.inventory.InventoryType;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.InventoryView;
+import org.bukkit.inventory.ItemStack;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * A wrapper for {@link InventoryView} methods that apply when {@link InventoryView} was an abstract class.
+ *
+ * @since 0.10.16
+ */
+public interface AbstractInventoryViewUtil {
+
+ /**
+ * Behaves according to {@link InventoryView#getBottomInventory()}.
+ *
+ * @param view the {@link InventoryView} to invoke {@link InventoryView#getBottomInventory()} on
+ * @return the result of invoking {@link InventoryView#getBottomInventory()}
+ * @since 0.10.16
+ */
+ @NotNull
+ Inventory getBottomInventory(@NotNull InventoryView view);
+
+ /**
+ * Behaves according to {@link InventoryView#getCursor()}.
+ *
+ * @param view the {@link InventoryView} to invoke {@link InventoryView#getCursor()} on
+ * @return the result of invoking {@link InventoryView#getCursor()}
+ * @since 0.10.16
+ */
+ @Nullable
+ ItemStack getCursor(@NotNull InventoryView view);
+
+ /**
+ * Behaves according to {@link InventoryView#setCursor(ItemStack)}.
+ *
+ * @param view the {@link InventoryView} to invoke {@link InventoryView#setCursor(ItemStack)} on
+ * @param item the {@link ItemStack} to apply when invoking {@link InventoryView#setCursor(ItemStack)}
+ * @since 0.10.16
+ */
+ void setCursor(@NotNull InventoryView view, @Nullable ItemStack item);
+
+ /**
+ * Behaves according to {@link InventoryView#getInventory(int)}.
+ *
+ * @param view the {@link InventoryView} to invoke {@link InventoryView#getInventory(int)} on
+ * @param slot the slot to apply when invoking {@link InventoryView#getInventory(int)}
+ * @return the result of invoking {@link InventoryView#getInventory(int)}
+ * @since 0.10.16
+ */
+ @Nullable
+ Inventory getInventory(@NotNull InventoryView view, int slot);
+
+ /**
+ * Behaves according to {@link InventoryView#getSlotType(int)}.
+ *
+ * @param view the {@link InventoryView} to invoke {@link InventoryView#getSlotType(int)} on
+ * @param slot the slot to apply when invoking {@link InventoryView#getSlotType(int)}
+ * @return the result of invoking {@link InventoryView#getSlotType(int)}
+ * @since 0.10.16
+ */
+ @NotNull
+ InventoryType.SlotType getSlotType(@NotNull InventoryView view, int slot);
+
+ /**
+ * Behaves according to {@link InventoryView#getTitle()}.
+ *
+ * @param view the {@link InventoryView} to invoke {@link InventoryView#getTitle()} on
+ * @return the result of invoking {@link InventoryView#getTitle()}
+ * @since 0.10.16
+ */
+ @NotNull
+ String getTitle(@NotNull InventoryView view);
+
+ /**
+ * Behaves according to {@link InventoryView#getTopInventory()}.
+ *
+ * @param view the {@link InventoryView} to invoke {@link InventoryView#getTopInventory()} on
+ * @return the result of invoking {@link InventoryView#getTopInventory()}
+ * @since 0.10.16
+ */
+ @NotNull
+ Inventory getTopInventory(@NotNull InventoryView view);
+}
diff --git a/inventory-view/iv-interface/pom.xml b/inventory-view/iv-interface/pom.xml
new file mode 100644
index 000000000..cd6e8cf4c
--- /dev/null
+++ b/inventory-view/iv-interface/pom.xml
@@ -0,0 +1,47 @@
+
+
+ 4.0.0
+
+ com.github.stefvanschie.inventoryframework
+ IF-parent
+ 0.10.18
+ ../../pom.xml
+
+
+ iv-interface
+
+
+ true
+
+
+
+
+ spigot-repo
+ https://hub.spigotmc.org/nexus/content/repositories/snapshots/
+
+
+
+
+
+ com.github.stefvanschie.inventoryframework
+ iv-abstraction
+ ${project.version}
+
+
+ org.spigotmc
+ spigot-api
+ 1.21-R0.1-SNAPSHOT
+ provided
+
+
+
+ org.apache.commons
+ commons-lang3
+
+
+
+
+
+
\ No newline at end of file
diff --git a/inventory-view/iv-interface/src/main/java/com/github/stefvanschie/inventoryframework/inventoryview/interface_/InventoryViewUtil.java b/inventory-view/iv-interface/src/main/java/com/github/stefvanschie/inventoryframework/inventoryview/interface_/InventoryViewUtil.java
new file mode 100644
index 000000000..9d94062a0
--- /dev/null
+++ b/inventory-view/iv-interface/src/main/java/com/github/stefvanschie/inventoryframework/inventoryview/interface_/InventoryViewUtil.java
@@ -0,0 +1,77 @@
+package com.github.stefvanschie.inventoryframework.inventoryview.interface_;
+
+import com.github.stefvanschie.inventoryframework.inventoryview.abstraction.AbstractInventoryViewUtil;
+import org.bukkit.event.inventory.InventoryType;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.InventoryView;
+import org.bukkit.inventory.ItemStack;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * A wrapper for {@link InventoryView} methods that apply when {@link InventoryView} was an abstract class.
+ *
+ * @since 0.10.16
+ */
+public class InventoryViewUtil implements AbstractInventoryViewUtil {
+
+ /**
+ * Instance of this singleton class.
+ */
+ @NotNull
+ private static final InventoryViewUtil INSTANCE = new InventoryViewUtil();
+
+ @NotNull
+ @Override
+ public Inventory getBottomInventory(@NotNull InventoryView view) {
+ return view.getBottomInventory();
+ }
+
+ @Nullable
+ @Override
+ public ItemStack getCursor(@NotNull InventoryView view) {
+ return view.getCursor();
+ }
+
+ @Override
+ public void setCursor(@NotNull InventoryView view, @Nullable ItemStack item) {
+ view.setCursor(item);
+ }
+
+ @Nullable
+ @Override
+ public Inventory getInventory(@NotNull InventoryView view, int slot) {
+ return view.getInventory(slot);
+ }
+
+ @NotNull
+ @Override
+ public InventoryType.SlotType getSlotType(@NotNull InventoryView view, int slot) {
+ return view.getSlotType(slot);
+ }
+
+ @NotNull
+ @Override
+ public String getTitle(@NotNull InventoryView view) {
+ return view.getTitle();
+ }
+
+ @NotNull
+ @Override
+ public Inventory getTopInventory(@NotNull InventoryView view) {
+ return view.getTopInventory();
+ }
+
+ /**
+ * Gets the singleton instance of this class.
+ *
+ * @return the instance of this class
+ * @since 0.10.16
+ */
+ @NotNull
+ @Contract(pure = true)
+ public static InventoryViewUtil getInstance() {
+ return INSTANCE;
+ }
+}
diff --git a/nms/1_14_R1/pom.xml b/nms/1_14/pom.xml
similarity index 86%
rename from nms/1_14_R1/pom.xml
rename to nms/1_14/pom.xml
index 6dbcde799..dad32016c 100644
--- a/nms/1_14_R1/pom.xml
+++ b/nms/1_14/pom.xml
@@ -5,12 +5,12 @@
IF-parent
com.github.stefvanschie.inventoryframework
- 0.9.8
+ 0.10.18
../../pom.xml
4.0.0
- 1_14_R1
+ 1_14
true
@@ -18,8 +18,8 @@
- org.spigotmc
- spigot
+ io.papermc
+ paper
1.14.4-R0.1-SNAPSHOT
provided
diff --git a/nms/1_14/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_14/AnvilInventoryImpl.java b/nms/1_14/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_14/AnvilInventoryImpl.java
new file mode 100644
index 000000000..9b30ed8bc
--- /dev/null
+++ b/nms/1_14/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_14/AnvilInventoryImpl.java
@@ -0,0 +1,381 @@
+package com.github.stefvanschie.inventoryframework.nms.v1_14;
+
+import com.github.stefvanschie.inventoryframework.abstraction.AnvilInventory;
+import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
+import com.github.stefvanschie.inventoryframework.nms.v1_14.util.TextHolderUtil;
+import net.minecraft.server.v1_14_R1.*;
+import org.bukkit.craftbukkit.v1_14_R1.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_14_R1.event.CraftEventFactory;
+import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftItemStack;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.InventoryHolder;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.lang.reflect.Field;
+import java.util.Collections;
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * Internal anvil inventory for 1.14 R1
+ *
+ * @since 0.8.0
+ */
+public class AnvilInventoryImpl extends AnvilInventory {
+
+ public AnvilInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
+ super(inventoryHolder);
+ }
+
+ @Override
+ public Inventory openInventory(@NotNull Player player, @NotNull TextHolder title,
+ @Nullable org.bukkit.inventory.ItemStack[] items) {
+ int itemAmount = items.length;
+
+ if (itemAmount != 3) {
+ throw new IllegalArgumentException(
+ "The amount of items for an anvil should be 3, but is '" + itemAmount + "'"
+ );
+ }
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ //ignore deprecation: superseding method is only available on Paper
+ //noinspection deprecation
+ CraftEventFactory.handleInventoryCloseEvent(entityPlayer);
+
+ entityPlayer.activeContainer = entityPlayer.defaultContainer;
+
+ IChatBaseComponent message = TextHolderUtil.toComponent(title);
+ ContainerAnvilImpl containerAnvil = new ContainerAnvilImpl(entityPlayer, message);
+
+ Inventory inventory = containerAnvil.getBukkitView().getTopInventory();
+
+ inventory.setItem(0, items[0]);
+ inventory.setItem(1, items[1]);
+ inventory.setItem(2, items[2]);
+
+ int containerId = containerAnvil.getContainerId();
+
+ entityPlayer.playerConnection.sendPacket(new PacketPlayOutOpenWindow(containerId, Containers.ANVIL, message));
+ entityPlayer.activeContainer = containerAnvil;
+ entityPlayer.syncInventory();
+
+ return inventory;
+ }
+
+ @Override
+ public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
+ NonNullList nmsItems = NonNullList.a(
+ ItemStack.a,
+ CraftItemStack.asNMSCopy(items[0]),
+ CraftItemStack.asNMSCopy(items[1]),
+ CraftItemStack.asNMSCopy(items[2])
+ );
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
+ }
+
+ @Override
+ public void sendFirstItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+ ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutSetSlot(getWindowId(entityPlayer), 0, nmsItem));
+ }
+
+ @Override
+ public void sendSecondItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+ ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutSetSlot(getWindowId(entityPlayer), 1, nmsItem));
+ }
+
+ @Override
+ public void sendResultItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
+ sendResultItem(player, CraftItemStack.asNMSCopy(item));
+ }
+
+ @Override
+ public void clearResultItem(@NotNull Player player) {
+ sendResultItem(player, ItemStack.a);
+ }
+
+ @Override
+ public void setCursor(@NotNull Player player, @NotNull org.bukkit.inventory.ItemStack item) {
+ setCursor(player, CraftItemStack.asNMSCopy(item));
+ }
+
+ @Override
+ public void clearCursor(@NotNull Player player) {
+ getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.a));
+ }
+
+ /**
+ * Sets the cursor of the given player
+ *
+ * @param player the player to set the cursor
+ * @param item the item to set the cursor to
+ * @since 0.8.0
+ * @deprecated no longer used internally
+ */
+ @Deprecated
+ private void setCursor(@NotNull Player player, @NotNull ItemStack item) {
+ getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, item));
+ }
+
+ /**
+ * Sends the result item to the specified player with the given item
+ *
+ * @param player the player to send the result item to
+ * @param item the result item
+ * @since 0.8.0
+ * @deprecated no longer used internally
+ */
+ @Deprecated
+ private void sendResultItem(@NotNull Player player, @NotNull ItemStack item) {
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutSetSlot(getWindowId(entityPlayer), 2, item));
+ }
+
+ /**
+ * Gets the window id for the inventory view the player currently has open
+ *
+ * @param entityPlayer the player to get the window id for
+ * @return the window id
+ * @since 0.8.0
+ * @deprecated no longer used internally
+ */
+ @Contract(pure = true)
+ @Deprecated
+ private int getWindowId(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.activeContainer.windowId;
+ }
+
+ /**
+ * Gets the player connection for the specified player
+ *
+ * @param entityPlayer the player to get the player connection from
+ * @return the player connection
+ * @since 0.8.0
+ * @deprecated no longer used internally
+ */
+ @NotNull
+ @Contract(pure = true)
+ @Deprecated
+ private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.playerConnection;
+ }
+
+ /**
+ * Gets the entity player associated to this player
+ *
+ * @param player the player to get the entity player from
+ * @return the entity player
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private EntityPlayer getEntityPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * A custom container anvil for responding to item renaming
+ *
+ * @since 0.8.0
+ */
+ private class ContainerAnvilImpl extends ContainerAnvil {
+
+ /**
+ * The index of the result slot
+ */
+ private static final int RESULT_SLOT_INDEX = 2;
+
+ /**
+ * A unique item
+ */
+ @NotNull
+ private final ItemStack uniqueItem;
+
+ /**
+ * The field containing the listeners for this container
+ */
+ @NotNull
+ private final Field listenersField;
+
+ /**
+ * Creates a new custom anvil container for the specified player
+ *
+ * @param entityPlayer the player for whom this anvil container is
+ * @param title the title of the inventory
+ * @since 0.10.8
+ */
+ public ContainerAnvilImpl(@NotNull EntityPlayer entityPlayer, @NotNull IChatBaseComponent title) {
+ super(entityPlayer.nextContainerCounter(), entityPlayer.inventory,
+ ContainerAccess.at(entityPlayer.getWorld(), new BlockPosition(0, 0, 0)));
+
+ this.checkReachable = false;
+
+ try {
+ //stores all the registered container properties
+ Field dField = Container.class.getDeclaredField("d");
+ dField.setAccessible(true);
+
+ //get rid of the level cost property
+ ((List>) dField.get(this)).clear();
+ } catch (NoSuchFieldException | IllegalAccessException exception) {
+ throw new RuntimeException("Unable to access field 'd'", exception);
+ }
+
+ try {
+ this.listenersField = Container.class.getDeclaredField("listeners");
+ this.listenersField.setAccessible(true);
+ } catch (NoSuchFieldException exception) {
+ throw new RuntimeException("Unable to access field 'listeners'", exception);
+ }
+
+ //register a new property for the level cost
+ ContainerProperty levelCost = a(new ContainerProperty() {
+ private int value;
+
+ @Override
+ public int get() {
+ return value;
+ }
+
+ @Override
+ public void set(int value) {
+ this.value = value;
+ }
+
+ /*
+ This checks whether there have been any changes, but we want to override the client prediction. This
+ means the server should be sending the data to the client, even if it didn't change server-side. To
+ force this, we tell the server the data has always changed.
+ */
+ @Override
+ public boolean c() {
+ return true;
+ }
+ });
+
+ levelCost.set(AnvilInventoryImpl.super.cost);
+
+ setTitle(title);
+
+ Slot originalSlot = this.slots.get(RESULT_SLOT_INDEX);
+
+ Slot newSlot = new Slot(originalSlot.inventory, originalSlot.index, originalSlot.e, originalSlot.f) {
+ @Override
+ public boolean isAllowed(ItemStack itemStack) {
+ return true;
+ }
+
+ @Override
+ public boolean isAllowed(EntityHuman entityHuman) {
+ return true;
+ }
+
+ @Override
+ public ItemStack a(EntityHuman entityHuman, @NotNull ItemStack itemStack) {
+ return itemStack;
+ }
+ };
+
+ this.slots.set(RESULT_SLOT_INDEX, newSlot);
+
+ this.uniqueItem = new ItemStack(Items.COOKIE);
+
+ //to make the item unique, we add a random uuid as nbt to it
+ UUID uuid = UUID.randomUUID();
+ NBTTagCompound nbtTagCompound = new NBTTagCompound();
+
+ nbtTagCompound.set("uuid", new NBTTagLongArray(new long [] {
+ uuid.getLeastSignificantBits(),
+ uuid.getMostSignificantBits()
+ }));
+
+ this.uniqueItem.setTag(nbtTagCompound);
+ }
+
+ @Override
+ public void a(@Nullable String name) {
+ name = name == null ? "" : name;
+
+ /* Only update if the name is actually different. This may be called even if the name is not different,
+ particularly when putting an item in the first slot. */
+ if (!name.equals(AnvilInventoryImpl.super.observableText.get())) {
+ AnvilInventoryImpl.super.observableText.set(name);
+ }
+
+ //the client predicts the output result, so we broadcast the state again to override it
+ forceUpdate();
+ }
+
+ @Override
+ public void e() {}
+
+ @Override
+ public void b(EntityHuman entityHuman) {}
+
+ @Override
+ protected void a(EntityHuman entityHuman, World world, @NotNull IInventory inventory) {}
+
+ @Override
+ public ItemStack a(int i, int j, InventoryClickType inventoryclicktype, EntityHuman entityhuman) {
+ ItemStack itemStack = super.a(i, j, inventoryclicktype, entityhuman);
+
+ //the client predicts the allowed movement of the item, so we broadcast the state again to override it
+ forceUpdate();
+
+ return itemStack;
+ }
+
+ public int getContainerId() {
+ return this.windowId;
+ }
+
+ /**
+ * Forcefully updates the client state, sending all items, container properties and the held item.
+ *
+ * @since 0.10.8
+ */
+ public void forceUpdate() {
+ /*
+ The server will not send the items when they haven't changed, so we will overwrite every item with a unique
+ item first to ensure the server is going to send our items.
+ */
+ Collections.fill(this.items, this.uniqueItem);
+
+ c();
+
+ List extends ICrafting> listeners;
+
+ try {
+ //noinspection unchecked
+ listeners = (List extends ICrafting>) listenersField.get(this);
+ } catch (IllegalAccessException exception) {
+ throw new RuntimeException("Unable to access field 'listeners'", exception);
+ }
+
+ for (ICrafting listener : listeners) {
+ if (!(listener instanceof EntityPlayer)) {
+ continue;
+ }
+
+ EntityPlayer player = (EntityPlayer) listener;
+
+ player.e = false;
+ player.broadcastCarriedItem();
+ }
+ }
+ }
+}
diff --git a/nms/1_14_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_14_R1/BeaconInventoryImpl.java b/nms/1_14/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_14/BeaconInventoryImpl.java
similarity index 95%
rename from nms/1_14_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_14_R1/BeaconInventoryImpl.java
rename to nms/1_14/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_14/BeaconInventoryImpl.java
index e6fb366da..407358326 100644
--- a/nms/1_14_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_14_R1/BeaconInventoryImpl.java
+++ b/nms/1_14/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_14/BeaconInventoryImpl.java
@@ -1,181 +1,181 @@
-package com.github.stefvanschie.inventoryframework.nms.v1_14_R1;
-
-import com.github.stefvanschie.inventoryframework.abstraction.BeaconInventory;
-import net.minecraft.server.v1_14_R1.*;
-import org.bukkit.craftbukkit.v1_14_R1.entity.CraftPlayer;
-import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftInventory;
-import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftInventoryBeacon;
-import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftInventoryView;
-import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftItemStack;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.InventoryHolder;
-import org.jetbrains.annotations.Contract;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.lang.reflect.Field;
-
-/**
- * Internal beacon inventory for 1.14 R1
- *
- * @since 0.8.0
- */
-public class BeaconInventoryImpl extends BeaconInventory {
-
- public BeaconInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
- super(inventoryHolder);
- }
-
- @Override
- public void openInventory(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
- EntityPlayer entityPlayer = getEntityPlayer(player);
- ContainerBeaconImpl containerBeacon = new ContainerBeaconImpl(entityPlayer, item);
-
- entityPlayer.activeContainer = containerBeacon;
-
- int id = containerBeacon.windowId;
- ChatMessage message = new ChatMessage("Beacon");
-
- entityPlayer.playerConnection.sendPacket(new PacketPlayOutOpenWindow(id, Containers.BEACON, message));
-
- sendItem(player, item);
- }
-
- @Override
- public void sendItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
- NonNullList items = NonNullList.a(
- ItemStack.a, //the first item doesn't count for some reason, so send a dummy item
- CraftItemStack.asNMSCopy(item)
- );
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), items));
- }
-
- @Override
- public void clearCursor(@NotNull Player player) {
- getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.a));
- }
-
- /**
- * Gets the window id for the inventory view the player currently has open
- *
- * @param entityPlayer the player to get the window id for
- * @return the window id
- * @since 0.8.0
- */
- @Contract(pure = true)
- private int getWindowId(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.activeContainer.windowId;
- }
-
- /**
- * Gets the player connection for the specified player
- *
- * @param entityPlayer the player to get the player connection from
- * @return the player connection
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.playerConnection;
- }
-
- /**
- * Gets the entity player associated to this player
- *
- * @param player the player to get the entity player from
- * @return the entity player
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private EntityPlayer getEntityPlayer(@NotNull Player player) {
- return ((CraftPlayer) player).getHandle();
- }
-
- /**
- * A custom container beacon
- *
- * @since 0.8.0
- */
- private class ContainerBeaconImpl extends ContainerBeacon {
-
- /**
- * The player for this beacon container
- */
- @NotNull
- private final Player player;
-
- /**
- * The internal bukkit entity for this container beacon
- */
- @Nullable
- private CraftInventoryView bukkitEntity;
-
- /**
- * Field for accessing the beacon field
- */
- @NotNull
- private final Field beaconField;
-
- public ContainerBeaconImpl(@NotNull EntityPlayer entityPlayer, @Nullable org.bukkit.inventory.ItemStack item) {
- super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
-
- this.player = entityPlayer.getBukkitEntity();
-
- try {
- this.beaconField = ContainerBeacon.class.getDeclaredField("beacon");
- this.beaconField.setAccessible(true);
- } catch (NoSuchFieldException exception) {
- throw new RuntimeException(exception);
- }
-
- try {
- ItemStack itemStack = CraftItemStack.asNMSCopy(item);
-
- ((IInventory) beaconField.get(this)).setItem(0, itemStack);
- } catch (IllegalAccessException exception) {
- throw new RuntimeException(exception);
- }
- }
-
- @NotNull
- @Override
- public CraftInventoryView getBukkitView() {
- if (bukkitEntity == null) {
- try {
- CraftInventory inventory = new CraftInventoryBeacon((IInventory) beaconField.get(this)) {
- @NotNull
- @Contract(pure = true)
- @Override
- public InventoryHolder getHolder() {
- return inventoryHolder;
- }
- };
-
- bukkitEntity = new CraftInventoryView(player, inventory, this);
- } catch (IllegalAccessException exception) {
- throw new RuntimeException(exception);
- }
- }
-
- return bukkitEntity;
- }
-
- @Contract(pure = true, value = "_ -> true")
- @Override
- public boolean canUse(@Nullable EntityHuman entityhuman) {
- return true;
- }
-
- @Override
- public void a(IInventory inventory) {}
-
- @Override
- public void b(EntityHuman entityhuman) {}
-
- }
-}
+package com.github.stefvanschie.inventoryframework.nms.v1_14;
+
+import com.github.stefvanschie.inventoryframework.abstraction.BeaconInventory;
+import net.minecraft.server.v1_14_R1.*;
+import org.bukkit.craftbukkit.v1_14_R1.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftInventory;
+import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftInventoryBeacon;
+import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftInventoryView;
+import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftItemStack;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.InventoryHolder;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.lang.reflect.Field;
+
+/**
+ * Internal beacon inventory for 1.14 R1
+ *
+ * @since 0.8.0
+ */
+public class BeaconInventoryImpl extends BeaconInventory {
+
+ public BeaconInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
+ super(inventoryHolder);
+ }
+
+ @Override
+ public void openInventory(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+ ContainerBeaconImpl containerBeacon = new ContainerBeaconImpl(entityPlayer, item);
+
+ entityPlayer.activeContainer = containerBeacon;
+
+ int id = containerBeacon.windowId;
+ ChatMessage message = new ChatMessage("Beacon");
+
+ entityPlayer.playerConnection.sendPacket(new PacketPlayOutOpenWindow(id, Containers.BEACON, message));
+
+ sendItem(player, item);
+ }
+
+ @Override
+ public void sendItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
+ NonNullList items = NonNullList.a(
+ ItemStack.a, //the first item doesn't count for some reason, so send a dummy item
+ CraftItemStack.asNMSCopy(item)
+ );
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), items));
+ }
+
+ @Override
+ public void clearCursor(@NotNull Player player) {
+ getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.a));
+ }
+
+ /**
+ * Gets the window id for the inventory view the player currently has open
+ *
+ * @param entityPlayer the player to get the window id for
+ * @return the window id
+ * @since 0.8.0
+ */
+ @Contract(pure = true)
+ private int getWindowId(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.activeContainer.windowId;
+ }
+
+ /**
+ * Gets the player connection for the specified player
+ *
+ * @param entityPlayer the player to get the player connection from
+ * @return the player connection
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.playerConnection;
+ }
+
+ /**
+ * Gets the entity player associated to this player
+ *
+ * @param player the player to get the entity player from
+ * @return the entity player
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private EntityPlayer getEntityPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * A custom container beacon
+ *
+ * @since 0.8.0
+ */
+ private class ContainerBeaconImpl extends ContainerBeacon {
+
+ /**
+ * The player for this beacon container
+ */
+ @NotNull
+ private final Player player;
+
+ /**
+ * The internal bukkit entity for this container beacon
+ */
+ @Nullable
+ private CraftInventoryView bukkitEntity;
+
+ /**
+ * Field for accessing the beacon field
+ */
+ @NotNull
+ private final Field beaconField;
+
+ public ContainerBeaconImpl(@NotNull EntityPlayer entityPlayer, @Nullable org.bukkit.inventory.ItemStack item) {
+ super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
+
+ this.player = entityPlayer.getBukkitEntity();
+
+ try {
+ this.beaconField = ContainerBeacon.class.getDeclaredField("beacon");
+ this.beaconField.setAccessible(true);
+ } catch (NoSuchFieldException exception) {
+ throw new RuntimeException(exception);
+ }
+
+ try {
+ ItemStack itemStack = CraftItemStack.asNMSCopy(item);
+
+ ((IInventory) beaconField.get(this)).setItem(0, itemStack);
+ } catch (IllegalAccessException exception) {
+ throw new RuntimeException(exception);
+ }
+ }
+
+ @NotNull
+ @Override
+ public CraftInventoryView getBukkitView() {
+ if (bukkitEntity == null) {
+ try {
+ CraftInventory inventory = new CraftInventoryBeacon((IInventory) beaconField.get(this)) {
+ @NotNull
+ @Contract(pure = true)
+ @Override
+ public InventoryHolder getHolder() {
+ return inventoryHolder;
+ }
+ };
+
+ bukkitEntity = new CraftInventoryView(player, inventory, this);
+ } catch (IllegalAccessException exception) {
+ throw new RuntimeException(exception);
+ }
+ }
+
+ return bukkitEntity;
+ }
+
+ @Contract(pure = true, value = "_ -> true")
+ @Override
+ public boolean canUse(@Nullable EntityHuman entityhuman) {
+ return true;
+ }
+
+ @Override
+ public void a(IInventory inventory) {}
+
+ @Override
+ public void b(EntityHuman entityhuman) {}
+
+ }
+}
diff --git a/nms/1_14_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_14_R1/CartographyTableInventoryImpl.java b/nms/1_14/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_14/CartographyTableInventoryImpl.java
similarity index 94%
rename from nms/1_14_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_14_R1/CartographyTableInventoryImpl.java
rename to nms/1_14/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_14/CartographyTableInventoryImpl.java
index 75766664d..fe2798387 100644
--- a/nms/1_14_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_14_R1/CartographyTableInventoryImpl.java
+++ b/nms/1_14/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_14/CartographyTableInventoryImpl.java
@@ -1,199 +1,201 @@
-package com.github.stefvanschie.inventoryframework.nms.v1_14_R1;
-
-import com.github.stefvanschie.inventoryframework.abstraction.CartographyTableInventory;
-import net.minecraft.server.v1_14_R1.*;
-import org.bukkit.craftbukkit.v1_14_R1.entity.CraftPlayer;
-import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftInventory;
-import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftInventoryCartography;
-import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftInventoryView;
-import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftItemStack;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.InventoryHolder;
-import org.jetbrains.annotations.Contract;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.lang.reflect.Field;
-
-/**
- * Internal cartography table inventory for 1.14 R1
- *
- * @since 0.8.0
- */
-public class CartographyTableInventoryImpl extends CartographyTableInventory {
-
- public CartographyTableInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
- super(inventoryHolder);
- }
-
- @Override
- public void openInventory(@NotNull Player player, @NotNull String title,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- int itemAmount = items.length;
-
- if (itemAmount != 3) {
- throw new IllegalArgumentException(
- "The amount of items for a cartography table should be 3, but is '" + itemAmount + "'"
- );
- }
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
- ContainerCartographyTableImpl containerCartographyTable = new ContainerCartographyTableImpl(
- entityPlayer, items
- );
-
- entityPlayer.activeContainer = containerCartographyTable;
-
- int id = containerCartographyTable.windowId;
- ChatMessage message = new ChatMessage(title);
- PacketPlayOutOpenWindow packet = new PacketPlayOutOpenWindow(id, Containers.CARTOGRAPHY, message);
-
- entityPlayer.playerConnection.sendPacket(packet);
-
- sendItems(player, items);
- }
-
- @Override
- public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
- NonNullList nmsItems = NonNullList.a(
- ItemStack.a,
- CraftItemStack.asNMSCopy(items[0]),
- CraftItemStack.asNMSCopy(items[1]),
- CraftItemStack.asNMSCopy(items[2])
- );
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
- }
-
- @Override
- public void clearCursor(@NotNull Player player) {
- getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.a));
- }
-
- /**
- * Gets the window id for the inventory view the player currently has open
- *
- * @param entityPlayer the player to get the window id for
- * @return the window id
- * @since 0.8.0
- */
- @Contract(pure = true)
- private int getWindowId(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.activeContainer.windowId;
- }
-
- /**
- * Gets the player connection for the specified player
- *
- * @param entityPlayer the player to get the player connection from
- * @return the player connection
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.playerConnection;
- }
-
- /**
- * Gets the entity player associated to this player
- *
- * @param player the player to get the entity player from
- * @return the entity player
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private EntityPlayer getEntityPlayer(@NotNull Player player) {
- return ((CraftPlayer) player).getHandle();
- }
-
- /**
- * A custom container cartography table
- *
- * @since 0.8.0
- */
- private class ContainerCartographyTableImpl extends ContainerCartography {
-
- /**
- * The player for this cartography table container
- */
- @NotNull
- private final Player player;
-
- /**
- * The internal bukkit entity for this container cartography table
- */
- @Nullable
- private CraftInventoryView bukkitEntity;
-
- /**
- * Field for accessing the result inventory field
- */
- @NotNull
- private final Field resultInventoryField;
-
- public ContainerCartographyTableImpl(@NotNull EntityPlayer entityPlayer,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
-
- this.player = entityPlayer.getBukkitEntity();
-
- try {
- this.resultInventoryField = ContainerCartography.class.getDeclaredField("resultInventory");
- this.resultInventoryField.setAccessible(true);
- } catch (NoSuchFieldException exception) {
- throw new RuntimeException(exception);
- }
-
- inventory.setItem(0, CraftItemStack.asNMSCopy(items[0]));
- inventory.setItem(1, CraftItemStack.asNMSCopy(items[1]));
-
- getResultInventory().setItem(0, CraftItemStack.asNMSCopy(items[2]));
- }
-
- @NotNull
- @Override
- public CraftInventoryView getBukkitView() {
- if (bukkitEntity == null) {
- CraftInventory inventory = new CraftInventoryCartography(super.inventory, getResultInventory()) {
- @NotNull
- @Contract(pure = true)
- @Override
- public InventoryHolder getHolder() {
- return inventoryHolder;
- }
- };
-
- bukkitEntity = new CraftInventoryView(player, inventory, this);
- }
-
- return bukkitEntity;
- }
-
- @Contract(pure = true, value = "_ -> true")
- @Override
- public boolean canUse(@Nullable EntityHuman entityhuman) {
- return true;
- }
-
- @Override
- public void a(IInventory inventory) {}
-
- @Override
- public void b(EntityHuman entityhuman) {}
-
- @NotNull
- @Contract(pure = true)
- private IInventory getResultInventory() {
- try {
- return (IInventory) resultInventoryField.get(this);
- } catch (IllegalAccessException exception) {
- throw new RuntimeException(exception);
- }
- }
-
- }
-}
+package com.github.stefvanschie.inventoryframework.nms.v1_14;
+
+import com.github.stefvanschie.inventoryframework.abstraction.CartographyTableInventory;
+import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
+import com.github.stefvanschie.inventoryframework.nms.v1_14.util.TextHolderUtil;
+import net.minecraft.server.v1_14_R1.*;
+import org.bukkit.craftbukkit.v1_14_R1.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftInventory;
+import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftInventoryCartography;
+import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftInventoryView;
+import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftItemStack;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.InventoryHolder;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.lang.reflect.Field;
+
+/**
+ * Internal cartography table inventory for 1.14 R1
+ *
+ * @since 0.8.0
+ */
+public class CartographyTableInventoryImpl extends CartographyTableInventory {
+
+ public CartographyTableInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
+ super(inventoryHolder);
+ }
+
+ @Override
+ public void openInventory(@NotNull Player player, @NotNull TextHolder title,
+ @Nullable org.bukkit.inventory.ItemStack[] items) {
+ int itemAmount = items.length;
+
+ if (itemAmount != 3) {
+ throw new IllegalArgumentException(
+ "The amount of items for a cartography table should be 3, but is '" + itemAmount + "'"
+ );
+ }
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+ ContainerCartographyTableImpl containerCartographyTable = new ContainerCartographyTableImpl(
+ entityPlayer, items
+ );
+
+ entityPlayer.activeContainer = containerCartographyTable;
+
+ int id = containerCartographyTable.windowId;
+ IChatBaseComponent message = TextHolderUtil.toComponent(title);
+ PacketPlayOutOpenWindow packet = new PacketPlayOutOpenWindow(id, Containers.CARTOGRAPHY, message);
+
+ entityPlayer.playerConnection.sendPacket(packet);
+
+ sendItems(player, items);
+ }
+
+ @Override
+ public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
+ NonNullList nmsItems = NonNullList.a(
+ ItemStack.a,
+ CraftItemStack.asNMSCopy(items[0]),
+ CraftItemStack.asNMSCopy(items[1]),
+ CraftItemStack.asNMSCopy(items[2])
+ );
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
+ }
+
+ @Override
+ public void clearCursor(@NotNull Player player) {
+ getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.a));
+ }
+
+ /**
+ * Gets the window id for the inventory view the player currently has open
+ *
+ * @param entityPlayer the player to get the window id for
+ * @return the window id
+ * @since 0.8.0
+ */
+ @Contract(pure = true)
+ private int getWindowId(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.activeContainer.windowId;
+ }
+
+ /**
+ * Gets the player connection for the specified player
+ *
+ * @param entityPlayer the player to get the player connection from
+ * @return the player connection
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.playerConnection;
+ }
+
+ /**
+ * Gets the entity player associated to this player
+ *
+ * @param player the player to get the entity player from
+ * @return the entity player
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private EntityPlayer getEntityPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * A custom container cartography table
+ *
+ * @since 0.8.0
+ */
+ private class ContainerCartographyTableImpl extends ContainerCartography {
+
+ /**
+ * The player for this cartography table container
+ */
+ @NotNull
+ private final Player player;
+
+ /**
+ * The internal bukkit entity for this container cartography table
+ */
+ @Nullable
+ private CraftInventoryView bukkitEntity;
+
+ /**
+ * Field for accessing the result inventory field
+ */
+ @NotNull
+ private final Field resultInventoryField;
+
+ public ContainerCartographyTableImpl(@NotNull EntityPlayer entityPlayer,
+ @Nullable org.bukkit.inventory.ItemStack[] items) {
+ super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
+
+ this.player = entityPlayer.getBukkitEntity();
+
+ try {
+ this.resultInventoryField = ContainerCartography.class.getDeclaredField("resultInventory");
+ this.resultInventoryField.setAccessible(true);
+ } catch (NoSuchFieldException exception) {
+ throw new RuntimeException(exception);
+ }
+
+ inventory.setItem(0, CraftItemStack.asNMSCopy(items[0]));
+ inventory.setItem(1, CraftItemStack.asNMSCopy(items[1]));
+
+ getResultInventory().setItem(0, CraftItemStack.asNMSCopy(items[2]));
+ }
+
+ @NotNull
+ @Override
+ public CraftInventoryView getBukkitView() {
+ if (bukkitEntity == null) {
+ CraftInventory inventory = new CraftInventoryCartography(super.inventory, getResultInventory()) {
+ @NotNull
+ @Contract(pure = true)
+ @Override
+ public InventoryHolder getHolder() {
+ return inventoryHolder;
+ }
+ };
+
+ bukkitEntity = new CraftInventoryView(player, inventory, this);
+ }
+
+ return bukkitEntity;
+ }
+
+ @Contract(pure = true, value = "_ -> true")
+ @Override
+ public boolean canUse(@Nullable EntityHuman entityhuman) {
+ return true;
+ }
+
+ @Override
+ public void a(IInventory inventory) {}
+
+ @Override
+ public void b(EntityHuman entityhuman) {}
+
+ @NotNull
+ @Contract(pure = true)
+ private IInventory getResultInventory() {
+ try {
+ return (IInventory) resultInventoryField.get(this);
+ } catch (IllegalAccessException exception) {
+ throw new RuntimeException(exception);
+ }
+ }
+
+ }
+}
diff --git a/nms/1_14_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_14_R1/EnchantingTableInventoryImpl.java b/nms/1_14/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_14/EnchantingTableInventoryImpl.java
similarity index 94%
rename from nms/1_14_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_14_R1/EnchantingTableInventoryImpl.java
rename to nms/1_14/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_14/EnchantingTableInventoryImpl.java
index 0acb73900..ae6bb4e44 100644
--- a/nms/1_14_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_14_R1/EnchantingTableInventoryImpl.java
+++ b/nms/1_14/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_14/EnchantingTableInventoryImpl.java
@@ -1,194 +1,196 @@
-package com.github.stefvanschie.inventoryframework.nms.v1_14_R1;
-
-import com.github.stefvanschie.inventoryframework.abstraction.EnchantingTableInventory;
-import net.minecraft.server.v1_14_R1.*;
-import org.bukkit.craftbukkit.v1_14_R1.entity.CraftPlayer;
-import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftInventory;
-import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftInventoryEnchanting;
-import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftInventoryView;
-import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftItemStack;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.InventoryHolder;
-import org.jetbrains.annotations.Contract;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.lang.reflect.Field;
-
-/**
- * Internal enchanting table inventory for 1.14 R1
- *
- * @since 0.8.0
- */
-public class EnchantingTableInventoryImpl extends EnchantingTableInventory {
-
- public EnchantingTableInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
- super(inventoryHolder);
- }
-
- @Override
- public void openInventory(@NotNull Player player, @NotNull String title,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- int itemAmount = items.length;
-
- if (itemAmount != 2) {
- throw new IllegalArgumentException(
- "The amount of items for an enchanting table should be 2, but is '" + itemAmount + "'"
- );
- }
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
- ContainerEnchantingTableImpl containerEnchantmentTable = new ContainerEnchantingTableImpl(entityPlayer, items);
-
- entityPlayer.activeContainer = containerEnchantmentTable;
-
- int id = containerEnchantmentTable.windowId;
- ChatMessage message = new ChatMessage(title);
- PacketPlayOutOpenWindow packet = new PacketPlayOutOpenWindow(id, Containers.ENCHANTMENT, message);
-
- entityPlayer.playerConnection.sendPacket(packet);
-
- sendItems(player, items);
- }
-
- @Override
- public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
- NonNullList nmsItems = NonNullList.a(
- ItemStack.a,
- CraftItemStack.asNMSCopy(items[0]),
- CraftItemStack.asNMSCopy(items[1])
- );
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
- }
-
- @Override
- public void clearCursor(@NotNull Player player) {
- getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.a));
- }
-
- /**
- * Gets the window id for the inventory view the player currently has open
- *
- * @param entityPlayer the player to get the window id for
- * @return the window id
- * @since 0.8.0
- */
- @Contract(pure = true)
- private int getWindowId(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.activeContainer.windowId;
- }
-
- /**
- * Gets the player connection for the specified player
- *
- * @param entityPlayer the player to get the player connection from
- * @return the player connection
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.playerConnection;
- }
-
- /**
- * Gets the entity player associated to this player
- *
- * @param player the player to get the entity player from
- * @return the entity player
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private EntityPlayer getEntityPlayer(@NotNull Player player) {
- return ((CraftPlayer) player).getHandle();
- }
-
- /**
- * A custom container enchanting table
- *
- * @since 0.8.0
- */
- private class ContainerEnchantingTableImpl extends ContainerEnchantTable {
-
- /**
- * The player for this enchanting table container
- */
- @NotNull
- private final Player player;
-
- /**
- * The internal bukkit entity for this container enchanting table
- */
- @Nullable
- private CraftInventoryView bukkitEntity;
-
- /**
- * Field for accessing the enchant slots field
- */
- @NotNull
- private final Field enchantSlotsField;
-
- public ContainerEnchantingTableImpl(@NotNull EntityPlayer entityPlayer,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
-
- this.player = entityPlayer.getBukkitEntity();
-
- try {
- this.enchantSlotsField = ContainerEnchantTable.class.getDeclaredField("enchantSlots");
- this.enchantSlotsField.setAccessible(true);
- } catch (NoSuchFieldException exception) {
- throw new RuntimeException(exception);
- }
-
- try {
- IInventory input = (IInventory) enchantSlotsField.get(this);
-
- input.setItem(0, CraftItemStack.asNMSCopy(items[0]));
- input.setItem(1, CraftItemStack.asNMSCopy(items[1]));
- } catch (IllegalAccessException e) {
- e.printStackTrace();
- }
- }
-
- @NotNull
- @Override
- public CraftInventoryView getBukkitView() {
- if (bukkitEntity == null) {
- try {
- CraftInventory inventory = new CraftInventoryEnchanting((IInventory) enchantSlotsField.get(this)) {
- @NotNull
- @Contract(pure = true)
- @Override
- public InventoryHolder getHolder() {
- return inventoryHolder;
- }
- };
-
- bukkitEntity = new CraftInventoryView(player, inventory, this);
- } catch (IllegalAccessException exception) {
- exception.printStackTrace();
- }
- }
-
- return bukkitEntity;
- }
-
- @Contract(pure = true, value = "_ -> true")
- @Override
- public boolean canUse(@Nullable EntityHuman entityhuman) {
- return true;
- }
-
- @Override
- public void a(IInventory inventory) {}
-
- @Override
- public void b(EntityHuman entityhuman) {}
-
- }
-}
+package com.github.stefvanschie.inventoryframework.nms.v1_14;
+
+import com.github.stefvanschie.inventoryframework.abstraction.EnchantingTableInventory;
+import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
+import com.github.stefvanschie.inventoryframework.nms.v1_14.util.TextHolderUtil;
+import net.minecraft.server.v1_14_R1.*;
+import org.bukkit.craftbukkit.v1_14_R1.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftInventory;
+import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftInventoryEnchanting;
+import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftInventoryView;
+import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftItemStack;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.InventoryHolder;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.lang.reflect.Field;
+
+/**
+ * Internal enchanting table inventory for 1.14 R1
+ *
+ * @since 0.8.0
+ */
+public class EnchantingTableInventoryImpl extends EnchantingTableInventory {
+
+ public EnchantingTableInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
+ super(inventoryHolder);
+ }
+
+ @Override
+ public void openInventory(@NotNull Player player, @NotNull TextHolder title,
+ @Nullable org.bukkit.inventory.ItemStack[] items) {
+ int itemAmount = items.length;
+
+ if (itemAmount != 2) {
+ throw new IllegalArgumentException(
+ "The amount of items for an enchanting table should be 2, but is '" + itemAmount + "'"
+ );
+ }
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+ ContainerEnchantingTableImpl containerEnchantmentTable = new ContainerEnchantingTableImpl(entityPlayer, items);
+
+ entityPlayer.activeContainer = containerEnchantmentTable;
+
+ int id = containerEnchantmentTable.windowId;
+ IChatBaseComponent message = TextHolderUtil.toComponent(title);
+ PacketPlayOutOpenWindow packet = new PacketPlayOutOpenWindow(id, Containers.ENCHANTMENT, message);
+
+ entityPlayer.playerConnection.sendPacket(packet);
+
+ sendItems(player, items);
+ }
+
+ @Override
+ public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
+ NonNullList nmsItems = NonNullList.a(
+ ItemStack.a,
+ CraftItemStack.asNMSCopy(items[0]),
+ CraftItemStack.asNMSCopy(items[1])
+ );
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
+ }
+
+ @Override
+ public void clearCursor(@NotNull Player player) {
+ getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.a));
+ }
+
+ /**
+ * Gets the window id for the inventory view the player currently has open
+ *
+ * @param entityPlayer the player to get the window id for
+ * @return the window id
+ * @since 0.8.0
+ */
+ @Contract(pure = true)
+ private int getWindowId(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.activeContainer.windowId;
+ }
+
+ /**
+ * Gets the player connection for the specified player
+ *
+ * @param entityPlayer the player to get the player connection from
+ * @return the player connection
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.playerConnection;
+ }
+
+ /**
+ * Gets the entity player associated to this player
+ *
+ * @param player the player to get the entity player from
+ * @return the entity player
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private EntityPlayer getEntityPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * A custom container enchanting table
+ *
+ * @since 0.8.0
+ */
+ private class ContainerEnchantingTableImpl extends ContainerEnchantTable {
+
+ /**
+ * The player for this enchanting table container
+ */
+ @NotNull
+ private final Player player;
+
+ /**
+ * The internal bukkit entity for this container enchanting table
+ */
+ @Nullable
+ private CraftInventoryView bukkitEntity;
+
+ /**
+ * Field for accessing the enchant slots field
+ */
+ @NotNull
+ private final Field enchantSlotsField;
+
+ public ContainerEnchantingTableImpl(@NotNull EntityPlayer entityPlayer,
+ @Nullable org.bukkit.inventory.ItemStack[] items) {
+ super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
+
+ this.player = entityPlayer.getBukkitEntity();
+
+ try {
+ this.enchantSlotsField = ContainerEnchantTable.class.getDeclaredField("enchantSlots");
+ this.enchantSlotsField.setAccessible(true);
+ } catch (NoSuchFieldException exception) {
+ throw new RuntimeException(exception);
+ }
+
+ try {
+ IInventory input = (IInventory) enchantSlotsField.get(this);
+
+ input.setItem(0, CraftItemStack.asNMSCopy(items[0]));
+ input.setItem(1, CraftItemStack.asNMSCopy(items[1]));
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @NotNull
+ @Override
+ public CraftInventoryView getBukkitView() {
+ if (bukkitEntity == null) {
+ try {
+ CraftInventory inventory = new CraftInventoryEnchanting((IInventory) enchantSlotsField.get(this)) {
+ @NotNull
+ @Contract(pure = true)
+ @Override
+ public InventoryHolder getHolder() {
+ return inventoryHolder;
+ }
+ };
+
+ bukkitEntity = new CraftInventoryView(player, inventory, this);
+ } catch (IllegalAccessException exception) {
+ exception.printStackTrace();
+ }
+ }
+
+ return bukkitEntity;
+ }
+
+ @Contract(pure = true, value = "_ -> true")
+ @Override
+ public boolean canUse(@Nullable EntityHuman entityhuman) {
+ return true;
+ }
+
+ @Override
+ public void a(IInventory inventory) {}
+
+ @Override
+ public void b(EntityHuman entityhuman) {}
+
+ }
+}
diff --git a/nms/1_14/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_14/GrindstoneInventoryImpl.java b/nms/1_14/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_14/GrindstoneInventoryImpl.java
new file mode 100644
index 000000000..f382990ab
--- /dev/null
+++ b/nms/1_14/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_14/GrindstoneInventoryImpl.java
@@ -0,0 +1,272 @@
+package com.github.stefvanschie.inventoryframework.nms.v1_14;
+
+import com.github.stefvanschie.inventoryframework.abstraction.GrindstoneInventory;
+import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
+import com.github.stefvanschie.inventoryframework.nms.v1_14.util.TextHolderUtil;
+import net.minecraft.server.v1_14_R1.*;
+import org.bukkit.craftbukkit.v1_14_R1.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_14_R1.event.CraftEventFactory;
+import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftItemStack;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.InventoryHolder;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.lang.reflect.Field;
+import java.util.Collections;
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * Internal grindstone inventory for 1.14 R1
+ *
+ * @since 0.8.0
+ */
+public class GrindstoneInventoryImpl extends GrindstoneInventory {
+
+ public GrindstoneInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
+ super(inventoryHolder);
+ }
+
+ @Override
+ public Inventory openInventory(@NotNull Player player, @NotNull TextHolder title,
+ @Nullable org.bukkit.inventory.ItemStack[] items) {
+ int itemAmount = items.length;
+
+ if (itemAmount != 3) {
+ throw new IllegalArgumentException(
+ "The amount of items for a grindstone should be 3, but is '" + itemAmount + "'"
+ );
+ }
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ //ignore deprecation: superseding method is only available on Paper
+ //noinspection deprecation
+ CraftEventFactory.handleInventoryCloseEvent(entityPlayer);
+
+ entityPlayer.activeContainer = entityPlayer.defaultContainer;
+
+ IChatBaseComponent message = TextHolderUtil.toComponent(title);
+ ContainerGrindstoneImpl containerGrindstone = new ContainerGrindstoneImpl(entityPlayer);
+
+ Inventory inventory = containerGrindstone.getBukkitView().getTopInventory();
+
+ inventory.setItem(0, items[0]);
+ inventory.setItem(1, items[1]);
+ inventory.setItem(2, items[2]);
+
+ int windowId = containerGrindstone.getWindowId();
+
+ entityPlayer.playerConnection.sendPacket(new PacketPlayOutOpenWindow(windowId, Containers.GRINDSTONE, message));
+ entityPlayer.activeContainer = containerGrindstone;
+ entityPlayer.syncInventory();
+
+ return inventory;
+ }
+
+ @Override
+ public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items,
+ @Nullable org.bukkit.inventory.ItemStack cursor) {
+ NonNullList nmsItems = NonNullList.a(
+ ItemStack.a,
+ CraftItemStack.asNMSCopy(items[0]),
+ CraftItemStack.asNMSCopy(items[1]),
+ CraftItemStack.asNMSCopy(items[2])
+ );
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
+ }
+
+ @Override
+ public void clearCursor(@NotNull Player player) {
+ getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.a));
+ }
+
+ /**
+ * Gets the window id for the inventory view the player currently has open
+ *
+ * @param entityPlayer the player to get the window id for
+ * @return the window id
+ * @since 0.8.0
+ * @deprecated no longer used internally
+ */
+ @Contract(pure = true)
+ @Deprecated
+ private int getWindowId(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.activeContainer.windowId;
+ }
+
+ /**
+ * Gets the player connection for the specified player
+ *
+ * @param entityPlayer the player to get the player connection from
+ * @return the player connection
+ * @since 0.8.0
+ * @deprecated no longer used internally
+ */
+ @NotNull
+ @Contract(pure = true)
+ @Deprecated
+ private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.playerConnection;
+ }
+
+ /**
+ * Gets the entity player associated to this player
+ *
+ * @param player the player to get the entity player from
+ * @return the entity player
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private EntityPlayer getEntityPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * A custom container grindstone
+ *
+ * @since 0.8.0
+ */
+ private static class ContainerGrindstoneImpl extends ContainerGrindstone {
+
+ /**
+ * A unique item
+ */
+ @NotNull
+ private final ItemStack uniqueItem;
+
+ /**
+ * The field containing the listeners for this container
+ */
+ @NotNull
+ private final Field listenersField;
+
+ /**
+ * Creates a new grindstone container
+ *
+ * @param entityPlayer the player for whom this container should be opened
+ * @since 0.10.8
+ */
+ public ContainerGrindstoneImpl(@NotNull EntityPlayer entityPlayer) {
+ super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
+
+ try {
+ this.listenersField = Container.class.getDeclaredField("listeners");
+ this.listenersField.setAccessible(true);
+ } catch (NoSuchFieldException exception) {
+ throw new RuntimeException("Unable to access field 'listeners'", exception);
+ }
+
+ Slot firstSlot = this.slots.get(0);
+ Slot secondSlot = this.slots.get(1);
+ Slot thirdSlot = this.slots.get(2);
+
+ this.slots.set(0, new Slot(firstSlot.inventory, firstSlot.rawSlotIndex, firstSlot.e, firstSlot.f) {
+ @Override
+ public boolean isAllowed(ItemStack stack) {
+ return true;
+ }
+ });
+
+ this.slots.set(1, new Slot(secondSlot.inventory, secondSlot.rawSlotIndex, secondSlot.e, secondSlot.f) {
+ @Override
+ public boolean isAllowed(ItemStack stack) {
+ return true;
+ }
+ });
+
+ this.slots.set(2, new Slot(thirdSlot.inventory, thirdSlot.rawSlotIndex, thirdSlot.e, thirdSlot.f) {
+ @Override
+ public boolean isAllowed(ItemStack stack) {
+ return true;
+ }
+
+ @Override
+ public ItemStack a(EntityHuman entityHuman, ItemStack itemStack) {
+ return itemStack;
+ }
+ });
+
+ this.uniqueItem = new ItemStack(Items.COOKIE);
+
+ //to make the item unique, we add a random uuid as nbt to it
+ UUID uuid = UUID.randomUUID();
+ NBTTagCompound nbtTagCompound = new NBTTagCompound();
+
+ nbtTagCompound.set("uuid", new NBTTagLongArray(new long [] {
+ uuid.getLeastSignificantBits(),
+ uuid.getMostSignificantBits()
+ }));
+
+ this.uniqueItem.setTag(nbtTagCompound);
+ }
+
+ /**
+ * Forcefully updates the client state, sending all items, container properties and the held item.
+ *
+ * @since 0.10.8
+ */
+ public void forceUpdate() {
+ /*
+ The server will not send the items when they haven't changed, so we will overwrite every item with a unique
+ item first to ensure the server is going to send our items.
+ */
+ Collections.fill(this.items, this.uniqueItem);
+
+ c();
+
+ List extends ICrafting> listeners;
+
+ try {
+ //noinspection unchecked
+ listeners = (List extends ICrafting>) listenersField.get(this);
+ } catch (IllegalAccessException exception) {
+ throw new RuntimeException("Unable to access field 'listeners'", exception);
+ }
+
+ for (ICrafting listener : listeners) {
+ if (!(listener instanceof EntityPlayer)) {
+ continue;
+ }
+
+ EntityPlayer player = (EntityPlayer) listener;
+
+ player.e = false;
+ player.broadcastCarriedItem();
+ }
+ }
+
+ @Override
+ public ItemStack a(int i, int j, InventoryClickType inventoryclicktype, EntityHuman entityhuman) {
+ ItemStack itemStack = super.a(i, j, inventoryclicktype, entityhuman);
+
+ //the client predicts the allowed movement of the item, so we broadcast the state again to override it
+ forceUpdate();
+
+ return itemStack;
+ }
+
+ @Contract(pure = true, value = "_ -> true")
+ @Override
+ public boolean canUse(@Nullable EntityHuman entityHuman) {
+ return true;
+ }
+
+ @Override
+ public void a(IInventory inventory) {}
+
+ @Override
+ public void b(EntityHuman entityHuman) {}
+
+ public int getWindowId() {
+ return this.windowId;
+ }
+ }
+}
diff --git a/nms/1_14/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_14/MerchantInventoryImpl.java b/nms/1_14/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_14/MerchantInventoryImpl.java
new file mode 100644
index 000000000..326c2ed8d
--- /dev/null
+++ b/nms/1_14/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_14/MerchantInventoryImpl.java
@@ -0,0 +1,95 @@
+package com.github.stefvanschie.inventoryframework.nms.v1_14;
+
+import com.github.stefvanschie.inventoryframework.abstraction.MerchantInventory;
+import net.minecraft.server.v1_14_R1.EntityPlayer;
+import net.minecraft.server.v1_14_R1.MerchantRecipeList;
+import org.bukkit.craftbukkit.v1_14_R1.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftItemStack;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.MerchantRecipe;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Internal merchant inventory for 1.14
+ *
+ * @since 0.10.1
+ */
+public class MerchantInventoryImpl extends MerchantInventory {
+
+ @Override
+ public void sendMerchantOffers(@NotNull Player player,
+ @NotNull List extends Map.Entry extends MerchantRecipe, ? extends Integer>> trades,
+ int level, int experience) {
+ MerchantRecipeList offers = new MerchantRecipeList();
+
+ for (Map.Entry extends MerchantRecipe, ? extends Integer> entry : trades) {
+ MerchantRecipe recipe = entry.getKey();
+ List ingredients = recipe.getIngredients();
+
+ if (ingredients.size() < 1) {
+ throw new IllegalStateException("Merchant recipe has no ingredients");
+ }
+
+ ItemStack itemA = ingredients.get(0);
+ ItemStack itemB = null;
+
+ if (ingredients.size() >= 2) {
+ itemB = ingredients.get(1);
+ }
+
+ net.minecraft.server.v1_14_R1.ItemStack nmsItemA = CraftItemStack.asNMSCopy(itemA);
+ net.minecraft.server.v1_14_R1.ItemStack nmsItemB = net.minecraft.server.v1_14_R1.ItemStack.a;
+ net.minecraft.server.v1_14_R1.ItemStack nmsItemResult = CraftItemStack.asNMSCopy(recipe.getResult());
+
+ if (itemB != null) {
+ nmsItemB = CraftItemStack.asNMSCopy(itemB);
+ }
+
+ int uses = recipe.getUses();
+ int maxUses = recipe.getMaxUses();
+ int exp = recipe.getVillagerExperience();
+ float multiplier = recipe.getPriceMultiplier();
+
+ net.minecraft.server.v1_14_R1.MerchantRecipe merchantOffer = new net.minecraft.server.v1_14_R1.MerchantRecipe(
+ nmsItemA, nmsItemB, nmsItemResult, uses, maxUses, exp, multiplier
+ );
+ merchantOffer.setSpecialPrice(entry.getValue());
+
+ offers.add(merchantOffer);
+ }
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ entityPlayer.openTrade(getWindowId(entityPlayer), offers, level, experience, true, false);
+ }
+
+ /**
+ * Gets the entity player associated to this player
+ *
+ * @param player the player to get the entity player from
+ * @return the entity player
+ * @since 0.10.1
+ */
+ @NotNull
+ @Contract(pure = true)
+ private EntityPlayer getEntityPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * Gets the window id for the inventory view the player currently has open
+ *
+ * @param entityPlayer the player to get the window id for
+ * @return the window id
+ * @since 0.10.1
+ */
+ @Contract(pure = true)
+ private int getWindowId(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.activeContainer.windowId;
+ }
+}
diff --git a/nms/1_14_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_14_R1/StonecutterInventoryImpl.java b/nms/1_14/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_14/StonecutterInventoryImpl.java
similarity index 94%
rename from nms/1_14_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_14_R1/StonecutterInventoryImpl.java
rename to nms/1_14/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_14/StonecutterInventoryImpl.java
index a193a995d..877624db6 100644
--- a/nms/1_14_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_14_R1/StonecutterInventoryImpl.java
+++ b/nms/1_14/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_14/StonecutterInventoryImpl.java
@@ -1,199 +1,201 @@
-package com.github.stefvanschie.inventoryframework.nms.v1_14_R1;
-
-import com.github.stefvanschie.inventoryframework.abstraction.StonecutterInventory;
-import net.minecraft.server.v1_14_R1.*;
-import org.bukkit.craftbukkit.v1_14_R1.entity.CraftPlayer;
-import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftInventory;
-import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftInventoryStonecutter;
-import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftInventoryView;
-import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftItemStack;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.InventoryHolder;
-import org.jetbrains.annotations.Contract;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.lang.reflect.Field;
-
-/**
- * Internal stonecutter inventory for 1.14 R1
- *
- * @since 0.8.0
- */
-public class StonecutterInventoryImpl extends StonecutterInventory {
-
- public StonecutterInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
- super(inventoryHolder);
- }
-
- @Override
- public void openInventory(@NotNull Player player, @NotNull String title,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- int itemAmount = items.length;
-
- if (itemAmount != 2) {
- throw new IllegalArgumentException(
- "The amount of items for a stonecutter should be 2, but is '" + itemAmount + "'"
- );
- }
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
- ContainerStonecutterImpl containerEnchantmentTable = new ContainerStonecutterImpl(entityPlayer, items);
-
- entityPlayer.activeContainer = containerEnchantmentTable;
-
- int id = containerEnchantmentTable.windowId;
- ChatMessage message = new ChatMessage(title);
- PacketPlayOutOpenWindow packet = new PacketPlayOutOpenWindow(id, Containers.STONECUTTER, message);
-
- entityPlayer.playerConnection.sendPacket(packet);
-
- sendItems(player, items);
- }
-
- @Override
- public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
- NonNullList nmsItems = NonNullList.a(
- ItemStack.a,
- CraftItemStack.asNMSCopy(items[0]),
- CraftItemStack.asNMSCopy(items[1])
- );
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
- }
-
- @Override
- public void clearCursor(@NotNull Player player) {
- getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.a));
- }
-
- /**
- * Gets the window id for the inventory view the player currently has open
- *
- * @param entityPlayer the player to get the window id for
- * @return the window id
- * @since 0.8.0
- */
- @Contract(pure = true)
- private int getWindowId(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.activeContainer.windowId;
- }
-
- /**
- * Gets the player connection for the specified player
- *
- * @param entityPlayer the player to get the player connection from
- * @return the player connection
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.playerConnection;
- }
-
- /**
- * Gets the entity player associated to this player
- *
- * @param player the player to get the entity player from
- * @return the entity player
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private EntityPlayer getEntityPlayer(@NotNull Player player) {
- return ((CraftPlayer) player).getHandle();
- }
-
- /**
- * A custom container enchanting table
- *
- * @since 0.8.0
- */
- private class ContainerStonecutterImpl extends ContainerStonecutter {
-
- /**
- * The player for this enchanting table container
- */
- @NotNull
- private final Player player;
-
- /**
- * The internal bukkit entity for this container enchanting table
- */
- @Nullable
- private CraftInventoryView bukkitEntity;
-
- /**
- * Field for accessing the result inventory field
- */
- @NotNull
- private final Field resultInventoryField;
-
- public ContainerStonecutterImpl(@NotNull EntityPlayer entityPlayer,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
-
- this.player = entityPlayer.getBukkitEntity();
-
- try {
- this.resultInventoryField = ContainerStonecutter.class.getDeclaredField("resultInventory");
- this.resultInventoryField.setAccessible(true);
- } catch (NoSuchFieldException exception) {
- throw new RuntimeException(exception);
- }
-
- inventory.setItem(0, CraftItemStack.asNMSCopy(items[0]));
- getResultInventory().setItem(0, CraftItemStack.asNMSCopy(items[1]));
- }
-
- @NotNull
- @Override
- public CraftInventoryView getBukkitView() {
- if (bukkitEntity == null) {
- CraftInventory inventory = new CraftInventoryStonecutter(this.inventory, getResultInventory()) {
- @NotNull
- @Contract(pure = true)
- @Override
- public InventoryHolder getHolder() {
- return inventoryHolder;
- }
- };
-
- bukkitEntity = new CraftInventoryView(player, inventory, this);
- }
-
- return bukkitEntity;
- }
-
- @Contract(pure = true, value = "_ -> true")
- @Override
- public boolean canUse(@Nullable EntityHuman entityhuman) {
- return true;
- }
-
- @Override
- public void a(IInventory inventory) {}
-
- @Override
- public void b(EntityHuman entityhuman) {}
-
- /**
- * Gets the result inventory
- *
- * @return the result inventory
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- public IInventory getResultInventory() {
- try {
- return (IInventory) resultInventoryField.get(this);
- } catch (IllegalAccessException exception) {
- throw new RuntimeException(exception);
- }
- }
- }
-}
+package com.github.stefvanschie.inventoryframework.nms.v1_14;
+
+import com.github.stefvanschie.inventoryframework.abstraction.StonecutterInventory;
+import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
+import com.github.stefvanschie.inventoryframework.nms.v1_14.util.TextHolderUtil;
+import net.minecraft.server.v1_14_R1.*;
+import org.bukkit.craftbukkit.v1_14_R1.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftInventory;
+import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftInventoryStonecutter;
+import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftInventoryView;
+import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftItemStack;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.InventoryHolder;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.lang.reflect.Field;
+
+/**
+ * Internal stonecutter inventory for 1.14 R1
+ *
+ * @since 0.8.0
+ */
+public class StonecutterInventoryImpl extends StonecutterInventory {
+
+ public StonecutterInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
+ super(inventoryHolder);
+ }
+
+ @Override
+ public void openInventory(@NotNull Player player, @NotNull TextHolder title,
+ @Nullable org.bukkit.inventory.ItemStack[] items) {
+ int itemAmount = items.length;
+
+ if (itemAmount != 2) {
+ throw new IllegalArgumentException(
+ "The amount of items for a stonecutter should be 2, but is '" + itemAmount + "'"
+ );
+ }
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+ ContainerStonecutterImpl containerEnchantmentTable = new ContainerStonecutterImpl(entityPlayer, items);
+
+ entityPlayer.activeContainer = containerEnchantmentTable;
+
+ int id = containerEnchantmentTable.windowId;
+ IChatBaseComponent message = TextHolderUtil.toComponent(title);
+ PacketPlayOutOpenWindow packet = new PacketPlayOutOpenWindow(id, Containers.STONECUTTER, message);
+
+ entityPlayer.playerConnection.sendPacket(packet);
+
+ sendItems(player, items);
+ }
+
+ @Override
+ public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
+ NonNullList nmsItems = NonNullList.a(
+ ItemStack.a,
+ CraftItemStack.asNMSCopy(items[0]),
+ CraftItemStack.asNMSCopy(items[1])
+ );
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
+ }
+
+ @Override
+ public void clearCursor(@NotNull Player player) {
+ getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.a));
+ }
+
+ /**
+ * Gets the window id for the inventory view the player currently has open
+ *
+ * @param entityPlayer the player to get the window id for
+ * @return the window id
+ * @since 0.8.0
+ */
+ @Contract(pure = true)
+ private int getWindowId(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.activeContainer.windowId;
+ }
+
+ /**
+ * Gets the player connection for the specified player
+ *
+ * @param entityPlayer the player to get the player connection from
+ * @return the player connection
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.playerConnection;
+ }
+
+ /**
+ * Gets the entity player associated to this player
+ *
+ * @param player the player to get the entity player from
+ * @return the entity player
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private EntityPlayer getEntityPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * A custom container enchanting table
+ *
+ * @since 0.8.0
+ */
+ private class ContainerStonecutterImpl extends ContainerStonecutter {
+
+ /**
+ * The player for this enchanting table container
+ */
+ @NotNull
+ private final Player player;
+
+ /**
+ * The internal bukkit entity for this container enchanting table
+ */
+ @Nullable
+ private CraftInventoryView bukkitEntity;
+
+ /**
+ * Field for accessing the result inventory field
+ */
+ @NotNull
+ private final Field resultInventoryField;
+
+ public ContainerStonecutterImpl(@NotNull EntityPlayer entityPlayer,
+ @Nullable org.bukkit.inventory.ItemStack[] items) {
+ super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
+
+ this.player = entityPlayer.getBukkitEntity();
+
+ try {
+ this.resultInventoryField = ContainerStonecutter.class.getDeclaredField("resultInventory");
+ this.resultInventoryField.setAccessible(true);
+ } catch (NoSuchFieldException exception) {
+ throw new RuntimeException(exception);
+ }
+
+ inventory.setItem(0, CraftItemStack.asNMSCopy(items[0]));
+ getResultInventory().setItem(0, CraftItemStack.asNMSCopy(items[1]));
+ }
+
+ @NotNull
+ @Override
+ public CraftInventoryView getBukkitView() {
+ if (bukkitEntity == null) {
+ CraftInventory inventory = new CraftInventoryStonecutter(this.inventory, getResultInventory()) {
+ @NotNull
+ @Contract(pure = true)
+ @Override
+ public InventoryHolder getHolder() {
+ return inventoryHolder;
+ }
+ };
+
+ bukkitEntity = new CraftInventoryView(player, inventory, this);
+ }
+
+ return bukkitEntity;
+ }
+
+ @Contract(pure = true, value = "_ -> true")
+ @Override
+ public boolean canUse(@Nullable EntityHuman entityhuman) {
+ return true;
+ }
+
+ @Override
+ public void a(IInventory inventory) {}
+
+ @Override
+ public void b(EntityHuman entityhuman) {}
+
+ /**
+ * Gets the result inventory
+ *
+ * @return the result inventory
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ public IInventory getResultInventory() {
+ try {
+ return (IInventory) resultInventoryField.get(this);
+ } catch (IllegalAccessException exception) {
+ throw new RuntimeException(exception);
+ }
+ }
+ }
+}
diff --git a/nms/1_14/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_14/util/TextHolderUtil.java b/nms/1_14/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_14/util/TextHolderUtil.java
new file mode 100644
index 000000000..5f628de0d
--- /dev/null
+++ b/nms/1_14/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_14/util/TextHolderUtil.java
@@ -0,0 +1,66 @@
+package com.github.stefvanschie.inventoryframework.nms.v1_14.util;
+
+import com.github.stefvanschie.inventoryframework.adventuresupport.ComponentHolder;
+import com.github.stefvanschie.inventoryframework.adventuresupport.StringHolder;
+import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
+import net.minecraft.server.v1_14_R1.ChatComponentText;
+import net.minecraft.server.v1_14_R1.IChatBaseComponent;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Objects;
+
+/**
+ * A utility class for adding {@link TextHolder} support.
+ *
+ * @since 0.10.0
+ */
+public final class TextHolderUtil {
+
+ private TextHolderUtil() {
+ //private constructor to prevent construction
+ }
+
+ /**
+ * Converts the specified value to a vanilla component.
+ *
+ * @param holder the value to convert
+ * @return the value as a vanilla component
+ * @since 0.10.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ public static IChatBaseComponent toComponent(@NotNull TextHolder holder) {
+ if (holder instanceof StringHolder) {
+ return toComponent((StringHolder) holder);
+ } else {
+ return toComponent((ComponentHolder) holder);
+ }
+ }
+
+ /**
+ * Converts the specified legacy string holder to a vanilla component.
+ *
+ * @param holder the value to convert
+ * @return the value as a vanilla component
+ * @since 0.10.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private static IChatBaseComponent toComponent(@NotNull StringHolder holder) {
+ return new ChatComponentText(holder.asLegacyString());
+ }
+
+ /**
+ * Converts the specified Adventure component holder to a vanilla component.
+ *
+ * @param holder the value to convert
+ * @return the value as a vanilla component
+ * @since 0.10.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private static IChatBaseComponent toComponent(@NotNull ComponentHolder holder) {
+ return Objects.requireNonNull(IChatBaseComponent.ChatSerializer.a(holder.asJson()));
+ }
+}
diff --git a/nms/1_14_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_14_R1/AnvilInventoryImpl.java b/nms/1_14_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_14_R1/AnvilInventoryImpl.java
deleted file mode 100644
index a17945e39..000000000
--- a/nms/1_14_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_14_R1/AnvilInventoryImpl.java
+++ /dev/null
@@ -1,304 +0,0 @@
-package com.github.stefvanschie.inventoryframework.nms.v1_14_R1;
-
-import com.github.stefvanschie.inventoryframework.abstraction.AnvilInventory;
-import net.minecraft.server.v1_14_R1.*;
-import org.bukkit.Location;
-import org.bukkit.craftbukkit.v1_14_R1.entity.CraftPlayer;
-import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftInventory;
-import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftInventoryAnvil;
-import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftInventoryView;
-import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftItemStack;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.InventoryHolder;
-import org.jetbrains.annotations.Contract;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.lang.reflect.Field;
-
-/**
- * Internal anvil inventory for 1.14 R1
- *
- * @since 0.8.0
- */
-public class AnvilInventoryImpl extends AnvilInventory {
-
- public AnvilInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
- super(inventoryHolder);
- }
-
- @Override
- public void openInventory(@NotNull Player player, @NotNull String title,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- int itemAmount = items.length;
-
- if (itemAmount != 3) {
- throw new IllegalArgumentException(
- "The amount of items for an anvil should be 3, but is '" + itemAmount + "'"
- );
- }
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
- ContainerAnvilImpl containerAnvil = new ContainerAnvilImpl(entityPlayer, items);
-
- entityPlayer.activeContainer = containerAnvil;
-
- int id = containerAnvil.windowId;
- ChatMessage message = new ChatMessage(title);
-
- entityPlayer.playerConnection.sendPacket(new PacketPlayOutOpenWindow(id, Containers.ANVIL, message));
-
- sendItems(player, items);
- }
-
- @Override
- public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
- NonNullList nmsItems = NonNullList.a(
- ItemStack.a,
- CraftItemStack.asNMSCopy(items[0]),
- CraftItemStack.asNMSCopy(items[1]),
- CraftItemStack.asNMSCopy(items[2])
- );
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
- }
-
- @Override
- public void sendFirstItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
- EntityPlayer entityPlayer = getEntityPlayer(player);
- ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutSetSlot(getWindowId(entityPlayer), 0, nmsItem));
- }
-
- @Override
- public void sendSecondItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
- EntityPlayer entityPlayer = getEntityPlayer(player);
- ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutSetSlot(getWindowId(entityPlayer), 1, nmsItem));
- }
-
- @Override
- public void sendResultItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
- sendResultItem(player, CraftItemStack.asNMSCopy(item));
- }
-
- @Override
- public void clearResultItem(@NotNull Player player) {
- sendResultItem(player, ItemStack.a);
- }
-
- @Override
- public void setCursor(@NotNull Player player, @NotNull org.bukkit.inventory.ItemStack item) {
- setCursor(player, CraftItemStack.asNMSCopy(item));
- }
-
- @Override
- public void clearCursor(@NotNull Player player) {
- getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.a));
- }
-
- /**
- * Sets the cursor of the given player
- *
- * @param player the player to set the cursor
- * @param item the item to set the cursor to
- * @since 0.8.0
- */
- private void setCursor(@NotNull Player player, @NotNull ItemStack item) {
- getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, item));
- }
-
- /**
- * Sends the result item to the specified player with the given item
- *
- * @param player the player to send the result item to
- * @param item the result item
- * @since 0.8.0
- */
- private void sendResultItem(@NotNull Player player, @NotNull ItemStack item) {
- EntityPlayer entityPlayer = getEntityPlayer(player);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutSetSlot(getWindowId(entityPlayer), 2, item));
- }
-
- /**
- * Gets the window id for the inventory view the player currently has open
- *
- * @param entityPlayer the player to get the window id for
- * @return the window id
- * @since 0.8.0
- */
- @Contract(pure = true)
- private int getWindowId(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.activeContainer.windowId;
- }
-
- /**
- * Gets the player connection for the specified player
- *
- * @param entityPlayer the player to get the player connection from
- * @return the player connection
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.playerConnection;
- }
-
- /**
- * Gets the entity player associated to this player
- *
- * @param player the player to get the entity player from
- * @return the entity player
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private EntityPlayer getEntityPlayer(@NotNull Player player) {
- return ((CraftPlayer) player).getHandle();
- }
-
- /**
- * A custom container anvil for responding to item renaming
- *
- * @since 0.8.0
- */
- private class ContainerAnvilImpl extends ContainerAnvil {
-
- /**
- * The player for whom this anvil container is
- */
- @NotNull
- private final Player player;
-
- /**
- * The internal bukkit entity for this container anvil
- */
- @Nullable
- private CraftInventoryView bukkitEntity;
-
- /**
- * Field for accessing the repair inventory field
- */
- @NotNull
- private final Field repairInventoryField;
-
- /**
- * Field for accessing the result inventory field
- */
- @NotNull
- private final Field resultInventoryField;
-
- /**
- * Field for accessing the container access field
- */
- @NotNull
- private final Field containerAccessField;
-
- /**
- * Creates a new custom anvil container for the specified player
- *
- * @param entityPlayer the player for who this anvil container is
- * @since 0.8.0
- */
- public ContainerAnvilImpl(@NotNull EntityPlayer entityPlayer,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- super(entityPlayer.nextContainerCounter(), entityPlayer.inventory,
- ContainerAccess.at(entityPlayer.getWorld(), new BlockPosition(0, 0, 0)));
-
- this.player = entityPlayer.getBukkitEntity();
-
- try {
- repairInventoryField = ContainerAnvil.class.getDeclaredField("repairInventory");
- repairInventoryField.setAccessible(true);
-
- resultInventoryField = ContainerAnvil.class.getDeclaredField("resultInventory");
- resultInventoryField.setAccessible(true);
-
- containerAccessField = ContainerAnvil.class.getDeclaredField("containerAccess");
- containerAccessField.setAccessible(true);
- } catch (NoSuchFieldException exception) {
- throw new RuntimeException(exception);
- }
-
- getRepairInventory().setItem(0, CraftItemStack.asNMSCopy(items[0]));
- getRepairInventory().setItem(1, CraftItemStack.asNMSCopy(items[1]));
- getResultInventory().setItem(0, CraftItemStack.asNMSCopy(items[2]));
- }
-
- @NotNull
- @Override
- public CraftInventoryView getBukkitView() {
- if (bukkitEntity == null) {
- Location location = getContainerAccess().getLocation();
- CraftInventory inventory = new CraftInventoryAnvil(location, getRepairInventory(), getResultInventory(),
- this) {
- @NotNull
- @Contract(pure = true)
- @Override
- public InventoryHolder getHolder() {
- return inventoryHolder;
- }
- };
-
- bukkitEntity = new CraftInventoryView(player, inventory, this);
- }
-
- return bukkitEntity;
- }
-
- @Override
- public void a(@Nullable String name) {
- text = name == null ? "" : name;
-
- sendResultItem(player, getResultInventory().getItem(0));
- }
-
- @Contract(pure = true, value = "_ -> true")
- @Override
- public boolean canUse(@Nullable EntityHuman entityhuman) {
- return true;
- }
-
- @Override
- public void a(IInventory inventory) {}
-
- @Override
- public void b(EntityHuman entityhuman) {}
-
- @NotNull
- @Contract(pure = true)
- private IInventory getRepairInventory() {
- try {
- return (IInventory) repairInventoryField.get(this);
- } catch (IllegalAccessException exception) {
- throw new RuntimeException(exception);
- }
- }
-
- @NotNull
- @Contract(pure = true)
- private IInventory getResultInventory() {
- try {
- return (IInventory) resultInventoryField.get(this);
- } catch (IllegalAccessException exception) {
- throw new RuntimeException(exception);
- }
- }
-
- @NotNull
- @Contract(pure = true)
- private ContainerAccess getContainerAccess() {
- try {
- return (ContainerAccess) containerAccessField.get(this);
- } catch (IllegalAccessException exception) {
- throw new RuntimeException(exception);
- }
- }
- }
-}
diff --git a/nms/1_14_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_14_R1/GrindstoneInventoryImpl.java b/nms/1_14_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_14_R1/GrindstoneInventoryImpl.java
deleted file mode 100644
index c93769a78..000000000
--- a/nms/1_14_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_14_R1/GrindstoneInventoryImpl.java
+++ /dev/null
@@ -1,227 +0,0 @@
-package com.github.stefvanschie.inventoryframework.nms.v1_14_R1;
-
-import com.github.stefvanschie.inventoryframework.abstraction.GrindstoneInventory;
-import net.minecraft.server.v1_14_R1.*;
-import org.bukkit.craftbukkit.v1_14_R1.entity.CraftPlayer;
-import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftInventory;
-import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftInventoryGrindstone;
-import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftInventoryView;
-import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftItemStack;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.InventoryHolder;
-import org.jetbrains.annotations.Contract;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.lang.reflect.Field;
-
-/**
- * Internal grindstone inventory for 1.14 R1
- *
- * @since 0.8.0
- */
-public class GrindstoneInventoryImpl extends GrindstoneInventory {
-
- public GrindstoneInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
- super(inventoryHolder);
- }
-
- @Override
- public void openInventory(@NotNull Player player, @NotNull String title,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- int itemAmount = items.length;
-
- if (itemAmount != 3) {
- throw new IllegalArgumentException(
- "The amount of items for a grindstone should be 3, but is '" + itemAmount + "'"
- );
- }
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
- ContainerGrindstoneImpl containerGrindstone = new ContainerGrindstoneImpl(entityPlayer, items);
-
- entityPlayer.activeContainer = containerGrindstone;
-
- int id = containerGrindstone.windowId;
- ChatMessage message = new ChatMessage(title);
- PacketPlayOutOpenWindow packet = new PacketPlayOutOpenWindow(id, Containers.GRINDSTONE, message);
-
- entityPlayer.playerConnection.sendPacket(packet);
-
- sendItems(player, items);
- }
-
- @Override
- public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
- NonNullList nmsItems = NonNullList.a(
- ItemStack.a,
- CraftItemStack.asNMSCopy(items[0]),
- CraftItemStack.asNMSCopy(items[1]),
- CraftItemStack.asNMSCopy(items[2])
- );
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
- }
-
- @Override
- public void clearCursor(@NotNull Player player) {
- getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.a));
- }
-
- /**
- * Gets the window id for the inventory view the player currently has open
- *
- * @param entityPlayer the player to get the window id for
- * @return the window id
- * @since 0.8.0
- */
- @Contract(pure = true)
- private int getWindowId(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.activeContainer.windowId;
- }
-
- /**
- * Gets the player connection for the specified player
- *
- * @param entityPlayer the player to get the player connection from
- * @return the player connection
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.playerConnection;
- }
-
- /**
- * Gets the entity player associated to this player
- *
- * @param player the player to get the entity player from
- * @return the entity player
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private EntityPlayer getEntityPlayer(@NotNull Player player) {
- return ((CraftPlayer) player).getHandle();
- }
-
- /**
- * A custom container grindstone
- *
- * @since 0.8.0
- */
- private class ContainerGrindstoneImpl extends ContainerGrindstone {
-
- /**
- * The player for this grindstone container
- */
- @NotNull
- private final Player player;
-
- /**
- * The internal bukkit entity for this container grindstone
- */
- @Nullable
- private CraftInventoryView bukkitEntity;
-
- /**
- * Field for accessing the craft inventory field
- */
- @NotNull
- private final Field craftInventoryField;
-
- /**
- * Field for accessing the result inventory field
- */
- @NotNull
- private final Field resultInventoryField;
-
- public ContainerGrindstoneImpl(@NotNull EntityPlayer entityPlayer,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
-
- this.player = entityPlayer.getBukkitEntity();
-
- try {
- this.craftInventoryField = ContainerGrindstone.class.getDeclaredField("craftInventory");
- this.craftInventoryField.setAccessible(true);
-
- this.resultInventoryField = ContainerGrindstone.class.getDeclaredField("resultInventory");
- this.resultInventoryField.setAccessible(true);
- } catch (NoSuchFieldException exception) {
- throw new RuntimeException(exception);
- }
-
- getCraftInventory().setItem(0, CraftItemStack.asNMSCopy(items[0]));
- getCraftInventory().setItem(1, CraftItemStack.asNMSCopy(items[1]));
-
- getResultInventory().setItem(2, CraftItemStack.asNMSCopy(items[2]));
- }
-
- @NotNull
- @Override
- public CraftInventoryView getBukkitView() {
- if (bukkitEntity == null) {
- CraftInventory inventory = new CraftInventoryGrindstone(getCraftInventory(), getResultInventory()) {
- @NotNull
- @Contract(pure = true)
- @Override
- public InventoryHolder getHolder() {
- return inventoryHolder;
- }
- };
-
- bukkitEntity = new CraftInventoryView(player, inventory, this);
- }
-
- return bukkitEntity;
- }
-
- @Contract(pure = true, value = "_ -> true")
- @Override
- public boolean canUse(@Nullable EntityHuman entityhuman) {
- return true;
- }
-
- @Override
- public void a(IInventory inventory) {}
-
- @Override
- public void b(EntityHuman entityhuman) {}
-
- /**
- * Gets the craft inventory
- *
- * @return the craft inventory
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private IInventory getCraftInventory() {
- try {
- return (IInventory) craftInventoryField.get(this);
- } catch (IllegalAccessException exception) {
- throw new RuntimeException(exception);
- }
- }
-
- /**
- * Gets the result inventory
- *
- * @return the result inventory
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private IInventory getResultInventory() {
- try {
- return (IInventory) resultInventoryField.get(this);
- } catch (IllegalAccessException exception) {
- throw new RuntimeException(exception);
- }
- }
- }
-}
diff --git a/nms/1_15_R1/pom.xml b/nms/1_15/pom.xml
similarity index 86%
rename from nms/1_15_R1/pom.xml
rename to nms/1_15/pom.xml
index 8cbdc5417..c85530eb7 100644
--- a/nms/1_15_R1/pom.xml
+++ b/nms/1_15/pom.xml
@@ -5,12 +5,12 @@
IF-parent
com.github.stefvanschie.inventoryframework
- 0.9.8
+ 0.10.18
../../pom.xml
4.0.0
- 1_15_R1
+ 1_15
true
@@ -18,8 +18,8 @@
- org.spigotmc
- spigot
+ io.papermc
+ paper
1.15.2-R0.1-SNAPSHOT
provided
diff --git a/nms/1_15/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_15/AnvilInventoryImpl.java b/nms/1_15/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_15/AnvilInventoryImpl.java
new file mode 100644
index 000000000..aff83a514
--- /dev/null
+++ b/nms/1_15/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_15/AnvilInventoryImpl.java
@@ -0,0 +1,381 @@
+package com.github.stefvanschie.inventoryframework.nms.v1_15;
+
+import com.github.stefvanschie.inventoryframework.abstraction.AnvilInventory;
+import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
+import com.github.stefvanschie.inventoryframework.nms.v1_15.util.TextHolderUtil;
+import net.minecraft.server.v1_15_R1.*;
+import org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_15_R1.event.CraftEventFactory;
+import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftItemStack;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.InventoryHolder;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.lang.reflect.Field;
+import java.util.Collections;
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * Internal anvil inventory for 1.15 R1
+ *
+ * @since 0.8.0
+ */
+public class AnvilInventoryImpl extends AnvilInventory {
+
+ public AnvilInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
+ super(inventoryHolder);
+ }
+
+ @Override
+ public Inventory openInventory(@NotNull Player player, @NotNull TextHolder title,
+ @Nullable org.bukkit.inventory.ItemStack[] items) {
+ int itemAmount = items.length;
+
+ if (itemAmount != 3) {
+ throw new IllegalArgumentException(
+ "The amount of items for an anvil should be 3, but is '" + itemAmount + "'"
+ );
+ }
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ //ignore deprecation: superseding method is only available on Paper
+ //noinspection deprecation
+ CraftEventFactory.handleInventoryCloseEvent(entityPlayer);
+
+ entityPlayer.activeContainer = entityPlayer.defaultContainer;
+
+ IChatBaseComponent message = TextHolderUtil.toComponent(title);
+ ContainerAnvilImpl containerAnvil = new ContainerAnvilImpl(entityPlayer, message);
+
+ Inventory inventory = containerAnvil.getBukkitView().getTopInventory();
+
+ inventory.setItem(0, items[0]);
+ inventory.setItem(1, items[1]);
+ inventory.setItem(2, items[2]);
+
+ int containerId = containerAnvil.getContainerId();
+
+ entityPlayer.playerConnection.sendPacket(new PacketPlayOutOpenWindow(containerId, Containers.ANVIL, message));
+ entityPlayer.activeContainer = containerAnvil;
+ entityPlayer.syncInventory();
+
+ return inventory;
+ }
+
+ @Override
+ public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
+ NonNullList nmsItems = NonNullList.a(
+ ItemStack.a,
+ CraftItemStack.asNMSCopy(items[0]),
+ CraftItemStack.asNMSCopy(items[1]),
+ CraftItemStack.asNMSCopy(items[2])
+ );
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
+ }
+
+ @Override
+ public void sendFirstItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+ ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutSetSlot(getWindowId(entityPlayer), 0, nmsItem));
+ }
+
+ @Override
+ public void sendSecondItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+ ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutSetSlot(getWindowId(entityPlayer), 1, nmsItem));
+ }
+
+ @Override
+ public void sendResultItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
+ sendResultItem(player, CraftItemStack.asNMSCopy(item));
+ }
+
+ @Override
+ public void clearResultItem(@NotNull Player player) {
+ sendResultItem(player, ItemStack.a);
+ }
+
+ @Override
+ public void setCursor(@NotNull Player player, @NotNull org.bukkit.inventory.ItemStack item) {
+ setCursor(player, CraftItemStack.asNMSCopy(item));
+ }
+
+ @Override
+ public void clearCursor(@NotNull Player player) {
+ getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.a));
+ }
+
+ /**
+ * Sets the cursor of the given player
+ *
+ * @param player the player to set the cursor
+ * @param item the item to set the cursor to
+ * @since 0.8.0
+ * @deprecated no longer used internally
+ */
+ @Deprecated
+ private void setCursor(@NotNull Player player, @NotNull ItemStack item) {
+ getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, item));
+ }
+
+ /**
+ * Sends the result item to the specified player with the given item
+ *
+ * @param player the player to send the result item to
+ * @param item the result item
+ * @since 0.8.0
+ * @deprecated no longer used internally
+ */
+ @Deprecated
+ private void sendResultItem(@NotNull Player player, @NotNull ItemStack item) {
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutSetSlot(getWindowId(entityPlayer), 2, item));
+ }
+
+ /**
+ * Gets the window id for the inventory view the player currently has open
+ *
+ * @param entityPlayer the player to get the window id for
+ * @return the window id
+ * @since 0.8.0
+ * @deprecated no longer used internally
+ */
+ @Contract(pure = true)
+ @Deprecated
+ private int getWindowId(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.activeContainer.windowId;
+ }
+
+ /**
+ * Gets the player connection for the specified player
+ *
+ * @param entityPlayer the player to get the player connection from
+ * @return the player connection
+ * @since 0.8.0
+ * @deprecated no longer used internally
+ */
+ @NotNull
+ @Contract(pure = true)
+ @Deprecated
+ private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.playerConnection;
+ }
+
+ /**
+ * Gets the entity player associated to this player
+ *
+ * @param player the player to get the entity player from
+ * @return the entity player
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private EntityPlayer getEntityPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * A custom container anvil for responding to item renaming
+ *
+ * @since 0.8.0
+ */
+ private class ContainerAnvilImpl extends ContainerAnvil {
+
+ /**
+ * The index of the result slot
+ */
+ private static final int RESULT_SLOT_INDEX = 2;
+
+ /**
+ * A unique item
+ */
+ @NotNull
+ private final ItemStack uniqueItem;
+
+ /**
+ * The field containing the listeners for this container
+ */
+ @NotNull
+ private final Field listenersField;
+
+ /**
+ * Creates a new custom anvil container for the specified player
+ *
+ * @param entityPlayer the player for whom this anvil container is
+ * @param title the title of the inventory
+ * @since 0.10.8
+ */
+ public ContainerAnvilImpl(@NotNull EntityPlayer entityPlayer, @NotNull IChatBaseComponent title) {
+ super(entityPlayer.nextContainerCounter(), entityPlayer.inventory,
+ ContainerAccess.at(entityPlayer.getWorld(), new BlockPosition(0, 0, 0)));
+
+ this.checkReachable = false;
+
+ try {
+ //stores all the registered container properties
+ Field dField = Container.class.getDeclaredField("d");
+ dField.setAccessible(true);
+
+ //get rid of the level cost property
+ ((List>) dField.get(this)).clear();
+ } catch (NoSuchFieldException | IllegalAccessException exception) {
+ throw new RuntimeException("Unable to access field 'd'", exception);
+ }
+
+ try {
+ this.listenersField = Container.class.getDeclaredField("listeners");
+ this.listenersField.setAccessible(true);
+ } catch (NoSuchFieldException exception) {
+ throw new RuntimeException("Unable to access field 'listeners'", exception);
+ }
+
+ //register a new property for the level cost
+ ContainerProperty levelCost = a(new ContainerProperty() {
+ private int value;
+
+ @Override
+ public int get() {
+ return value;
+ }
+
+ @Override
+ public void set(int value) {
+ this.value = value;
+ }
+
+ /*
+ This checks whether there have been any changes, but we want to override the client prediction. This
+ means the server should be sending the data to the client, even if it didn't change server-side. To
+ force this, we tell the server the data has always changed.
+ */
+ @Override
+ public boolean c() {
+ return true;
+ }
+ });
+
+ levelCost.set(AnvilInventoryImpl.super.cost);
+
+ setTitle(title);
+
+ Slot originalSlot = this.slots.get(RESULT_SLOT_INDEX);
+
+ Slot newSlot = new Slot(originalSlot.inventory, originalSlot.index, originalSlot.e, originalSlot.f) {
+ @Override
+ public boolean isAllowed(ItemStack itemStack) {
+ return true;
+ }
+
+ @Override
+ public boolean isAllowed(EntityHuman entityHuman) {
+ return true;
+ }
+
+ @Override
+ public ItemStack a(EntityHuman entityHuman, @NotNull ItemStack itemStack) {
+ return itemStack;
+ }
+ };
+
+ this.slots.set(RESULT_SLOT_INDEX, newSlot);
+
+ this.uniqueItem = new ItemStack(Items.COOKIE);
+
+ //to make the item unique, we add a random uuid as nbt to it
+ UUID uuid = UUID.randomUUID();
+ NBTTagCompound nbtTagCompound = new NBTTagCompound();
+
+ nbtTagCompound.set("uuid", new NBTTagLongArray(new long [] {
+ uuid.getLeastSignificantBits(),
+ uuid.getMostSignificantBits()
+ }));
+
+ this.uniqueItem.setTag(nbtTagCompound);
+ }
+
+ @Override
+ public void a(@Nullable String name) {
+ name = name == null ? "" : name;
+
+ /* Only update if the name is actually different. This may be called even if the name is not different,
+ particularly when putting an item in the first slot. */
+ if (!name.equals(AnvilInventoryImpl.super.observableText.get())) {
+ AnvilInventoryImpl.super.observableText.set(name);
+ }
+
+ //the client predicts the output result, so we broadcast the state again to override it
+ forceUpdate();
+ }
+
+ @Override
+ public void e() {}
+
+ @Override
+ public void b(EntityHuman entityHuman) {}
+
+ @Override
+ protected void a(EntityHuman entityHuman, World world, @NotNull IInventory inventory) {}
+
+ @Override
+ public ItemStack a(int i, int j, InventoryClickType inventoryclicktype, EntityHuman entityhuman) {
+ ItemStack itemStack = super.a(i, j, inventoryclicktype, entityhuman);
+
+ //the client predicts the allowed movement of the item, so we broadcast the state again to override it
+ forceUpdate();
+
+ return itemStack;
+ }
+
+ public int getContainerId() {
+ return this.windowId;
+ }
+
+ /**
+ * Forcefully updates the client state, sending all items, container properties and the held item.
+ *
+ * @since 0.10.8
+ */
+ public void forceUpdate() {
+ /*
+ The server will not send the items when they haven't changed, so we will overwrite every item with a unique
+ item first to ensure the server is going to send our items.
+ */
+ Collections.fill(this.items, this.uniqueItem);
+
+ c();
+
+ List extends ICrafting> listeners;
+
+ try {
+ //noinspection unchecked
+ listeners = (List extends ICrafting>) listenersField.get(this);
+ } catch (IllegalAccessException exception) {
+ throw new RuntimeException("Unable to access field 'listeners'", exception);
+ }
+
+ for (ICrafting listener : listeners) {
+ if (!(listener instanceof EntityPlayer)) {
+ continue;
+ }
+
+ EntityPlayer player = (EntityPlayer) listener;
+
+ player.e = false;
+ player.broadcastCarriedItem();
+ }
+ }
+ }
+}
diff --git a/nms/1_15_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_15_R1/BeaconInventoryImpl.java b/nms/1_15/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_15/BeaconInventoryImpl.java
similarity index 95%
rename from nms/1_15_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_15_R1/BeaconInventoryImpl.java
rename to nms/1_15/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_15/BeaconInventoryImpl.java
index 38d7d21df..f6cc4814a 100644
--- a/nms/1_15_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_15_R1/BeaconInventoryImpl.java
+++ b/nms/1_15/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_15/BeaconInventoryImpl.java
@@ -1,181 +1,181 @@
-package com.github.stefvanschie.inventoryframework.nms.v1_15_R1;
-
-import com.github.stefvanschie.inventoryframework.abstraction.BeaconInventory;
-import net.minecraft.server.v1_15_R1.*;
-import org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer;
-import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftInventory;
-import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftInventoryBeacon;
-import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftInventoryView;
-import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftItemStack;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.InventoryHolder;
-import org.jetbrains.annotations.Contract;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.lang.reflect.Field;
-
-/**
- * Internal beacon inventory for 1.15 R1
- *
- * @since 0.8.0
- */
-public class BeaconInventoryImpl extends BeaconInventory {
-
- public BeaconInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
- super(inventoryHolder);
- }
-
- @Override
- public void openInventory(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
- EntityPlayer entityPlayer = getEntityPlayer(player);
- ContainerBeaconImpl containerBeacon = new ContainerBeaconImpl(entityPlayer, item);
-
- entityPlayer.activeContainer = containerBeacon;
-
- int id = containerBeacon.windowId;
- ChatMessage message = new ChatMessage("Beacon");
-
- entityPlayer.playerConnection.sendPacket(new PacketPlayOutOpenWindow(id, Containers.BEACON, message));
-
- sendItem(player, item);
- }
-
- @Override
- public void sendItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
- NonNullList items = NonNullList.a(
- ItemStack.a, //the first item doesn't count for some reason, so send a dummy item
- CraftItemStack.asNMSCopy(item)
- );
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), items));
- }
-
- @Override
- public void clearCursor(@NotNull Player player) {
- getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.a));
- }
-
- /**
- * Gets the window id for the inventory view the player currently has open
- *
- * @param entityPlayer the player to get the window id for
- * @return the window id
- * @since 0.8.0
- */
- @Contract(pure = true)
- private int getWindowId(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.activeContainer.windowId;
- }
-
- /**
- * Gets the player connection for the specified player
- *
- * @param entityPlayer the player to get the player connection from
- * @return the player connection
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.playerConnection;
- }
-
- /**
- * Gets the entity player associated to this player
- *
- * @param player the player to get the entity player from
- * @return the entity player
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private EntityPlayer getEntityPlayer(@NotNull Player player) {
- return ((CraftPlayer) player).getHandle();
- }
-
- /**
- * A custom container beacon
- *
- * @since 0.8.0
- */
- private class ContainerBeaconImpl extends ContainerBeacon {
-
- /**
- * The player for this beacon container
- */
- @NotNull
- private final Player player;
-
- /**
- * The internal bukkit entity for this container beacon
- */
- @Nullable
- private CraftInventoryView bukkitEntity;
-
- /**
- * Field for accessing the beacon field
- */
- @NotNull
- private final Field beaconField;
-
- public ContainerBeaconImpl(@NotNull EntityPlayer entityPlayer, @Nullable org.bukkit.inventory.ItemStack item) {
- super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
-
- this.player = entityPlayer.getBukkitEntity();
-
- try {
- this.beaconField = ContainerBeacon.class.getDeclaredField("beacon");
- this.beaconField.setAccessible(true);
- } catch (NoSuchFieldException exception) {
- throw new RuntimeException(exception);
- }
-
- try {
- ItemStack itemStack = CraftItemStack.asNMSCopy(item);
-
- ((IInventory) beaconField.get(this)).setItem(0, itemStack);
- } catch (IllegalAccessException exception) {
- throw new RuntimeException(exception);
- }
- }
-
- @NotNull
- @Override
- public CraftInventoryView getBukkitView() {
- if (bukkitEntity == null) {
- try {
- CraftInventory inventory = new CraftInventoryBeacon((IInventory) beaconField.get(this)) {
- @NotNull
- @Contract(pure = true)
- @Override
- public InventoryHolder getHolder() {
- return inventoryHolder;
- }
- };
-
- bukkitEntity = new CraftInventoryView(player, inventory, this);
- } catch (IllegalAccessException exception) {
- throw new RuntimeException(exception);
- }
- }
-
- return bukkitEntity;
- }
-
- @Contract(pure = true, value = "_ -> true")
- @Override
- public boolean canUse(@Nullable EntityHuman entityhuman) {
- return true;
- }
-
- @Override
- public void a(IInventory inventory) {}
-
- @Override
- public void b(EntityHuman entityhuman) {}
-
- }
-}
+package com.github.stefvanschie.inventoryframework.nms.v1_15;
+
+import com.github.stefvanschie.inventoryframework.abstraction.BeaconInventory;
+import net.minecraft.server.v1_15_R1.*;
+import org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftInventory;
+import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftInventoryBeacon;
+import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftInventoryView;
+import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftItemStack;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.InventoryHolder;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.lang.reflect.Field;
+
+/**
+ * Internal beacon inventory for 1.15 R1
+ *
+ * @since 0.8.0
+ */
+public class BeaconInventoryImpl extends BeaconInventory {
+
+ public BeaconInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
+ super(inventoryHolder);
+ }
+
+ @Override
+ public void openInventory(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+ ContainerBeaconImpl containerBeacon = new ContainerBeaconImpl(entityPlayer, item);
+
+ entityPlayer.activeContainer = containerBeacon;
+
+ int id = containerBeacon.windowId;
+ ChatMessage message = new ChatMessage("Beacon");
+
+ entityPlayer.playerConnection.sendPacket(new PacketPlayOutOpenWindow(id, Containers.BEACON, message));
+
+ sendItem(player, item);
+ }
+
+ @Override
+ public void sendItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
+ NonNullList items = NonNullList.a(
+ ItemStack.a, //the first item doesn't count for some reason, so send a dummy item
+ CraftItemStack.asNMSCopy(item)
+ );
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), items));
+ }
+
+ @Override
+ public void clearCursor(@NotNull Player player) {
+ getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.a));
+ }
+
+ /**
+ * Gets the window id for the inventory view the player currently has open
+ *
+ * @param entityPlayer the player to get the window id for
+ * @return the window id
+ * @since 0.8.0
+ */
+ @Contract(pure = true)
+ private int getWindowId(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.activeContainer.windowId;
+ }
+
+ /**
+ * Gets the player connection for the specified player
+ *
+ * @param entityPlayer the player to get the player connection from
+ * @return the player connection
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.playerConnection;
+ }
+
+ /**
+ * Gets the entity player associated to this player
+ *
+ * @param player the player to get the entity player from
+ * @return the entity player
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private EntityPlayer getEntityPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * A custom container beacon
+ *
+ * @since 0.8.0
+ */
+ private class ContainerBeaconImpl extends ContainerBeacon {
+
+ /**
+ * The player for this beacon container
+ */
+ @NotNull
+ private final Player player;
+
+ /**
+ * The internal bukkit entity for this container beacon
+ */
+ @Nullable
+ private CraftInventoryView bukkitEntity;
+
+ /**
+ * Field for accessing the beacon field
+ */
+ @NotNull
+ private final Field beaconField;
+
+ public ContainerBeaconImpl(@NotNull EntityPlayer entityPlayer, @Nullable org.bukkit.inventory.ItemStack item) {
+ super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
+
+ this.player = entityPlayer.getBukkitEntity();
+
+ try {
+ this.beaconField = ContainerBeacon.class.getDeclaredField("beacon");
+ this.beaconField.setAccessible(true);
+ } catch (NoSuchFieldException exception) {
+ throw new RuntimeException(exception);
+ }
+
+ try {
+ ItemStack itemStack = CraftItemStack.asNMSCopy(item);
+
+ ((IInventory) beaconField.get(this)).setItem(0, itemStack);
+ } catch (IllegalAccessException exception) {
+ throw new RuntimeException(exception);
+ }
+ }
+
+ @NotNull
+ @Override
+ public CraftInventoryView getBukkitView() {
+ if (bukkitEntity == null) {
+ try {
+ CraftInventory inventory = new CraftInventoryBeacon((IInventory) beaconField.get(this)) {
+ @NotNull
+ @Contract(pure = true)
+ @Override
+ public InventoryHolder getHolder() {
+ return inventoryHolder;
+ }
+ };
+
+ bukkitEntity = new CraftInventoryView(player, inventory, this);
+ } catch (IllegalAccessException exception) {
+ throw new RuntimeException(exception);
+ }
+ }
+
+ return bukkitEntity;
+ }
+
+ @Contract(pure = true, value = "_ -> true")
+ @Override
+ public boolean canUse(@Nullable EntityHuman entityhuman) {
+ return true;
+ }
+
+ @Override
+ public void a(IInventory inventory) {}
+
+ @Override
+ public void b(EntityHuman entityhuman) {}
+
+ }
+}
diff --git a/nms/1_15_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_15_R1/CartographyTableInventoryImpl.java b/nms/1_15/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_15/CartographyTableInventoryImpl.java
similarity index 94%
rename from nms/1_15_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_15_R1/CartographyTableInventoryImpl.java
rename to nms/1_15/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_15/CartographyTableInventoryImpl.java
index 9748a472a..bc6ada39f 100644
--- a/nms/1_15_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_15_R1/CartographyTableInventoryImpl.java
+++ b/nms/1_15/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_15/CartographyTableInventoryImpl.java
@@ -1,199 +1,201 @@
-package com.github.stefvanschie.inventoryframework.nms.v1_15_R1;
-
-import com.github.stefvanschie.inventoryframework.abstraction.CartographyTableInventory;
-import net.minecraft.server.v1_15_R1.*;
-import org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer;
-import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftInventory;
-import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftInventoryCartography;
-import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftInventoryView;
-import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftItemStack;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.InventoryHolder;
-import org.jetbrains.annotations.Contract;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.lang.reflect.Field;
-
-/**
- * Internal cartography table inventory for 1.15 R1
- *
- * @since 0.8.0
- */
-public class CartographyTableInventoryImpl extends CartographyTableInventory {
-
- public CartographyTableInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
- super(inventoryHolder);
- }
-
- @Override
- public void openInventory(@NotNull Player player, @NotNull String title,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- int itemAmount = items.length;
-
- if (itemAmount != 3) {
- throw new IllegalArgumentException(
- "The amount of items for a cartography table should be 3, but is '" + itemAmount + "'"
- );
- }
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
- ContainerCartographyTableImpl containerCartographyTable = new ContainerCartographyTableImpl(
- entityPlayer, items
- );
-
- entityPlayer.activeContainer = containerCartographyTable;
-
- int id = containerCartographyTable.windowId;
- ChatMessage message = new ChatMessage(title);
- PacketPlayOutOpenWindow packet = new PacketPlayOutOpenWindow(id, Containers.CARTOGRAPHY_TABLE, message);
-
- entityPlayer.playerConnection.sendPacket(packet);
-
- sendItems(player, items);
- }
-
- @Override
- public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
- NonNullList nmsItems = NonNullList.a(
- ItemStack.a,
- CraftItemStack.asNMSCopy(items[0]),
- CraftItemStack.asNMSCopy(items[1]),
- CraftItemStack.asNMSCopy(items[2])
- );
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
- }
-
- @Override
- public void clearCursor(@NotNull Player player) {
- getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.a));
- }
-
- /**
- * Gets the window id for the inventory view the player currently has open
- *
- * @param entityPlayer the player to get the window id for
- * @return the window id
- * @since 0.8.0
- */
- @Contract(pure = true)
- private int getWindowId(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.activeContainer.windowId;
- }
-
- /**
- * Gets the player connection for the specified player
- *
- * @param entityPlayer the player to get the player connection from
- * @return the player connection
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.playerConnection;
- }
-
- /**
- * Gets the entity player associated to this player
- *
- * @param player the player to get the entity player from
- * @return the entity player
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private EntityPlayer getEntityPlayer(@NotNull Player player) {
- return ((CraftPlayer) player).getHandle();
- }
-
- /**
- * A custom container cartography table
- *
- * @since 0.8.0
- */
- private class ContainerCartographyTableImpl extends ContainerCartography {
-
- /**
- * The player for this cartography table container
- */
- @NotNull
- private final Player player;
-
- /**
- * The internal bukkit entity for this container cartography table
- */
- @Nullable
- private CraftInventoryView bukkitEntity;
-
- /**
- * Field for accessing the result inventory field
- */
- @NotNull
- private final Field resultInventoryField;
-
- public ContainerCartographyTableImpl(@NotNull EntityPlayer entityPlayer,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
-
- this.player = entityPlayer.getBukkitEntity();
-
- try {
- this.resultInventoryField = ContainerCartography.class.getDeclaredField("resultInventory");
- this.resultInventoryField.setAccessible(true);
- } catch (NoSuchFieldException exception) {
- throw new RuntimeException(exception);
- }
-
- inventory.setItem(0, CraftItemStack.asNMSCopy(items[0]));
- inventory.setItem(1, CraftItemStack.asNMSCopy(items[1]));
-
- getResultInventory().setItem(0, CraftItemStack.asNMSCopy(items[2]));
- }
-
- @NotNull
- @Override
- public CraftInventoryView getBukkitView() {
- if (bukkitEntity == null) {
- CraftInventory inventory = new CraftInventoryCartography(super.inventory, getResultInventory()) {
- @NotNull
- @Contract(pure = true)
- @Override
- public InventoryHolder getHolder() {
- return inventoryHolder;
- }
- };
-
- bukkitEntity = new CraftInventoryView(player, inventory, this);
- }
-
- return bukkitEntity;
- }
-
- @Contract(pure = true, value = "_ -> true")
- @Override
- public boolean canUse(@Nullable EntityHuman entityhuman) {
- return true;
- }
-
- @Override
- public void a(IInventory inventory) {}
-
- @Override
- public void b(EntityHuman entityhuman) {}
-
- @NotNull
- @Contract(pure = true)
- private IInventory getResultInventory() {
- try {
- return (IInventory) resultInventoryField.get(this);
- } catch (IllegalAccessException exception) {
- throw new RuntimeException(exception);
- }
- }
-
- }
-}
+package com.github.stefvanschie.inventoryframework.nms.v1_15;
+
+import com.github.stefvanschie.inventoryframework.abstraction.CartographyTableInventory;
+import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
+import com.github.stefvanschie.inventoryframework.nms.v1_15.util.TextHolderUtil;
+import net.minecraft.server.v1_15_R1.*;
+import org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftInventory;
+import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftInventoryCartography;
+import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftInventoryView;
+import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftItemStack;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.InventoryHolder;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.lang.reflect.Field;
+
+/**
+ * Internal cartography table inventory for 1.15 R1
+ *
+ * @since 0.8.0
+ */
+public class CartographyTableInventoryImpl extends CartographyTableInventory {
+
+ public CartographyTableInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
+ super(inventoryHolder);
+ }
+
+ @Override
+ public void openInventory(@NotNull Player player, @NotNull TextHolder title,
+ @Nullable org.bukkit.inventory.ItemStack[] items) {
+ int itemAmount = items.length;
+
+ if (itemAmount != 3) {
+ throw new IllegalArgumentException(
+ "The amount of items for a cartography table should be 3, but is '" + itemAmount + "'"
+ );
+ }
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+ ContainerCartographyTableImpl containerCartographyTable = new ContainerCartographyTableImpl(
+ entityPlayer, items
+ );
+
+ entityPlayer.activeContainer = containerCartographyTable;
+
+ int id = containerCartographyTable.windowId;
+ IChatBaseComponent message = TextHolderUtil.toComponent(title);
+ PacketPlayOutOpenWindow packet = new PacketPlayOutOpenWindow(id, Containers.CARTOGRAPHY_TABLE, message);
+
+ entityPlayer.playerConnection.sendPacket(packet);
+
+ sendItems(player, items);
+ }
+
+ @Override
+ public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
+ NonNullList nmsItems = NonNullList.a(
+ ItemStack.a,
+ CraftItemStack.asNMSCopy(items[0]),
+ CraftItemStack.asNMSCopy(items[1]),
+ CraftItemStack.asNMSCopy(items[2])
+ );
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
+ }
+
+ @Override
+ public void clearCursor(@NotNull Player player) {
+ getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.a));
+ }
+
+ /**
+ * Gets the window id for the inventory view the player currently has open
+ *
+ * @param entityPlayer the player to get the window id for
+ * @return the window id
+ * @since 0.8.0
+ */
+ @Contract(pure = true)
+ private int getWindowId(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.activeContainer.windowId;
+ }
+
+ /**
+ * Gets the player connection for the specified player
+ *
+ * @param entityPlayer the player to get the player connection from
+ * @return the player connection
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.playerConnection;
+ }
+
+ /**
+ * Gets the entity player associated to this player
+ *
+ * @param player the player to get the entity player from
+ * @return the entity player
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private EntityPlayer getEntityPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * A custom container cartography table
+ *
+ * @since 0.8.0
+ */
+ private class ContainerCartographyTableImpl extends ContainerCartography {
+
+ /**
+ * The player for this cartography table container
+ */
+ @NotNull
+ private final Player player;
+
+ /**
+ * The internal bukkit entity for this container cartography table
+ */
+ @Nullable
+ private CraftInventoryView bukkitEntity;
+
+ /**
+ * Field for accessing the result inventory field
+ */
+ @NotNull
+ private final Field resultInventoryField;
+
+ public ContainerCartographyTableImpl(@NotNull EntityPlayer entityPlayer,
+ @Nullable org.bukkit.inventory.ItemStack[] items) {
+ super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
+
+ this.player = entityPlayer.getBukkitEntity();
+
+ try {
+ this.resultInventoryField = ContainerCartography.class.getDeclaredField("resultInventory");
+ this.resultInventoryField.setAccessible(true);
+ } catch (NoSuchFieldException exception) {
+ throw new RuntimeException(exception);
+ }
+
+ inventory.setItem(0, CraftItemStack.asNMSCopy(items[0]));
+ inventory.setItem(1, CraftItemStack.asNMSCopy(items[1]));
+
+ getResultInventory().setItem(0, CraftItemStack.asNMSCopy(items[2]));
+ }
+
+ @NotNull
+ @Override
+ public CraftInventoryView getBukkitView() {
+ if (bukkitEntity == null) {
+ CraftInventory inventory = new CraftInventoryCartography(super.inventory, getResultInventory()) {
+ @NotNull
+ @Contract(pure = true)
+ @Override
+ public InventoryHolder getHolder() {
+ return inventoryHolder;
+ }
+ };
+
+ bukkitEntity = new CraftInventoryView(player, inventory, this);
+ }
+
+ return bukkitEntity;
+ }
+
+ @Contract(pure = true, value = "_ -> true")
+ @Override
+ public boolean canUse(@Nullable EntityHuman entityhuman) {
+ return true;
+ }
+
+ @Override
+ public void a(IInventory inventory) {}
+
+ @Override
+ public void b(EntityHuman entityhuman) {}
+
+ @NotNull
+ @Contract(pure = true)
+ private IInventory getResultInventory() {
+ try {
+ return (IInventory) resultInventoryField.get(this);
+ } catch (IllegalAccessException exception) {
+ throw new RuntimeException(exception);
+ }
+ }
+
+ }
+}
diff --git a/nms/1_15_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_15_R1/EnchantingTableInventoryImpl.java b/nms/1_15/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_15/EnchantingTableInventoryImpl.java
similarity index 94%
rename from nms/1_15_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_15_R1/EnchantingTableInventoryImpl.java
rename to nms/1_15/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_15/EnchantingTableInventoryImpl.java
index 42018e6c9..280f3e242 100644
--- a/nms/1_15_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_15_R1/EnchantingTableInventoryImpl.java
+++ b/nms/1_15/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_15/EnchantingTableInventoryImpl.java
@@ -1,194 +1,196 @@
-package com.github.stefvanschie.inventoryframework.nms.v1_15_R1;
-
-import com.github.stefvanschie.inventoryframework.abstraction.EnchantingTableInventory;
-import net.minecraft.server.v1_15_R1.*;
-import org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer;
-import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftInventory;
-import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftInventoryEnchanting;
-import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftInventoryView;
-import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftItemStack;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.InventoryHolder;
-import org.jetbrains.annotations.Contract;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.lang.reflect.Field;
-
-/**
- * Internal enchanting table inventory for 1.15 R1
- *
- * @since 0.8.0
- */
-public class EnchantingTableInventoryImpl extends EnchantingTableInventory {
-
- public EnchantingTableInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
- super(inventoryHolder);
- }
-
- @Override
- public void openInventory(@NotNull Player player, @NotNull String title,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- int itemAmount = items.length;
-
- if (itemAmount != 2) {
- throw new IllegalArgumentException(
- "The amount of items for an enchanting table should be 2, but is '" + itemAmount + "'"
- );
- }
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
- ContainerEnchantingTableImpl containerEnchantmentTable = new ContainerEnchantingTableImpl(entityPlayer, items);
-
- entityPlayer.activeContainer = containerEnchantmentTable;
-
- int id = containerEnchantmentTable.windowId;
- ChatMessage message = new ChatMessage(title);
- PacketPlayOutOpenWindow packet = new PacketPlayOutOpenWindow(id, Containers.ENCHANTMENT, message);
-
- entityPlayer.playerConnection.sendPacket(packet);
-
- sendItems(player, items);
- }
-
- @Override
- public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
- NonNullList nmsItems = NonNullList.a(
- ItemStack.a,
- CraftItemStack.asNMSCopy(items[0]),
- CraftItemStack.asNMSCopy(items[1])
- );
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
- }
-
- @Override
- public void clearCursor(@NotNull Player player) {
- getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.a));
- }
-
- /**
- * Gets the window id for the inventory view the player currently has open
- *
- * @param entityPlayer the player to get the window id for
- * @return the window id
- * @since 0.8.0
- */
- @Contract(pure = true)
- private int getWindowId(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.activeContainer.windowId;
- }
-
- /**
- * Gets the player connection for the specified player
- *
- * @param entityPlayer the player to get the player connection from
- * @return the player connection
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.playerConnection;
- }
-
- /**
- * Gets the entity player associated to this player
- *
- * @param player the player to get the entity player from
- * @return the entity player
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private EntityPlayer getEntityPlayer(@NotNull Player player) {
- return ((CraftPlayer) player).getHandle();
- }
-
- /**
- * A custom container enchanting table
- *
- * @since 0.8.0
- */
- private class ContainerEnchantingTableImpl extends ContainerEnchantTable {
-
- /**
- * The player for this enchanting table container
- */
- @NotNull
- private final Player player;
-
- /**
- * The internal bukkit entity for this container enchanting table
- */
- @Nullable
- private CraftInventoryView bukkitEntity;
-
- /**
- * Field for accessing the enchant slots field
- */
- @NotNull
- private final Field enchantSlotsField;
-
- public ContainerEnchantingTableImpl(@NotNull EntityPlayer entityPlayer,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
-
- this.player = entityPlayer.getBukkitEntity();
-
- try {
- this.enchantSlotsField = ContainerEnchantTable.class.getDeclaredField("enchantSlots");
- this.enchantSlotsField.setAccessible(true);
- } catch (NoSuchFieldException exception) {
- throw new RuntimeException(exception);
- }
-
- try {
- IInventory input = (IInventory) enchantSlotsField.get(this);
-
- input.setItem(0, CraftItemStack.asNMSCopy(items[0]));
- input.setItem(1, CraftItemStack.asNMSCopy(items[1]));
- } catch (IllegalAccessException e) {
- e.printStackTrace();
- }
- }
-
- @NotNull
- @Override
- public CraftInventoryView getBukkitView() {
- if (bukkitEntity == null) {
- try {
- CraftInventory inventory = new CraftInventoryEnchanting((IInventory) enchantSlotsField.get(this)) {
- @NotNull
- @Contract(pure = true)
- @Override
- public InventoryHolder getHolder() {
- return inventoryHolder;
- }
- };
-
- bukkitEntity = new CraftInventoryView(player, inventory, this);
- } catch (IllegalAccessException exception) {
- exception.printStackTrace();
- }
- }
-
- return bukkitEntity;
- }
-
- @Contract(pure = true, value = "_ -> true")
- @Override
- public boolean canUse(@Nullable EntityHuman entityhuman) {
- return true;
- }
-
- @Override
- public void a(IInventory inventory) {}
-
- @Override
- public void b(EntityHuman entityhuman) {}
-
- }
-}
+package com.github.stefvanschie.inventoryframework.nms.v1_15;
+
+import com.github.stefvanschie.inventoryframework.abstraction.EnchantingTableInventory;
+import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
+import com.github.stefvanschie.inventoryframework.nms.v1_15.util.TextHolderUtil;
+import net.minecraft.server.v1_15_R1.*;
+import org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftInventory;
+import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftInventoryEnchanting;
+import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftInventoryView;
+import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftItemStack;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.InventoryHolder;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.lang.reflect.Field;
+
+/**
+ * Internal enchanting table inventory for 1.15 R1
+ *
+ * @since 0.8.0
+ */
+public class EnchantingTableInventoryImpl extends EnchantingTableInventory {
+
+ public EnchantingTableInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
+ super(inventoryHolder);
+ }
+
+ @Override
+ public void openInventory(@NotNull Player player, @NotNull TextHolder title,
+ @Nullable org.bukkit.inventory.ItemStack[] items) {
+ int itemAmount = items.length;
+
+ if (itemAmount != 2) {
+ throw new IllegalArgumentException(
+ "The amount of items for an enchanting table should be 2, but is '" + itemAmount + "'"
+ );
+ }
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+ ContainerEnchantingTableImpl containerEnchantmentTable = new ContainerEnchantingTableImpl(entityPlayer, items);
+
+ entityPlayer.activeContainer = containerEnchantmentTable;
+
+ int id = containerEnchantmentTable.windowId;
+ IChatBaseComponent message = TextHolderUtil.toComponent(title);
+ PacketPlayOutOpenWindow packet = new PacketPlayOutOpenWindow(id, Containers.ENCHANTMENT, message);
+
+ entityPlayer.playerConnection.sendPacket(packet);
+
+ sendItems(player, items);
+ }
+
+ @Override
+ public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
+ NonNullList nmsItems = NonNullList.a(
+ ItemStack.a,
+ CraftItemStack.asNMSCopy(items[0]),
+ CraftItemStack.asNMSCopy(items[1])
+ );
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
+ }
+
+ @Override
+ public void clearCursor(@NotNull Player player) {
+ getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.a));
+ }
+
+ /**
+ * Gets the window id for the inventory view the player currently has open
+ *
+ * @param entityPlayer the player to get the window id for
+ * @return the window id
+ * @since 0.8.0
+ */
+ @Contract(pure = true)
+ private int getWindowId(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.activeContainer.windowId;
+ }
+
+ /**
+ * Gets the player connection for the specified player
+ *
+ * @param entityPlayer the player to get the player connection from
+ * @return the player connection
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.playerConnection;
+ }
+
+ /**
+ * Gets the entity player associated to this player
+ *
+ * @param player the player to get the entity player from
+ * @return the entity player
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private EntityPlayer getEntityPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * A custom container enchanting table
+ *
+ * @since 0.8.0
+ */
+ private class ContainerEnchantingTableImpl extends ContainerEnchantTable {
+
+ /**
+ * The player for this enchanting table container
+ */
+ @NotNull
+ private final Player player;
+
+ /**
+ * The internal bukkit entity for this container enchanting table
+ */
+ @Nullable
+ private CraftInventoryView bukkitEntity;
+
+ /**
+ * Field for accessing the enchant slots field
+ */
+ @NotNull
+ private final Field enchantSlotsField;
+
+ public ContainerEnchantingTableImpl(@NotNull EntityPlayer entityPlayer,
+ @Nullable org.bukkit.inventory.ItemStack[] items) {
+ super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
+
+ this.player = entityPlayer.getBukkitEntity();
+
+ try {
+ this.enchantSlotsField = ContainerEnchantTable.class.getDeclaredField("enchantSlots");
+ this.enchantSlotsField.setAccessible(true);
+ } catch (NoSuchFieldException exception) {
+ throw new RuntimeException(exception);
+ }
+
+ try {
+ IInventory input = (IInventory) enchantSlotsField.get(this);
+
+ input.setItem(0, CraftItemStack.asNMSCopy(items[0]));
+ input.setItem(1, CraftItemStack.asNMSCopy(items[1]));
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @NotNull
+ @Override
+ public CraftInventoryView getBukkitView() {
+ if (bukkitEntity == null) {
+ try {
+ CraftInventory inventory = new CraftInventoryEnchanting((IInventory) enchantSlotsField.get(this)) {
+ @NotNull
+ @Contract(pure = true)
+ @Override
+ public InventoryHolder getHolder() {
+ return inventoryHolder;
+ }
+ };
+
+ bukkitEntity = new CraftInventoryView(player, inventory, this);
+ } catch (IllegalAccessException exception) {
+ exception.printStackTrace();
+ }
+ }
+
+ return bukkitEntity;
+ }
+
+ @Contract(pure = true, value = "_ -> true")
+ @Override
+ public boolean canUse(@Nullable EntityHuman entityhuman) {
+ return true;
+ }
+
+ @Override
+ public void a(IInventory inventory) {}
+
+ @Override
+ public void b(EntityHuman entityhuman) {}
+
+ }
+}
diff --git a/nms/1_15/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_15/GrindstoneInventoryImpl.java b/nms/1_15/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_15/GrindstoneInventoryImpl.java
new file mode 100644
index 000000000..e34d4fbdd
--- /dev/null
+++ b/nms/1_15/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_15/GrindstoneInventoryImpl.java
@@ -0,0 +1,272 @@
+package com.github.stefvanschie.inventoryframework.nms.v1_15;
+
+import com.github.stefvanschie.inventoryframework.abstraction.GrindstoneInventory;
+import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
+import com.github.stefvanschie.inventoryframework.nms.v1_15.util.TextHolderUtil;
+import net.minecraft.server.v1_15_R1.*;
+import org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_15_R1.event.CraftEventFactory;
+import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftItemStack;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.InventoryHolder;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.lang.reflect.Field;
+import java.util.Collections;
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * Internal grindstone inventory for 1.15 R1
+ *
+ * @since 0.8.0
+ */
+public class GrindstoneInventoryImpl extends GrindstoneInventory {
+
+ public GrindstoneInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
+ super(inventoryHolder);
+ }
+
+ @Override
+ public Inventory openInventory(@NotNull Player player, @NotNull TextHolder title,
+ @Nullable org.bukkit.inventory.ItemStack[] items) {
+ int itemAmount = items.length;
+
+ if (itemAmount != 3) {
+ throw new IllegalArgumentException(
+ "The amount of items for a grindstone should be 3, but is '" + itemAmount + "'"
+ );
+ }
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ //ignore deprecation: superseding method is only available on Paper
+ //noinspection deprecation
+ CraftEventFactory.handleInventoryCloseEvent(entityPlayer);
+
+ entityPlayer.activeContainer = entityPlayer.defaultContainer;
+
+ IChatBaseComponent message = TextHolderUtil.toComponent(title);
+ ContainerGrindstoneImpl containerGrindstone = new ContainerGrindstoneImpl(entityPlayer);
+
+ Inventory inventory = containerGrindstone.getBukkitView().getTopInventory();
+
+ inventory.setItem(0, items[0]);
+ inventory.setItem(1, items[1]);
+ inventory.setItem(2, items[2]);
+
+ int windowId = containerGrindstone.getWindowId();
+
+ entityPlayer.playerConnection.sendPacket(new PacketPlayOutOpenWindow(windowId, Containers.GRINDSTONE, message));
+ entityPlayer.activeContainer = containerGrindstone;
+ entityPlayer.syncInventory();
+
+ return inventory;
+ }
+
+ @Override
+ public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items,
+ @Nullable org.bukkit.inventory.ItemStack cursor) {
+ NonNullList nmsItems = NonNullList.a(
+ ItemStack.a,
+ CraftItemStack.asNMSCopy(items[0]),
+ CraftItemStack.asNMSCopy(items[1]),
+ CraftItemStack.asNMSCopy(items[2])
+ );
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
+ }
+
+ @Override
+ public void clearCursor(@NotNull Player player) {
+ getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.a));
+ }
+
+ /**
+ * Gets the window id for the inventory view the player currently has open
+ *
+ * @param entityPlayer the player to get the window id for
+ * @return the window id
+ * @since 0.8.0
+ * @deprecated no longer used internally
+ */
+ @Contract(pure = true)
+ @Deprecated
+ private int getWindowId(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.activeContainer.windowId;
+ }
+
+ /**
+ * Gets the player connection for the specified player
+ *
+ * @param entityPlayer the player to get the player connection from
+ * @return the player connection
+ * @since 0.8.0
+ * @deprecated no longer used internally
+ */
+ @NotNull
+ @Contract(pure = true)
+ @Deprecated
+ private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.playerConnection;
+ }
+
+ /**
+ * Gets the entity player associated to this player
+ *
+ * @param player the player to get the entity player from
+ * @return the entity player
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private EntityPlayer getEntityPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * A custom container grindstone
+ *
+ * @since 0.8.0
+ */
+ private static class ContainerGrindstoneImpl extends ContainerGrindstone {
+
+ /**
+ * A unique item
+ */
+ @NotNull
+ private final ItemStack uniqueItem;
+
+ /**
+ * The field containing the listeners for this container
+ */
+ @NotNull
+ private final Field listenersField;
+
+ /**
+ * Creates a new grindstone container
+ *
+ * @param entityPlayer the player for whom this container should be opened
+ * @since 0.10.8
+ */
+ public ContainerGrindstoneImpl(@NotNull EntityPlayer entityPlayer) {
+ super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
+
+ try {
+ this.listenersField = Container.class.getDeclaredField("listeners");
+ this.listenersField.setAccessible(true);
+ } catch (NoSuchFieldException exception) {
+ throw new RuntimeException("Unable to access field 'listeners'", exception);
+ }
+
+ Slot firstSlot = this.slots.get(0);
+ Slot secondSlot = this.slots.get(1);
+ Slot thirdSlot = this.slots.get(2);
+
+ this.slots.set(0, new Slot(firstSlot.inventory, firstSlot.rawSlotIndex, firstSlot.e, firstSlot.f) {
+ @Override
+ public boolean isAllowed(ItemStack stack) {
+ return true;
+ }
+ });
+
+ this.slots.set(1, new Slot(secondSlot.inventory, secondSlot.rawSlotIndex, secondSlot.e, secondSlot.f) {
+ @Override
+ public boolean isAllowed(ItemStack stack) {
+ return true;
+ }
+ });
+
+ this.slots.set(2, new Slot(thirdSlot.inventory, thirdSlot.rawSlotIndex, thirdSlot.e, thirdSlot.f) {
+ @Override
+ public boolean isAllowed(ItemStack stack) {
+ return true;
+ }
+
+ @Override
+ public ItemStack a(EntityHuman entityHuman, ItemStack itemStack) {
+ return itemStack;
+ }
+ });
+
+ this.uniqueItem = new ItemStack(Items.COOKIE);
+
+ //to make the item unique, we add a random uuid as nbt to it
+ UUID uuid = UUID.randomUUID();
+ NBTTagCompound nbtTagCompound = new NBTTagCompound();
+
+ nbtTagCompound.set("uuid", new NBTTagLongArray(new long [] {
+ uuid.getLeastSignificantBits(),
+ uuid.getMostSignificantBits()
+ }));
+
+ this.uniqueItem.setTag(nbtTagCompound);
+ }
+
+ /**
+ * Forcefully updates the client state, sending all items, container properties and the held item.
+ *
+ * @since 0.10.8
+ */
+ public void forceUpdate() {
+ /*
+ The server will not send the items when they haven't changed, so we will overwrite every item with a unique
+ item first to ensure the server is going to send our items.
+ */
+ Collections.fill(this.items, this.uniqueItem);
+
+ c();
+
+ List extends ICrafting> listeners;
+
+ try {
+ //noinspection unchecked
+ listeners = (List extends ICrafting>) listenersField.get(this);
+ } catch (IllegalAccessException exception) {
+ throw new RuntimeException("Unable to access field 'listeners'", exception);
+ }
+
+ for (ICrafting listener : listeners) {
+ if (!(listener instanceof EntityPlayer)) {
+ continue;
+ }
+
+ EntityPlayer player = (EntityPlayer) listener;
+
+ player.e = false;
+ player.broadcastCarriedItem();
+ }
+ }
+
+ @Override
+ public ItemStack a(int i, int j, InventoryClickType inventoryclicktype, EntityHuman entityhuman) {
+ ItemStack itemStack = super.a(i, j, inventoryclicktype, entityhuman);
+
+ //the client predicts the allowed movement of the item, so we broadcast the state again to override it
+ forceUpdate();
+
+ return itemStack;
+ }
+
+ @Contract(pure = true, value = "_ -> true")
+ @Override
+ public boolean canUse(@Nullable EntityHuman entityHuman) {
+ return true;
+ }
+
+ @Override
+ public void a(IInventory inventory) {}
+
+ @Override
+ public void b(EntityHuman entityHuman) {}
+
+ public int getWindowId() {
+ return this.windowId;
+ }
+ }
+}
diff --git a/nms/1_15/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_15/MerchantInventoryImpl.java b/nms/1_15/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_15/MerchantInventoryImpl.java
new file mode 100644
index 000000000..2b296f202
--- /dev/null
+++ b/nms/1_15/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_15/MerchantInventoryImpl.java
@@ -0,0 +1,95 @@
+package com.github.stefvanschie.inventoryframework.nms.v1_15;
+
+import com.github.stefvanschie.inventoryframework.abstraction.MerchantInventory;
+import net.minecraft.server.v1_15_R1.EntityPlayer;
+import net.minecraft.server.v1_15_R1.MerchantRecipeList;
+import org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftItemStack;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.MerchantRecipe;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Internal merchant inventory for 1.15
+ *
+ * @since 0.10.1
+ */
+public class MerchantInventoryImpl extends MerchantInventory {
+
+ @Override
+ public void sendMerchantOffers(@NotNull Player player,
+ @NotNull List extends Map.Entry extends MerchantRecipe, ? extends Integer>> trades,
+ int level, int experience) {
+ MerchantRecipeList offers = new MerchantRecipeList();
+
+ for (Map.Entry extends MerchantRecipe, ? extends Integer> entry : trades) {
+ MerchantRecipe recipe = entry.getKey();
+ List ingredients = recipe.getIngredients();
+
+ if (ingredients.size() < 1) {
+ throw new IllegalStateException("Merchant recipe has no ingredients");
+ }
+
+ ItemStack itemA = ingredients.get(0);
+ ItemStack itemB = null;
+
+ if (ingredients.size() >= 2) {
+ itemB = ingredients.get(1);
+ }
+
+ net.minecraft.server.v1_15_R1.ItemStack nmsItemA = CraftItemStack.asNMSCopy(itemA);
+ net.minecraft.server.v1_15_R1.ItemStack nmsItemB = net.minecraft.server.v1_15_R1.ItemStack.a;
+ net.minecraft.server.v1_15_R1.ItemStack nmsItemResult = CraftItemStack.asNMSCopy(recipe.getResult());
+
+ if (itemB != null) {
+ nmsItemB = CraftItemStack.asNMSCopy(itemB);
+ }
+
+ int uses = recipe.getUses();
+ int maxUses = recipe.getMaxUses();
+ int exp = recipe.getVillagerExperience();
+ float multiplier = recipe.getPriceMultiplier();
+
+ net.minecraft.server.v1_15_R1.MerchantRecipe merchantOffer = new net.minecraft.server.v1_15_R1.MerchantRecipe(
+ nmsItemA, nmsItemB, nmsItemResult, uses, maxUses, exp, multiplier
+ );
+ merchantOffer.setSpecialPrice(entry.getValue());
+
+ offers.add(merchantOffer);
+ }
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ entityPlayer.openTrade(getWindowId(entityPlayer), offers, level, experience, true, false);
+ }
+
+ /**
+ * Gets the entity player associated to this player
+ *
+ * @param player the player to get the entity player from
+ * @return the entity player
+ * @since 0.10.1
+ */
+ @NotNull
+ @Contract(pure = true)
+ private EntityPlayer getEntityPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * Gets the window id for the inventory view the player currently has open
+ *
+ * @param entityPlayer the player to get the window id for
+ * @return the window id
+ * @since 0.10.1
+ */
+ @Contract(pure = true)
+ private int getWindowId(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.activeContainer.windowId;
+ }
+}
diff --git a/nms/1_15_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_15_R1/StonecutterInventoryImpl.java b/nms/1_15/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_15/StonecutterInventoryImpl.java
similarity index 94%
rename from nms/1_15_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_15_R1/StonecutterInventoryImpl.java
rename to nms/1_15/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_15/StonecutterInventoryImpl.java
index ded6bb0d1..88118970e 100644
--- a/nms/1_15_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_15_R1/StonecutterInventoryImpl.java
+++ b/nms/1_15/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_15/StonecutterInventoryImpl.java
@@ -1,199 +1,201 @@
-package com.github.stefvanschie.inventoryframework.nms.v1_15_R1;
-
-import com.github.stefvanschie.inventoryframework.abstraction.StonecutterInventory;
-import net.minecraft.server.v1_15_R1.*;
-import org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer;
-import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftInventory;
-import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftInventoryStonecutter;
-import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftInventoryView;
-import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftItemStack;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.InventoryHolder;
-import org.jetbrains.annotations.Contract;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.lang.reflect.Field;
-
-/**
- * Internal stonecutter inventory for 1.15 R1
- *
- * @since 0.8.0
- */
-public class StonecutterInventoryImpl extends StonecutterInventory {
-
- public StonecutterInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
- super(inventoryHolder);
- }
-
- @Override
- public void openInventory(@NotNull Player player, @NotNull String title,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- int itemAmount = items.length;
-
- if (itemAmount != 2) {
- throw new IllegalArgumentException(
- "The amount of items for a stonecutter should be 2, but is '" + itemAmount + "'"
- );
- }
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
- ContainerStonecutterImpl containerEnchantmentTable = new ContainerStonecutterImpl(entityPlayer, items);
-
- entityPlayer.activeContainer = containerEnchantmentTable;
-
- int id = containerEnchantmentTable.windowId;
- ChatMessage message = new ChatMessage(title);
- PacketPlayOutOpenWindow packet = new PacketPlayOutOpenWindow(id, Containers.STONECUTTER, message);
-
- entityPlayer.playerConnection.sendPacket(packet);
-
- sendItems(player, items);
- }
-
- @Override
- public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
- NonNullList nmsItems = NonNullList.a(
- ItemStack.a,
- CraftItemStack.asNMSCopy(items[0]),
- CraftItemStack.asNMSCopy(items[1])
- );
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
- }
-
- @Override
- public void clearCursor(@NotNull Player player) {
- getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.a));
- }
-
- /**
- * Gets the window id for the inventory view the player currently has open
- *
- * @param entityPlayer the player to get the window id for
- * @return the window id
- * @since 0.8.0
- */
- @Contract(pure = true)
- private int getWindowId(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.activeContainer.windowId;
- }
-
- /**
- * Gets the player connection for the specified player
- *
- * @param entityPlayer the player to get the player connection from
- * @return the player connection
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.playerConnection;
- }
-
- /**
- * Gets the entity player associated to this player
- *
- * @param player the player to get the entity player from
- * @return the entity player
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private EntityPlayer getEntityPlayer(@NotNull Player player) {
- return ((CraftPlayer) player).getHandle();
- }
-
- /**
- * A custom container enchanting table
- *
- * @since 0.8.0
- */
- private class ContainerStonecutterImpl extends ContainerStonecutter {
-
- /**
- * The player for this enchanting table container
- */
- @NotNull
- private final Player player;
-
- /**
- * The internal bukkit entity for this container enchanting table
- */
- @Nullable
- private CraftInventoryView bukkitEntity;
-
- /**
- * Field for accessing the result inventory field
- */
- @NotNull
- private final Field resultInventoryField;
-
- public ContainerStonecutterImpl(@NotNull EntityPlayer entityPlayer,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
-
- this.player = entityPlayer.getBukkitEntity();
-
- try {
- this.resultInventoryField = ContainerStonecutter.class.getDeclaredField("resultInventory");
- this.resultInventoryField.setAccessible(true);
- } catch (NoSuchFieldException exception) {
- throw new RuntimeException(exception);
- }
-
- inventory.setItem(0, CraftItemStack.asNMSCopy(items[0]));
- getResultInventory().setItem(0, CraftItemStack.asNMSCopy(items[1]));
- }
-
- @NotNull
- @Override
- public CraftInventoryView getBukkitView() {
- if (bukkitEntity == null) {
- CraftInventory inventory = new CraftInventoryStonecutter(this.inventory, getResultInventory()) {
- @NotNull
- @Contract(pure = true)
- @Override
- public InventoryHolder getHolder() {
- return inventoryHolder;
- }
- };
-
- bukkitEntity = new CraftInventoryView(player, inventory, this);
- }
-
- return bukkitEntity;
- }
-
- @Contract(pure = true, value = "_ -> true")
- @Override
- public boolean canUse(@Nullable EntityHuman entityhuman) {
- return true;
- }
-
- @Override
- public void a(IInventory inventory) {}
-
- @Override
- public void b(EntityHuman entityhuman) {}
-
- /**
- * Gets the result inventory
- *
- * @return the result inventory
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- public IInventory getResultInventory() {
- try {
- return (IInventory) resultInventoryField.get(this);
- } catch (IllegalAccessException exception) {
- throw new RuntimeException(exception);
- }
- }
- }
-}
+package com.github.stefvanschie.inventoryframework.nms.v1_15;
+
+import com.github.stefvanschie.inventoryframework.abstraction.StonecutterInventory;
+import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
+import com.github.stefvanschie.inventoryframework.nms.v1_15.util.TextHolderUtil;
+import net.minecraft.server.v1_15_R1.*;
+import org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftInventory;
+import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftInventoryStonecutter;
+import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftInventoryView;
+import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftItemStack;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.InventoryHolder;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.lang.reflect.Field;
+
+/**
+ * Internal stonecutter inventory for 1.15 R1
+ *
+ * @since 0.8.0
+ */
+public class StonecutterInventoryImpl extends StonecutterInventory {
+
+ public StonecutterInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
+ super(inventoryHolder);
+ }
+
+ @Override
+ public void openInventory(@NotNull Player player, @NotNull TextHolder title,
+ @Nullable org.bukkit.inventory.ItemStack[] items) {
+ int itemAmount = items.length;
+
+ if (itemAmount != 2) {
+ throw new IllegalArgumentException(
+ "The amount of items for a stonecutter should be 2, but is '" + itemAmount + "'"
+ );
+ }
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+ ContainerStonecutterImpl containerEnchantmentTable = new ContainerStonecutterImpl(entityPlayer, items);
+
+ entityPlayer.activeContainer = containerEnchantmentTable;
+
+ int id = containerEnchantmentTable.windowId;
+ IChatBaseComponent message = TextHolderUtil.toComponent(title);
+ PacketPlayOutOpenWindow packet = new PacketPlayOutOpenWindow(id, Containers.STONECUTTER, message);
+
+ entityPlayer.playerConnection.sendPacket(packet);
+
+ sendItems(player, items);
+ }
+
+ @Override
+ public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
+ NonNullList nmsItems = NonNullList.a(
+ ItemStack.a,
+ CraftItemStack.asNMSCopy(items[0]),
+ CraftItemStack.asNMSCopy(items[1])
+ );
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
+ }
+
+ @Override
+ public void clearCursor(@NotNull Player player) {
+ getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.a));
+ }
+
+ /**
+ * Gets the window id for the inventory view the player currently has open
+ *
+ * @param entityPlayer the player to get the window id for
+ * @return the window id
+ * @since 0.8.0
+ */
+ @Contract(pure = true)
+ private int getWindowId(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.activeContainer.windowId;
+ }
+
+ /**
+ * Gets the player connection for the specified player
+ *
+ * @param entityPlayer the player to get the player connection from
+ * @return the player connection
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.playerConnection;
+ }
+
+ /**
+ * Gets the entity player associated to this player
+ *
+ * @param player the player to get the entity player from
+ * @return the entity player
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private EntityPlayer getEntityPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * A custom container enchanting table
+ *
+ * @since 0.8.0
+ */
+ private class ContainerStonecutterImpl extends ContainerStonecutter {
+
+ /**
+ * The player for this enchanting table container
+ */
+ @NotNull
+ private final Player player;
+
+ /**
+ * The internal bukkit entity for this container enchanting table
+ */
+ @Nullable
+ private CraftInventoryView bukkitEntity;
+
+ /**
+ * Field for accessing the result inventory field
+ */
+ @NotNull
+ private final Field resultInventoryField;
+
+ public ContainerStonecutterImpl(@NotNull EntityPlayer entityPlayer,
+ @Nullable org.bukkit.inventory.ItemStack[] items) {
+ super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
+
+ this.player = entityPlayer.getBukkitEntity();
+
+ try {
+ this.resultInventoryField = ContainerStonecutter.class.getDeclaredField("resultInventory");
+ this.resultInventoryField.setAccessible(true);
+ } catch (NoSuchFieldException exception) {
+ throw new RuntimeException(exception);
+ }
+
+ inventory.setItem(0, CraftItemStack.asNMSCopy(items[0]));
+ getResultInventory().setItem(0, CraftItemStack.asNMSCopy(items[1]));
+ }
+
+ @NotNull
+ @Override
+ public CraftInventoryView getBukkitView() {
+ if (bukkitEntity == null) {
+ CraftInventory inventory = new CraftInventoryStonecutter(this.inventory, getResultInventory()) {
+ @NotNull
+ @Contract(pure = true)
+ @Override
+ public InventoryHolder getHolder() {
+ return inventoryHolder;
+ }
+ };
+
+ bukkitEntity = new CraftInventoryView(player, inventory, this);
+ }
+
+ return bukkitEntity;
+ }
+
+ @Contract(pure = true, value = "_ -> true")
+ @Override
+ public boolean canUse(@Nullable EntityHuman entityhuman) {
+ return true;
+ }
+
+ @Override
+ public void a(IInventory inventory) {}
+
+ @Override
+ public void b(EntityHuman entityhuman) {}
+
+ /**
+ * Gets the result inventory
+ *
+ * @return the result inventory
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ public IInventory getResultInventory() {
+ try {
+ return (IInventory) resultInventoryField.get(this);
+ } catch (IllegalAccessException exception) {
+ throw new RuntimeException(exception);
+ }
+ }
+ }
+}
diff --git a/nms/1_15/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_15/util/TextHolderUtil.java b/nms/1_15/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_15/util/TextHolderUtil.java
new file mode 100644
index 000000000..7554a5bc6
--- /dev/null
+++ b/nms/1_15/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_15/util/TextHolderUtil.java
@@ -0,0 +1,66 @@
+package com.github.stefvanschie.inventoryframework.nms.v1_15.util;
+
+import com.github.stefvanschie.inventoryframework.adventuresupport.ComponentHolder;
+import com.github.stefvanschie.inventoryframework.adventuresupport.StringHolder;
+import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
+import net.minecraft.server.v1_15_R1.ChatComponentText;
+import net.minecraft.server.v1_15_R1.IChatBaseComponent;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Objects;
+
+/**
+ * A utility class for adding {@link TextHolder} support.
+ *
+ * @since 0.10.0
+ */
+public final class TextHolderUtil {
+
+ private TextHolderUtil() {
+ //private constructor to prevent construction
+ }
+
+ /**
+ * Converts the specified value to a vanilla component.
+ *
+ * @param holder the value to convert
+ * @return the value as a vanilla component
+ * @since 0.10.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ public static IChatBaseComponent toComponent(@NotNull TextHolder holder) {
+ if (holder instanceof StringHolder) {
+ return toComponent((StringHolder) holder);
+ } else {
+ return toComponent((ComponentHolder) holder);
+ }
+ }
+
+ /**
+ * Converts the specified legacy string holder to a vanilla component.
+ *
+ * @param holder the value to convert
+ * @return the value as a vanilla component
+ * @since 0.10.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private static IChatBaseComponent toComponent(@NotNull StringHolder holder) {
+ return new ChatComponentText(holder.asLegacyString());
+ }
+
+ /**
+ * Converts the specified Adventure component holder to a vanilla component.
+ *
+ * @param holder the value to convert
+ * @return the value as a vanilla component
+ * @since 0.10.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private static IChatBaseComponent toComponent(@NotNull ComponentHolder holder) {
+ return Objects.requireNonNull(IChatBaseComponent.ChatSerializer.a(holder.asJson()));
+ }
+}
diff --git a/nms/1_15_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_15_R1/AnvilInventoryImpl.java b/nms/1_15_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_15_R1/AnvilInventoryImpl.java
deleted file mode 100644
index 2cbfc8c58..000000000
--- a/nms/1_15_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_15_R1/AnvilInventoryImpl.java
+++ /dev/null
@@ -1,304 +0,0 @@
-package com.github.stefvanschie.inventoryframework.nms.v1_15_R1;
-
-import com.github.stefvanschie.inventoryframework.abstraction.AnvilInventory;
-import net.minecraft.server.v1_15_R1.*;
-import org.bukkit.Location;
-import org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer;
-import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftInventory;
-import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftInventoryAnvil;
-import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftInventoryView;
-import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftItemStack;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.InventoryHolder;
-import org.jetbrains.annotations.Contract;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.lang.reflect.Field;
-
-/**
- * Internal anvil inventory for 1.15 R1
- *
- * @since 0.8.0
- */
-public class AnvilInventoryImpl extends AnvilInventory {
-
- public AnvilInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
- super(inventoryHolder);
- }
-
- @Override
- public void openInventory(@NotNull Player player, @NotNull String title,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- int itemAmount = items.length;
-
- if (itemAmount != 3) {
- throw new IllegalArgumentException(
- "The amount of items for an anvil should be 3, but is '" + itemAmount + "'"
- );
- }
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
- ContainerAnvilImpl containerAnvil = new ContainerAnvilImpl(entityPlayer, items);
-
- entityPlayer.activeContainer = containerAnvil;
-
- int id = containerAnvil.windowId;
- ChatMessage message = new ChatMessage(title);
-
- entityPlayer.playerConnection.sendPacket(new PacketPlayOutOpenWindow(id, Containers.ANVIL, message));
-
- sendItems(player, items);
- }
-
- @Override
- public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
- NonNullList nmsItems = NonNullList.a(
- ItemStack.a,
- CraftItemStack.asNMSCopy(items[0]),
- CraftItemStack.asNMSCopy(items[1]),
- CraftItemStack.asNMSCopy(items[2])
- );
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
- }
-
- @Override
- public void sendFirstItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
- EntityPlayer entityPlayer = getEntityPlayer(player);
- ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutSetSlot(getWindowId(entityPlayer), 0, nmsItem));
- }
-
- @Override
- public void sendSecondItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
- EntityPlayer entityPlayer = getEntityPlayer(player);
- ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutSetSlot(getWindowId(entityPlayer), 1, nmsItem));
- }
-
- @Override
- public void sendResultItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
- sendResultItem(player, CraftItemStack.asNMSCopy(item));
- }
-
- @Override
- public void clearResultItem(@NotNull Player player) {
- sendResultItem(player, ItemStack.a);
- }
-
- @Override
- public void setCursor(@NotNull Player player, @NotNull org.bukkit.inventory.ItemStack item) {
- setCursor(player, CraftItemStack.asNMSCopy(item));
- }
-
- @Override
- public void clearCursor(@NotNull Player player) {
- getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.a));
- }
-
- /**
- * Sets the cursor of the given player
- *
- * @param player the player to set the cursor
- * @param item the item to set the cursor to
- * @since 0.8.0
- */
- private void setCursor(@NotNull Player player, @NotNull ItemStack item) {
- getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, item));
- }
-
- /**
- * Sends the result item to the specified player with the given item
- *
- * @param player the player to send the result item to
- * @param item the result item
- * @since 0.8.0
- */
- private void sendResultItem(@NotNull Player player, @NotNull ItemStack item) {
- EntityPlayer entityPlayer = getEntityPlayer(player);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutSetSlot(getWindowId(entityPlayer), 2, item));
- }
-
- /**
- * Gets the window id for the inventory view the player currently has open
- *
- * @param entityPlayer the player to get the window id for
- * @return the window id
- * @since 0.8.0
- */
- @Contract(pure = true)
- private int getWindowId(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.activeContainer.windowId;
- }
-
- /**
- * Gets the player connection for the specified player
- *
- * @param entityPlayer the player to get the player connection from
- * @return the player connection
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.playerConnection;
- }
-
- /**
- * Gets the entity player associated to this player
- *
- * @param player the player to get the entity player from
- * @return the entity player
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private EntityPlayer getEntityPlayer(@NotNull Player player) {
- return ((CraftPlayer) player).getHandle();
- }
-
- /**
- * A custom container anvil for responding to item renaming
- *
- * @since 0.8.0
- */
- private class ContainerAnvilImpl extends ContainerAnvil {
-
- /**
- * The player for whom this anvil container is
- */
- @NotNull
- private final Player player;
-
- /**
- * The internal bukkit entity for this container anvil
- */
- @Nullable
- private CraftInventoryView bukkitEntity;
-
- /**
- * Field for accessing the repair inventory field
- */
- @NotNull
- private final Field repairInventoryField;
-
- /**
- * Field for accessing the result inventory field
- */
- @NotNull
- private final Field resultInventoryField;
-
- /**
- * Field for accessing the container access field
- */
- @NotNull
- private final Field containerAccessField;
-
- /**
- * Creates a new custom anvil container for the specified player
- *
- * @param entityPlayer the player for who this anvil container is
- * @since 0.8.0
- */
- public ContainerAnvilImpl(@NotNull EntityPlayer entityPlayer,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- super(entityPlayer.nextContainerCounter(), entityPlayer.inventory,
- ContainerAccess.at(entityPlayer.getWorld(), new BlockPosition(0, 0, 0)));
-
- this.player = entityPlayer.getBukkitEntity();
-
- try {
- repairInventoryField = ContainerAnvil.class.getDeclaredField("repairInventory");
- repairInventoryField.setAccessible(true);
-
- resultInventoryField = ContainerAnvil.class.getDeclaredField("resultInventory");
- resultInventoryField.setAccessible(true);
-
- containerAccessField = ContainerAnvil.class.getDeclaredField("containerAccess");
- containerAccessField.setAccessible(true);
- } catch (NoSuchFieldException exception) {
- throw new RuntimeException(exception);
- }
-
- getRepairInventory().setItem(0, CraftItemStack.asNMSCopy(items[0]));
- getRepairInventory().setItem(1, CraftItemStack.asNMSCopy(items[1]));
- getResultInventory().setItem(0, CraftItemStack.asNMSCopy(items[2]));
- }
-
- @NotNull
- @Override
- public CraftInventoryView getBukkitView() {
- if (bukkitEntity == null) {
- Location location = getContainerAccess().getLocation();
- CraftInventory inventory = new CraftInventoryAnvil(location, getRepairInventory(), getResultInventory(),
- this) {
- @NotNull
- @Contract(pure = true)
- @Override
- public InventoryHolder getHolder() {
- return inventoryHolder;
- }
- };
-
- bukkitEntity = new CraftInventoryView(player, inventory, this);
- }
-
- return bukkitEntity;
- }
-
- @Override
- public void a(@Nullable String name) {
- text = name == null ? "" : name;
-
- sendResultItem(player, getResultInventory().getItem(0));
- }
-
- @Contract(pure = true, value = "_ -> true")
- @Override
- public boolean canUse(@Nullable EntityHuman entityhuman) {
- return true;
- }
-
- @Override
- public void a(IInventory inventory) {}
-
- @Override
- public void b(EntityHuman entityhuman) {}
-
- @NotNull
- @Contract(pure = true)
- private IInventory getRepairInventory() {
- try {
- return (IInventory) repairInventoryField.get(this);
- } catch (IllegalAccessException exception) {
- throw new RuntimeException(exception);
- }
- }
-
- @NotNull
- @Contract(pure = true)
- private IInventory getResultInventory() {
- try {
- return (IInventory) resultInventoryField.get(this);
- } catch (IllegalAccessException exception) {
- throw new RuntimeException(exception);
- }
- }
-
- @NotNull
- @Contract(pure = true)
- private ContainerAccess getContainerAccess() {
- try {
- return (ContainerAccess) containerAccessField.get(this);
- } catch (IllegalAccessException exception) {
- throw new RuntimeException(exception);
- }
- }
- }
-}
diff --git a/nms/1_15_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_15_R1/GrindstoneInventoryImpl.java b/nms/1_15_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_15_R1/GrindstoneInventoryImpl.java
deleted file mode 100644
index d582f5fcc..000000000
--- a/nms/1_15_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_15_R1/GrindstoneInventoryImpl.java
+++ /dev/null
@@ -1,227 +0,0 @@
-package com.github.stefvanschie.inventoryframework.nms.v1_15_R1;
-
-import com.github.stefvanschie.inventoryframework.abstraction.GrindstoneInventory;
-import net.minecraft.server.v1_15_R1.*;
-import org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer;
-import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftInventory;
-import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftInventoryGrindstone;
-import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftInventoryView;
-import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftItemStack;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.InventoryHolder;
-import org.jetbrains.annotations.Contract;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.lang.reflect.Field;
-
-/**
- * Internal grindstone inventory for 1.15 R1
- *
- * @since 0.8.0
- */
-public class GrindstoneInventoryImpl extends GrindstoneInventory {
-
- public GrindstoneInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
- super(inventoryHolder);
- }
-
- @Override
- public void openInventory(@NotNull Player player, @NotNull String title,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- int itemAmount = items.length;
-
- if (itemAmount != 3) {
- throw new IllegalArgumentException(
- "The amount of items for a grindstone should be 3, but is '" + itemAmount + "'"
- );
- }
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
- ContainerGrindstoneImpl containerGrindstone = new ContainerGrindstoneImpl(entityPlayer, items);
-
- entityPlayer.activeContainer = containerGrindstone;
-
- int id = containerGrindstone.windowId;
- ChatMessage message = new ChatMessage(title);
- PacketPlayOutOpenWindow packet = new PacketPlayOutOpenWindow(id, Containers.GRINDSTONE, message);
-
- entityPlayer.playerConnection.sendPacket(packet);
-
- sendItems(player, items);
- }
-
- @Override
- public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
- NonNullList nmsItems = NonNullList.a(
- ItemStack.a,
- CraftItemStack.asNMSCopy(items[0]),
- CraftItemStack.asNMSCopy(items[1]),
- CraftItemStack.asNMSCopy(items[2])
- );
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
- }
-
- @Override
- public void clearCursor(@NotNull Player player) {
- getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.a));
- }
-
- /**
- * Gets the window id for the inventory view the player currently has open
- *
- * @param entityPlayer the player to get the window id for
- * @return the window id
- * @since 0.8.0
- */
- @Contract(pure = true)
- private int getWindowId(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.activeContainer.windowId;
- }
-
- /**
- * Gets the player connection for the specified player
- *
- * @param entityPlayer the player to get the player connection from
- * @return the player connection
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.playerConnection;
- }
-
- /**
- * Gets the entity player associated to this player
- *
- * @param player the player to get the entity player from
- * @return the entity player
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private EntityPlayer getEntityPlayer(@NotNull Player player) {
- return ((CraftPlayer) player).getHandle();
- }
-
- /**
- * A custom container grindstone
- *
- * @since 0.8.0
- */
- private class ContainerGrindstoneImpl extends ContainerGrindstone {
-
- /**
- * The player for this grindstone container
- */
- @NotNull
- private final Player player;
-
- /**
- * The internal bukkit entity for this container grindstone
- */
- @Nullable
- private CraftInventoryView bukkitEntity;
-
- /**
- * Field for accessing the craft inventory field
- */
- @NotNull
- private final Field craftInventoryField;
-
- /**
- * Field for accessing the result inventory field
- */
- @NotNull
- private final Field resultInventoryField;
-
- public ContainerGrindstoneImpl(@NotNull EntityPlayer entityPlayer,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
-
- this.player = entityPlayer.getBukkitEntity();
-
- try {
- this.craftInventoryField = ContainerGrindstone.class.getDeclaredField("craftInventory");
- this.craftInventoryField.setAccessible(true);
-
- this.resultInventoryField = ContainerGrindstone.class.getDeclaredField("resultInventory");
- this.resultInventoryField.setAccessible(true);
- } catch (NoSuchFieldException exception) {
- throw new RuntimeException(exception);
- }
-
- getCraftInventory().setItem(0, CraftItemStack.asNMSCopy(items[0]));
- getCraftInventory().setItem(1, CraftItemStack.asNMSCopy(items[1]));
-
- getResultInventory().setItem(2, CraftItemStack.asNMSCopy(items[2]));
- }
-
- @NotNull
- @Override
- public CraftInventoryView getBukkitView() {
- if (bukkitEntity == null) {
- CraftInventory inventory = new CraftInventoryGrindstone(getCraftInventory(), getResultInventory()) {
- @NotNull
- @Contract(pure = true)
- @Override
- public InventoryHolder getHolder() {
- return inventoryHolder;
- }
- };
-
- bukkitEntity = new CraftInventoryView(player, inventory, this);
- }
-
- return bukkitEntity;
- }
-
- @Contract(pure = true, value = "_ -> true")
- @Override
- public boolean canUse(@Nullable EntityHuman entityhuman) {
- return true;
- }
-
- @Override
- public void a(IInventory inventory) {}
-
- @Override
- public void b(EntityHuman entityhuman) {}
-
- /**
- * Gets the craft inventory
- *
- * @return the craft inventory
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private IInventory getCraftInventory() {
- try {
- return (IInventory) craftInventoryField.get(this);
- } catch (IllegalAccessException exception) {
- throw new RuntimeException(exception);
- }
- }
-
- /**
- * Gets the result inventory
- *
- * @return the result inventory
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private IInventory getResultInventory() {
- try {
- return (IInventory) resultInventoryField.get(this);
- } catch (IllegalAccessException exception) {
- throw new RuntimeException(exception);
- }
- }
- }
-}
diff --git a/nms/1_16_R1/pom.xml b/nms/1_16_1/pom.xml
similarity index 86%
rename from nms/1_16_R1/pom.xml
rename to nms/1_16_1/pom.xml
index 47e02eab6..6ad0fba2a 100644
--- a/nms/1_16_R1/pom.xml
+++ b/nms/1_16_1/pom.xml
@@ -5,12 +5,12 @@
IF-parent
com.github.stefvanschie.inventoryframework
- 0.9.8
+ 0.10.18
../../pom.xml
4.0.0
- 1_16_R1
+ 1_16_1
true
@@ -18,8 +18,8 @@
- org.spigotmc
- spigot
+ io.papermc
+ paper
1.16.1-R0.1-SNAPSHOT
provided
diff --git a/nms/1_16_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_1/AnvilInventoryImpl.java b/nms/1_16_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_1/AnvilInventoryImpl.java
new file mode 100644
index 000000000..098c90241
--- /dev/null
+++ b/nms/1_16_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_1/AnvilInventoryImpl.java
@@ -0,0 +1,386 @@
+package com.github.stefvanschie.inventoryframework.nms.v1_16_1;
+
+import com.github.stefvanschie.inventoryframework.abstraction.AnvilInventory;
+import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
+import com.github.stefvanschie.inventoryframework.nms.v1_16_1.util.TextHolderUtil;
+import net.minecraft.server.v1_16_R1.*;
+import org.bukkit.craftbukkit.v1_16_R1.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_16_R1.event.CraftEventFactory;
+import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftItemStack;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.InventoryHolder;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.lang.reflect.Field;
+import java.util.Collections;
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * Internal anvil inventory for 1.16 R1
+ *
+ * @since 0.8.0
+ */
+public class AnvilInventoryImpl extends AnvilInventory {
+
+ public AnvilInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
+ super(inventoryHolder);
+ }
+
+ @Override
+ public Inventory openInventory(@NotNull Player player, @NotNull TextHolder title,
+ @Nullable org.bukkit.inventory.ItemStack[] items) {
+ int itemAmount = items.length;
+
+ if (itemAmount != 3) {
+ throw new IllegalArgumentException(
+ "The amount of items for an anvil should be 3, but is '" + itemAmount + "'"
+ );
+ }
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ //ignore deprecation: superseding method is only available on Paper
+ //noinspection deprecation
+ CraftEventFactory.handleInventoryCloseEvent(entityPlayer);
+
+ entityPlayer.activeContainer = entityPlayer.defaultContainer;
+
+ IChatBaseComponent message = TextHolderUtil.toComponent(title);
+ ContainerAnvilImpl containerAnvil = new ContainerAnvilImpl(entityPlayer, message);
+
+ Inventory inventory = containerAnvil.getBukkitView().getTopInventory();
+
+ inventory.setItem(0, items[0]);
+ inventory.setItem(1, items[1]);
+ inventory.setItem(2, items[2]);
+
+ int containerId = containerAnvil.getContainerId();
+
+ entityPlayer.playerConnection.sendPacket(new PacketPlayOutOpenWindow(containerId, Containers.ANVIL, message));
+ entityPlayer.activeContainer = containerAnvil;
+ entityPlayer.syncInventory();
+
+ return inventory;
+ }
+
+ @Override
+ public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
+ NonNullList nmsItems = NonNullList.a(
+ ItemStack.b,
+ CraftItemStack.asNMSCopy(items[0]),
+ CraftItemStack.asNMSCopy(items[1]),
+ CraftItemStack.asNMSCopy(items[2])
+ );
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
+ }
+
+ @Override
+ public void sendFirstItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+ ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutSetSlot(getWindowId(entityPlayer), 0, nmsItem));
+ }
+
+ @Override
+ public void sendSecondItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+ ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutSetSlot(getWindowId(entityPlayer), 1, nmsItem));
+ }
+
+ @Override
+ public void sendResultItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
+ sendResultItem(player, CraftItemStack.asNMSCopy(item));
+ }
+
+ @Override
+ public void clearResultItem(@NotNull Player player) {
+ sendResultItem(player, ItemStack.b);
+ }
+
+ @Override
+ public void setCursor(@NotNull Player player, @NotNull org.bukkit.inventory.ItemStack item) {
+ setCursor(player, CraftItemStack.asNMSCopy(item));
+ }
+
+ @Override
+ public void clearCursor(@NotNull Player player) {
+ getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.b));
+ }
+
+ /**
+ * Sets the cursor of the given player
+ *
+ * @param player the player to set the cursor
+ * @param item the item to set the cursor to
+ * @since 0.8.0
+ * @deprecated no longer used internally
+ */
+ @Deprecated
+ private void setCursor(@NotNull Player player, @NotNull ItemStack item) {
+ getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, item));
+ }
+
+ /**
+ * Sends the result item to the specified player with the given item
+ *
+ * @param player the player to send the result item to
+ * @param item the result item
+ * @since 0.8.0
+ * @deprecated no longer used internally
+ */
+ @Deprecated
+ private void sendResultItem(@NotNull Player player, @NotNull ItemStack item) {
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutSetSlot(getWindowId(entityPlayer), 2, item));
+ }
+
+ /**
+ * Gets the window id for the inventory view the player currently has open
+ *
+ * @param entityPlayer the player to get the window id for
+ * @return the window id
+ * @since 0.8.0
+ * @deprecated no longer used internally
+ */
+ @Contract(pure = true)
+ @Deprecated
+ private int getWindowId(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.activeContainer.windowId;
+ }
+
+ /**
+ * Gets the player connection for the specified player
+ *
+ * @param entityPlayer the player to get the player connection from
+ * @return the player connection
+ * @since 0.8.0
+ * @deprecated no longer used internally
+ */
+ @NotNull
+ @Contract(pure = true)
+ @Deprecated
+ private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.playerConnection;
+ }
+
+ /**
+ * Gets the entity player associated to this player
+ *
+ * @param player the player to get the entity player from
+ * @return the entity player
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private EntityPlayer getEntityPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * A custom container anvil for responding to item renaming
+ *
+ * @since 0.8.0
+ */
+ private class ContainerAnvilImpl extends ContainerAnvil {
+
+ /**
+ * The index of the result slot
+ */
+ private static final int RESULT_SLOT_INDEX = 2;
+
+ /**
+ * A unique item
+ */
+ @NotNull
+ private final ItemStack uniqueItem;
+
+ /**
+ * The field containing the listeners for this container
+ */
+ @NotNull
+ private final Field listenersField;
+
+ /**
+ * Creates a new custom anvil container for the specified player
+ *
+ * @param entityPlayer the player for whom this anvil container is
+ * @param title the title of the inventory
+ * @since 0.10.8
+ */
+ public ContainerAnvilImpl(@NotNull EntityPlayer entityPlayer, @NotNull IChatBaseComponent title) {
+ super(entityPlayer.nextContainerCounter(), entityPlayer.inventory,
+ ContainerAccess.at(entityPlayer.getWorld(), new BlockPosition(0, 0, 0)));
+
+ this.checkReachable = false;
+
+ try {
+ //stores all the registered container properties
+ Field dField = Container.class.getDeclaredField("d");
+ dField.setAccessible(true);
+
+ //get rid of the level cost property
+ ((List>) dField.get(this)).clear();
+ } catch (NoSuchFieldException | IllegalAccessException exception) {
+ throw new RuntimeException("Unable to access field 'd'", exception);
+ }
+
+ try {
+ this.listenersField = Container.class.getDeclaredField("listeners");
+ this.listenersField.setAccessible(true);
+ } catch (NoSuchFieldException exception) {
+ throw new RuntimeException("Unable to access field 'listeners'", exception);
+ }
+
+ //register a new property for the level cost
+ ContainerProperty levelCost = a(new ContainerProperty() {
+ private int value;
+
+ @Override
+ public int get() {
+ return value;
+ }
+
+ @Override
+ public void set(int value) {
+ this.value = value;
+ }
+
+ /*
+ This checks whether there have been any changes, but we want to override the client prediction. This
+ means the server should be sending the data to the client, even if it didn't change server-side. To
+ force this, we tell the server the data has always changed.
+ */
+ @Override
+ public boolean c() {
+ return true;
+ }
+ });
+
+ levelCost.set(AnvilInventoryImpl.super.cost);
+
+ setTitle(title);
+
+ Slot originalSlot = this.slots.get(RESULT_SLOT_INDEX);
+
+ Slot newSlot = new Slot(originalSlot.inventory, originalSlot.index, originalSlot.e, originalSlot.f) {
+ @Override
+ public boolean isAllowed(ItemStack itemStack) {
+ return true;
+ }
+
+ @Override
+ public boolean isAllowed(EntityHuman entityHuman) {
+ return true;
+ }
+
+ @Override
+ public ItemStack a(EntityHuman entityHuman, @NotNull ItemStack itemStack) {
+ return originalSlot.a(entityHuman, itemStack);
+ }
+ };
+
+ this.slots.set(RESULT_SLOT_INDEX, newSlot);
+
+ this.uniqueItem = new ItemStack(Items.COOKIE);
+
+ //to make the item unique, we add a random uuid as nbt to it
+ UUID uuid = UUID.randomUUID();
+ NBTTagCompound nbtTagCompound = new NBTTagCompound();
+
+ nbtTagCompound.set("uuid", new NBTTagLongArray(new long [] {
+ uuid.getLeastSignificantBits(),
+ uuid.getMostSignificantBits()
+ }));
+
+ this.uniqueItem.setTag(nbtTagCompound);
+ }
+
+ @Override
+ public void a(@Nullable String name) {
+ name = name == null ? "" : name;
+
+ /* Only update if the name is actually different. This may be called even if the name is not different,
+ particularly when putting an item in the first slot. */
+ if (!name.equals(AnvilInventoryImpl.super.observableText.get())) {
+ AnvilInventoryImpl.super.observableText.set(name);
+ }
+
+ //the client predicts the output result, so we broadcast the state again to override it
+ forceUpdate();
+ }
+
+ @Override
+ public void e() {}
+
+ @Override
+ public void b(EntityHuman entityHuman) {}
+
+ @Override
+ protected void a(EntityHuman entityHuman, World world, @NotNull IInventory inventory) {}
+
+ @Override
+ protected ItemStack a(EntityHuman entityHuman, @NotNull ItemStack itemStack) {
+ return itemStack;
+ }
+
+ @Override
+ public ItemStack a(int i, int j, InventoryClickType inventoryclicktype, EntityHuman entityhuman) {
+ ItemStack itemStack = super.a(i, j, inventoryclicktype, entityhuman);
+
+ //the client predicts the allowed movement of the item, so we broadcast the state again to override it
+ forceUpdate();
+
+ return itemStack;
+ }
+
+ public int getContainerId() {
+ return this.windowId;
+ }
+
+ /**
+ * Forcefully updates the client state, sending all items, container properties and the held item.
+ *
+ * @since 0.10.8
+ */
+ public void forceUpdate() {
+ /*
+ The server will not send the items when they haven't changed, so we will overwrite every item with a unique
+ item first to ensure the server is going to send our items.
+ */
+ Collections.fill(this.items, this.uniqueItem);
+
+ c();
+
+ List extends ICrafting> listeners;
+
+ try {
+ //noinspection unchecked
+ listeners = (List extends ICrafting>) listenersField.get(this);
+ } catch (IllegalAccessException exception) {
+ throw new RuntimeException("Unable to access field 'listeners'", exception);
+ }
+
+ for (ICrafting listener : listeners) {
+ if (!(listener instanceof EntityPlayer)) {
+ continue;
+ }
+
+ EntityPlayer player = (EntityPlayer) listener;
+
+ player.e = false;
+ player.broadcastCarriedItem();
+ }
+ }
+ }
+}
diff --git a/nms/1_16_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R1/BeaconInventoryImpl.java b/nms/1_16_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_1/BeaconInventoryImpl.java
similarity index 95%
rename from nms/1_16_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R1/BeaconInventoryImpl.java
rename to nms/1_16_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_1/BeaconInventoryImpl.java
index 3bfc1f68b..68183b72b 100644
--- a/nms/1_16_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R1/BeaconInventoryImpl.java
+++ b/nms/1_16_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_1/BeaconInventoryImpl.java
@@ -1,181 +1,181 @@
-package com.github.stefvanschie.inventoryframework.nms.v1_16_R1;
-
-import com.github.stefvanschie.inventoryframework.abstraction.BeaconInventory;
-import net.minecraft.server.v1_16_R1.*;
-import org.bukkit.craftbukkit.v1_16_R1.entity.CraftPlayer;
-import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftInventory;
-import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftInventoryBeacon;
-import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftInventoryView;
-import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftItemStack;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.InventoryHolder;
-import org.jetbrains.annotations.Contract;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.lang.reflect.Field;
-
-/**
- * Internal beacon inventory for 1.16 R1
- *
- * @since 0.8.0
- */
-public class BeaconInventoryImpl extends BeaconInventory {
-
- public BeaconInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
- super(inventoryHolder);
- }
-
- @Override
- public void openInventory(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
- EntityPlayer entityPlayer = getEntityPlayer(player);
- ContainerBeaconImpl containerBeacon = new ContainerBeaconImpl(entityPlayer, item);
-
- entityPlayer.activeContainer = containerBeacon;
-
- int id = containerBeacon.windowId;
- ChatMessage message = new ChatMessage("Beacon");
-
- entityPlayer.playerConnection.sendPacket(new PacketPlayOutOpenWindow(id, Containers.BEACON, message));
-
- sendItem(player, item);
- }
-
- @Override
- public void sendItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
- NonNullList items = NonNullList.a(
- ItemStack.b, //the first item doesn't count for some reason, so send a dummy item
- CraftItemStack.asNMSCopy(item)
- );
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), items));
- }
-
- @Override
- public void clearCursor(@NotNull Player player) {
- getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.b));
- }
-
- /**
- * Gets the window id for the inventory view the player currently has open
- *
- * @param entityPlayer the player to get the window id for
- * @return the window id
- * @since 0.8.0
- */
- @Contract(pure = true)
- private int getWindowId(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.activeContainer.windowId;
- }
-
- /**
- * Gets the player connection for the specified player
- *
- * @param entityPlayer the player to get the player connection from
- * @return the player connection
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.playerConnection;
- }
-
- /**
- * Gets the entity player associated to this player
- *
- * @param player the player to get the entity player from
- * @return the entity player
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private EntityPlayer getEntityPlayer(@NotNull Player player) {
- return ((CraftPlayer) player).getHandle();
- }
-
- /**
- * A custom container beacon
- *
- * @since 0.8.0
- */
- private class ContainerBeaconImpl extends ContainerBeacon {
-
- /**
- * The player for this beacon container
- */
- @NotNull
- private final Player player;
-
- /**
- * The internal bukkit entity for this container beacon
- */
- @Nullable
- private CraftInventoryView bukkitEntity;
-
- /**
- * Field for accessing the beacon field
- */
- @NotNull
- private final Field beaconField;
-
- public ContainerBeaconImpl(@NotNull EntityPlayer entityPlayer, @Nullable org.bukkit.inventory.ItemStack item) {
- super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
-
- this.player = entityPlayer.getBukkitEntity();
-
- try {
- this.beaconField = ContainerBeacon.class.getDeclaredField("beacon");
- this.beaconField.setAccessible(true);
- } catch (NoSuchFieldException exception) {
- throw new RuntimeException(exception);
- }
-
- try {
- ItemStack itemStack = CraftItemStack.asNMSCopy(item);
-
- ((IInventory) beaconField.get(this)).setItem(0, itemStack);
- } catch (IllegalAccessException exception) {
- throw new RuntimeException(exception);
- }
- }
-
- @NotNull
- @Override
- public CraftInventoryView getBukkitView() {
- if (bukkitEntity == null) {
- try {
- CraftInventory inventory = new CraftInventoryBeacon((IInventory) beaconField.get(this)) {
- @NotNull
- @Contract(pure = true)
- @Override
- public InventoryHolder getHolder() {
- return inventoryHolder;
- }
- };
-
- bukkitEntity = new CraftInventoryView(player, inventory, this);
- } catch (IllegalAccessException exception) {
- throw new RuntimeException(exception);
- }
- }
-
- return bukkitEntity;
- }
-
- @Contract(pure = true, value = "_ -> true")
- @Override
- public boolean canUse(@Nullable EntityHuman entityhuman) {
- return true;
- }
-
- @Override
- public void a(IInventory inventory) {}
-
- @Override
- public void b(EntityHuman entityhuman) {}
-
- }
-}
+package com.github.stefvanschie.inventoryframework.nms.v1_16_1;
+
+import com.github.stefvanschie.inventoryframework.abstraction.BeaconInventory;
+import net.minecraft.server.v1_16_R1.*;
+import org.bukkit.craftbukkit.v1_16_R1.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftInventory;
+import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftInventoryBeacon;
+import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftInventoryView;
+import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftItemStack;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.InventoryHolder;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.lang.reflect.Field;
+
+/**
+ * Internal beacon inventory for 1.16 R1
+ *
+ * @since 0.8.0
+ */
+public class BeaconInventoryImpl extends BeaconInventory {
+
+ public BeaconInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
+ super(inventoryHolder);
+ }
+
+ @Override
+ public void openInventory(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+ ContainerBeaconImpl containerBeacon = new ContainerBeaconImpl(entityPlayer, item);
+
+ entityPlayer.activeContainer = containerBeacon;
+
+ int id = containerBeacon.windowId;
+ ChatMessage message = new ChatMessage("Beacon");
+
+ entityPlayer.playerConnection.sendPacket(new PacketPlayOutOpenWindow(id, Containers.BEACON, message));
+
+ sendItem(player, item);
+ }
+
+ @Override
+ public void sendItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
+ NonNullList items = NonNullList.a(
+ ItemStack.b, //the first item doesn't count for some reason, so send a dummy item
+ CraftItemStack.asNMSCopy(item)
+ );
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), items));
+ }
+
+ @Override
+ public void clearCursor(@NotNull Player player) {
+ getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.b));
+ }
+
+ /**
+ * Gets the window id for the inventory view the player currently has open
+ *
+ * @param entityPlayer the player to get the window id for
+ * @return the window id
+ * @since 0.8.0
+ */
+ @Contract(pure = true)
+ private int getWindowId(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.activeContainer.windowId;
+ }
+
+ /**
+ * Gets the player connection for the specified player
+ *
+ * @param entityPlayer the player to get the player connection from
+ * @return the player connection
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.playerConnection;
+ }
+
+ /**
+ * Gets the entity player associated to this player
+ *
+ * @param player the player to get the entity player from
+ * @return the entity player
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private EntityPlayer getEntityPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * A custom container beacon
+ *
+ * @since 0.8.0
+ */
+ private class ContainerBeaconImpl extends ContainerBeacon {
+
+ /**
+ * The player for this beacon container
+ */
+ @NotNull
+ private final Player player;
+
+ /**
+ * The internal bukkit entity for this container beacon
+ */
+ @Nullable
+ private CraftInventoryView bukkitEntity;
+
+ /**
+ * Field for accessing the beacon field
+ */
+ @NotNull
+ private final Field beaconField;
+
+ public ContainerBeaconImpl(@NotNull EntityPlayer entityPlayer, @Nullable org.bukkit.inventory.ItemStack item) {
+ super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
+
+ this.player = entityPlayer.getBukkitEntity();
+
+ try {
+ this.beaconField = ContainerBeacon.class.getDeclaredField("beacon");
+ this.beaconField.setAccessible(true);
+ } catch (NoSuchFieldException exception) {
+ throw new RuntimeException(exception);
+ }
+
+ try {
+ ItemStack itemStack = CraftItemStack.asNMSCopy(item);
+
+ ((IInventory) beaconField.get(this)).setItem(0, itemStack);
+ } catch (IllegalAccessException exception) {
+ throw new RuntimeException(exception);
+ }
+ }
+
+ @NotNull
+ @Override
+ public CraftInventoryView getBukkitView() {
+ if (bukkitEntity == null) {
+ try {
+ CraftInventory inventory = new CraftInventoryBeacon((IInventory) beaconField.get(this)) {
+ @NotNull
+ @Contract(pure = true)
+ @Override
+ public InventoryHolder getHolder() {
+ return inventoryHolder;
+ }
+ };
+
+ bukkitEntity = new CraftInventoryView(player, inventory, this);
+ } catch (IllegalAccessException exception) {
+ throw new RuntimeException(exception);
+ }
+ }
+
+ return bukkitEntity;
+ }
+
+ @Contract(pure = true, value = "_ -> true")
+ @Override
+ public boolean canUse(@Nullable EntityHuman entityhuman) {
+ return true;
+ }
+
+ @Override
+ public void a(IInventory inventory) {}
+
+ @Override
+ public void b(EntityHuman entityhuman) {}
+
+ }
+}
diff --git a/nms/1_16_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R1/CartographyTableInventoryImpl.java b/nms/1_16_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_1/CartographyTableInventoryImpl.java
similarity index 94%
rename from nms/1_16_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R1/CartographyTableInventoryImpl.java
rename to nms/1_16_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_1/CartographyTableInventoryImpl.java
index e4d3895a0..b80f7bafb 100644
--- a/nms/1_16_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R1/CartographyTableInventoryImpl.java
+++ b/nms/1_16_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_1/CartographyTableInventoryImpl.java
@@ -1,199 +1,201 @@
-package com.github.stefvanschie.inventoryframework.nms.v1_16_R1;
-
-import com.github.stefvanschie.inventoryframework.abstraction.CartographyTableInventory;
-import net.minecraft.server.v1_16_R1.*;
-import org.bukkit.craftbukkit.v1_16_R1.entity.CraftPlayer;
-import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftInventory;
-import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftInventoryCartography;
-import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftInventoryView;
-import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftItemStack;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.InventoryHolder;
-import org.jetbrains.annotations.Contract;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.lang.reflect.Field;
-
-/**
- * Internal cartography table inventory for 1.16 R1
- *
- * @since 0.8.0
- */
-public class CartographyTableInventoryImpl extends CartographyTableInventory {
-
- public CartographyTableInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
- super(inventoryHolder);
- }
-
- @Override
- public void openInventory(@NotNull Player player, @NotNull String title,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- int itemAmount = items.length;
-
- if (itemAmount != 3) {
- throw new IllegalArgumentException(
- "The amount of items for a cartography table should be 3, but is '" + itemAmount + "'"
- );
- }
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
- ContainerCartographyTableImpl containerCartographyTable = new ContainerCartographyTableImpl(
- entityPlayer, items
- );
-
- entityPlayer.activeContainer = containerCartographyTable;
-
- int id = containerCartographyTable.windowId;
- ChatMessage message = new ChatMessage(title);
- PacketPlayOutOpenWindow packet = new PacketPlayOutOpenWindow(id, Containers.CARTOGRAPHY_TABLE, message);
-
- entityPlayer.playerConnection.sendPacket(packet);
-
- sendItems(player, items);
- }
-
- @Override
- public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
- NonNullList nmsItems = NonNullList.a(
- ItemStack.b,
- CraftItemStack.asNMSCopy(items[0]),
- CraftItemStack.asNMSCopy(items[1]),
- CraftItemStack.asNMSCopy(items[2])
- );
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
- }
-
- @Override
- public void clearCursor(@NotNull Player player) {
- getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.b));
- }
-
- /**
- * Gets the window id for the inventory view the player currently has open
- *
- * @param entityPlayer the player to get the window id for
- * @return the window id
- * @since 0.8.0
- */
- @Contract(pure = true)
- private int getWindowId(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.activeContainer.windowId;
- }
-
- /**
- * Gets the player connection for the specified player
- *
- * @param entityPlayer the player to get the player connection from
- * @return the player connection
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.playerConnection;
- }
-
- /**
- * Gets the entity player associated to this player
- *
- * @param player the player to get the entity player from
- * @return the entity player
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private EntityPlayer getEntityPlayer(@NotNull Player player) {
- return ((CraftPlayer) player).getHandle();
- }
-
- /**
- * A custom container cartography table
- *
- * @since 0.8.0
- */
- private class ContainerCartographyTableImpl extends ContainerCartography {
-
- /**
- * The player for this cartography table container
- */
- @NotNull
- private final Player player;
-
- /**
- * The internal bukkit entity for this container cartography table
- */
- @Nullable
- private CraftInventoryView bukkitEntity;
-
- /**
- * Field for accessing the result inventory field
- */
- @NotNull
- private final Field resultInventoryField;
-
- public ContainerCartographyTableImpl(@NotNull EntityPlayer entityPlayer,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
-
- this.player = entityPlayer.getBukkitEntity();
-
- try {
- this.resultInventoryField = ContainerCartography.class.getDeclaredField("resultInventory");
- this.resultInventoryField.setAccessible(true);
- } catch (NoSuchFieldException exception) {
- throw new RuntimeException(exception);
- }
-
- inventory.setItem(0, CraftItemStack.asNMSCopy(items[0]));
- inventory.setItem(1, CraftItemStack.asNMSCopy(items[1]));
-
- getResultInventory().setItem(0, CraftItemStack.asNMSCopy(items[2]));
- }
-
- @NotNull
- @Override
- public CraftInventoryView getBukkitView() {
- if (bukkitEntity == null) {
- CraftInventory inventory = new CraftInventoryCartography(super.inventory, getResultInventory()) {
- @NotNull
- @Contract(pure = true)
- @Override
- public InventoryHolder getHolder() {
- return inventoryHolder;
- }
- };
-
- bukkitEntity = new CraftInventoryView(player, inventory, this);
- }
-
- return bukkitEntity;
- }
-
- @Contract(pure = true, value = "_ -> true")
- @Override
- public boolean canUse(@Nullable EntityHuman entityhuman) {
- return true;
- }
-
- @Override
- public void a(IInventory inventory) {}
-
- @Override
- public void b(EntityHuman entityhuman) {}
-
- @NotNull
- @Contract(pure = true)
- private IInventory getResultInventory() {
- try {
- return (IInventory) resultInventoryField.get(this);
- } catch (IllegalAccessException exception) {
- throw new RuntimeException(exception);
- }
- }
-
- }
-}
+package com.github.stefvanschie.inventoryframework.nms.v1_16_1;
+
+import com.github.stefvanschie.inventoryframework.abstraction.CartographyTableInventory;
+import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
+import com.github.stefvanschie.inventoryframework.nms.v1_16_1.util.TextHolderUtil;
+import net.minecraft.server.v1_16_R1.*;
+import org.bukkit.craftbukkit.v1_16_R1.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftInventory;
+import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftInventoryCartography;
+import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftInventoryView;
+import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftItemStack;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.InventoryHolder;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.lang.reflect.Field;
+
+/**
+ * Internal cartography table inventory for 1.16 R1
+ *
+ * @since 0.8.0
+ */
+public class CartographyTableInventoryImpl extends CartographyTableInventory {
+
+ public CartographyTableInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
+ super(inventoryHolder);
+ }
+
+ @Override
+ public void openInventory(@NotNull Player player, @NotNull TextHolder title,
+ @Nullable org.bukkit.inventory.ItemStack[] items) {
+ int itemAmount = items.length;
+
+ if (itemAmount != 3) {
+ throw new IllegalArgumentException(
+ "The amount of items for a cartography table should be 3, but is '" + itemAmount + "'"
+ );
+ }
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+ ContainerCartographyTableImpl containerCartographyTable = new ContainerCartographyTableImpl(
+ entityPlayer, items
+ );
+
+ entityPlayer.activeContainer = containerCartographyTable;
+
+ int id = containerCartographyTable.windowId;
+ IChatBaseComponent message = TextHolderUtil.toComponent(title);
+ PacketPlayOutOpenWindow packet = new PacketPlayOutOpenWindow(id, Containers.CARTOGRAPHY_TABLE, message);
+
+ entityPlayer.playerConnection.sendPacket(packet);
+
+ sendItems(player, items);
+ }
+
+ @Override
+ public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
+ NonNullList nmsItems = NonNullList.a(
+ ItemStack.b,
+ CraftItemStack.asNMSCopy(items[0]),
+ CraftItemStack.asNMSCopy(items[1]),
+ CraftItemStack.asNMSCopy(items[2])
+ );
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
+ }
+
+ @Override
+ public void clearCursor(@NotNull Player player) {
+ getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.b));
+ }
+
+ /**
+ * Gets the window id for the inventory view the player currently has open
+ *
+ * @param entityPlayer the player to get the window id for
+ * @return the window id
+ * @since 0.8.0
+ */
+ @Contract(pure = true)
+ private int getWindowId(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.activeContainer.windowId;
+ }
+
+ /**
+ * Gets the player connection for the specified player
+ *
+ * @param entityPlayer the player to get the player connection from
+ * @return the player connection
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.playerConnection;
+ }
+
+ /**
+ * Gets the entity player associated to this player
+ *
+ * @param player the player to get the entity player from
+ * @return the entity player
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private EntityPlayer getEntityPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * A custom container cartography table
+ *
+ * @since 0.8.0
+ */
+ private class ContainerCartographyTableImpl extends ContainerCartography {
+
+ /**
+ * The player for this cartography table container
+ */
+ @NotNull
+ private final Player player;
+
+ /**
+ * The internal bukkit entity for this container cartography table
+ */
+ @Nullable
+ private CraftInventoryView bukkitEntity;
+
+ /**
+ * Field for accessing the result inventory field
+ */
+ @NotNull
+ private final Field resultInventoryField;
+
+ public ContainerCartographyTableImpl(@NotNull EntityPlayer entityPlayer,
+ @Nullable org.bukkit.inventory.ItemStack[] items) {
+ super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
+
+ this.player = entityPlayer.getBukkitEntity();
+
+ try {
+ this.resultInventoryField = ContainerCartography.class.getDeclaredField("resultInventory");
+ this.resultInventoryField.setAccessible(true);
+ } catch (NoSuchFieldException exception) {
+ throw new RuntimeException(exception);
+ }
+
+ inventory.setItem(0, CraftItemStack.asNMSCopy(items[0]));
+ inventory.setItem(1, CraftItemStack.asNMSCopy(items[1]));
+
+ getResultInventory().setItem(0, CraftItemStack.asNMSCopy(items[2]));
+ }
+
+ @NotNull
+ @Override
+ public CraftInventoryView getBukkitView() {
+ if (bukkitEntity == null) {
+ CraftInventory inventory = new CraftInventoryCartography(super.inventory, getResultInventory()) {
+ @NotNull
+ @Contract(pure = true)
+ @Override
+ public InventoryHolder getHolder() {
+ return inventoryHolder;
+ }
+ };
+
+ bukkitEntity = new CraftInventoryView(player, inventory, this);
+ }
+
+ return bukkitEntity;
+ }
+
+ @Contract(pure = true, value = "_ -> true")
+ @Override
+ public boolean canUse(@Nullable EntityHuman entityhuman) {
+ return true;
+ }
+
+ @Override
+ public void a(IInventory inventory) {}
+
+ @Override
+ public void b(EntityHuman entityhuman) {}
+
+ @NotNull
+ @Contract(pure = true)
+ private IInventory getResultInventory() {
+ try {
+ return (IInventory) resultInventoryField.get(this);
+ } catch (IllegalAccessException exception) {
+ throw new RuntimeException(exception);
+ }
+ }
+
+ }
+}
diff --git a/nms/1_16_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R1/EnchantingTableInventoryImpl.java b/nms/1_16_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_1/EnchantingTableInventoryImpl.java
similarity index 94%
rename from nms/1_16_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R1/EnchantingTableInventoryImpl.java
rename to nms/1_16_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_1/EnchantingTableInventoryImpl.java
index 901cceb5e..73a9c5f62 100644
--- a/nms/1_16_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R1/EnchantingTableInventoryImpl.java
+++ b/nms/1_16_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_1/EnchantingTableInventoryImpl.java
@@ -1,194 +1,196 @@
-package com.github.stefvanschie.inventoryframework.nms.v1_16_R1;
-
-import com.github.stefvanschie.inventoryframework.abstraction.EnchantingTableInventory;
-import net.minecraft.server.v1_16_R1.*;
-import org.bukkit.craftbukkit.v1_16_R1.entity.CraftPlayer;
-import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftInventory;
-import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftInventoryEnchanting;
-import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftInventoryView;
-import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftItemStack;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.InventoryHolder;
-import org.jetbrains.annotations.Contract;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.lang.reflect.Field;
-
-/**
- * Internal enchanting table inventory for 1.16 R1
- *
- * @since 0.8.0
- */
-public class EnchantingTableInventoryImpl extends EnchantingTableInventory {
-
- public EnchantingTableInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
- super(inventoryHolder);
- }
-
- @Override
- public void openInventory(@NotNull Player player, @NotNull String title,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- int itemAmount = items.length;
-
- if (itemAmount != 2) {
- throw new IllegalArgumentException(
- "The amount of items for an enchanting table should be 2, but is '" + itemAmount + "'"
- );
- }
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
- ContainerEnchantingTableImpl containerEnchantmentTable = new ContainerEnchantingTableImpl(entityPlayer, items);
-
- entityPlayer.activeContainer = containerEnchantmentTable;
-
- int id = containerEnchantmentTable.windowId;
- ChatMessage message = new ChatMessage(title);
- PacketPlayOutOpenWindow packet = new PacketPlayOutOpenWindow(id, Containers.ENCHANTMENT, message);
-
- entityPlayer.playerConnection.sendPacket(packet);
-
- sendItems(player, items);
- }
-
- @Override
- public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
- NonNullList nmsItems = NonNullList.a(
- ItemStack.b,
- CraftItemStack.asNMSCopy(items[0]),
- CraftItemStack.asNMSCopy(items[1])
- );
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
- }
-
- @Override
- public void clearCursor(@NotNull Player player) {
- getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.b));
- }
-
- /**
- * Gets the window id for the inventory view the player currently has open
- *
- * @param entityPlayer the player to get the window id for
- * @return the window id
- * @since 0.8.0
- */
- @Contract(pure = true)
- private int getWindowId(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.activeContainer.windowId;
- }
-
- /**
- * Gets the player connection for the specified player
- *
- * @param entityPlayer the player to get the player connection from
- * @return the player connection
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.playerConnection;
- }
-
- /**
- * Gets the entity player associated to this player
- *
- * @param player the player to get the entity player from
- * @return the entity player
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private EntityPlayer getEntityPlayer(@NotNull Player player) {
- return ((CraftPlayer) player).getHandle();
- }
-
- /**
- * A custom container enchanting table
- *
- * @since 0.8.0
- */
- private class ContainerEnchantingTableImpl extends ContainerEnchantTable {
-
- /**
- * The player for this enchanting table container
- */
- @NotNull
- private final Player player;
-
- /**
- * The internal bukkit entity for this container enchanting table
- */
- @Nullable
- private CraftInventoryView bukkitEntity;
-
- /**
- * Field for accessing the enchant slots field
- */
- @NotNull
- private final Field enchantSlotsField;
-
- public ContainerEnchantingTableImpl(@NotNull EntityPlayer entityPlayer,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
-
- this.player = entityPlayer.getBukkitEntity();
-
- try {
- this.enchantSlotsField = ContainerEnchantTable.class.getDeclaredField("enchantSlots");
- this.enchantSlotsField.setAccessible(true);
- } catch (NoSuchFieldException exception) {
- throw new RuntimeException(exception);
- }
-
- try {
- IInventory input = (IInventory) enchantSlotsField.get(this);
-
- input.setItem(0, CraftItemStack.asNMSCopy(items[0]));
- input.setItem(1, CraftItemStack.asNMSCopy(items[1]));
- } catch (IllegalAccessException e) {
- e.printStackTrace();
- }
- }
-
- @NotNull
- @Override
- public CraftInventoryView getBukkitView() {
- if (bukkitEntity == null) {
- try {
- CraftInventory inventory = new CraftInventoryEnchanting((IInventory) enchantSlotsField.get(this)) {
- @NotNull
- @Contract(pure = true)
- @Override
- public InventoryHolder getHolder() {
- return inventoryHolder;
- }
- };
-
- bukkitEntity = new CraftInventoryView(player, inventory, this);
- } catch (IllegalAccessException exception) {
- exception.printStackTrace();
- }
- }
-
- return bukkitEntity;
- }
-
- @Contract(pure = true, value = "_ -> true")
- @Override
- public boolean canUse(@Nullable EntityHuman entityhuman) {
- return true;
- }
-
- @Override
- public void a(IInventory inventory) {}
-
- @Override
- public void b(EntityHuman entityhuman) {}
-
- }
-}
+package com.github.stefvanschie.inventoryframework.nms.v1_16_1;
+
+import com.github.stefvanschie.inventoryframework.abstraction.EnchantingTableInventory;
+import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
+import com.github.stefvanschie.inventoryframework.nms.v1_16_1.util.TextHolderUtil;
+import net.minecraft.server.v1_16_R1.*;
+import org.bukkit.craftbukkit.v1_16_R1.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftInventory;
+import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftInventoryEnchanting;
+import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftInventoryView;
+import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftItemStack;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.InventoryHolder;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.lang.reflect.Field;
+
+/**
+ * Internal enchanting table inventory for 1.16 R1
+ *
+ * @since 0.8.0
+ */
+public class EnchantingTableInventoryImpl extends EnchantingTableInventory {
+
+ public EnchantingTableInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
+ super(inventoryHolder);
+ }
+
+ @Override
+ public void openInventory(@NotNull Player player, @NotNull TextHolder title,
+ @Nullable org.bukkit.inventory.ItemStack[] items) {
+ int itemAmount = items.length;
+
+ if (itemAmount != 2) {
+ throw new IllegalArgumentException(
+ "The amount of items for an enchanting table should be 2, but is '" + itemAmount + "'"
+ );
+ }
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+ ContainerEnchantingTableImpl containerEnchantmentTable = new ContainerEnchantingTableImpl(entityPlayer, items);
+
+ entityPlayer.activeContainer = containerEnchantmentTable;
+
+ int id = containerEnchantmentTable.windowId;
+ IChatBaseComponent message = TextHolderUtil.toComponent(title);
+ PacketPlayOutOpenWindow packet = new PacketPlayOutOpenWindow(id, Containers.ENCHANTMENT, message);
+
+ entityPlayer.playerConnection.sendPacket(packet);
+
+ sendItems(player, items);
+ }
+
+ @Override
+ public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
+ NonNullList nmsItems = NonNullList.a(
+ ItemStack.b,
+ CraftItemStack.asNMSCopy(items[0]),
+ CraftItemStack.asNMSCopy(items[1])
+ );
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
+ }
+
+ @Override
+ public void clearCursor(@NotNull Player player) {
+ getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.b));
+ }
+
+ /**
+ * Gets the window id for the inventory view the player currently has open
+ *
+ * @param entityPlayer the player to get the window id for
+ * @return the window id
+ * @since 0.8.0
+ */
+ @Contract(pure = true)
+ private int getWindowId(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.activeContainer.windowId;
+ }
+
+ /**
+ * Gets the player connection for the specified player
+ *
+ * @param entityPlayer the player to get the player connection from
+ * @return the player connection
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.playerConnection;
+ }
+
+ /**
+ * Gets the entity player associated to this player
+ *
+ * @param player the player to get the entity player from
+ * @return the entity player
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private EntityPlayer getEntityPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * A custom container enchanting table
+ *
+ * @since 0.8.0
+ */
+ private class ContainerEnchantingTableImpl extends ContainerEnchantTable {
+
+ /**
+ * The player for this enchanting table container
+ */
+ @NotNull
+ private final Player player;
+
+ /**
+ * The internal bukkit entity for this container enchanting table
+ */
+ @Nullable
+ private CraftInventoryView bukkitEntity;
+
+ /**
+ * Field for accessing the enchant slots field
+ */
+ @NotNull
+ private final Field enchantSlotsField;
+
+ public ContainerEnchantingTableImpl(@NotNull EntityPlayer entityPlayer,
+ @Nullable org.bukkit.inventory.ItemStack[] items) {
+ super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
+
+ this.player = entityPlayer.getBukkitEntity();
+
+ try {
+ this.enchantSlotsField = ContainerEnchantTable.class.getDeclaredField("enchantSlots");
+ this.enchantSlotsField.setAccessible(true);
+ } catch (NoSuchFieldException exception) {
+ throw new RuntimeException(exception);
+ }
+
+ try {
+ IInventory input = (IInventory) enchantSlotsField.get(this);
+
+ input.setItem(0, CraftItemStack.asNMSCopy(items[0]));
+ input.setItem(1, CraftItemStack.asNMSCopy(items[1]));
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @NotNull
+ @Override
+ public CraftInventoryView getBukkitView() {
+ if (bukkitEntity == null) {
+ try {
+ CraftInventory inventory = new CraftInventoryEnchanting((IInventory) enchantSlotsField.get(this)) {
+ @NotNull
+ @Contract(pure = true)
+ @Override
+ public InventoryHolder getHolder() {
+ return inventoryHolder;
+ }
+ };
+
+ bukkitEntity = new CraftInventoryView(player, inventory, this);
+ } catch (IllegalAccessException exception) {
+ exception.printStackTrace();
+ }
+ }
+
+ return bukkitEntity;
+ }
+
+ @Contract(pure = true, value = "_ -> true")
+ @Override
+ public boolean canUse(@Nullable EntityHuman entityhuman) {
+ return true;
+ }
+
+ @Override
+ public void a(IInventory inventory) {}
+
+ @Override
+ public void b(EntityHuman entityhuman) {}
+
+ }
+}
diff --git a/nms/1_16_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_1/GrindstoneInventoryImpl.java b/nms/1_16_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_1/GrindstoneInventoryImpl.java
new file mode 100644
index 000000000..c349af46c
--- /dev/null
+++ b/nms/1_16_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_1/GrindstoneInventoryImpl.java
@@ -0,0 +1,268 @@
+package com.github.stefvanschie.inventoryframework.nms.v1_16_1;
+
+import com.github.stefvanschie.inventoryframework.abstraction.GrindstoneInventory;
+import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
+import com.github.stefvanschie.inventoryframework.nms.v1_16_1.util.TextHolderUtil;
+import net.minecraft.server.v1_16_R1.*;
+import org.bukkit.craftbukkit.v1_16_R1.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_16_R1.event.CraftEventFactory;
+import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftItemStack;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.InventoryHolder;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.lang.reflect.Field;
+import java.util.Collections;
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * Internal grindstone inventory for 1.16 R1
+ *
+ * @since 0.8.0
+ */
+public class GrindstoneInventoryImpl extends GrindstoneInventory {
+
+ public GrindstoneInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
+ super(inventoryHolder);
+ }
+
+ @Override
+ public Inventory openInventory(@NotNull Player player, @NotNull TextHolder title,
+ @Nullable org.bukkit.inventory.ItemStack[] items) {
+ int itemAmount = items.length;
+
+ if (itemAmount != 3) {
+ throw new IllegalArgumentException(
+ "The amount of items for a grindstone should be 3, but is '" + itemAmount + "'"
+ );
+ }
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ //ignore deprecation: superseding method is only available on Paper
+ //noinspection deprecation
+ CraftEventFactory.handleInventoryCloseEvent(entityPlayer);
+
+ entityPlayer.activeContainer = entityPlayer.defaultContainer;
+
+ IChatBaseComponent message = TextHolderUtil.toComponent(title);
+ ContainerGrindstoneImpl containerGrindstone = new ContainerGrindstoneImpl(entityPlayer);
+
+ Inventory inventory = containerGrindstone.getBukkitView().getTopInventory();
+
+ inventory.setItem(0, items[0]);
+ inventory.setItem(1, items[1]);
+ inventory.setItem(2, items[2]);
+
+ int windowId = containerGrindstone.getWindowId();
+
+ entityPlayer.playerConnection.sendPacket(new PacketPlayOutOpenWindow(windowId, Containers.GRINDSTONE, message));
+ entityPlayer.activeContainer = containerGrindstone;
+ entityPlayer.syncInventory();
+
+ return inventory;
+ }
+
+ @Override
+ public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items,
+ @Nullable org.bukkit.inventory.ItemStack cursor) {
+ NonNullList nmsItems = NonNullList.a(
+ ItemStack.b,
+ CraftItemStack.asNMSCopy(items[0]),
+ CraftItemStack.asNMSCopy(items[1]),
+ CraftItemStack.asNMSCopy(items[2])
+ );
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
+ }
+
+ @Override
+ public void clearCursor(@NotNull Player player) {
+ getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.b));
+ }
+
+ /**
+ * Gets the window id for the inventory view the player currently has open
+ *
+ * @param entityPlayer the player to get the window id for
+ * @return the window id
+ * @since 0.8.0
+ */
+ @Contract(pure = true)
+ private int getWindowId(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.activeContainer.windowId;
+ }
+
+ /**
+ * Gets the player connection for the specified player
+ *
+ * @param entityPlayer the player to get the player connection from
+ * @return the player connection
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.playerConnection;
+ }
+
+ /**
+ * Gets the entity player associated to this player
+ *
+ * @param player the player to get the entity player from
+ * @return the entity player
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private EntityPlayer getEntityPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * A custom container grindstone
+ *
+ * @since 0.8.0
+ */
+ private static class ContainerGrindstoneImpl extends ContainerGrindstone {
+
+ /**
+ * A unique item
+ */
+ @NotNull
+ private final ItemStack uniqueItem;
+
+ /**
+ * The field containing the listeners for this container
+ */
+ @NotNull
+ private final Field listenersField;
+
+ /**
+ * Creates a new grindstone container
+ *
+ * @param entityPlayer the player for whom this container should be opened
+ * @since 0.10.8
+ */
+ public ContainerGrindstoneImpl(@NotNull EntityPlayer entityPlayer) {
+ super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
+
+ try {
+ this.listenersField = Container.class.getDeclaredField("listeners");
+ this.listenersField.setAccessible(true);
+ } catch (NoSuchFieldException exception) {
+ throw new RuntimeException("Unable to access field 'listeners'", exception);
+ }
+
+ Slot firstSlot = this.slots.get(0);
+ Slot secondSlot = this.slots.get(1);
+ Slot thirdSlot = this.slots.get(2);
+
+ this.slots.set(0, new Slot(firstSlot.inventory, firstSlot.rawSlotIndex, firstSlot.e, firstSlot.f) {
+ @Override
+ public boolean isAllowed(ItemStack stack) {
+ return true;
+ }
+ });
+
+ this.slots.set(1, new Slot(secondSlot.inventory, secondSlot.rawSlotIndex, secondSlot.e, secondSlot.f) {
+ @Override
+ public boolean isAllowed(ItemStack stack) {
+ return true;
+ }
+ });
+
+ this.slots.set(2, new Slot(thirdSlot.inventory, thirdSlot.rawSlotIndex, thirdSlot.e, thirdSlot.f) {
+ @Override
+ public boolean isAllowed(ItemStack stack) {
+ return true;
+ }
+
+ @Override
+ public ItemStack a(EntityHuman entityHuman, ItemStack itemStack) {
+ return itemStack;
+ }
+ });
+
+ this.uniqueItem = new ItemStack(Items.COOKIE);
+
+ //to make the item unique, we add a random uuid as nbt to it
+ UUID uuid = UUID.randomUUID();
+ NBTTagCompound nbtTagCompound = new NBTTagCompound();
+
+ nbtTagCompound.set("uuid", new NBTTagLongArray(new long [] {
+ uuid.getLeastSignificantBits(),
+ uuid.getMostSignificantBits()
+ }));
+
+ this.uniqueItem.setTag(nbtTagCompound);
+ }
+
+ /**
+ * Forcefully updates the client state, sending all items, container properties and the held item.
+ *
+ * @since 0.10.8
+ */
+ public void forceUpdate() {
+ /*
+ The server will not send the items when they haven't changed, so we will overwrite every item with a unique
+ item first to ensure the server is going to send our items.
+ */
+ Collections.fill(this.items, this.uniqueItem);
+
+ notifyListeners();
+
+ List extends ICrafting> listeners;
+
+ try {
+ //noinspection unchecked
+ listeners = (List extends ICrafting>) listenersField.get(this);
+ } catch (IllegalAccessException exception) {
+ throw new RuntimeException("Unable to access field 'listeners'", exception);
+ }
+
+ for (ICrafting listener : listeners) {
+ if (!(listener instanceof EntityPlayer)) {
+ continue;
+ }
+
+ EntityPlayer player = (EntityPlayer) listener;
+
+ player.e = false;
+ player.broadcastCarriedItem();
+ }
+ }
+
+ @Override
+ public ItemStack a(int i, int j, InventoryClickType inventoryclicktype, EntityHuman entityhuman) {
+ ItemStack itemStack = super.a(i, j, inventoryclicktype, entityhuman);
+
+ //the client predicts the allowed movement of the item, so we broadcast the state again to override it
+ forceUpdate();
+
+ return itemStack;
+ }
+
+ @Contract(pure = true, value = "_ -> true")
+ @Override
+ public boolean canUse(@Nullable EntityHuman entityHuman) {
+ return true;
+ }
+
+ @Override
+ public void a(IInventory inventory) {}
+
+ @Override
+ public void b(EntityHuman entityHuman) {}
+
+ public int getWindowId() {
+ return this.windowId;
+ }
+ }
+}
diff --git a/nms/1_16_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_1/MerchantInventoryImpl.java b/nms/1_16_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_1/MerchantInventoryImpl.java
new file mode 100644
index 000000000..b54526b3e
--- /dev/null
+++ b/nms/1_16_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_1/MerchantInventoryImpl.java
@@ -0,0 +1,95 @@
+package com.github.stefvanschie.inventoryframework.nms.v1_16_1;
+
+import com.github.stefvanschie.inventoryframework.abstraction.MerchantInventory;
+import net.minecraft.server.v1_16_R1.EntityPlayer;
+import net.minecraft.server.v1_16_R1.MerchantRecipeList;
+import org.bukkit.craftbukkit.v1_16_R1.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftItemStack;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.MerchantRecipe;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Internal merchant inventory for 1.16.1
+ *
+ * @since 0.10.1
+ */
+public class MerchantInventoryImpl extends MerchantInventory {
+
+ @Override
+ public void sendMerchantOffers(@NotNull Player player,
+ @NotNull List extends Map.Entry extends MerchantRecipe, ? extends Integer>> trades,
+ int level, int experience) {
+ MerchantRecipeList offers = new MerchantRecipeList();
+
+ for (Map.Entry extends MerchantRecipe, ? extends Integer> entry : trades) {
+ MerchantRecipe recipe = entry.getKey();
+ List ingredients = recipe.getIngredients();
+
+ if (ingredients.size() < 1) {
+ throw new IllegalStateException("Merchant recipe has no ingredients");
+ }
+
+ ItemStack itemA = ingredients.get(0);
+ ItemStack itemB = null;
+
+ if (ingredients.size() >= 2) {
+ itemB = ingredients.get(1);
+ }
+
+ net.minecraft.server.v1_16_R1.ItemStack nmsItemA = CraftItemStack.asNMSCopy(itemA);
+ net.minecraft.server.v1_16_R1.ItemStack nmsItemB = net.minecraft.server.v1_16_R1.ItemStack.b;
+ net.minecraft.server.v1_16_R1.ItemStack nmsItemResult = CraftItemStack.asNMSCopy(recipe.getResult());
+
+ if (itemB != null) {
+ nmsItemB = CraftItemStack.asNMSCopy(itemB);
+ }
+
+ int uses = recipe.getUses();
+ int maxUses = recipe.getMaxUses();
+ int exp = recipe.getVillagerExperience();
+ float multiplier = recipe.getPriceMultiplier();
+
+ net.minecraft.server.v1_16_R1.MerchantRecipe merchantOffer = new net.minecraft.server.v1_16_R1.MerchantRecipe(
+ nmsItemA, nmsItemB, nmsItemResult, uses, maxUses, exp, multiplier
+ );
+ merchantOffer.setSpecialPrice(entry.getValue());
+
+ offers.add(merchantOffer);
+ }
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ entityPlayer.openTrade(getWindowId(entityPlayer), offers, level, experience, true, false);
+ }
+
+ /**
+ * Gets the entity player associated to this player
+ *
+ * @param player the player to get the entity player from
+ * @return the entity player
+ * @since 0.10.1
+ */
+ @NotNull
+ @Contract(pure = true)
+ private EntityPlayer getEntityPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * Gets the window id for the inventory view the player currently has open
+ *
+ * @param entityPlayer the player to get the window id for
+ * @return the window id
+ * @since 0.10.1
+ */
+ @Contract(pure = true)
+ private int getWindowId(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.activeContainer.windowId;
+ }
+}
diff --git a/nms/1_16_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R1/SmithingTableInventoryImpl.java b/nms/1_16_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_1/SmithingTableInventoryImpl.java
similarity index 91%
rename from nms/1_16_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R1/SmithingTableInventoryImpl.java
rename to nms/1_16_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_1/SmithingTableInventoryImpl.java
index c9e30f97c..d662e556c 100644
--- a/nms/1_16_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R1/SmithingTableInventoryImpl.java
+++ b/nms/1_16_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_1/SmithingTableInventoryImpl.java
@@ -1,226 +1,233 @@
-package com.github.stefvanschie.inventoryframework.nms.v1_16_R1;
-
-import com.github.stefvanschie.inventoryframework.abstraction.SmithingTableInventory;
-import net.minecraft.server.v1_16_R1.*;
-import org.bukkit.craftbukkit.v1_16_R1.entity.CraftPlayer;
-import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftInventory;
-import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftInventorySmithing;
-import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftInventoryView;
-import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftItemStack;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.InventoryHolder;
-import org.jetbrains.annotations.Contract;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-/**
- * Internal smithing table inventory for 1.16 R1
- *
- * @since 0.8.0
- */
-public class SmithingTableInventoryImpl extends SmithingTableInventory {
-
- public SmithingTableInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
- super(inventoryHolder);
- }
-
- @Override
- public void openInventory(@NotNull Player player, @NotNull String title,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- int itemAmount = items.length;
-
- if (itemAmount != 3) {
- throw new IllegalArgumentException(
- "The amount of items for a stonecutter should be 3, but is '" + itemAmount + "'"
- );
- }
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
- ContainerSmithingTableImpl containerSmithingTable = new ContainerSmithingTableImpl(entityPlayer, items);
-
- entityPlayer.activeContainer = containerSmithingTable;
-
- int id = containerSmithingTable.windowId;
- ChatMessage message = new ChatMessage(title);
- PacketPlayOutOpenWindow packet = new PacketPlayOutOpenWindow(id, Containers.SMITHING, message);
-
- entityPlayer.playerConnection.sendPacket(packet);
-
- sendItems(player, items);
- }
-
- @Override
- public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
- NonNullList nmsItems = NonNullList.a(
- ItemStack.b,
- CraftItemStack.asNMSCopy(items[0]),
- CraftItemStack.asNMSCopy(items[1]),
- CraftItemStack.asNMSCopy(items[2])
- );
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
- }
-
- @Override
- public void sendFirstItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
- EntityPlayer entityPlayer = getEntityPlayer(player);
- ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutSetSlot(getWindowId(entityPlayer), 0, nmsItem));
- }
-
- @Override
- public void sendSecondItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
- EntityPlayer entityPlayer = getEntityPlayer(player);
- ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutSetSlot(getWindowId(entityPlayer), 1, nmsItem));
- }
-
- @Override
- public void sendResultItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
- sendResultItem(player, CraftItemStack.asNMSCopy(item));
- }
-
- @Override
- public void clearResultItem(@NotNull Player player) {
- sendResultItem(player, ItemStack.b);
- }
-
- @Override
- public void setCursor(@NotNull Player player, @NotNull org.bukkit.inventory.ItemStack item) {
- setCursor(player, CraftItemStack.asNMSCopy(item));
- }
-
- @Override
- public void clearCursor(@NotNull Player player) {
- getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.b));
- }
-
- /**
- * Sets the cursor of the given player
- *
- * @param player the player to set the cursor
- * @param item the item to set the cursor to
- * @since 0.8.0
- */
- private void setCursor(@NotNull Player player, @NotNull ItemStack item) {
- getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, item));
- }
-
- /**
- * Sends the result item to the specified player with the given item
- *
- * @param player the player to send the result item to
- * @param item the result item
- * @since 0.8.0
- */
- private void sendResultItem(@NotNull Player player, @NotNull ItemStack item) {
- EntityPlayer entityPlayer = getEntityPlayer(player);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutSetSlot(getWindowId(entityPlayer), 2, item));
- }
-
- /**
- * Gets the window id for the inventory view the player currently has open
- *
- * @param entityPlayer the player to get the window id for
- * @return the window id
- * @since 0.8.0
- */
- @Contract(pure = true)
- private int getWindowId(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.activeContainer.windowId;
- }
-
- /**
- * Gets the player connection for the specified player
- *
- * @param entityPlayer the player to get the player connection from
- * @return the player connection
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.playerConnection;
- }
-
- /**
- * Gets the entity player associated to this player
- *
- * @param player the player to get the entity player from
- * @return the entity player
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private EntityPlayer getEntityPlayer(@NotNull Player player) {
- return ((CraftPlayer) player).getHandle();
- }
-
- /**
- * A custom container smithing table
- *
- * @since 0.8.0
- */
- private class ContainerSmithingTableImpl extends ContainerSmithing {
-
- /**
- * The player for this smithing table container
- */
- @NotNull
- private final Player player;
-
- /**
- * The internal bukkit entity for this container smithing table
- */
- @Nullable
- private CraftInventoryView bukkitEntity;
-
- public ContainerSmithingTableImpl(@NotNull EntityPlayer entityPlayer,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- super(entityPlayer.nextContainerCounter(), entityPlayer.inventory,
- ContainerAccess.at(entityPlayer.getWorld(), new BlockPosition(0, 0, 0)));
-
- this.player = entityPlayer.getBukkitEntity();
-
- repairInventory.setItem(0, CraftItemStack.asNMSCopy(items[0]));
- repairInventory.setItem(1, CraftItemStack.asNMSCopy(items[1]));
- resultInventory.setItem(0, CraftItemStack.asNMSCopy(items[2]));
- }
-
- @NotNull
- @Override
- public CraftInventoryView getBukkitView() {
- if (bukkitEntity == null) {
- CraftInventory inventory = new CraftInventorySmithing(repairInventory, resultInventory) {
- @NotNull
- @Contract(pure = true)
- @Override
- public InventoryHolder getHolder() {
- return inventoryHolder;
- }
- };
-
- bukkitEntity = new CraftInventoryView(player, inventory, this);
- }
-
- return bukkitEntity;
- }
-
- @Contract(pure = true, value = "_ -> true")
- @Override
- public boolean canUse(@Nullable EntityHuman entityhuman) {
- return true;
- }
-
- @Override
- public void a(IInventory inventory) {}
-
- @Override
- public void b(EntityHuman entityhuman) {}
- }
-}
+package com.github.stefvanschie.inventoryframework.nms.v1_16_1;
+
+import com.github.stefvanschie.inventoryframework.abstraction.SmithingTableInventory;
+import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
+import com.github.stefvanschie.inventoryframework.nms.v1_16_1.util.TextHolderUtil;
+import net.minecraft.server.v1_16_R1.*;
+import org.bukkit.craftbukkit.v1_16_R1.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftInventory;
+import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftInventorySmithing;
+import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftInventoryView;
+import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftItemStack;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.InventoryHolder;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Internal smithing table inventory for 1.16 R1
+ *
+ * @since 0.8.0
+ */
+public class SmithingTableInventoryImpl extends SmithingTableInventory {
+
+ public SmithingTableInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
+ super(inventoryHolder);
+ }
+
+ @Nullable
+ @Override
+ public Inventory openInventory(@NotNull Player player, @NotNull TextHolder title,
+ @Nullable org.bukkit.inventory.ItemStack[] items) {
+ int itemAmount = items.length;
+
+ if (itemAmount != 3) {
+ throw new IllegalArgumentException(
+ "The amount of items for a stonecutter should be 3, but is '" + itemAmount + "'"
+ );
+ }
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+ ContainerSmithingTableImpl containerSmithingTable = new ContainerSmithingTableImpl(entityPlayer, items);
+
+ entityPlayer.activeContainer = containerSmithingTable;
+
+ int id = containerSmithingTable.windowId;
+ IChatBaseComponent message = TextHolderUtil.toComponent(title);
+ PacketPlayOutOpenWindow packet = new PacketPlayOutOpenWindow(id, Containers.SMITHING, message);
+
+ entityPlayer.playerConnection.sendPacket(packet);
+
+ sendItems(player, items, null);
+
+ return null;
+ }
+
+ @Override
+ public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items,
+ @Nullable org.bukkit.inventory.ItemStack cursor) {
+ NonNullList nmsItems = NonNullList.a(
+ ItemStack.b,
+ CraftItemStack.asNMSCopy(items[0]),
+ CraftItemStack.asNMSCopy(items[1]),
+ CraftItemStack.asNMSCopy(items[2])
+ );
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
+ }
+
+ @Override
+ public void sendFirstItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+ ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutSetSlot(getWindowId(entityPlayer), 0, nmsItem));
+ }
+
+ @Override
+ public void sendSecondItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+ ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutSetSlot(getWindowId(entityPlayer), 1, nmsItem));
+ }
+
+ @Override
+ public void sendResultItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
+ sendResultItem(player, CraftItemStack.asNMSCopy(item));
+ }
+
+ @Override
+ public void clearResultItem(@NotNull Player player) {
+ sendResultItem(player, ItemStack.b);
+ }
+
+ @Override
+ public void setCursor(@NotNull Player player, @NotNull org.bukkit.inventory.ItemStack item) {
+ setCursor(player, CraftItemStack.asNMSCopy(item));
+ }
+
+ @Override
+ public void clearCursor(@NotNull Player player) {
+ getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.b));
+ }
+
+ /**
+ * Sets the cursor of the given player
+ *
+ * @param player the player to set the cursor
+ * @param item the item to set the cursor to
+ * @since 0.8.0
+ */
+ private void setCursor(@NotNull Player player, @NotNull ItemStack item) {
+ getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, item));
+ }
+
+ /**
+ * Sends the result item to the specified player with the given item
+ *
+ * @param player the player to send the result item to
+ * @param item the result item
+ * @since 0.8.0
+ */
+ private void sendResultItem(@NotNull Player player, @NotNull ItemStack item) {
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutSetSlot(getWindowId(entityPlayer), 2, item));
+ }
+
+ /**
+ * Gets the window id for the inventory view the player currently has open
+ *
+ * @param entityPlayer the player to get the window id for
+ * @return the window id
+ * @since 0.8.0
+ */
+ @Contract(pure = true)
+ private int getWindowId(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.activeContainer.windowId;
+ }
+
+ /**
+ * Gets the player connection for the specified player
+ *
+ * @param entityPlayer the player to get the player connection from
+ * @return the player connection
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.playerConnection;
+ }
+
+ /**
+ * Gets the entity player associated to this player
+ *
+ * @param player the player to get the entity player from
+ * @return the entity player
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private EntityPlayer getEntityPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * A custom container smithing table
+ *
+ * @since 0.8.0
+ */
+ private class ContainerSmithingTableImpl extends ContainerSmithing {
+
+ /**
+ * The player for this smithing table container
+ */
+ @NotNull
+ private final Player player;
+
+ /**
+ * The internal bukkit entity for this container smithing table
+ */
+ @Nullable
+ private CraftInventoryView bukkitEntity;
+
+ public ContainerSmithingTableImpl(@NotNull EntityPlayer entityPlayer,
+ @Nullable org.bukkit.inventory.ItemStack[] items) {
+ super(entityPlayer.nextContainerCounter(), entityPlayer.inventory,
+ ContainerAccess.at(entityPlayer.getWorld(), new BlockPosition(0, 0, 0)));
+
+ this.player = entityPlayer.getBukkitEntity();
+
+ repairInventory.setItem(0, CraftItemStack.asNMSCopy(items[0]));
+ repairInventory.setItem(1, CraftItemStack.asNMSCopy(items[1]));
+ resultInventory.setItem(0, CraftItemStack.asNMSCopy(items[2]));
+ }
+
+ @NotNull
+ @Override
+ public CraftInventoryView getBukkitView() {
+ if (bukkitEntity == null) {
+ CraftInventory inventory = new CraftInventorySmithing(repairInventory, resultInventory) {
+ @NotNull
+ @Contract(pure = true)
+ @Override
+ public InventoryHolder getHolder() {
+ return inventoryHolder;
+ }
+ };
+
+ bukkitEntity = new CraftInventoryView(player, inventory, this);
+ }
+
+ return bukkitEntity;
+ }
+
+ @Contract(pure = true, value = "_ -> true")
+ @Override
+ public boolean canUse(@Nullable EntityHuman entityhuman) {
+ return true;
+ }
+
+ @Override
+ public void a(IInventory inventory) {}
+
+ @Override
+ public void b(EntityHuman entityhuman) {}
+ }
+}
diff --git a/nms/1_16_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R1/StonecutterInventoryImpl.java b/nms/1_16_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_1/StonecutterInventoryImpl.java
similarity index 94%
rename from nms/1_16_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R1/StonecutterInventoryImpl.java
rename to nms/1_16_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_1/StonecutterInventoryImpl.java
index 8c76fb843..aa9889fcd 100644
--- a/nms/1_16_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R1/StonecutterInventoryImpl.java
+++ b/nms/1_16_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_1/StonecutterInventoryImpl.java
@@ -1,199 +1,201 @@
-package com.github.stefvanschie.inventoryframework.nms.v1_16_R1;
-
-import com.github.stefvanschie.inventoryframework.abstraction.StonecutterInventory;
-import net.minecraft.server.v1_16_R1.*;
-import org.bukkit.craftbukkit.v1_16_R1.entity.CraftPlayer;
-import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftInventory;
-import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftInventoryStonecutter;
-import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftInventoryView;
-import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftItemStack;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.InventoryHolder;
-import org.jetbrains.annotations.Contract;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.lang.reflect.Field;
-
-/**
- * Internal stonecutter inventory for 1.16 R1
- *
- * @since 0.8.0
- */
-public class StonecutterInventoryImpl extends StonecutterInventory {
-
- public StonecutterInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
- super(inventoryHolder);
- }
-
- @Override
- public void openInventory(@NotNull Player player, @NotNull String title,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- int itemAmount = items.length;
-
- if (itemAmount != 2) {
- throw new IllegalArgumentException(
- "The amount of items for a stonecutter should be 2, but is '" + itemAmount + "'"
- );
- }
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
- ContainerStonecutterImpl containerEnchantmentTable = new ContainerStonecutterImpl(entityPlayer, items);
-
- entityPlayer.activeContainer = containerEnchantmentTable;
-
- int id = containerEnchantmentTable.windowId;
- ChatMessage message = new ChatMessage(title);
- PacketPlayOutOpenWindow packet = new PacketPlayOutOpenWindow(id, Containers.STONECUTTER, message);
-
- entityPlayer.playerConnection.sendPacket(packet);
-
- sendItems(player, items);
- }
-
- @Override
- public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
- NonNullList nmsItems = NonNullList.a(
- ItemStack.b,
- CraftItemStack.asNMSCopy(items[0]),
- CraftItemStack.asNMSCopy(items[1])
- );
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
- }
-
- @Override
- public void clearCursor(@NotNull Player player) {
- getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.b));
- }
-
- /**
- * Gets the window id for the inventory view the player currently has open
- *
- * @param entityPlayer the player to get the window id for
- * @return the window id
- * @since 0.8.0
- */
- @Contract(pure = true)
- private int getWindowId(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.activeContainer.windowId;
- }
-
- /**
- * Gets the player connection for the specified player
- *
- * @param entityPlayer the player to get the player connection from
- * @return the player connection
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.playerConnection;
- }
-
- /**
- * Gets the entity player associated to this player
- *
- * @param player the player to get the entity player from
- * @return the entity player
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private EntityPlayer getEntityPlayer(@NotNull Player player) {
- return ((CraftPlayer) player).getHandle();
- }
-
- /**
- * A custom container enchanting table
- *
- * @since 0.8.0
- */
- private class ContainerStonecutterImpl extends ContainerStonecutter {
-
- /**
- * The player for this enchanting table container
- */
- @NotNull
- private final Player player;
-
- /**
- * The internal bukkit entity for this container enchanting table
- */
- @Nullable
- private CraftInventoryView bukkitEntity;
-
- /**
- * Field for accessing the result inventory field
- */
- @NotNull
- private final Field resultInventoryField;
-
- public ContainerStonecutterImpl(@NotNull EntityPlayer entityPlayer,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
-
- this.player = entityPlayer.getBukkitEntity();
-
- try {
- this.resultInventoryField = ContainerStonecutter.class.getDeclaredField("resultInventory");
- this.resultInventoryField.setAccessible(true);
- } catch (NoSuchFieldException exception) {
- throw new RuntimeException(exception);
- }
-
- inventory.setItem(0, CraftItemStack.asNMSCopy(items[0]));
- getResultInventory().setItem(0, CraftItemStack.asNMSCopy(items[1]));
- }
-
- @NotNull
- @Override
- public CraftInventoryView getBukkitView() {
- if (bukkitEntity == null) {
- CraftInventory inventory = new CraftInventoryStonecutter(this.inventory, getResultInventory()) {
- @NotNull
- @Contract(pure = true)
- @Override
- public InventoryHolder getHolder() {
- return inventoryHolder;
- }
- };
-
- bukkitEntity = new CraftInventoryView(player, inventory, this);
- }
-
- return bukkitEntity;
- }
-
- @Contract(pure = true, value = "_ -> true")
- @Override
- public boolean canUse(@Nullable EntityHuman entityhuman) {
- return true;
- }
-
- @Override
- public void a(IInventory inventory) {}
-
- @Override
- public void b(EntityHuman entityhuman) {}
-
- /**
- * Gets the result inventory
- *
- * @return the result inventory
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- public IInventory getResultInventory() {
- try {
- return (IInventory) resultInventoryField.get(this);
- } catch (IllegalAccessException exception) {
- throw new RuntimeException(exception);
- }
- }
- }
-}
+package com.github.stefvanschie.inventoryframework.nms.v1_16_1;
+
+import com.github.stefvanschie.inventoryframework.abstraction.StonecutterInventory;
+import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
+import com.github.stefvanschie.inventoryframework.nms.v1_16_1.util.TextHolderUtil;
+import net.minecraft.server.v1_16_R1.*;
+import org.bukkit.craftbukkit.v1_16_R1.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftInventory;
+import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftInventoryStonecutter;
+import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftInventoryView;
+import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftItemStack;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.InventoryHolder;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.lang.reflect.Field;
+
+/**
+ * Internal stonecutter inventory for 1.16 R1
+ *
+ * @since 0.8.0
+ */
+public class StonecutterInventoryImpl extends StonecutterInventory {
+
+ public StonecutterInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
+ super(inventoryHolder);
+ }
+
+ @Override
+ public void openInventory(@NotNull Player player, @NotNull TextHolder title,
+ @Nullable org.bukkit.inventory.ItemStack[] items) {
+ int itemAmount = items.length;
+
+ if (itemAmount != 2) {
+ throw new IllegalArgumentException(
+ "The amount of items for a stonecutter should be 2, but is '" + itemAmount + "'"
+ );
+ }
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+ ContainerStonecutterImpl containerEnchantmentTable = new ContainerStonecutterImpl(entityPlayer, items);
+
+ entityPlayer.activeContainer = containerEnchantmentTable;
+
+ int id = containerEnchantmentTable.windowId;
+ IChatBaseComponent message = TextHolderUtil.toComponent(title);
+ PacketPlayOutOpenWindow packet = new PacketPlayOutOpenWindow(id, Containers.STONECUTTER, message);
+
+ entityPlayer.playerConnection.sendPacket(packet);
+
+ sendItems(player, items);
+ }
+
+ @Override
+ public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
+ NonNullList nmsItems = NonNullList.a(
+ ItemStack.b,
+ CraftItemStack.asNMSCopy(items[0]),
+ CraftItemStack.asNMSCopy(items[1])
+ );
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
+ }
+
+ @Override
+ public void clearCursor(@NotNull Player player) {
+ getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.b));
+ }
+
+ /**
+ * Gets the window id for the inventory view the player currently has open
+ *
+ * @param entityPlayer the player to get the window id for
+ * @return the window id
+ * @since 0.8.0
+ */
+ @Contract(pure = true)
+ private int getWindowId(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.activeContainer.windowId;
+ }
+
+ /**
+ * Gets the player connection for the specified player
+ *
+ * @param entityPlayer the player to get the player connection from
+ * @return the player connection
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.playerConnection;
+ }
+
+ /**
+ * Gets the entity player associated to this player
+ *
+ * @param player the player to get the entity player from
+ * @return the entity player
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private EntityPlayer getEntityPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * A custom container enchanting table
+ *
+ * @since 0.8.0
+ */
+ private class ContainerStonecutterImpl extends ContainerStonecutter {
+
+ /**
+ * The player for this enchanting table container
+ */
+ @NotNull
+ private final Player player;
+
+ /**
+ * The internal bukkit entity for this container enchanting table
+ */
+ @Nullable
+ private CraftInventoryView bukkitEntity;
+
+ /**
+ * Field for accessing the result inventory field
+ */
+ @NotNull
+ private final Field resultInventoryField;
+
+ public ContainerStonecutterImpl(@NotNull EntityPlayer entityPlayer,
+ @Nullable org.bukkit.inventory.ItemStack[] items) {
+ super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
+
+ this.player = entityPlayer.getBukkitEntity();
+
+ try {
+ this.resultInventoryField = ContainerStonecutter.class.getDeclaredField("resultInventory");
+ this.resultInventoryField.setAccessible(true);
+ } catch (NoSuchFieldException exception) {
+ throw new RuntimeException(exception);
+ }
+
+ inventory.setItem(0, CraftItemStack.asNMSCopy(items[0]));
+ getResultInventory().setItem(0, CraftItemStack.asNMSCopy(items[1]));
+ }
+
+ @NotNull
+ @Override
+ public CraftInventoryView getBukkitView() {
+ if (bukkitEntity == null) {
+ CraftInventory inventory = new CraftInventoryStonecutter(this.inventory, getResultInventory()) {
+ @NotNull
+ @Contract(pure = true)
+ @Override
+ public InventoryHolder getHolder() {
+ return inventoryHolder;
+ }
+ };
+
+ bukkitEntity = new CraftInventoryView(player, inventory, this);
+ }
+
+ return bukkitEntity;
+ }
+
+ @Contract(pure = true, value = "_ -> true")
+ @Override
+ public boolean canUse(@Nullable EntityHuman entityhuman) {
+ return true;
+ }
+
+ @Override
+ public void a(IInventory inventory) {}
+
+ @Override
+ public void b(EntityHuman entityhuman) {}
+
+ /**
+ * Gets the result inventory
+ *
+ * @return the result inventory
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ public IInventory getResultInventory() {
+ try {
+ return (IInventory) resultInventoryField.get(this);
+ } catch (IllegalAccessException exception) {
+ throw new RuntimeException(exception);
+ }
+ }
+ }
+}
diff --git a/nms/1_16_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_1/util/TextHolderUtil.java b/nms/1_16_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_1/util/TextHolderUtil.java
new file mode 100644
index 000000000..1e805f59b
--- /dev/null
+++ b/nms/1_16_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_1/util/TextHolderUtil.java
@@ -0,0 +1,66 @@
+package com.github.stefvanschie.inventoryframework.nms.v1_16_1.util;
+
+import com.github.stefvanschie.inventoryframework.adventuresupport.ComponentHolder;
+import com.github.stefvanschie.inventoryframework.adventuresupport.StringHolder;
+import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
+import net.minecraft.server.v1_16_R1.ChatComponentText;
+import net.minecraft.server.v1_16_R1.IChatBaseComponent;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Objects;
+
+/**
+ * A utility class for adding {@link TextHolder} support.
+ *
+ * @since 0.10.0
+ */
+public final class TextHolderUtil {
+
+ private TextHolderUtil() {
+ //private constructor to prevent construction
+ }
+
+ /**
+ * Converts the specified value to a vanilla component.
+ *
+ * @param holder the value to convert
+ * @return the value as a vanilla component
+ * @since 0.10.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ public static IChatBaseComponent toComponent(@NotNull TextHolder holder) {
+ if (holder instanceof StringHolder) {
+ return toComponent((StringHolder) holder);
+ } else {
+ return toComponent((ComponentHolder) holder);
+ }
+ }
+
+ /**
+ * Converts the specified legacy string holder to a vanilla component.
+ *
+ * @param holder the value to convert
+ * @return the value as a vanilla component
+ * @since 0.10.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private static IChatBaseComponent toComponent(@NotNull StringHolder holder) {
+ return new ChatComponentText(holder.asLegacyString());
+ }
+
+ /**
+ * Converts the specified Adventure component holder to a vanilla component.
+ *
+ * @param holder the value to convert
+ * @return the value as a vanilla component
+ * @since 0.10.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private static IChatBaseComponent toComponent(@NotNull ComponentHolder holder) {
+ return Objects.requireNonNull(IChatBaseComponent.ChatSerializer.a(holder.asJson()));
+ }
+}
diff --git a/nms/1_16_R2/pom.xml b/nms/1_16_2-3/pom.xml
similarity index 86%
rename from nms/1_16_R2/pom.xml
rename to nms/1_16_2-3/pom.xml
index f630a7f1e..147afb076 100644
--- a/nms/1_16_R2/pom.xml
+++ b/nms/1_16_2-3/pom.xml
@@ -5,12 +5,12 @@
IF-parent
com.github.stefvanschie.inventoryframework
- 0.9.8
+ 0.10.18
../../pom.xml
4.0.0
- 1_16_R2
+ 1_16_2-3
true
@@ -18,8 +18,8 @@
- org.spigotmc
- spigot
+ io.papermc
+ paper
1.16.3-R0.1-SNAPSHOT
provided
diff --git a/nms/1_16_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_2_3/AnvilInventoryImpl.java b/nms/1_16_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_2_3/AnvilInventoryImpl.java
new file mode 100644
index 000000000..83b57373d
--- /dev/null
+++ b/nms/1_16_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_2_3/AnvilInventoryImpl.java
@@ -0,0 +1,386 @@
+package com.github.stefvanschie.inventoryframework.nms.v1_16_2_3;
+
+import com.github.stefvanschie.inventoryframework.abstraction.AnvilInventory;
+import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
+import com.github.stefvanschie.inventoryframework.nms.v1_16_2_3.util.TextHolderUtil;
+import net.minecraft.server.v1_16_R2.*;
+import org.bukkit.craftbukkit.v1_16_R2.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_16_R2.event.CraftEventFactory;
+import org.bukkit.craftbukkit.v1_16_R2.inventory.CraftItemStack;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.InventoryHolder;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.lang.reflect.Field;
+import java.util.Collections;
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * Internal anvil inventory for 1.16 R2
+ *
+ * @since 0.8.0
+ */
+public class AnvilInventoryImpl extends AnvilInventory {
+
+ public AnvilInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
+ super(inventoryHolder);
+ }
+
+ @Override
+ public Inventory openInventory(@NotNull Player player, @NotNull TextHolder title,
+ @Nullable org.bukkit.inventory.ItemStack[] items) {
+ int itemAmount = items.length;
+
+ if (itemAmount != 3) {
+ throw new IllegalArgumentException(
+ "The amount of items for an anvil should be 3, but is '" + itemAmount + "'"
+ );
+ }
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ //ignore deprecation: superseding method is only available on Paper
+ //noinspection deprecation
+ CraftEventFactory.handleInventoryCloseEvent(entityPlayer);
+
+ entityPlayer.activeContainer = entityPlayer.defaultContainer;
+
+ IChatBaseComponent message = TextHolderUtil.toComponent(title);
+ ContainerAnvilImpl containerAnvil = new ContainerAnvilImpl(entityPlayer, message);
+
+ Inventory inventory = containerAnvil.getBukkitView().getTopInventory();
+
+ inventory.setItem(0, items[0]);
+ inventory.setItem(1, items[1]);
+ inventory.setItem(2, items[2]);
+
+ int containerId = containerAnvil.getContainerId();
+
+ entityPlayer.playerConnection.sendPacket(new PacketPlayOutOpenWindow(containerId, Containers.ANVIL, message));
+ entityPlayer.activeContainer = containerAnvil;
+ entityPlayer.syncInventory();
+
+ return inventory;
+ }
+
+ @Override
+ public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
+ NonNullList nmsItems = NonNullList.a(
+ ItemStack.b,
+ CraftItemStack.asNMSCopy(items[0]),
+ CraftItemStack.asNMSCopy(items[1]),
+ CraftItemStack.asNMSCopy(items[2])
+ );
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
+ }
+
+ @Override
+ public void sendFirstItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+ ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutSetSlot(getWindowId(entityPlayer), 0, nmsItem));
+ }
+
+ @Override
+ public void sendSecondItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+ ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutSetSlot(getWindowId(entityPlayer), 1, nmsItem));
+ }
+
+ @Override
+ public void sendResultItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
+ sendResultItem(player, CraftItemStack.asNMSCopy(item));
+ }
+
+ @Override
+ public void clearResultItem(@NotNull Player player) {
+ sendResultItem(player, ItemStack.b);
+ }
+
+ @Override
+ public void setCursor(@NotNull Player player, @NotNull org.bukkit.inventory.ItemStack item) {
+ setCursor(player, CraftItemStack.asNMSCopy(item));
+ }
+
+ @Override
+ public void clearCursor(@NotNull Player player) {
+ getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.b));
+ }
+
+ /**
+ * Sets the cursor of the given player
+ *
+ * @param player the player to set the cursor
+ * @param item the item to set the cursor to
+ * @since 0.8.0
+ * @deprecated no longer used internally
+ */
+ @Deprecated
+ private void setCursor(@NotNull Player player, @NotNull ItemStack item) {
+ getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, item));
+ }
+
+ /**
+ * Sends the result item to the specified player with the given item
+ *
+ * @param player the player to send the result item to
+ * @param item the result item
+ * @since 0.8.0
+ * @deprecated no longer used internally
+ */
+ @Deprecated
+ private void sendResultItem(@NotNull Player player, @NotNull ItemStack item) {
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutSetSlot(getWindowId(entityPlayer), 2, item));
+ }
+
+ /**
+ * Gets the window id for the inventory view the player currently has open
+ *
+ * @param entityPlayer the player to get the window id for
+ * @return the window id
+ * @since 0.8.0
+ * @deprecated no longer used internally
+ */
+ @Contract(pure = true)
+ @Deprecated
+ private int getWindowId(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.activeContainer.windowId;
+ }
+
+ /**
+ * Gets the player connection for the specified player
+ *
+ * @param entityPlayer the player to get the player connection from
+ * @return the player connection
+ * @since 0.8.0
+ * @deprecated no longer used internally
+ */
+ @NotNull
+ @Contract(pure = true)
+ @Deprecated
+ private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.playerConnection;
+ }
+
+ /**
+ * Gets the entity player associated to this player
+ *
+ * @param player the player to get the entity player from
+ * @return the entity player
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private EntityPlayer getEntityPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * A custom container anvil for responding to item renaming
+ *
+ * @since 0.8.0
+ */
+ private class ContainerAnvilImpl extends ContainerAnvil {
+
+ /**
+ * The index of the result slot
+ */
+ private static final int RESULT_SLOT_INDEX = 2;
+
+ /**
+ * A unique item
+ */
+ @NotNull
+ private final ItemStack uniqueItem;
+
+ /**
+ * The field containing the listeners for this container
+ */
+ @NotNull
+ private final Field listenersField;
+
+ /**
+ * Creates a new custom anvil container for the specified player
+ *
+ * @param entityPlayer the player for whom this anvil container is
+ * @param title the title of the inventory
+ * @since 0.10.8
+ */
+ public ContainerAnvilImpl(@NotNull EntityPlayer entityPlayer, @NotNull IChatBaseComponent title) {
+ super(entityPlayer.nextContainerCounter(), entityPlayer.inventory,
+ ContainerAccess.at(entityPlayer.getWorld(), new BlockPosition(0, 0, 0)));
+
+ this.checkReachable = false;
+
+ try {
+ //stores all the registered container properties
+ Field dField = Container.class.getDeclaredField("d");
+ dField.setAccessible(true);
+
+ //get rid of the level cost property
+ ((List>) dField.get(this)).clear();
+ } catch (NoSuchFieldException | IllegalAccessException exception) {
+ throw new RuntimeException("Unable to access field 'd'", exception);
+ }
+
+ try {
+ this.listenersField = Container.class.getDeclaredField("listeners");
+ this.listenersField.setAccessible(true);
+ } catch (NoSuchFieldException exception) {
+ throw new RuntimeException("Unable to access field 'listeners'", exception);
+ }
+
+ //register a new property for the level cost
+ ContainerProperty levelCost = a(new ContainerProperty() {
+ private int value;
+
+ @Override
+ public int get() {
+ return value;
+ }
+
+ @Override
+ public void set(int value) {
+ this.value = value;
+ }
+
+ /*
+ This checks whether there have been any changes, but we want to override the client prediction. This
+ means the server should be sending the data to the client, even if it didn't change server-side. To
+ force this, we tell the server the data has always changed.
+ */
+ @Override
+ public boolean c() {
+ return true;
+ }
+ });
+
+ levelCost.set(AnvilInventoryImpl.super.cost);
+
+ setTitle(title);
+
+ Slot originalSlot = this.slots.get(RESULT_SLOT_INDEX);
+
+ Slot newSlot = new Slot(originalSlot.inventory, originalSlot.index, originalSlot.e, originalSlot.f) {
+ @Override
+ public boolean isAllowed(ItemStack itemStack) {
+ return true;
+ }
+
+ @Override
+ public boolean isAllowed(EntityHuman entityHuman) {
+ return true;
+ }
+
+ @Override
+ public ItemStack a(EntityHuman entityHuman, @NotNull ItemStack itemStack) {
+ return originalSlot.a(entityHuman, itemStack);
+ }
+ };
+
+ this.slots.set(RESULT_SLOT_INDEX, newSlot);
+
+ this.uniqueItem = new ItemStack(Items.COOKIE);
+
+ //to make the item unique, we add a random uuid as nbt to it
+ UUID uuid = UUID.randomUUID();
+ NBTTagCompound nbtTagCompound = new NBTTagCompound();
+
+ nbtTagCompound.set("uuid", new NBTTagLongArray(new long [] {
+ uuid.getLeastSignificantBits(),
+ uuid.getMostSignificantBits()
+ }));
+
+ this.uniqueItem.setTag(nbtTagCompound);
+ }
+
+ @Override
+ public void a(@Nullable String name) {
+ name = name == null ? "" : name;
+
+ /* Only update if the name is actually different. This may be called even if the name is not different,
+ particularly when putting an item in the first slot. */
+ if (!name.equals(AnvilInventoryImpl.super.observableText.get())) {
+ AnvilInventoryImpl.super.observableText.set(name);
+ }
+
+ //the client predicts the output result, so we broadcast the state again to override it
+ forceUpdate();
+ }
+
+ @Override
+ public void e() {}
+
+ @Override
+ public void b(EntityHuman entityHuman) {}
+
+ @Override
+ protected void a(EntityHuman entityHuman, World world, @NotNull IInventory inventory) {}
+
+ @Override
+ protected ItemStack a(EntityHuman entityHuman, @NotNull ItemStack itemStack) {
+ return itemStack;
+ }
+
+ @Override
+ public ItemStack a(int i, int j, InventoryClickType inventoryclicktype, EntityHuman entityhuman) {
+ ItemStack itemStack = super.a(i, j, inventoryclicktype, entityhuman);
+
+ //the client predicts the allowed movement of the item, so we broadcast the state again to override it
+ forceUpdate();
+
+ return itemStack;
+ }
+
+ public int getContainerId() {
+ return this.windowId;
+ }
+
+ /**
+ * Forcefully updates the client state, sending all items, container properties and the held item.
+ *
+ * @since 0.10.8
+ */
+ public void forceUpdate() {
+ /*
+ The server will not send the items when they haven't changed, so we will overwrite every item with a unique
+ item first to ensure the server is going to send our items.
+ */
+ Collections.fill(this.items, this.uniqueItem);
+
+ c();
+
+ List extends ICrafting> listeners;
+
+ try {
+ //noinspection unchecked
+ listeners = (List extends ICrafting>) listenersField.get(this);
+ } catch (IllegalAccessException exception) {
+ throw new RuntimeException("Unable to access field 'listeners'", exception);
+ }
+
+ for (ICrafting listener : listeners) {
+ if (!(listener instanceof EntityPlayer)) {
+ continue;
+ }
+
+ EntityPlayer player = (EntityPlayer) listener;
+
+ player.e = false;
+ player.broadcastCarriedItem();
+ }
+ }
+ }
+}
diff --git a/nms/1_16_R2/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R2/BeaconInventoryImpl.java b/nms/1_16_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_2_3/BeaconInventoryImpl.java
similarity index 95%
rename from nms/1_16_R2/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R2/BeaconInventoryImpl.java
rename to nms/1_16_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_2_3/BeaconInventoryImpl.java
index 2a8d3cc64..80e5b9a93 100644
--- a/nms/1_16_R2/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R2/BeaconInventoryImpl.java
+++ b/nms/1_16_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_2_3/BeaconInventoryImpl.java
@@ -1,178 +1,178 @@
-package com.github.stefvanschie.inventoryframework.nms.v1_16_R2;
-
-import com.github.stefvanschie.inventoryframework.abstraction.BeaconInventory;
-import net.minecraft.server.v1_16_R2.*;
-import org.bukkit.craftbukkit.v1_16_R2.entity.CraftPlayer;
-import org.bukkit.craftbukkit.v1_16_R2.inventory.*;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.InventoryHolder;
-import org.jetbrains.annotations.Contract;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.lang.reflect.Field;
-
-/**
- * Internal beacon inventory for 1.16 R2
- *
- * @since 0.8.0
- */
-public class BeaconInventoryImpl extends BeaconInventory {
-
- public BeaconInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
- super(inventoryHolder);
- }
-
- @Override
- public void openInventory(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
- EntityPlayer entityPlayer = getEntityPlayer(player);
- ContainerBeaconImpl containerBeacon = new ContainerBeaconImpl(entityPlayer, item);
-
- entityPlayer.activeContainer = containerBeacon;
-
- int id = containerBeacon.windowId;
- ChatMessage message = new ChatMessage("Beacon");
-
- entityPlayer.playerConnection.sendPacket(new PacketPlayOutOpenWindow(id, Containers.BEACON, message));
-
- sendItem(player, item);
- }
-
- @Override
- public void sendItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
- NonNullList items = NonNullList.a(
- ItemStack.b, //the first item doesn't count for some reason, so send a dummy item
- CraftItemStack.asNMSCopy(item)
- );
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), items));
- }
-
- @Override
- public void clearCursor(@NotNull Player player) {
- getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.b));
- }
-
- /**
- * Gets the window id for the inventory view the player currently has open
- *
- * @param entityPlayer the player to get the window id for
- * @return the window id
- * @since 0.8.0
- */
- @Contract(pure = true)
- private int getWindowId(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.activeContainer.windowId;
- }
-
- /**
- * Gets the player connection for the specified player
- *
- * @param entityPlayer the player to get the player connection from
- * @return the player connection
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.playerConnection;
- }
-
- /**
- * Gets the entity player associated to this player
- *
- * @param player the player to get the entity player from
- * @return the entity player
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private EntityPlayer getEntityPlayer(@NotNull Player player) {
- return ((CraftPlayer) player).getHandle();
- }
-
- /**
- * A custom container beacon
- *
- * @since 0.8.0
- */
- private class ContainerBeaconImpl extends ContainerBeacon {
-
- /**
- * The player for this beacon container
- */
- @NotNull
- private final Player player;
-
- /**
- * The internal bukkit entity for this container beacon
- */
- @Nullable
- private CraftInventoryView bukkitEntity;
-
- /**
- * Field for accessing the beacon field
- */
- @NotNull
- private final Field beaconField;
-
- public ContainerBeaconImpl(@NotNull EntityPlayer entityPlayer, @Nullable org.bukkit.inventory.ItemStack item) {
- super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
-
- this.player = entityPlayer.getBukkitEntity();
-
- try {
- this.beaconField = ContainerBeacon.class.getDeclaredField("beacon");
- this.beaconField.setAccessible(true);
- } catch (NoSuchFieldException exception) {
- throw new RuntimeException(exception);
- }
-
- try {
- ItemStack itemStack = CraftItemStack.asNMSCopy(item);
-
- ((IInventory) beaconField.get(this)).setItem(0, itemStack);
- } catch (IllegalAccessException exception) {
- throw new RuntimeException(exception);
- }
- }
-
- @NotNull
- @Override
- public CraftInventoryView getBukkitView() {
- if (bukkitEntity == null) {
- try {
- CraftInventory inventory = new CraftInventoryBeacon((IInventory) beaconField.get(this)) {
- @NotNull
- @Contract(pure = true)
- @Override
- public InventoryHolder getHolder() {
- return inventoryHolder;
- }
- };
-
- bukkitEntity = new CraftInventoryView(player, inventory, this);
- } catch (IllegalAccessException exception) {
- throw new RuntimeException(exception);
- }
- }
-
- return bukkitEntity;
- }
-
- @Contract(pure = true, value = "_ -> true")
- @Override
- public boolean canUse(@Nullable EntityHuman entityhuman) {
- return true;
- }
-
- @Override
- public void a(IInventory inventory) {}
-
- @Override
- public void b(EntityHuman entityhuman) {}
-
- }
-}
+package com.github.stefvanschie.inventoryframework.nms.v1_16_2_3;
+
+import com.github.stefvanschie.inventoryframework.abstraction.BeaconInventory;
+import net.minecraft.server.v1_16_R2.*;
+import org.bukkit.craftbukkit.v1_16_R2.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_16_R2.inventory.*;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.InventoryHolder;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.lang.reflect.Field;
+
+/**
+ * Internal beacon inventory for 1.16 R2
+ *
+ * @since 0.8.0
+ */
+public class BeaconInventoryImpl extends BeaconInventory {
+
+ public BeaconInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
+ super(inventoryHolder);
+ }
+
+ @Override
+ public void openInventory(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+ ContainerBeaconImpl containerBeacon = new ContainerBeaconImpl(entityPlayer, item);
+
+ entityPlayer.activeContainer = containerBeacon;
+
+ int id = containerBeacon.windowId;
+ ChatMessage message = new ChatMessage("Beacon");
+
+ entityPlayer.playerConnection.sendPacket(new PacketPlayOutOpenWindow(id, Containers.BEACON, message));
+
+ sendItem(player, item);
+ }
+
+ @Override
+ public void sendItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
+ NonNullList items = NonNullList.a(
+ ItemStack.b, //the first item doesn't count for some reason, so send a dummy item
+ CraftItemStack.asNMSCopy(item)
+ );
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), items));
+ }
+
+ @Override
+ public void clearCursor(@NotNull Player player) {
+ getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.b));
+ }
+
+ /**
+ * Gets the window id for the inventory view the player currently has open
+ *
+ * @param entityPlayer the player to get the window id for
+ * @return the window id
+ * @since 0.8.0
+ */
+ @Contract(pure = true)
+ private int getWindowId(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.activeContainer.windowId;
+ }
+
+ /**
+ * Gets the player connection for the specified player
+ *
+ * @param entityPlayer the player to get the player connection from
+ * @return the player connection
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.playerConnection;
+ }
+
+ /**
+ * Gets the entity player associated to this player
+ *
+ * @param player the player to get the entity player from
+ * @return the entity player
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private EntityPlayer getEntityPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * A custom container beacon
+ *
+ * @since 0.8.0
+ */
+ private class ContainerBeaconImpl extends ContainerBeacon {
+
+ /**
+ * The player for this beacon container
+ */
+ @NotNull
+ private final Player player;
+
+ /**
+ * The internal bukkit entity for this container beacon
+ */
+ @Nullable
+ private CraftInventoryView bukkitEntity;
+
+ /**
+ * Field for accessing the beacon field
+ */
+ @NotNull
+ private final Field beaconField;
+
+ public ContainerBeaconImpl(@NotNull EntityPlayer entityPlayer, @Nullable org.bukkit.inventory.ItemStack item) {
+ super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
+
+ this.player = entityPlayer.getBukkitEntity();
+
+ try {
+ this.beaconField = ContainerBeacon.class.getDeclaredField("beacon");
+ this.beaconField.setAccessible(true);
+ } catch (NoSuchFieldException exception) {
+ throw new RuntimeException(exception);
+ }
+
+ try {
+ ItemStack itemStack = CraftItemStack.asNMSCopy(item);
+
+ ((IInventory) beaconField.get(this)).setItem(0, itemStack);
+ } catch (IllegalAccessException exception) {
+ throw new RuntimeException(exception);
+ }
+ }
+
+ @NotNull
+ @Override
+ public CraftInventoryView getBukkitView() {
+ if (bukkitEntity == null) {
+ try {
+ CraftInventory inventory = new CraftInventoryBeacon((IInventory) beaconField.get(this)) {
+ @NotNull
+ @Contract(pure = true)
+ @Override
+ public InventoryHolder getHolder() {
+ return inventoryHolder;
+ }
+ };
+
+ bukkitEntity = new CraftInventoryView(player, inventory, this);
+ } catch (IllegalAccessException exception) {
+ throw new RuntimeException(exception);
+ }
+ }
+
+ return bukkitEntity;
+ }
+
+ @Contract(pure = true, value = "_ -> true")
+ @Override
+ public boolean canUse(@Nullable EntityHuman entityhuman) {
+ return true;
+ }
+
+ @Override
+ public void a(IInventory inventory) {}
+
+ @Override
+ public void b(EntityHuman entityhuman) {}
+
+ }
+}
diff --git a/nms/1_16_R2/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R2/CartographyTableInventoryImpl.java b/nms/1_16_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_2_3/CartographyTableInventoryImpl.java
similarity index 94%
rename from nms/1_16_R2/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R2/CartographyTableInventoryImpl.java
rename to nms/1_16_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_2_3/CartographyTableInventoryImpl.java
index b11ac0f23..bf6d8ba59 100644
--- a/nms/1_16_R2/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R2/CartographyTableInventoryImpl.java
+++ b/nms/1_16_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_2_3/CartographyTableInventoryImpl.java
@@ -1,196 +1,198 @@
-package com.github.stefvanschie.inventoryframework.nms.v1_16_R2;
-
-import com.github.stefvanschie.inventoryframework.abstraction.CartographyTableInventory;
-import net.minecraft.server.v1_16_R2.*;
-import org.bukkit.craftbukkit.v1_16_R2.entity.CraftPlayer;
-import org.bukkit.craftbukkit.v1_16_R2.inventory.*;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.InventoryHolder;
-import org.jetbrains.annotations.Contract;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.lang.reflect.Field;
-
-/**
- * Internal cartography table inventory for 1.16 R2
- *
- * @since 0.8.0
- */
-public class CartographyTableInventoryImpl extends CartographyTableInventory {
-
- public CartographyTableInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
- super(inventoryHolder);
- }
-
- @Override
- public void openInventory(@NotNull Player player, @NotNull String title,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- int itemAmount = items.length;
-
- if (itemAmount != 3) {
- throw new IllegalArgumentException(
- "The amount of items for a cartography table should be 3, but is '" + itemAmount + "'"
- );
- }
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
- ContainerCartographyTableImpl containerCartographyTable = new ContainerCartographyTableImpl(
- entityPlayer, items
- );
-
- entityPlayer.activeContainer = containerCartographyTable;
-
- int id = containerCartographyTable.windowId;
- ChatMessage message = new ChatMessage(title);
- PacketPlayOutOpenWindow packet = new PacketPlayOutOpenWindow(id, Containers.CARTOGRAPHY_TABLE, message);
-
- entityPlayer.playerConnection.sendPacket(packet);
-
- sendItems(player, items);
- }
-
- @Override
- public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
- NonNullList nmsItems = NonNullList.a(
- ItemStack.b,
- CraftItemStack.asNMSCopy(items[0]),
- CraftItemStack.asNMSCopy(items[1]),
- CraftItemStack.asNMSCopy(items[2])
- );
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
- }
-
- @Override
- public void clearCursor(@NotNull Player player) {
- getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.b));
- }
-
- /**
- * Gets the window id for the inventory view the player currently has open
- *
- * @param entityPlayer the player to get the window id for
- * @return the window id
- * @since 0.8.0
- */
- @Contract(pure = true)
- private int getWindowId(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.activeContainer.windowId;
- }
-
- /**
- * Gets the player connection for the specified player
- *
- * @param entityPlayer the player to get the player connection from
- * @return the player connection
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.playerConnection;
- }
-
- /**
- * Gets the entity player associated to this player
- *
- * @param player the player to get the entity player from
- * @return the entity player
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private EntityPlayer getEntityPlayer(@NotNull Player player) {
- return ((CraftPlayer) player).getHandle();
- }
-
- /**
- * A custom container cartography table
- *
- * @since 0.8.0
- */
- private class ContainerCartographyTableImpl extends ContainerCartography {
-
- /**
- * The player for this cartography table container
- */
- @NotNull
- private final Player player;
-
- /**
- * The internal bukkit entity for this container cartography table
- */
- @Nullable
- private CraftInventoryView bukkitEntity;
-
- /**
- * Field for accessing the result inventory field
- */
- @NotNull
- private final Field resultInventoryField;
-
- public ContainerCartographyTableImpl(@NotNull EntityPlayer entityPlayer,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
-
- this.player = entityPlayer.getBukkitEntity();
-
- try {
- this.resultInventoryField = ContainerCartography.class.getDeclaredField("resultInventory");
- this.resultInventoryField.setAccessible(true);
- } catch (NoSuchFieldException exception) {
- throw new RuntimeException(exception);
- }
-
- inventory.setItem(0, CraftItemStack.asNMSCopy(items[0]));
- inventory.setItem(1, CraftItemStack.asNMSCopy(items[1]));
-
- getResultInventory().setItem(0, CraftItemStack.asNMSCopy(items[2]));
- }
-
- @NotNull
- @Override
- public CraftInventoryView getBukkitView() {
- if (bukkitEntity == null) {
- CraftInventory inventory = new CraftInventoryCartography(super.inventory, getResultInventory()) {
- @NotNull
- @Contract(pure = true)
- @Override
- public InventoryHolder getHolder() {
- return inventoryHolder;
- }
- };
-
- bukkitEntity = new CraftInventoryView(player, inventory, this);
- }
-
- return bukkitEntity;
- }
-
- @Contract(pure = true, value = "_ -> true")
- @Override
- public boolean canUse(@Nullable EntityHuman entityhuman) {
- return true;
- }
-
- @Override
- public void a(IInventory inventory) {}
-
- @Override
- public void b(EntityHuman entityhuman) {}
-
- @NotNull
- @Contract(pure = true)
- private IInventory getResultInventory() {
- try {
- return (IInventory) resultInventoryField.get(this);
- } catch (IllegalAccessException exception) {
- throw new RuntimeException(exception);
- }
- }
-
- }
-}
+package com.github.stefvanschie.inventoryframework.nms.v1_16_2_3;
+
+import com.github.stefvanschie.inventoryframework.abstraction.CartographyTableInventory;
+import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
+import com.github.stefvanschie.inventoryframework.nms.v1_16_2_3.util.TextHolderUtil;
+import net.minecraft.server.v1_16_R2.*;
+import org.bukkit.craftbukkit.v1_16_R2.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_16_R2.inventory.*;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.InventoryHolder;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.lang.reflect.Field;
+
+/**
+ * Internal cartography table inventory for 1.16 R2
+ *
+ * @since 0.8.0
+ */
+public class CartographyTableInventoryImpl extends CartographyTableInventory {
+
+ public CartographyTableInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
+ super(inventoryHolder);
+ }
+
+ @Override
+ public void openInventory(@NotNull Player player, @NotNull TextHolder title,
+ @Nullable org.bukkit.inventory.ItemStack[] items) {
+ int itemAmount = items.length;
+
+ if (itemAmount != 3) {
+ throw new IllegalArgumentException(
+ "The amount of items for a cartography table should be 3, but is '" + itemAmount + "'"
+ );
+ }
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+ ContainerCartographyTableImpl containerCartographyTable = new ContainerCartographyTableImpl(
+ entityPlayer, items
+ );
+
+ entityPlayer.activeContainer = containerCartographyTable;
+
+ int id = containerCartographyTable.windowId;
+ IChatBaseComponent message = TextHolderUtil.toComponent(title);
+ PacketPlayOutOpenWindow packet = new PacketPlayOutOpenWindow(id, Containers.CARTOGRAPHY_TABLE, message);
+
+ entityPlayer.playerConnection.sendPacket(packet);
+
+ sendItems(player, items);
+ }
+
+ @Override
+ public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
+ NonNullList nmsItems = NonNullList.a(
+ ItemStack.b,
+ CraftItemStack.asNMSCopy(items[0]),
+ CraftItemStack.asNMSCopy(items[1]),
+ CraftItemStack.asNMSCopy(items[2])
+ );
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
+ }
+
+ @Override
+ public void clearCursor(@NotNull Player player) {
+ getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.b));
+ }
+
+ /**
+ * Gets the window id for the inventory view the player currently has open
+ *
+ * @param entityPlayer the player to get the window id for
+ * @return the window id
+ * @since 0.8.0
+ */
+ @Contract(pure = true)
+ private int getWindowId(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.activeContainer.windowId;
+ }
+
+ /**
+ * Gets the player connection for the specified player
+ *
+ * @param entityPlayer the player to get the player connection from
+ * @return the player connection
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.playerConnection;
+ }
+
+ /**
+ * Gets the entity player associated to this player
+ *
+ * @param player the player to get the entity player from
+ * @return the entity player
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private EntityPlayer getEntityPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * A custom container cartography table
+ *
+ * @since 0.8.0
+ */
+ private class ContainerCartographyTableImpl extends ContainerCartography {
+
+ /**
+ * The player for this cartography table container
+ */
+ @NotNull
+ private final Player player;
+
+ /**
+ * The internal bukkit entity for this container cartography table
+ */
+ @Nullable
+ private CraftInventoryView bukkitEntity;
+
+ /**
+ * Field for accessing the result inventory field
+ */
+ @NotNull
+ private final Field resultInventoryField;
+
+ public ContainerCartographyTableImpl(@NotNull EntityPlayer entityPlayer,
+ @Nullable org.bukkit.inventory.ItemStack[] items) {
+ super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
+
+ this.player = entityPlayer.getBukkitEntity();
+
+ try {
+ this.resultInventoryField = ContainerCartography.class.getDeclaredField("resultInventory");
+ this.resultInventoryField.setAccessible(true);
+ } catch (NoSuchFieldException exception) {
+ throw new RuntimeException(exception);
+ }
+
+ inventory.setItem(0, CraftItemStack.asNMSCopy(items[0]));
+ inventory.setItem(1, CraftItemStack.asNMSCopy(items[1]));
+
+ getResultInventory().setItem(0, CraftItemStack.asNMSCopy(items[2]));
+ }
+
+ @NotNull
+ @Override
+ public CraftInventoryView getBukkitView() {
+ if (bukkitEntity == null) {
+ CraftInventory inventory = new CraftInventoryCartography(super.inventory, getResultInventory()) {
+ @NotNull
+ @Contract(pure = true)
+ @Override
+ public InventoryHolder getHolder() {
+ return inventoryHolder;
+ }
+ };
+
+ bukkitEntity = new CraftInventoryView(player, inventory, this);
+ }
+
+ return bukkitEntity;
+ }
+
+ @Contract(pure = true, value = "_ -> true")
+ @Override
+ public boolean canUse(@Nullable EntityHuman entityhuman) {
+ return true;
+ }
+
+ @Override
+ public void a(IInventory inventory) {}
+
+ @Override
+ public void b(EntityHuman entityhuman) {}
+
+ @NotNull
+ @Contract(pure = true)
+ private IInventory getResultInventory() {
+ try {
+ return (IInventory) resultInventoryField.get(this);
+ } catch (IllegalAccessException exception) {
+ throw new RuntimeException(exception);
+ }
+ }
+
+ }
+}
diff --git a/nms/1_16_R2/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R2/EnchantingTableInventoryImpl.java b/nms/1_16_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_2_3/EnchantingTableInventoryImpl.java
similarity index 94%
rename from nms/1_16_R2/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R2/EnchantingTableInventoryImpl.java
rename to nms/1_16_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_2_3/EnchantingTableInventoryImpl.java
index 89145689c..abf9e5393 100644
--- a/nms/1_16_R2/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R2/EnchantingTableInventoryImpl.java
+++ b/nms/1_16_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_2_3/EnchantingTableInventoryImpl.java
@@ -1,191 +1,193 @@
-package com.github.stefvanschie.inventoryframework.nms.v1_16_R2;
-
-import com.github.stefvanschie.inventoryframework.abstraction.EnchantingTableInventory;
-import net.minecraft.server.v1_16_R2.*;
-import org.bukkit.craftbukkit.v1_16_R2.entity.CraftPlayer;
-import org.bukkit.craftbukkit.v1_16_R2.inventory.*;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.InventoryHolder;
-import org.jetbrains.annotations.Contract;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.lang.reflect.Field;
-
-/**
- * Internal enchanting table inventory for 1.16 R2
- *
- * @since 0.8.0
- */
-public class EnchantingTableInventoryImpl extends EnchantingTableInventory {
-
- public EnchantingTableInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
- super(inventoryHolder);
- }
-
- @Override
- public void openInventory(@NotNull Player player, @NotNull String title,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- int itemAmount = items.length;
-
- if (itemAmount != 2) {
- throw new IllegalArgumentException(
- "The amount of items for an enchanting table should be 2, but is '" + itemAmount + "'"
- );
- }
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
- ContainerEnchantingTableImpl containerEnchantmentTable = new ContainerEnchantingTableImpl(entityPlayer, items);
-
- entityPlayer.activeContainer = containerEnchantmentTable;
-
- int id = containerEnchantmentTable.windowId;
- ChatMessage message = new ChatMessage(title);
- PacketPlayOutOpenWindow packet = new PacketPlayOutOpenWindow(id, Containers.ENCHANTMENT, message);
-
- entityPlayer.playerConnection.sendPacket(packet);
-
- sendItems(player, items);
- }
-
- @Override
- public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
- NonNullList nmsItems = NonNullList.a(
- ItemStack.b,
- CraftItemStack.asNMSCopy(items[0]),
- CraftItemStack.asNMSCopy(items[1])
- );
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
- }
-
- @Override
- public void clearCursor(@NotNull Player player) {
- getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.b));
- }
-
- /**
- * Gets the window id for the inventory view the player currently has open
- *
- * @param entityPlayer the player to get the window id for
- * @return the window id
- * @since 0.8.0
- */
- @Contract(pure = true)
- private int getWindowId(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.activeContainer.windowId;
- }
-
- /**
- * Gets the player connection for the specified player
- *
- * @param entityPlayer the player to get the player connection from
- * @return the player connection
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.playerConnection;
- }
-
- /**
- * Gets the entity player associated to this player
- *
- * @param player the player to get the entity player from
- * @return the entity player
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private EntityPlayer getEntityPlayer(@NotNull Player player) {
- return ((CraftPlayer) player).getHandle();
- }
-
- /**
- * A custom container enchanting table
- *
- * @since 0.8.0
- */
- private class ContainerEnchantingTableImpl extends ContainerEnchantTable {
-
- /**
- * The player for this enchanting table container
- */
- @NotNull
- private final Player player;
-
- /**
- * The internal bukkit entity for this container enchanting table
- */
- @Nullable
- private CraftInventoryView bukkitEntity;
-
- /**
- * Field for accessing the enchant slots field
- */
- @NotNull
- private final Field enchantSlotsField;
-
- public ContainerEnchantingTableImpl(@NotNull EntityPlayer entityPlayer,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
-
- this.player = entityPlayer.getBukkitEntity();
-
- try {
- this.enchantSlotsField = ContainerEnchantTable.class.getDeclaredField("enchantSlots");
- this.enchantSlotsField.setAccessible(true);
- } catch (NoSuchFieldException exception) {
- throw new RuntimeException(exception);
- }
-
- try {
- IInventory input = (IInventory) enchantSlotsField.get(this);
-
- input.setItem(0, CraftItemStack.asNMSCopy(items[0]));
- input.setItem(1, CraftItemStack.asNMSCopy(items[1]));
- } catch (IllegalAccessException e) {
- e.printStackTrace();
- }
- }
-
- @NotNull
- @Override
- public CraftInventoryView getBukkitView() {
- if (bukkitEntity == null) {
- try {
- CraftInventory inventory = new CraftInventoryEnchanting((IInventory) enchantSlotsField.get(this)) {
- @NotNull
- @Contract(pure = true)
- @Override
- public InventoryHolder getHolder() {
- return inventoryHolder;
- }
- };
-
- bukkitEntity = new CraftInventoryView(player, inventory, this);
- } catch (IllegalAccessException exception) {
- exception.printStackTrace();
- }
- }
-
- return bukkitEntity;
- }
-
- @Contract(pure = true, value = "_ -> true")
- @Override
- public boolean canUse(@Nullable EntityHuman entityhuman) {
- return true;
- }
-
- @Override
- public void a(IInventory inventory) {}
-
- @Override
- public void b(EntityHuman entityhuman) {}
-
- }
-}
+package com.github.stefvanschie.inventoryframework.nms.v1_16_2_3;
+
+import com.github.stefvanschie.inventoryframework.abstraction.EnchantingTableInventory;
+import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
+import com.github.stefvanschie.inventoryframework.nms.v1_16_2_3.util.TextHolderUtil;
+import net.minecraft.server.v1_16_R2.*;
+import org.bukkit.craftbukkit.v1_16_R2.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_16_R2.inventory.*;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.InventoryHolder;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.lang.reflect.Field;
+
+/**
+ * Internal enchanting table inventory for 1.16 R2
+ *
+ * @since 0.8.0
+ */
+public class EnchantingTableInventoryImpl extends EnchantingTableInventory {
+
+ public EnchantingTableInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
+ super(inventoryHolder);
+ }
+
+ @Override
+ public void openInventory(@NotNull Player player, @NotNull TextHolder title,
+ @Nullable org.bukkit.inventory.ItemStack[] items) {
+ int itemAmount = items.length;
+
+ if (itemAmount != 2) {
+ throw new IllegalArgumentException(
+ "The amount of items for an enchanting table should be 2, but is '" + itemAmount + "'"
+ );
+ }
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+ ContainerEnchantingTableImpl containerEnchantmentTable = new ContainerEnchantingTableImpl(entityPlayer, items);
+
+ entityPlayer.activeContainer = containerEnchantmentTable;
+
+ int id = containerEnchantmentTable.windowId;
+ IChatBaseComponent message = TextHolderUtil.toComponent(title);
+ PacketPlayOutOpenWindow packet = new PacketPlayOutOpenWindow(id, Containers.ENCHANTMENT, message);
+
+ entityPlayer.playerConnection.sendPacket(packet);
+
+ sendItems(player, items);
+ }
+
+ @Override
+ public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
+ NonNullList nmsItems = NonNullList.a(
+ ItemStack.b,
+ CraftItemStack.asNMSCopy(items[0]),
+ CraftItemStack.asNMSCopy(items[1])
+ );
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
+ }
+
+ @Override
+ public void clearCursor(@NotNull Player player) {
+ getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.b));
+ }
+
+ /**
+ * Gets the window id for the inventory view the player currently has open
+ *
+ * @param entityPlayer the player to get the window id for
+ * @return the window id
+ * @since 0.8.0
+ */
+ @Contract(pure = true)
+ private int getWindowId(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.activeContainer.windowId;
+ }
+
+ /**
+ * Gets the player connection for the specified player
+ *
+ * @param entityPlayer the player to get the player connection from
+ * @return the player connection
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.playerConnection;
+ }
+
+ /**
+ * Gets the entity player associated to this player
+ *
+ * @param player the player to get the entity player from
+ * @return the entity player
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private EntityPlayer getEntityPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * A custom container enchanting table
+ *
+ * @since 0.8.0
+ */
+ private class ContainerEnchantingTableImpl extends ContainerEnchantTable {
+
+ /**
+ * The player for this enchanting table container
+ */
+ @NotNull
+ private final Player player;
+
+ /**
+ * The internal bukkit entity for this container enchanting table
+ */
+ @Nullable
+ private CraftInventoryView bukkitEntity;
+
+ /**
+ * Field for accessing the enchant slots field
+ */
+ @NotNull
+ private final Field enchantSlotsField;
+
+ public ContainerEnchantingTableImpl(@NotNull EntityPlayer entityPlayer,
+ @Nullable org.bukkit.inventory.ItemStack[] items) {
+ super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
+
+ this.player = entityPlayer.getBukkitEntity();
+
+ try {
+ this.enchantSlotsField = ContainerEnchantTable.class.getDeclaredField("enchantSlots");
+ this.enchantSlotsField.setAccessible(true);
+ } catch (NoSuchFieldException exception) {
+ throw new RuntimeException(exception);
+ }
+
+ try {
+ IInventory input = (IInventory) enchantSlotsField.get(this);
+
+ input.setItem(0, CraftItemStack.asNMSCopy(items[0]));
+ input.setItem(1, CraftItemStack.asNMSCopy(items[1]));
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @NotNull
+ @Override
+ public CraftInventoryView getBukkitView() {
+ if (bukkitEntity == null) {
+ try {
+ CraftInventory inventory = new CraftInventoryEnchanting((IInventory) enchantSlotsField.get(this)) {
+ @NotNull
+ @Contract(pure = true)
+ @Override
+ public InventoryHolder getHolder() {
+ return inventoryHolder;
+ }
+ };
+
+ bukkitEntity = new CraftInventoryView(player, inventory, this);
+ } catch (IllegalAccessException exception) {
+ exception.printStackTrace();
+ }
+ }
+
+ return bukkitEntity;
+ }
+
+ @Contract(pure = true, value = "_ -> true")
+ @Override
+ public boolean canUse(@Nullable EntityHuman entityhuman) {
+ return true;
+ }
+
+ @Override
+ public void a(IInventory inventory) {}
+
+ @Override
+ public void b(EntityHuman entityhuman) {}
+
+ }
+}
diff --git a/nms/1_16_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_2_3/GrindstoneInventoryImpl.java b/nms/1_16_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_2_3/GrindstoneInventoryImpl.java
new file mode 100644
index 000000000..0950c0553
--- /dev/null
+++ b/nms/1_16_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_2_3/GrindstoneInventoryImpl.java
@@ -0,0 +1,271 @@
+package com.github.stefvanschie.inventoryframework.nms.v1_16_2_3;
+
+import com.github.stefvanschie.inventoryframework.abstraction.GrindstoneInventory;
+import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
+import com.github.stefvanschie.inventoryframework.nms.v1_16_2_3.util.TextHolderUtil;
+import net.minecraft.server.v1_16_R2.*;
+import org.bukkit.craftbukkit.v1_16_R2.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_16_R2.event.CraftEventFactory;
+import org.bukkit.craftbukkit.v1_16_R2.inventory.*;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.InventoryHolder;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.lang.reflect.Field;
+import java.util.Collections;
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * Internal grindstone inventory for 1.16 R2
+ *
+ * @since 0.8.0
+ */
+public class GrindstoneInventoryImpl extends GrindstoneInventory {
+
+ public GrindstoneInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
+ super(inventoryHolder);
+ }
+
+ @Override
+ public Inventory openInventory(@NotNull Player player, @NotNull TextHolder title,
+ @Nullable org.bukkit.inventory.ItemStack[] items) {
+ int itemAmount = items.length;
+
+ if (itemAmount != 3) {
+ throw new IllegalArgumentException(
+ "The amount of items for a grindstone should be 3, but is '" + itemAmount + "'"
+ );
+ }
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ //ignore deprecation: superseding method is only available on Paper
+ //noinspection deprecation
+ CraftEventFactory.handleInventoryCloseEvent(entityPlayer);
+
+ entityPlayer.activeContainer = entityPlayer.defaultContainer;
+
+ IChatBaseComponent message = TextHolderUtil.toComponent(title);
+ ContainerGrindstoneImpl containerGrindstone = new ContainerGrindstoneImpl(entityPlayer);
+
+ Inventory inventory = containerGrindstone.getBukkitView().getTopInventory();
+
+ inventory.setItem(0, items[0]);
+ inventory.setItem(1, items[1]);
+ inventory.setItem(2, items[2]);
+
+ int windowId = containerGrindstone.getWindowId();
+
+ entityPlayer.playerConnection.sendPacket(new PacketPlayOutOpenWindow(windowId, Containers.GRINDSTONE, message));
+ entityPlayer.activeContainer = containerGrindstone;
+ entityPlayer.syncInventory();
+
+ return inventory;
+ }
+
+ @Override
+ public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items,
+ @Nullable org.bukkit.inventory.ItemStack cursor) {
+ NonNullList nmsItems = NonNullList.a(
+ ItemStack.b,
+ CraftItemStack.asNMSCopy(items[0]),
+ CraftItemStack.asNMSCopy(items[1]),
+ CraftItemStack.asNMSCopy(items[2])
+ );
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
+ }
+
+ @Override
+ public void clearCursor(@NotNull Player player) {
+ getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.b));
+ }
+
+ /**
+ * Gets the window id for the inventory view the player currently has open
+ *
+ * @param entityPlayer the player to get the window id for
+ * @return the window id
+ * @since 0.8.0
+ * @deprecated no longer used internally
+ */
+ @Contract(pure = true)
+ private int getWindowId(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.activeContainer.windowId;
+ }
+
+ /**
+ * Gets the player connection for the specified player
+ *
+ * @param entityPlayer the player to get the player connection from
+ * @return the player connection
+ * @since 0.8.0
+ * @deprecated no longer used internally
+ */
+ @NotNull
+ @Contract(pure = true)
+ @Deprecated
+ private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.playerConnection;
+ }
+
+ /**
+ * Gets the entity player associated to this player
+ *
+ * @param player the player to get the entity player from
+ * @return the entity player
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private EntityPlayer getEntityPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * A custom container grindstone
+ *
+ * @since 0.8.0
+ */
+ private static class ContainerGrindstoneImpl extends ContainerGrindstone {
+
+ /**
+ * A unique item
+ */
+ @NotNull
+ private final ItemStack uniqueItem;
+
+ /**
+ * The field containing the listeners for this container
+ */
+ @NotNull
+ private final Field listenersField;
+
+ /**
+ * Creates a new grindstone container
+ *
+ * @param entityPlayer the player for whom this container should be opened
+ * @since 0.10.8
+ */
+ public ContainerGrindstoneImpl(@NotNull EntityPlayer entityPlayer) {
+ super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
+
+ try {
+ this.listenersField = Container.class.getDeclaredField("listeners");
+ this.listenersField.setAccessible(true);
+ } catch (NoSuchFieldException exception) {
+ throw new RuntimeException("Unable to access field 'listeners'", exception);
+ }
+
+ Slot firstSlot = this.slots.get(0);
+ Slot secondSlot = this.slots.get(1);
+ Slot thirdSlot = this.slots.get(2);
+
+ this.slots.set(0, new Slot(firstSlot.inventory, firstSlot.rawSlotIndex, firstSlot.e, firstSlot.f) {
+ @Override
+ public boolean isAllowed(ItemStack stack) {
+ return true;
+ }
+ });
+
+ this.slots.set(1, new Slot(secondSlot.inventory, secondSlot.rawSlotIndex, secondSlot.e, secondSlot.f) {
+ @Override
+ public boolean isAllowed(ItemStack stack) {
+ return true;
+ }
+ });
+
+ this.slots.set(2, new Slot(thirdSlot.inventory, thirdSlot.rawSlotIndex, thirdSlot.e, thirdSlot.f) {
+ @Override
+ public boolean isAllowed(ItemStack stack) {
+ return true;
+ }
+
+ @Override
+ public ItemStack a(EntityHuman entityHuman, ItemStack itemStack) {
+ return itemStack;
+ }
+ });
+
+ this.uniqueItem = new ItemStack(Items.COOKIE);
+
+ //to make the item unique, we add a random uuid as nbt to it
+ UUID uuid = UUID.randomUUID();
+ NBTTagCompound nbtTagCompound = new NBTTagCompound();
+
+ nbtTagCompound.set("uuid", new NBTTagLongArray(new long [] {
+ uuid.getLeastSignificantBits(),
+ uuid.getMostSignificantBits()
+ }));
+
+ this.uniqueItem.setTag(nbtTagCompound);
+ }
+
+ /**
+ * Forcefully updates the client state, sending all items, container properties and the held item.
+ *
+ * @since 0.10.8
+ */
+ public void forceUpdate() {
+ /*
+ The server will not send the items when they haven't changed, so we will overwrite every item with a unique
+ item first to ensure the server is going to send our items.
+ */
+ Collections.fill(this.items, this.uniqueItem);
+
+ notifyListeners();
+
+ List extends ICrafting> listeners;
+
+ try {
+ //noinspection unchecked
+ listeners = (List extends ICrafting>) listenersField.get(this);
+ } catch (IllegalAccessException exception) {
+ throw new RuntimeException("Unable to access field 'listeners'", exception);
+ }
+
+ for (ICrafting listener : listeners) {
+ if (!(listener instanceof EntityPlayer)) {
+ continue;
+ }
+
+ EntityPlayer player = (EntityPlayer) listener;
+
+ player.e = false;
+ player.broadcastCarriedItem();
+ }
+ }
+
+ @Override
+ public ItemStack a(int i, int j, InventoryClickType inventoryclicktype, EntityHuman entityhuman) {
+ ItemStack itemStack = super.a(i, j, inventoryclicktype, entityhuman);
+
+ //the client predicts the allowed movement of the item, so we broadcast the state again to override it
+ forceUpdate();
+
+ return itemStack;
+ }
+
+ @Contract(pure = true, value = "_ -> true")
+ @Override
+ public boolean canUse(@Nullable EntityHuman entityHuman) {
+ return true;
+ }
+
+ @Override
+ public void a(IInventory inventory) {}
+
+ @Override
+ public void b(EntityHuman entityHuman) {}
+
+ public int getWindowId() {
+ return this.windowId;
+ }
+ }
+}
diff --git a/nms/1_16_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_2_3/MerchantInventoryImpl.java b/nms/1_16_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_2_3/MerchantInventoryImpl.java
new file mode 100644
index 000000000..9401a94d1
--- /dev/null
+++ b/nms/1_16_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_2_3/MerchantInventoryImpl.java
@@ -0,0 +1,95 @@
+package com.github.stefvanschie.inventoryframework.nms.v1_16_2_3;
+
+import com.github.stefvanschie.inventoryframework.abstraction.MerchantInventory;
+import net.minecraft.server.v1_16_R2.EntityPlayer;
+import net.minecraft.server.v1_16_R2.MerchantRecipeList;
+import org.bukkit.craftbukkit.v1_16_R2.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_16_R2.inventory.CraftItemStack;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.MerchantRecipe;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Internal merchant inventory for 1.16.2 - 1.16.3
+ *
+ * @since 0.10.1
+ */
+public class MerchantInventoryImpl extends MerchantInventory {
+
+ @Override
+ public void sendMerchantOffers(@NotNull Player player,
+ @NotNull List extends Map.Entry extends MerchantRecipe, ? extends Integer>> trades,
+ int level, int experience) {
+ MerchantRecipeList offers = new MerchantRecipeList();
+
+ for (Map.Entry extends MerchantRecipe, ? extends Integer> entry : trades) {
+ MerchantRecipe recipe = entry.getKey();
+ List ingredients = recipe.getIngredients();
+
+ if (ingredients.size() < 1) {
+ throw new IllegalStateException("Merchant recipe has no ingredients");
+ }
+
+ ItemStack itemA = ingredients.get(0);
+ ItemStack itemB = null;
+
+ if (ingredients.size() >= 2) {
+ itemB = ingredients.get(1);
+ }
+
+ net.minecraft.server.v1_16_R2.ItemStack nmsItemA = CraftItemStack.asNMSCopy(itemA);
+ net.minecraft.server.v1_16_R2.ItemStack nmsItemB = net.minecraft.server.v1_16_R2.ItemStack.b;
+ net.minecraft.server.v1_16_R2.ItemStack nmsItemResult = CraftItemStack.asNMSCopy(recipe.getResult());
+
+ if (itemB != null) {
+ nmsItemB = CraftItemStack.asNMSCopy(itemB);
+ }
+
+ int uses = recipe.getUses();
+ int maxUses = recipe.getMaxUses();
+ int exp = recipe.getVillagerExperience();
+ float multiplier = recipe.getPriceMultiplier();
+
+ net.minecraft.server.v1_16_R2.MerchantRecipe merchantOffer = new net.minecraft.server.v1_16_R2.MerchantRecipe(
+ nmsItemA, nmsItemB, nmsItemResult, uses, maxUses, exp, multiplier
+ );
+ merchantOffer.setSpecialPrice(entry.getValue());
+
+ offers.add(merchantOffer);
+ }
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ entityPlayer.openTrade(getWindowId(entityPlayer), offers, level, experience, true, false);
+ }
+
+ /**
+ * Gets the entity player associated to this player
+ *
+ * @param player the player to get the entity player from
+ * @return the entity player
+ * @since 0.10.1
+ */
+ @NotNull
+ @Contract(pure = true)
+ private EntityPlayer getEntityPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * Gets the window id for the inventory view the player currently has open
+ *
+ * @param entityPlayer the player to get the window id for
+ * @return the window id
+ * @since 0.10.1
+ */
+ @Contract(pure = true)
+ private int getWindowId(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.activeContainer.windowId;
+ }
+}
diff --git a/nms/1_16_R2/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R2/SmithingTableInventoryImpl.java b/nms/1_16_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_2_3/SmithingTableInventoryImpl.java
similarity index 91%
rename from nms/1_16_R2/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R2/SmithingTableInventoryImpl.java
rename to nms/1_16_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_2_3/SmithingTableInventoryImpl.java
index 82779d966..18dad0415 100644
--- a/nms/1_16_R2/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R2/SmithingTableInventoryImpl.java
+++ b/nms/1_16_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_2_3/SmithingTableInventoryImpl.java
@@ -1,224 +1,231 @@
-package com.github.stefvanschie.inventoryframework.nms.v1_16_R2;
-
-import com.github.stefvanschie.inventoryframework.abstraction.SmithingTableInventory;
-import net.minecraft.server.v1_16_R2.*;
-import org.bukkit.craftbukkit.v1_16_R2.entity.CraftPlayer;
-import org.bukkit.craftbukkit.v1_16_R2.inventory.*;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.InventoryHolder;
-import org.jetbrains.annotations.Contract;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-/**
- * Internal smithing table inventory for 1.16 R2
- *
- * @since 0.8.0
- */
-public class SmithingTableInventoryImpl extends SmithingTableInventory {
-
- public SmithingTableInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
- super(inventoryHolder);
- }
-
- @Override
- public void openInventory(@NotNull Player player, @NotNull String title,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- int itemAmount = items.length;
-
- if (itemAmount != 3) {
- throw new IllegalArgumentException(
- "The amount of items for a stonecutter should be 3, but is '" + itemAmount + "'"
- );
- }
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
- ContainerSmithingTableImpl containerSmithingTable = new ContainerSmithingTableImpl(entityPlayer, items);
-
- entityPlayer.activeContainer = containerSmithingTable;
-
- int id = containerSmithingTable.windowId;
- ChatMessage message = new ChatMessage(title);
- PacketPlayOutOpenWindow packet = new PacketPlayOutOpenWindow(id, Containers.SMITHING, message);
-
- entityPlayer.playerConnection.sendPacket(packet);
-
- sendItems(player, items);
- }
-
- @Override
- public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
- NonNullList nmsItems = NonNullList.a(
- ItemStack.b,
- CraftItemStack.asNMSCopy(items[0]),
- CraftItemStack.asNMSCopy(items[1]),
- CraftItemStack.asNMSCopy(items[2])
- );
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
- }
-
- @Override
- public void sendFirstItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
- EntityPlayer entityPlayer = getEntityPlayer(player);
- ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutSetSlot(getWindowId(entityPlayer), 0, nmsItem));
- }
-
- @Override
- public void sendSecondItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
- EntityPlayer entityPlayer = getEntityPlayer(player);
- ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutSetSlot(getWindowId(entityPlayer), 1, nmsItem));
- }
-
- @Override
- public void sendResultItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
- sendResultItem(player, CraftItemStack.asNMSCopy(item));
- }
-
- @Override
- public void clearResultItem(@NotNull Player player) {
- sendResultItem(player, ItemStack.b);
- }
-
- @Override
- public void setCursor(@NotNull Player player, @NotNull org.bukkit.inventory.ItemStack item) {
- setCursor(player, CraftItemStack.asNMSCopy(item));
- }
-
- @Override
- public void clearCursor(@NotNull Player player) {
- getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.b));
- }
-
- /**
- * Sets the cursor of the given player
- *
- * @param player the player to set the cursor
- * @param item the item to set the cursor to
- * @since 0.8.0
- */
- private void setCursor(@NotNull Player player, @NotNull ItemStack item) {
- getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, item));
- }
-
- /**
- * Sends the result item to the specified player with the given item
- *
- * @param player the player to send the result item to
- * @param item the result item
- * @since 0.8.0
- */
- private void sendResultItem(@NotNull Player player, @NotNull ItemStack item) {
- EntityPlayer entityPlayer = getEntityPlayer(player);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutSetSlot(getWindowId(entityPlayer), 2, item));
- }
-
- /**
- * Gets the window id for the inventory view the player currently has open
- *
- * @param entityPlayer the player to get the window id for
- * @return the window id
- * @since 0.8.0
- */
- @Contract(pure = true)
- private int getWindowId(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.activeContainer.windowId;
- }
-
- /**
- * Gets the player connection for the specified player
- *
- * @param entityPlayer the player to get the player connection from
- * @return the player connection
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.playerConnection;
- }
-
- /**
- * Gets the entity player associated to this player
- *
- * @param player the player to get the entity player from
- * @return the entity player
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private EntityPlayer getEntityPlayer(@NotNull Player player) {
- return ((CraftPlayer) player).getHandle();
- }
-
- /**
- * A custom container smithing table
- *
- * @since 0.8.0
- */
- private class ContainerSmithingTableImpl extends ContainerSmithing {
-
- /**
- * The player for this smithing table container
- */
- @NotNull
- private final Player player;
-
- /**
- * The internal bukkit entity for this container smithing table
- */
- @Nullable
- private CraftInventoryView bukkitEntity;
-
- public ContainerSmithingTableImpl(@NotNull EntityPlayer entityPlayer,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- super(entityPlayer.nextContainerCounter(), entityPlayer.inventory,
- ContainerAccess.at(entityPlayer.getWorld(), new BlockPosition(0, 0, 0)));
-
- this.player = entityPlayer.getBukkitEntity();
-
- repairInventory.setItem(0, CraftItemStack.asNMSCopy(items[0]));
- repairInventory.setItem(1, CraftItemStack.asNMSCopy(items[1]));
- resultInventory.setItem(0, CraftItemStack.asNMSCopy(items[2]));
- }
-
- @NotNull
- @Override
- public CraftInventoryView getBukkitView() {
- if (bukkitEntity == null) {
- CraftInventory inventory = new CraftInventorySmithing(containerAccess.getLocation(), repairInventory,
- resultInventory) {
- @NotNull
- @Contract(pure = true)
- @Override
- public InventoryHolder getHolder() {
- return inventoryHolder;
- }
- };
-
- bukkitEntity = new CraftInventoryView(player, inventory, this);
- }
-
- return bukkitEntity;
- }
-
- @Contract(pure = true, value = "_ -> true")
- @Override
- public boolean canUse(@Nullable EntityHuman entityhuman) {
- return true;
- }
-
- @Override
- public void a(IInventory inventory) {}
-
- @Override
- public void b(EntityHuman entityhuman) {}
- }
-}
+package com.github.stefvanschie.inventoryframework.nms.v1_16_2_3;
+
+import com.github.stefvanschie.inventoryframework.abstraction.SmithingTableInventory;
+import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
+import com.github.stefvanschie.inventoryframework.nms.v1_16_2_3.util.TextHolderUtil;
+import net.minecraft.server.v1_16_R2.*;
+import org.bukkit.craftbukkit.v1_16_R2.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_16_R2.inventory.*;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.InventoryHolder;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Internal smithing table inventory for 1.16 R2
+ *
+ * @since 0.8.0
+ */
+public class SmithingTableInventoryImpl extends SmithingTableInventory {
+
+ public SmithingTableInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
+ super(inventoryHolder);
+ }
+
+ @Nullable
+ @Override
+ public Inventory openInventory(@NotNull Player player, @NotNull TextHolder title,
+ @Nullable org.bukkit.inventory.ItemStack[] items) {
+ int itemAmount = items.length;
+
+ if (itemAmount != 3) {
+ throw new IllegalArgumentException(
+ "The amount of items for a stonecutter should be 3, but is '" + itemAmount + "'"
+ );
+ }
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+ ContainerSmithingTableImpl containerSmithingTable = new ContainerSmithingTableImpl(entityPlayer, items);
+
+ entityPlayer.activeContainer = containerSmithingTable;
+
+ int id = containerSmithingTable.windowId;
+ IChatBaseComponent message = TextHolderUtil.toComponent(title);
+ PacketPlayOutOpenWindow packet = new PacketPlayOutOpenWindow(id, Containers.SMITHING, message);
+
+ entityPlayer.playerConnection.sendPacket(packet);
+
+ sendItems(player, items, null);
+
+ return null;
+ }
+
+ @Override
+ public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items,
+ @Nullable org.bukkit.inventory.ItemStack cursor) {
+ NonNullList nmsItems = NonNullList.a(
+ ItemStack.b,
+ CraftItemStack.asNMSCopy(items[0]),
+ CraftItemStack.asNMSCopy(items[1]),
+ CraftItemStack.asNMSCopy(items[2])
+ );
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
+ }
+
+ @Override
+ public void sendFirstItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+ ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutSetSlot(getWindowId(entityPlayer), 0, nmsItem));
+ }
+
+ @Override
+ public void sendSecondItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+ ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutSetSlot(getWindowId(entityPlayer), 1, nmsItem));
+ }
+
+ @Override
+ public void sendResultItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
+ sendResultItem(player, CraftItemStack.asNMSCopy(item));
+ }
+
+ @Override
+ public void clearResultItem(@NotNull Player player) {
+ sendResultItem(player, ItemStack.b);
+ }
+
+ @Override
+ public void setCursor(@NotNull Player player, @NotNull org.bukkit.inventory.ItemStack item) {
+ setCursor(player, CraftItemStack.asNMSCopy(item));
+ }
+
+ @Override
+ public void clearCursor(@NotNull Player player) {
+ getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.b));
+ }
+
+ /**
+ * Sets the cursor of the given player
+ *
+ * @param player the player to set the cursor
+ * @param item the item to set the cursor to
+ * @since 0.8.0
+ */
+ private void setCursor(@NotNull Player player, @NotNull ItemStack item) {
+ getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, item));
+ }
+
+ /**
+ * Sends the result item to the specified player with the given item
+ *
+ * @param player the player to send the result item to
+ * @param item the result item
+ * @since 0.8.0
+ */
+ private void sendResultItem(@NotNull Player player, @NotNull ItemStack item) {
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutSetSlot(getWindowId(entityPlayer), 2, item));
+ }
+
+ /**
+ * Gets the window id for the inventory view the player currently has open
+ *
+ * @param entityPlayer the player to get the window id for
+ * @return the window id
+ * @since 0.8.0
+ */
+ @Contract(pure = true)
+ private int getWindowId(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.activeContainer.windowId;
+ }
+
+ /**
+ * Gets the player connection for the specified player
+ *
+ * @param entityPlayer the player to get the player connection from
+ * @return the player connection
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.playerConnection;
+ }
+
+ /**
+ * Gets the entity player associated to this player
+ *
+ * @param player the player to get the entity player from
+ * @return the entity player
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private EntityPlayer getEntityPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * A custom container smithing table
+ *
+ * @since 0.8.0
+ */
+ private class ContainerSmithingTableImpl extends ContainerSmithing {
+
+ /**
+ * The player for this smithing table container
+ */
+ @NotNull
+ private final Player player;
+
+ /**
+ * The internal bukkit entity for this container smithing table
+ */
+ @Nullable
+ private CraftInventoryView bukkitEntity;
+
+ public ContainerSmithingTableImpl(@NotNull EntityPlayer entityPlayer,
+ @Nullable org.bukkit.inventory.ItemStack[] items) {
+ super(entityPlayer.nextContainerCounter(), entityPlayer.inventory,
+ ContainerAccess.at(entityPlayer.getWorld(), new BlockPosition(0, 0, 0)));
+
+ this.player = entityPlayer.getBukkitEntity();
+
+ repairInventory.setItem(0, CraftItemStack.asNMSCopy(items[0]));
+ repairInventory.setItem(1, CraftItemStack.asNMSCopy(items[1]));
+ resultInventory.setItem(0, CraftItemStack.asNMSCopy(items[2]));
+ }
+
+ @NotNull
+ @Override
+ public CraftInventoryView getBukkitView() {
+ if (bukkitEntity == null) {
+ CraftInventory inventory = new CraftInventorySmithing(containerAccess.getLocation(), repairInventory,
+ resultInventory) {
+ @NotNull
+ @Contract(pure = true)
+ @Override
+ public InventoryHolder getHolder() {
+ return inventoryHolder;
+ }
+ };
+
+ bukkitEntity = new CraftInventoryView(player, inventory, this);
+ }
+
+ return bukkitEntity;
+ }
+
+ @Contract(pure = true, value = "_ -> true")
+ @Override
+ public boolean canUse(@Nullable EntityHuman entityhuman) {
+ return true;
+ }
+
+ @Override
+ public void a(IInventory inventory) {}
+
+ @Override
+ public void b(EntityHuman entityhuman) {}
+ }
+}
diff --git a/nms/1_16_R2/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R2/StonecutterInventoryImpl.java b/nms/1_16_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_2_3/StonecutterInventoryImpl.java
similarity index 94%
rename from nms/1_16_R2/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R2/StonecutterInventoryImpl.java
rename to nms/1_16_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_2_3/StonecutterInventoryImpl.java
index 83d8d88d4..05f40294e 100644
--- a/nms/1_16_R2/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R2/StonecutterInventoryImpl.java
+++ b/nms/1_16_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_2_3/StonecutterInventoryImpl.java
@@ -1,196 +1,198 @@
-package com.github.stefvanschie.inventoryframework.nms.v1_16_R2;
-
-import com.github.stefvanschie.inventoryframework.abstraction.StonecutterInventory;
-import net.minecraft.server.v1_16_R2.*;
-import org.bukkit.craftbukkit.v1_16_R2.entity.CraftPlayer;
-import org.bukkit.craftbukkit.v1_16_R2.inventory.*;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.InventoryHolder;
-import org.jetbrains.annotations.Contract;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.lang.reflect.Field;
-
-/**
- * Internal stonecutter inventory for 1.16 R2
- *
- * @since 0.8.0
- */
-public class StonecutterInventoryImpl extends StonecutterInventory {
-
- public StonecutterInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
- super(inventoryHolder);
- }
-
- @Override
- public void openInventory(@NotNull Player player, @NotNull String title,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- int itemAmount = items.length;
-
- if (itemAmount != 2) {
- throw new IllegalArgumentException(
- "The amount of items for a stonecutter should be 2, but is '" + itemAmount + "'"
- );
- }
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
- ContainerStonecutterImpl containerEnchantmentTable = new ContainerStonecutterImpl(entityPlayer, items);
-
- entityPlayer.activeContainer = containerEnchantmentTable;
-
- int id = containerEnchantmentTable.windowId;
- ChatMessage message = new ChatMessage(title);
- PacketPlayOutOpenWindow packet = new PacketPlayOutOpenWindow(id, Containers.STONECUTTER, message);
-
- entityPlayer.playerConnection.sendPacket(packet);
-
- sendItems(player, items);
- }
-
- @Override
- public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
- NonNullList nmsItems = NonNullList.a(
- ItemStack.b,
- CraftItemStack.asNMSCopy(items[0]),
- CraftItemStack.asNMSCopy(items[1])
- );
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
- }
-
- @Override
- public void clearCursor(@NotNull Player player) {
- getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.b));
- }
-
- /**
- * Gets the window id for the inventory view the player currently has open
- *
- * @param entityPlayer the player to get the window id for
- * @return the window id
- * @since 0.8.0
- */
- @Contract(pure = true)
- private int getWindowId(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.activeContainer.windowId;
- }
-
- /**
- * Gets the player connection for the specified player
- *
- * @param entityPlayer the player to get the player connection from
- * @return the player connection
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.playerConnection;
- }
-
- /**
- * Gets the entity player associated to this player
- *
- * @param player the player to get the entity player from
- * @return the entity player
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private EntityPlayer getEntityPlayer(@NotNull Player player) {
- return ((CraftPlayer) player).getHandle();
- }
-
- /**
- * A custom container enchanting table
- *
- * @since 0.8.0
- */
- private class ContainerStonecutterImpl extends ContainerStonecutter {
-
- /**
- * The player for this enchanting table container
- */
- @NotNull
- private final Player player;
-
- /**
- * The internal bukkit entity for this container enchanting table
- */
- @Nullable
- private CraftInventoryView bukkitEntity;
-
- /**
- * Field for accessing the result inventory field
- */
- @NotNull
- private final Field resultInventoryField;
-
- public ContainerStonecutterImpl(@NotNull EntityPlayer entityPlayer,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
-
- this.player = entityPlayer.getBukkitEntity();
-
- try {
- this.resultInventoryField = ContainerStonecutter.class.getDeclaredField("resultInventory");
- this.resultInventoryField.setAccessible(true);
- } catch (NoSuchFieldException exception) {
- throw new RuntimeException(exception);
- }
-
- inventory.setItem(0, CraftItemStack.asNMSCopy(items[0]));
- getResultInventory().setItem(0, CraftItemStack.asNMSCopy(items[1]));
- }
-
- @NotNull
- @Override
- public CraftInventoryView getBukkitView() {
- if (bukkitEntity == null) {
- CraftInventory inventory = new CraftInventoryStonecutter(this.inventory, getResultInventory()) {
- @NotNull
- @Contract(pure = true)
- @Override
- public InventoryHolder getHolder() {
- return inventoryHolder;
- }
- };
-
- bukkitEntity = new CraftInventoryView(player, inventory, this);
- }
-
- return bukkitEntity;
- }
-
- @Contract(pure = true, value = "_ -> true")
- @Override
- public boolean canUse(@Nullable EntityHuman entityhuman) {
- return true;
- }
-
- @Override
- public void a(IInventory inventory) {}
-
- @Override
- public void b(EntityHuman entityhuman) {}
-
- /**
- * Gets the result inventory
- *
- * @return the result inventory
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- public IInventory getResultInventory() {
- try {
- return (IInventory) resultInventoryField.get(this);
- } catch (IllegalAccessException exception) {
- throw new RuntimeException(exception);
- }
- }
- }
-}
+package com.github.stefvanschie.inventoryframework.nms.v1_16_2_3;
+
+import com.github.stefvanschie.inventoryframework.abstraction.StonecutterInventory;
+import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
+import com.github.stefvanschie.inventoryframework.nms.v1_16_2_3.util.TextHolderUtil;
+import net.minecraft.server.v1_16_R2.*;
+import org.bukkit.craftbukkit.v1_16_R2.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_16_R2.inventory.*;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.InventoryHolder;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.lang.reflect.Field;
+
+/**
+ * Internal stonecutter inventory for 1.16 R2
+ *
+ * @since 0.8.0
+ */
+public class StonecutterInventoryImpl extends StonecutterInventory {
+
+ public StonecutterInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
+ super(inventoryHolder);
+ }
+
+ @Override
+ public void openInventory(@NotNull Player player, @NotNull TextHolder title,
+ @Nullable org.bukkit.inventory.ItemStack[] items) {
+ int itemAmount = items.length;
+
+ if (itemAmount != 2) {
+ throw new IllegalArgumentException(
+ "The amount of items for a stonecutter should be 2, but is '" + itemAmount + "'"
+ );
+ }
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+ ContainerStonecutterImpl containerEnchantmentTable = new ContainerStonecutterImpl(entityPlayer, items);
+
+ entityPlayer.activeContainer = containerEnchantmentTable;
+
+ int id = containerEnchantmentTable.windowId;
+ IChatBaseComponent message = TextHolderUtil.toComponent(title);
+ PacketPlayOutOpenWindow packet = new PacketPlayOutOpenWindow(id, Containers.STONECUTTER, message);
+
+ entityPlayer.playerConnection.sendPacket(packet);
+
+ sendItems(player, items);
+ }
+
+ @Override
+ public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
+ NonNullList nmsItems = NonNullList.a(
+ ItemStack.b,
+ CraftItemStack.asNMSCopy(items[0]),
+ CraftItemStack.asNMSCopy(items[1])
+ );
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
+ }
+
+ @Override
+ public void clearCursor(@NotNull Player player) {
+ getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.b));
+ }
+
+ /**
+ * Gets the window id for the inventory view the player currently has open
+ *
+ * @param entityPlayer the player to get the window id for
+ * @return the window id
+ * @since 0.8.0
+ */
+ @Contract(pure = true)
+ private int getWindowId(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.activeContainer.windowId;
+ }
+
+ /**
+ * Gets the player connection for the specified player
+ *
+ * @param entityPlayer the player to get the player connection from
+ * @return the player connection
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.playerConnection;
+ }
+
+ /**
+ * Gets the entity player associated to this player
+ *
+ * @param player the player to get the entity player from
+ * @return the entity player
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private EntityPlayer getEntityPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * A custom container enchanting table
+ *
+ * @since 0.8.0
+ */
+ private class ContainerStonecutterImpl extends ContainerStonecutter {
+
+ /**
+ * The player for this enchanting table container
+ */
+ @NotNull
+ private final Player player;
+
+ /**
+ * The internal bukkit entity for this container enchanting table
+ */
+ @Nullable
+ private CraftInventoryView bukkitEntity;
+
+ /**
+ * Field for accessing the result inventory field
+ */
+ @NotNull
+ private final Field resultInventoryField;
+
+ public ContainerStonecutterImpl(@NotNull EntityPlayer entityPlayer,
+ @Nullable org.bukkit.inventory.ItemStack[] items) {
+ super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
+
+ this.player = entityPlayer.getBukkitEntity();
+
+ try {
+ this.resultInventoryField = ContainerStonecutter.class.getDeclaredField("resultInventory");
+ this.resultInventoryField.setAccessible(true);
+ } catch (NoSuchFieldException exception) {
+ throw new RuntimeException(exception);
+ }
+
+ inventory.setItem(0, CraftItemStack.asNMSCopy(items[0]));
+ getResultInventory().setItem(0, CraftItemStack.asNMSCopy(items[1]));
+ }
+
+ @NotNull
+ @Override
+ public CraftInventoryView getBukkitView() {
+ if (bukkitEntity == null) {
+ CraftInventory inventory = new CraftInventoryStonecutter(this.inventory, getResultInventory()) {
+ @NotNull
+ @Contract(pure = true)
+ @Override
+ public InventoryHolder getHolder() {
+ return inventoryHolder;
+ }
+ };
+
+ bukkitEntity = new CraftInventoryView(player, inventory, this);
+ }
+
+ return bukkitEntity;
+ }
+
+ @Contract(pure = true, value = "_ -> true")
+ @Override
+ public boolean canUse(@Nullable EntityHuman entityhuman) {
+ return true;
+ }
+
+ @Override
+ public void a(IInventory inventory) {}
+
+ @Override
+ public void b(EntityHuman entityhuman) {}
+
+ /**
+ * Gets the result inventory
+ *
+ * @return the result inventory
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ public IInventory getResultInventory() {
+ try {
+ return (IInventory) resultInventoryField.get(this);
+ } catch (IllegalAccessException exception) {
+ throw new RuntimeException(exception);
+ }
+ }
+ }
+}
diff --git a/nms/1_16_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_2_3/util/TextHolderUtil.java b/nms/1_16_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_2_3/util/TextHolderUtil.java
new file mode 100644
index 000000000..42b2c9036
--- /dev/null
+++ b/nms/1_16_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_2_3/util/TextHolderUtil.java
@@ -0,0 +1,66 @@
+package com.github.stefvanschie.inventoryframework.nms.v1_16_2_3.util;
+
+import com.github.stefvanschie.inventoryframework.adventuresupport.ComponentHolder;
+import com.github.stefvanschie.inventoryframework.adventuresupport.StringHolder;
+import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
+import net.minecraft.server.v1_16_R2.ChatComponentText;
+import net.minecraft.server.v1_16_R2.IChatBaseComponent;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Objects;
+
+/**
+ * A utility class for adding {@link TextHolder} support.
+ *
+ * @since 0.10.0
+ */
+public final class TextHolderUtil {
+
+ private TextHolderUtil() {
+ //private constructor to prevent construction
+ }
+
+ /**
+ * Converts the specified value to a vanilla component.
+ *
+ * @param holder the value to convert
+ * @return the value as a vanilla component
+ * @since 0.10.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ public static IChatBaseComponent toComponent(@NotNull TextHolder holder) {
+ if (holder instanceof StringHolder) {
+ return toComponent((StringHolder) holder);
+ } else {
+ return toComponent((ComponentHolder) holder);
+ }
+ }
+
+ /**
+ * Converts the specified legacy string holder to a vanilla component.
+ *
+ * @param holder the value to convert
+ * @return the value as a vanilla component
+ * @since 0.10.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private static IChatBaseComponent toComponent(@NotNull StringHolder holder) {
+ return new ChatComponentText(holder.asLegacyString());
+ }
+
+ /**
+ * Converts the specified Adventure component holder to a vanilla component.
+ *
+ * @param holder the value to convert
+ * @return the value as a vanilla component
+ * @since 0.10.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private static IChatBaseComponent toComponent(@NotNull ComponentHolder holder) {
+ return Objects.requireNonNull(IChatBaseComponent.ChatSerializer.a(holder.asJson()));
+ }
+}
diff --git a/nms/1_16_R3/pom.xml b/nms/1_16_4-5/pom.xml
similarity index 86%
rename from nms/1_16_R3/pom.xml
rename to nms/1_16_4-5/pom.xml
index 5ddb316fd..8f5722fb5 100644
--- a/nms/1_16_R3/pom.xml
+++ b/nms/1_16_4-5/pom.xml
@@ -5,30 +5,30 @@
IF-parent
com.github.stefvanschie.inventoryframework
- 0.9.8
+ 0.10.18
../../pom.xml
4.0.0
- 1_16_R3
+ 1_16_4-5
true
+
+ io.papermc
+ paper
+ 1.16.4-R0.1-SNAPSHOT
+ provided
+
com.github.stefvanschie.inventoryframework
abstraction
${project.version}
compile
-
- org.spigotmc
- spigot
- 1.16.4-R0.1-SNAPSHOT
- provided
-
\ No newline at end of file
diff --git a/nms/1_16_4-5/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_4_5/AnvilInventoryImpl.java b/nms/1_16_4-5/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_4_5/AnvilInventoryImpl.java
new file mode 100644
index 000000000..99f65b47e
--- /dev/null
+++ b/nms/1_16_4-5/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_4_5/AnvilInventoryImpl.java
@@ -0,0 +1,386 @@
+package com.github.stefvanschie.inventoryframework.nms.v1_16_4_5;
+
+import com.github.stefvanschie.inventoryframework.abstraction.AnvilInventory;
+import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
+import com.github.stefvanschie.inventoryframework.nms.v1_16_4_5.util.TextHolderUtil;
+import net.minecraft.server.v1_16_R3.*;
+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.InventoryHolder;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.lang.reflect.Field;
+import java.util.Collections;
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * Internal anvil inventory for 1.16 R3
+ *
+ * @since 0.8.0
+ */
+public class AnvilInventoryImpl extends AnvilInventory {
+
+ public AnvilInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
+ super(inventoryHolder);
+ }
+
+ @Override
+ public Inventory openInventory(@NotNull Player player, @NotNull TextHolder title,
+ @Nullable org.bukkit.inventory.ItemStack[] items) {
+ int itemAmount = items.length;
+
+ if (itemAmount != 3) {
+ throw new IllegalArgumentException(
+ "The amount of items for an anvil should be 3, but is '" + itemAmount + "'"
+ );
+ }
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ //ignore deprecation: superseding method is only available on Paper
+ //noinspection deprecation
+ CraftEventFactory.handleInventoryCloseEvent(entityPlayer);
+
+ entityPlayer.activeContainer = entityPlayer.defaultContainer;
+
+ IChatBaseComponent message = TextHolderUtil.toComponent(title);
+ ContainerAnvilImpl containerAnvil = new ContainerAnvilImpl(entityPlayer, message);
+
+ Inventory inventory = containerAnvil.getBukkitView().getTopInventory();
+
+ inventory.setItem(0, items[0]);
+ inventory.setItem(1, items[1]);
+ inventory.setItem(2, items[2]);
+
+ int containerId = containerAnvil.getContainerId();
+
+ entityPlayer.playerConnection.sendPacket(new PacketPlayOutOpenWindow(containerId, Containers.ANVIL, message));
+ entityPlayer.activeContainer = containerAnvil;
+ entityPlayer.syncInventory();
+
+ return inventory;
+ }
+
+ @Override
+ public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
+ NonNullList nmsItems = NonNullList.a(
+ ItemStack.b,
+ CraftItemStack.asNMSCopy(items[0]),
+ CraftItemStack.asNMSCopy(items[1]),
+ CraftItemStack.asNMSCopy(items[2])
+ );
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
+ }
+
+ @Override
+ public void sendFirstItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+ ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutSetSlot(getWindowId(entityPlayer), 0, nmsItem));
+ }
+
+ @Override
+ public void sendSecondItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+ ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutSetSlot(getWindowId(entityPlayer), 1, nmsItem));
+ }
+
+ @Override
+ public void sendResultItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
+ sendResultItem(player, CraftItemStack.asNMSCopy(item));
+ }
+
+ @Override
+ public void clearResultItem(@NotNull Player player) {
+ sendResultItem(player, ItemStack.b);
+ }
+
+ @Override
+ public void setCursor(@NotNull Player player, @NotNull org.bukkit.inventory.ItemStack item) {
+ setCursor(player, CraftItemStack.asNMSCopy(item));
+ }
+
+ @Override
+ public void clearCursor(@NotNull Player player) {
+ getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.b));
+ }
+
+ /**
+ * Sets the cursor of the given player
+ *
+ * @param player the player to set the cursor
+ * @param item the item to set the cursor to
+ * @since 0.8.0
+ * @deprecated no longer used internally
+ */
+ @Deprecated
+ private void setCursor(@NotNull Player player, @NotNull ItemStack item) {
+ getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, item));
+ }
+
+ /**
+ * Sends the result item to the specified player with the given item
+ *
+ * @param player the player to send the result item to
+ * @param item the result item
+ * @since 0.8.0
+ * @deprecated no longer used internally
+ */
+ @Deprecated
+ private void sendResultItem(@NotNull Player player, @NotNull ItemStack item) {
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutSetSlot(getWindowId(entityPlayer), 2, item));
+ }
+
+ /**
+ * Gets the window id for the inventory view the player currently has open
+ *
+ * @param entityPlayer the player to get the window id for
+ * @return the window id
+ * @since 0.8.0
+ * @deprecated no longer used internally
+ */
+ @Contract(pure = true)
+ @Deprecated
+ private int getWindowId(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.activeContainer.windowId;
+ }
+
+ /**
+ * Gets the player connection for the specified player
+ *
+ * @param entityPlayer the player to get the player connection from
+ * @return the player connection
+ * @since 0.8.0
+ * @deprecated no longer used internally
+ */
+ @NotNull
+ @Contract(pure = true)
+ @Deprecated
+ private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.playerConnection;
+ }
+
+ /**
+ * Gets the entity player associated to this player
+ *
+ * @param player the player to get the entity player from
+ * @return the entity player
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private EntityPlayer getEntityPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * A custom container anvil for responding to item renaming
+ *
+ * @since 0.8.0
+ */
+ private class ContainerAnvilImpl extends ContainerAnvil {
+
+ /**
+ * The index of the result slot
+ */
+ private static final int RESULT_SLOT_INDEX = 2;
+
+ /**
+ * A unique item
+ */
+ @NotNull
+ private final ItemStack uniqueItem;
+
+ /**
+ * The field containing the listeners for this container
+ */
+ @NotNull
+ private final Field listenersField;
+
+ /**
+ * Creates a new custom anvil container for the specified player
+ *
+ * @param entityPlayer the player for whom this anvil container is
+ * @param title the title of the inventory
+ * @since 0.10.8
+ */
+ public ContainerAnvilImpl(@NotNull EntityPlayer entityPlayer, @NotNull IChatBaseComponent title) {
+ super(entityPlayer.nextContainerCounter(), entityPlayer.inventory,
+ ContainerAccess.at(entityPlayer.getWorld(), new BlockPosition(0, 0, 0)));
+
+ this.checkReachable = false;
+
+ try {
+ //stores all the registered container properties
+ Field dField = Container.class.getDeclaredField("d");
+ dField.setAccessible(true);
+
+ //get rid of the level cost property
+ ((List>) dField.get(this)).clear();
+ } catch (NoSuchFieldException | IllegalAccessException exception) {
+ throw new RuntimeException("Unable to access field 'd'", exception);
+ }
+
+ try {
+ this.listenersField = Container.class.getDeclaredField("listeners");
+ this.listenersField.setAccessible(true);
+ } catch (NoSuchFieldException exception) {
+ throw new RuntimeException("Unable to access field 'listeners'", exception);
+ }
+
+ //register a new property for the level cost
+ ContainerProperty levelCost = a(new ContainerProperty() {
+ private int value;
+
+ @Override
+ public int get() {
+ return value;
+ }
+
+ @Override
+ public void set(int value) {
+ this.value = value;
+ }
+
+ /*
+ This checks whether there have been any changes, but we want to override the client prediction. This
+ means the server should be sending the data to the client, even if it didn't change server-side. To
+ force this, we tell the server the data has always changed.
+ */
+ @Override
+ public boolean c() {
+ return true;
+ }
+ });
+
+ levelCost.set(AnvilInventoryImpl.super.cost);
+
+ setTitle(title);
+
+ Slot originalSlot = this.slots.get(RESULT_SLOT_INDEX);
+
+ Slot newSlot = new Slot(originalSlot.inventory, originalSlot.index, originalSlot.e, originalSlot.f) {
+ @Override
+ public boolean isAllowed(ItemStack itemStack) {
+ return true;
+ }
+
+ @Override
+ public boolean isAllowed(EntityHuman entityHuman) {
+ return true;
+ }
+
+ @Override
+ public ItemStack a(EntityHuman entityHuman, @NotNull ItemStack itemStack) {
+ return originalSlot.a(entityHuman, itemStack);
+ }
+ };
+
+ this.slots.set(RESULT_SLOT_INDEX, newSlot);
+
+ this.uniqueItem = new ItemStack(Items.COOKIE);
+
+ //to make the item unique, we add a random uuid as nbt to it
+ UUID uuid = UUID.randomUUID();
+ NBTTagCompound nbtTagCompound = new NBTTagCompound();
+
+ nbtTagCompound.set("uuid", new NBTTagLongArray(new long [] {
+ uuid.getLeastSignificantBits(),
+ uuid.getMostSignificantBits()
+ }));
+
+ this.uniqueItem.setTag(nbtTagCompound);
+ }
+
+ @Override
+ public void a(@Nullable String name) {
+ name = name == null ? "" : name;
+
+ /* Only update if the name is actually different. This may be called even if the name is not different,
+ particularly when putting an item in the first slot. */
+ if (!name.equals(AnvilInventoryImpl.super.observableText.get())) {
+ AnvilInventoryImpl.super.observableText.set(name);
+ }
+
+ //the client predicts the output result, so we broadcast the state again to override it
+ forceUpdate();
+ }
+
+ @Override
+ public void e() {}
+
+ @Override
+ public void b(EntityHuman entityHuman) {}
+
+ @Override
+ protected void a(EntityHuman entityHuman, World world, @NotNull IInventory inventory) {}
+
+ @Override
+ protected ItemStack a(EntityHuman entityHuman, @NotNull ItemStack itemStack) {
+ return itemStack;
+ }
+
+ @Override
+ public ItemStack a(int i, int j, InventoryClickType inventoryclicktype, EntityHuman entityhuman) {
+ ItemStack itemStack = super.a(i, j, inventoryclicktype, entityhuman);
+
+ //the client predicts the allowed movement of the item, so we broadcast the state again to override it
+ forceUpdate();
+
+ return itemStack;
+ }
+
+ public int getContainerId() {
+ return this.windowId;
+ }
+
+ /**
+ * Forcefully updates the client state, sending all items, container properties and the held item.
+ *
+ * @since 0.10.8
+ */
+ public void forceUpdate() {
+ /*
+ The server will not send the items when they haven't changed, so we will overwrite every item with a unique
+ item first to ensure the server is going to send our items.
+ */
+ Collections.fill(this.items, this.uniqueItem);
+
+ c();
+
+ List extends ICrafting> listeners;
+
+ try {
+ //noinspection unchecked
+ listeners = (List extends ICrafting>) listenersField.get(this);
+ } catch (IllegalAccessException exception) {
+ throw new RuntimeException("Unable to access field 'listeners'", exception);
+ }
+
+ for (ICrafting listener : listeners) {
+ if (!(listener instanceof EntityPlayer)) {
+ continue;
+ }
+
+ EntityPlayer player = (EntityPlayer) listener;
+
+ player.e = false;
+ player.broadcastCarriedItem();
+ }
+ }
+ }
+}
diff --git a/nms/1_16_R3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R3/BeaconInventoryImpl.java b/nms/1_16_4-5/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_4_5/BeaconInventoryImpl.java
similarity index 95%
rename from nms/1_16_R3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R3/BeaconInventoryImpl.java
rename to nms/1_16_4-5/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_4_5/BeaconInventoryImpl.java
index b1a433ab3..eaed00847 100644
--- a/nms/1_16_R3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R3/BeaconInventoryImpl.java
+++ b/nms/1_16_4-5/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_4_5/BeaconInventoryImpl.java
@@ -1,181 +1,181 @@
-package com.github.stefvanschie.inventoryframework.nms.v1_16_R3;
-
-import com.github.stefvanschie.inventoryframework.abstraction.BeaconInventory;
-import net.minecraft.server.v1_16_R3.*;
-import org.bukkit.craftbukkit.v1_16_R3.entity.CraftPlayer;
-import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftInventory;
-import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftInventoryBeacon;
-import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftInventoryView;
-import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftItemStack;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.InventoryHolder;
-import org.jetbrains.annotations.Contract;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.lang.reflect.Field;
-
-/**
- * Internal beacon inventory for 1.16 R3
- *
- * @since 0.8.0
- */
-public class BeaconInventoryImpl extends BeaconInventory {
-
- public BeaconInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
- super(inventoryHolder);
- }
-
- @Override
- public void openInventory(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
- EntityPlayer entityPlayer = getEntityPlayer(player);
- ContainerBeaconImpl containerBeacon = new ContainerBeaconImpl(entityPlayer, item);
-
- entityPlayer.activeContainer = containerBeacon;
-
- int id = containerBeacon.windowId;
- ChatMessage message = new ChatMessage("Beacon");
-
- entityPlayer.playerConnection.sendPacket(new PacketPlayOutOpenWindow(id, Containers.BEACON, message));
-
- sendItem(player, item);
- }
-
- @Override
- public void sendItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
- NonNullList items = NonNullList.a(
- ItemStack.b, //the first item doesn't count for some reason, so send a dummy item
- CraftItemStack.asNMSCopy(item)
- );
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), items));
- }
-
- @Override
- public void clearCursor(@NotNull Player player) {
- getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.b));
- }
-
- /**
- * Gets the window id for the inventory view the player currently has open
- *
- * @param entityPlayer the player to get the window id for
- * @return the window id
- * @since 0.8.0
- */
- @Contract(pure = true)
- private int getWindowId(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.activeContainer.windowId;
- }
-
- /**
- * Gets the player connection for the specified player
- *
- * @param entityPlayer the player to get the player connection from
- * @return the player connection
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.playerConnection;
- }
-
- /**
- * Gets the entity player associated to this player
- *
- * @param player the player to get the entity player from
- * @return the entity player
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private EntityPlayer getEntityPlayer(@NotNull Player player) {
- return ((CraftPlayer) player).getHandle();
- }
-
- /**
- * A custom container beacon
- *
- * @since 0.8.0
- */
- private class ContainerBeaconImpl extends ContainerBeacon {
-
- /**
- * The player for this beacon container
- */
- @NotNull
- private final Player player;
-
- /**
- * The internal bukkit entity for this container beacon
- */
- @Nullable
- private CraftInventoryView bukkitEntity;
-
- /**
- * Field for accessing the beacon field
- */
- @NotNull
- private final Field beaconField;
-
- public ContainerBeaconImpl(@NotNull EntityPlayer entityPlayer, @Nullable org.bukkit.inventory.ItemStack item) {
- super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
-
- this.player = entityPlayer.getBukkitEntity();
-
- try {
- this.beaconField = ContainerBeacon.class.getDeclaredField("beacon");
- this.beaconField.setAccessible(true);
- } catch (NoSuchFieldException exception) {
- throw new RuntimeException(exception);
- }
-
- try {
- ItemStack itemStack = CraftItemStack.asNMSCopy(item);
-
- ((IInventory) beaconField.get(this)).setItem(0, itemStack);
- } catch (IllegalAccessException exception) {
- throw new RuntimeException(exception);
- }
- }
-
- @NotNull
- @Override
- public CraftInventoryView getBukkitView() {
- if (bukkitEntity == null) {
- try {
- CraftInventory inventory = new CraftInventoryBeacon((IInventory) beaconField.get(this)) {
- @NotNull
- @Contract(pure = true)
- @Override
- public InventoryHolder getHolder() {
- return inventoryHolder;
- }
- };
-
- bukkitEntity = new CraftInventoryView(player, inventory, this);
- } catch (IllegalAccessException exception) {
- throw new RuntimeException(exception);
- }
- }
-
- return bukkitEntity;
- }
-
- @Contract(pure = true, value = "_ -> true")
- @Override
- public boolean canUse(@Nullable EntityHuman entityhuman) {
- return true;
- }
-
- @Override
- public void a(IInventory inventory) {}
-
- @Override
- public void b(EntityHuman entityhuman) {}
-
- }
-}
+package com.github.stefvanschie.inventoryframework.nms.v1_16_4_5;
+
+import com.github.stefvanschie.inventoryframework.abstraction.BeaconInventory;
+import net.minecraft.server.v1_16_R3.*;
+import org.bukkit.craftbukkit.v1_16_R3.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftInventory;
+import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftInventoryBeacon;
+import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftInventoryView;
+import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftItemStack;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.InventoryHolder;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.lang.reflect.Field;
+
+/**
+ * Internal beacon inventory for 1.16 R3
+ *
+ * @since 0.8.0
+ */
+public class BeaconInventoryImpl extends BeaconInventory {
+
+ public BeaconInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
+ super(inventoryHolder);
+ }
+
+ @Override
+ public void openInventory(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+ ContainerBeaconImpl containerBeacon = new ContainerBeaconImpl(entityPlayer, item);
+
+ entityPlayer.activeContainer = containerBeacon;
+
+ int id = containerBeacon.windowId;
+ ChatMessage message = new ChatMessage("Beacon");
+
+ entityPlayer.playerConnection.sendPacket(new PacketPlayOutOpenWindow(id, Containers.BEACON, message));
+
+ sendItem(player, item);
+ }
+
+ @Override
+ public void sendItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
+ NonNullList items = NonNullList.a(
+ ItemStack.b, //the first item doesn't count for some reason, so send a dummy item
+ CraftItemStack.asNMSCopy(item)
+ );
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), items));
+ }
+
+ @Override
+ public void clearCursor(@NotNull Player player) {
+ getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.b));
+ }
+
+ /**
+ * Gets the window id for the inventory view the player currently has open
+ *
+ * @param entityPlayer the player to get the window id for
+ * @return the window id
+ * @since 0.8.0
+ */
+ @Contract(pure = true)
+ private int getWindowId(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.activeContainer.windowId;
+ }
+
+ /**
+ * Gets the player connection for the specified player
+ *
+ * @param entityPlayer the player to get the player connection from
+ * @return the player connection
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.playerConnection;
+ }
+
+ /**
+ * Gets the entity player associated to this player
+ *
+ * @param player the player to get the entity player from
+ * @return the entity player
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private EntityPlayer getEntityPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * A custom container beacon
+ *
+ * @since 0.8.0
+ */
+ private class ContainerBeaconImpl extends ContainerBeacon {
+
+ /**
+ * The player for this beacon container
+ */
+ @NotNull
+ private final Player player;
+
+ /**
+ * The internal bukkit entity for this container beacon
+ */
+ @Nullable
+ private CraftInventoryView bukkitEntity;
+
+ /**
+ * Field for accessing the beacon field
+ */
+ @NotNull
+ private final Field beaconField;
+
+ public ContainerBeaconImpl(@NotNull EntityPlayer entityPlayer, @Nullable org.bukkit.inventory.ItemStack item) {
+ super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
+
+ this.player = entityPlayer.getBukkitEntity();
+
+ try {
+ this.beaconField = ContainerBeacon.class.getDeclaredField("beacon");
+ this.beaconField.setAccessible(true);
+ } catch (NoSuchFieldException exception) {
+ throw new RuntimeException(exception);
+ }
+
+ try {
+ ItemStack itemStack = CraftItemStack.asNMSCopy(item);
+
+ ((IInventory) beaconField.get(this)).setItem(0, itemStack);
+ } catch (IllegalAccessException exception) {
+ throw new RuntimeException(exception);
+ }
+ }
+
+ @NotNull
+ @Override
+ public CraftInventoryView getBukkitView() {
+ if (bukkitEntity == null) {
+ try {
+ CraftInventory inventory = new CraftInventoryBeacon((IInventory) beaconField.get(this)) {
+ @NotNull
+ @Contract(pure = true)
+ @Override
+ public InventoryHolder getHolder() {
+ return inventoryHolder;
+ }
+ };
+
+ bukkitEntity = new CraftInventoryView(player, inventory, this);
+ } catch (IllegalAccessException exception) {
+ throw new RuntimeException(exception);
+ }
+ }
+
+ return bukkitEntity;
+ }
+
+ @Contract(pure = true, value = "_ -> true")
+ @Override
+ public boolean canUse(@Nullable EntityHuman entityhuman) {
+ return true;
+ }
+
+ @Override
+ public void a(IInventory inventory) {}
+
+ @Override
+ public void b(EntityHuman entityhuman) {}
+
+ }
+}
diff --git a/nms/1_16_R3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R3/CartographyTableInventoryImpl.java b/nms/1_16_4-5/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_4_5/CartographyTableInventoryImpl.java
similarity index 94%
rename from nms/1_16_R3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R3/CartographyTableInventoryImpl.java
rename to nms/1_16_4-5/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_4_5/CartographyTableInventoryImpl.java
index e63aba2f3..fef838730 100644
--- a/nms/1_16_R3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R3/CartographyTableInventoryImpl.java
+++ b/nms/1_16_4-5/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_4_5/CartographyTableInventoryImpl.java
@@ -1,199 +1,201 @@
-package com.github.stefvanschie.inventoryframework.nms.v1_16_R3;
-
-import com.github.stefvanschie.inventoryframework.abstraction.CartographyTableInventory;
-import net.minecraft.server.v1_16_R3.*;
-import org.bukkit.craftbukkit.v1_16_R3.entity.CraftPlayer;
-import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftInventory;
-import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftInventoryCartography;
-import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftInventoryView;
-import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftItemStack;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.InventoryHolder;
-import org.jetbrains.annotations.Contract;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.lang.reflect.Field;
-
-/**
- * Internal cartography table inventory for 1.16 R3
- *
- * @since 0.8.0
- */
-public class CartographyTableInventoryImpl extends CartographyTableInventory {
-
- public CartographyTableInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
- super(inventoryHolder);
- }
-
- @Override
- public void openInventory(@NotNull Player player, @NotNull String title,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- int itemAmount = items.length;
-
- if (itemAmount != 3) {
- throw new IllegalArgumentException(
- "The amount of items for a cartography table should be 3, but is '" + itemAmount + "'"
- );
- }
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
- ContainerCartographyTableImpl containerCartographyTable = new ContainerCartographyTableImpl(
- entityPlayer, items
- );
-
- entityPlayer.activeContainer = containerCartographyTable;
-
- int id = containerCartographyTable.windowId;
- ChatMessage message = new ChatMessage(title);
- PacketPlayOutOpenWindow packet = new PacketPlayOutOpenWindow(id, Containers.CARTOGRAPHY_TABLE, message);
-
- entityPlayer.playerConnection.sendPacket(packet);
-
- sendItems(player, items);
- }
-
- @Override
- public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
- NonNullList nmsItems = NonNullList.a(
- ItemStack.b,
- CraftItemStack.asNMSCopy(items[0]),
- CraftItemStack.asNMSCopy(items[1]),
- CraftItemStack.asNMSCopy(items[2])
- );
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
- }
-
- @Override
- public void clearCursor(@NotNull Player player) {
- getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.b));
- }
-
- /**
- * Gets the window id for the inventory view the player currently has open
- *
- * @param entityPlayer the player to get the window id for
- * @return the window id
- * @since 0.8.0
- */
- @Contract(pure = true)
- private int getWindowId(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.activeContainer.windowId;
- }
-
- /**
- * Gets the player connection for the specified player
- *
- * @param entityPlayer the player to get the player connection from
- * @return the player connection
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.playerConnection;
- }
-
- /**
- * Gets the entity player associated to this player
- *
- * @param player the player to get the entity player from
- * @return the entity player
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private EntityPlayer getEntityPlayer(@NotNull Player player) {
- return ((CraftPlayer) player).getHandle();
- }
-
- /**
- * A custom container cartography table
- *
- * @since 0.8.0
- */
- private class ContainerCartographyTableImpl extends ContainerCartography {
-
- /**
- * The player for this cartography table container
- */
- @NotNull
- private final Player player;
-
- /**
- * The internal bukkit entity for this container cartography table
- */
- @Nullable
- private CraftInventoryView bukkitEntity;
-
- /**
- * Field for accessing the result inventory field
- */
- @NotNull
- private final Field resultInventoryField;
-
- public ContainerCartographyTableImpl(@NotNull EntityPlayer entityPlayer,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
-
- this.player = entityPlayer.getBukkitEntity();
-
- try {
- this.resultInventoryField = ContainerCartography.class.getDeclaredField("resultInventory");
- this.resultInventoryField.setAccessible(true);
- } catch (NoSuchFieldException exception) {
- throw new RuntimeException(exception);
- }
-
- inventory.setItem(0, CraftItemStack.asNMSCopy(items[0]));
- inventory.setItem(1, CraftItemStack.asNMSCopy(items[1]));
-
- getResultInventory().setItem(0, CraftItemStack.asNMSCopy(items[2]));
- }
-
- @NotNull
- @Override
- public CraftInventoryView getBukkitView() {
- if (bukkitEntity == null) {
- CraftInventory inventory = new CraftInventoryCartography(super.inventory, getResultInventory()) {
- @NotNull
- @Contract(pure = true)
- @Override
- public InventoryHolder getHolder() {
- return inventoryHolder;
- }
- };
-
- bukkitEntity = new CraftInventoryView(player, inventory, this);
- }
-
- return bukkitEntity;
- }
-
- @Contract(pure = true, value = "_ -> true")
- @Override
- public boolean canUse(@Nullable EntityHuman entityhuman) {
- return true;
- }
-
- @Override
- public void a(IInventory inventory) {}
-
- @Override
- public void b(EntityHuman entityhuman) {}
-
- @NotNull
- @Contract(pure = true)
- private IInventory getResultInventory() {
- try {
- return (IInventory) resultInventoryField.get(this);
- } catch (IllegalAccessException exception) {
- throw new RuntimeException(exception);
- }
- }
-
- }
-}
+package com.github.stefvanschie.inventoryframework.nms.v1_16_4_5;
+
+import com.github.stefvanschie.inventoryframework.abstraction.CartographyTableInventory;
+import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
+import com.github.stefvanschie.inventoryframework.nms.v1_16_4_5.util.TextHolderUtil;
+import net.minecraft.server.v1_16_R3.*;
+import org.bukkit.craftbukkit.v1_16_R3.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftInventory;
+import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftInventoryCartography;
+import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftInventoryView;
+import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftItemStack;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.InventoryHolder;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.lang.reflect.Field;
+
+/**
+ * Internal cartography table inventory for 1.16 R3
+ *
+ * @since 0.8.0
+ */
+public class CartographyTableInventoryImpl extends CartographyTableInventory {
+
+ public CartographyTableInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
+ super(inventoryHolder);
+ }
+
+ @Override
+ public void openInventory(@NotNull Player player, @NotNull TextHolder title,
+ @Nullable org.bukkit.inventory.ItemStack[] items) {
+ int itemAmount = items.length;
+
+ if (itemAmount != 3) {
+ throw new IllegalArgumentException(
+ "The amount of items for a cartography table should be 3, but is '" + itemAmount + "'"
+ );
+ }
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+ ContainerCartographyTableImpl containerCartographyTable = new ContainerCartographyTableImpl(
+ entityPlayer, items
+ );
+
+ entityPlayer.activeContainer = containerCartographyTable;
+
+ int id = containerCartographyTable.windowId;
+ IChatBaseComponent message = TextHolderUtil.toComponent(title);
+ PacketPlayOutOpenWindow packet = new PacketPlayOutOpenWindow(id, Containers.CARTOGRAPHY_TABLE, message);
+
+ entityPlayer.playerConnection.sendPacket(packet);
+
+ sendItems(player, items);
+ }
+
+ @Override
+ public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
+ NonNullList nmsItems = NonNullList.a(
+ ItemStack.b,
+ CraftItemStack.asNMSCopy(items[0]),
+ CraftItemStack.asNMSCopy(items[1]),
+ CraftItemStack.asNMSCopy(items[2])
+ );
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
+ }
+
+ @Override
+ public void clearCursor(@NotNull Player player) {
+ getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.b));
+ }
+
+ /**
+ * Gets the window id for the inventory view the player currently has open
+ *
+ * @param entityPlayer the player to get the window id for
+ * @return the window id
+ * @since 0.8.0
+ */
+ @Contract(pure = true)
+ private int getWindowId(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.activeContainer.windowId;
+ }
+
+ /**
+ * Gets the player connection for the specified player
+ *
+ * @param entityPlayer the player to get the player connection from
+ * @return the player connection
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.playerConnection;
+ }
+
+ /**
+ * Gets the entity player associated to this player
+ *
+ * @param player the player to get the entity player from
+ * @return the entity player
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private EntityPlayer getEntityPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * A custom container cartography table
+ *
+ * @since 0.8.0
+ */
+ private class ContainerCartographyTableImpl extends ContainerCartography {
+
+ /**
+ * The player for this cartography table container
+ */
+ @NotNull
+ private final Player player;
+
+ /**
+ * The internal bukkit entity for this container cartography table
+ */
+ @Nullable
+ private CraftInventoryView bukkitEntity;
+
+ /**
+ * Field for accessing the result inventory field
+ */
+ @NotNull
+ private final Field resultInventoryField;
+
+ public ContainerCartographyTableImpl(@NotNull EntityPlayer entityPlayer,
+ @Nullable org.bukkit.inventory.ItemStack[] items) {
+ super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
+
+ this.player = entityPlayer.getBukkitEntity();
+
+ try {
+ this.resultInventoryField = ContainerCartography.class.getDeclaredField("resultInventory");
+ this.resultInventoryField.setAccessible(true);
+ } catch (NoSuchFieldException exception) {
+ throw new RuntimeException(exception);
+ }
+
+ inventory.setItem(0, CraftItemStack.asNMSCopy(items[0]));
+ inventory.setItem(1, CraftItemStack.asNMSCopy(items[1]));
+
+ getResultInventory().setItem(0, CraftItemStack.asNMSCopy(items[2]));
+ }
+
+ @NotNull
+ @Override
+ public CraftInventoryView getBukkitView() {
+ if (bukkitEntity == null) {
+ CraftInventory inventory = new CraftInventoryCartography(super.inventory, getResultInventory()) {
+ @NotNull
+ @Contract(pure = true)
+ @Override
+ public InventoryHolder getHolder() {
+ return inventoryHolder;
+ }
+ };
+
+ bukkitEntity = new CraftInventoryView(player, inventory, this);
+ }
+
+ return bukkitEntity;
+ }
+
+ @Contract(pure = true, value = "_ -> true")
+ @Override
+ public boolean canUse(@Nullable EntityHuman entityhuman) {
+ return true;
+ }
+
+ @Override
+ public void a(IInventory inventory) {}
+
+ @Override
+ public void b(EntityHuman entityhuman) {}
+
+ @NotNull
+ @Contract(pure = true)
+ private IInventory getResultInventory() {
+ try {
+ return (IInventory) resultInventoryField.get(this);
+ } catch (IllegalAccessException exception) {
+ throw new RuntimeException(exception);
+ }
+ }
+
+ }
+}
diff --git a/nms/1_16_R3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R3/EnchantingTableInventoryImpl.java b/nms/1_16_4-5/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_4_5/EnchantingTableInventoryImpl.java
similarity index 94%
rename from nms/1_16_R3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R3/EnchantingTableInventoryImpl.java
rename to nms/1_16_4-5/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_4_5/EnchantingTableInventoryImpl.java
index 7c3584325..611a64ab5 100644
--- a/nms/1_16_R3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R3/EnchantingTableInventoryImpl.java
+++ b/nms/1_16_4-5/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_4_5/EnchantingTableInventoryImpl.java
@@ -1,194 +1,196 @@
-package com.github.stefvanschie.inventoryframework.nms.v1_16_R3;
-
-import com.github.stefvanschie.inventoryframework.abstraction.EnchantingTableInventory;
-import net.minecraft.server.v1_16_R3.*;
-import org.bukkit.craftbukkit.v1_16_R3.entity.CraftPlayer;
-import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftInventory;
-import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftInventoryEnchanting;
-import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftInventoryView;
-import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftItemStack;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.InventoryHolder;
-import org.jetbrains.annotations.Contract;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.lang.reflect.Field;
-
-/**
- * Internal enchanting table inventory for 1.16 R3
- *
- * @since 0.8.0
- */
-public class EnchantingTableInventoryImpl extends EnchantingTableInventory {
-
- public EnchantingTableInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
- super(inventoryHolder);
- }
-
- @Override
- public void openInventory(@NotNull Player player, @NotNull String title,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- int itemAmount = items.length;
-
- if (itemAmount != 2) {
- throw new IllegalArgumentException(
- "The amount of items for an enchanting table should be 2, but is '" + itemAmount + "'"
- );
- }
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
- ContainerEnchantingTableImpl containerEnchantmentTable = new ContainerEnchantingTableImpl(entityPlayer, items);
-
- entityPlayer.activeContainer = containerEnchantmentTable;
-
- int id = containerEnchantmentTable.windowId;
- ChatMessage message = new ChatMessage(title);
- PacketPlayOutOpenWindow packet = new PacketPlayOutOpenWindow(id, Containers.ENCHANTMENT, message);
-
- entityPlayer.playerConnection.sendPacket(packet);
-
- sendItems(player, items);
- }
-
- @Override
- public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
- NonNullList nmsItems = NonNullList.a(
- ItemStack.b,
- CraftItemStack.asNMSCopy(items[0]),
- CraftItemStack.asNMSCopy(items[1])
- );
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
- }
-
- @Override
- public void clearCursor(@NotNull Player player) {
- getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.b));
- }
-
- /**
- * Gets the window id for the inventory view the player currently has open
- *
- * @param entityPlayer the player to get the window id for
- * @return the window id
- * @since 0.8.0
- */
- @Contract(pure = true)
- private int getWindowId(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.activeContainer.windowId;
- }
-
- /**
- * Gets the player connection for the specified player
- *
- * @param entityPlayer the player to get the player connection from
- * @return the player connection
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.playerConnection;
- }
-
- /**
- * Gets the entity player associated to this player
- *
- * @param player the player to get the entity player from
- * @return the entity player
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private EntityPlayer getEntityPlayer(@NotNull Player player) {
- return ((CraftPlayer) player).getHandle();
- }
-
- /**
- * A custom container enchanting table
- *
- * @since 0.8.0
- */
- private class ContainerEnchantingTableImpl extends ContainerEnchantTable {
-
- /**
- * The player for this enchanting table container
- */
- @NotNull
- private final Player player;
-
- /**
- * The internal bukkit entity for this container enchanting table
- */
- @Nullable
- private CraftInventoryView bukkitEntity;
-
- /**
- * Field for accessing the enchant slots field
- */
- @NotNull
- private final Field enchantSlotsField;
-
- public ContainerEnchantingTableImpl(@NotNull EntityPlayer entityPlayer,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
-
- this.player = entityPlayer.getBukkitEntity();
-
- try {
- this.enchantSlotsField = ContainerEnchantTable.class.getDeclaredField("enchantSlots");
- this.enchantSlotsField.setAccessible(true);
- } catch (NoSuchFieldException exception) {
- throw new RuntimeException(exception);
- }
-
- try {
- IInventory input = (IInventory) enchantSlotsField.get(this);
-
- input.setItem(0, CraftItemStack.asNMSCopy(items[0]));
- input.setItem(1, CraftItemStack.asNMSCopy(items[1]));
- } catch (IllegalAccessException e) {
- e.printStackTrace();
- }
- }
-
- @NotNull
- @Override
- public CraftInventoryView getBukkitView() {
- if (bukkitEntity == null) {
- try {
- CraftInventory inventory = new CraftInventoryEnchanting((IInventory) enchantSlotsField.get(this)) {
- @NotNull
- @Contract(pure = true)
- @Override
- public InventoryHolder getHolder() {
- return inventoryHolder;
- }
- };
-
- bukkitEntity = new CraftInventoryView(player, inventory, this);
- } catch (IllegalAccessException exception) {
- exception.printStackTrace();
- }
- }
-
- return bukkitEntity;
- }
-
- @Contract(pure = true, value = "_ -> true")
- @Override
- public boolean canUse(@Nullable EntityHuman entityhuman) {
- return true;
- }
-
- @Override
- public void a(IInventory inventory) {}
-
- @Override
- public void b(EntityHuman entityhuman) {}
-
- }
-}
+package com.github.stefvanschie.inventoryframework.nms.v1_16_4_5;
+
+import com.github.stefvanschie.inventoryframework.abstraction.EnchantingTableInventory;
+import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
+import com.github.stefvanschie.inventoryframework.nms.v1_16_4_5.util.TextHolderUtil;
+import net.minecraft.server.v1_16_R3.*;
+import org.bukkit.craftbukkit.v1_16_R3.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftInventory;
+import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftInventoryEnchanting;
+import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftInventoryView;
+import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftItemStack;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.InventoryHolder;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.lang.reflect.Field;
+
+/**
+ * Internal enchanting table inventory for 1.16 R3
+ *
+ * @since 0.8.0
+ */
+public class EnchantingTableInventoryImpl extends EnchantingTableInventory {
+
+ public EnchantingTableInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
+ super(inventoryHolder);
+ }
+
+ @Override
+ public void openInventory(@NotNull Player player, @NotNull TextHolder title,
+ @Nullable org.bukkit.inventory.ItemStack[] items) {
+ int itemAmount = items.length;
+
+ if (itemAmount != 2) {
+ throw new IllegalArgumentException(
+ "The amount of items for an enchanting table should be 2, but is '" + itemAmount + "'"
+ );
+ }
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+ ContainerEnchantingTableImpl containerEnchantmentTable = new ContainerEnchantingTableImpl(entityPlayer, items);
+
+ entityPlayer.activeContainer = containerEnchantmentTable;
+
+ int id = containerEnchantmentTable.windowId;
+ IChatBaseComponent message = TextHolderUtil.toComponent(title);
+ PacketPlayOutOpenWindow packet = new PacketPlayOutOpenWindow(id, Containers.ENCHANTMENT, message);
+
+ entityPlayer.playerConnection.sendPacket(packet);
+
+ sendItems(player, items);
+ }
+
+ @Override
+ public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
+ NonNullList nmsItems = NonNullList.a(
+ ItemStack.b,
+ CraftItemStack.asNMSCopy(items[0]),
+ CraftItemStack.asNMSCopy(items[1])
+ );
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
+ }
+
+ @Override
+ public void clearCursor(@NotNull Player player) {
+ getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.b));
+ }
+
+ /**
+ * Gets the window id for the inventory view the player currently has open
+ *
+ * @param entityPlayer the player to get the window id for
+ * @return the window id
+ * @since 0.8.0
+ */
+ @Contract(pure = true)
+ private int getWindowId(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.activeContainer.windowId;
+ }
+
+ /**
+ * Gets the player connection for the specified player
+ *
+ * @param entityPlayer the player to get the player connection from
+ * @return the player connection
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.playerConnection;
+ }
+
+ /**
+ * Gets the entity player associated to this player
+ *
+ * @param player the player to get the entity player from
+ * @return the entity player
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private EntityPlayer getEntityPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * A custom container enchanting table
+ *
+ * @since 0.8.0
+ */
+ private class ContainerEnchantingTableImpl extends ContainerEnchantTable {
+
+ /**
+ * The player for this enchanting table container
+ */
+ @NotNull
+ private final Player player;
+
+ /**
+ * The internal bukkit entity for this container enchanting table
+ */
+ @Nullable
+ private CraftInventoryView bukkitEntity;
+
+ /**
+ * Field for accessing the enchant slots field
+ */
+ @NotNull
+ private final Field enchantSlotsField;
+
+ public ContainerEnchantingTableImpl(@NotNull EntityPlayer entityPlayer,
+ @Nullable org.bukkit.inventory.ItemStack[] items) {
+ super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
+
+ this.player = entityPlayer.getBukkitEntity();
+
+ try {
+ this.enchantSlotsField = ContainerEnchantTable.class.getDeclaredField("enchantSlots");
+ this.enchantSlotsField.setAccessible(true);
+ } catch (NoSuchFieldException exception) {
+ throw new RuntimeException(exception);
+ }
+
+ try {
+ IInventory input = (IInventory) enchantSlotsField.get(this);
+
+ input.setItem(0, CraftItemStack.asNMSCopy(items[0]));
+ input.setItem(1, CraftItemStack.asNMSCopy(items[1]));
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @NotNull
+ @Override
+ public CraftInventoryView getBukkitView() {
+ if (bukkitEntity == null) {
+ try {
+ CraftInventory inventory = new CraftInventoryEnchanting((IInventory) enchantSlotsField.get(this)) {
+ @NotNull
+ @Contract(pure = true)
+ @Override
+ public InventoryHolder getHolder() {
+ return inventoryHolder;
+ }
+ };
+
+ bukkitEntity = new CraftInventoryView(player, inventory, this);
+ } catch (IllegalAccessException exception) {
+ exception.printStackTrace();
+ }
+ }
+
+ return bukkitEntity;
+ }
+
+ @Contract(pure = true, value = "_ -> true")
+ @Override
+ public boolean canUse(@Nullable EntityHuman entityhuman) {
+ return true;
+ }
+
+ @Override
+ public void a(IInventory inventory) {}
+
+ @Override
+ public void b(EntityHuman entityhuman) {}
+
+ }
+}
diff --git a/nms/1_16_4-5/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_4_5/GrindstoneInventoryImpl.java b/nms/1_16_4-5/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_4_5/GrindstoneInventoryImpl.java
new file mode 100644
index 000000000..0ce518a25
--- /dev/null
+++ b/nms/1_16_4-5/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_4_5/GrindstoneInventoryImpl.java
@@ -0,0 +1,268 @@
+package com.github.stefvanschie.inventoryframework.nms.v1_16_4_5;
+
+import com.github.stefvanschie.inventoryframework.abstraction.GrindstoneInventory;
+import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
+import com.github.stefvanschie.inventoryframework.nms.v1_16_4_5.util.TextHolderUtil;
+import net.minecraft.server.v1_16_R3.*;
+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.InventoryHolder;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.lang.reflect.Field;
+import java.util.Collections;
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * Internal grindstone inventory for 1.16 R3
+ *
+ * @since 0.8.0
+ */
+public class GrindstoneInventoryImpl extends GrindstoneInventory {
+
+ public GrindstoneInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
+ super(inventoryHolder);
+ }
+
+ @Override
+ public Inventory openInventory(@NotNull Player player, @NotNull TextHolder title,
+ @Nullable org.bukkit.inventory.ItemStack[] items) {
+ int itemAmount = items.length;
+
+ if (itemAmount != 3) {
+ throw new IllegalArgumentException(
+ "The amount of items for a grindstone should be 3, but is '" + itemAmount + "'"
+ );
+ }
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ //ignore deprecation: superseding method is only available on Paper
+ //noinspection deprecation
+ CraftEventFactory.handleInventoryCloseEvent(entityPlayer);
+
+ entityPlayer.activeContainer = entityPlayer.defaultContainer;
+
+ IChatBaseComponent message = TextHolderUtil.toComponent(title);
+ ContainerGrindstoneImpl containerGrindstone = new ContainerGrindstoneImpl(entityPlayer);
+
+ Inventory inventory = containerGrindstone.getBukkitView().getTopInventory();
+
+ inventory.setItem(0, items[0]);
+ inventory.setItem(1, items[1]);
+ inventory.setItem(2, items[2]);
+
+ int windowId = containerGrindstone.getWindowId();
+
+ entityPlayer.playerConnection.sendPacket(new PacketPlayOutOpenWindow(windowId, Containers.GRINDSTONE, message));
+ entityPlayer.activeContainer = containerGrindstone;
+ entityPlayer.syncInventory();
+
+ return inventory;
+ }
+
+ @Override
+ public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items,
+ @Nullable org.bukkit.inventory.ItemStack cursor) {
+ NonNullList nmsItems = NonNullList.a(
+ ItemStack.b,
+ CraftItemStack.asNMSCopy(items[0]),
+ CraftItemStack.asNMSCopy(items[1]),
+ CraftItemStack.asNMSCopy(items[2])
+ );
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
+ }
+
+ @Override
+ public void clearCursor(@NotNull Player player) {
+ getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.b));
+ }
+
+ /**
+ * Gets the window id for the inventory view the player currently has open
+ *
+ * @param entityPlayer the player to get the window id for
+ * @return the window id
+ * @since 0.8.0
+ */
+ @Contract(pure = true)
+ private int getWindowId(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.activeContainer.windowId;
+ }
+
+ /**
+ * Gets the player connection for the specified player
+ *
+ * @param entityPlayer the player to get the player connection from
+ * @return the player connection
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.playerConnection;
+ }
+
+ /**
+ * Gets the entity player associated to this player
+ *
+ * @param player the player to get the entity player from
+ * @return the entity player
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private EntityPlayer getEntityPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * A custom container grindstone
+ *
+ * @since 0.8.0
+ */
+ private static class ContainerGrindstoneImpl extends ContainerGrindstone {
+
+ /**
+ * A unique item
+ */
+ @NotNull
+ private final ItemStack uniqueItem;
+
+ /**
+ * The field containing the listeners for this container
+ */
+ @NotNull
+ private final Field listenersField;
+
+ /**
+ * Creates a new grindstone container
+ *
+ * @param entityPlayer the player for whom this container should be opened
+ * @since 0.10.8
+ */
+ public ContainerGrindstoneImpl(@NotNull EntityPlayer entityPlayer) {
+ super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
+
+ try {
+ this.listenersField = Container.class.getDeclaredField("listeners");
+ this.listenersField.setAccessible(true);
+ } catch (NoSuchFieldException exception) {
+ throw new RuntimeException("Unable to access field 'listeners'", exception);
+ }
+
+ Slot firstSlot = this.slots.get(0);
+ Slot secondSlot = this.slots.get(1);
+ Slot thirdSlot = this.slots.get(2);
+
+ this.slots.set(0, new Slot(firstSlot.inventory, firstSlot.rawSlotIndex, firstSlot.e, firstSlot.f) {
+ @Override
+ public boolean isAllowed(ItemStack stack) {
+ return true;
+ }
+ });
+
+ this.slots.set(1, new Slot(secondSlot.inventory, secondSlot.rawSlotIndex, secondSlot.e, secondSlot.f) {
+ @Override
+ public boolean isAllowed(ItemStack stack) {
+ return true;
+ }
+ });
+
+ this.slots.set(2, new Slot(thirdSlot.inventory, thirdSlot.rawSlotIndex, thirdSlot.e, thirdSlot.f) {
+ @Override
+ public boolean isAllowed(ItemStack stack) {
+ return true;
+ }
+
+ @Override
+ public ItemStack a(EntityHuman entityHuman, ItemStack itemStack) {
+ return itemStack;
+ }
+ });
+
+ this.uniqueItem = new ItemStack(Items.COOKIE);
+
+ //to make the item unique, we add a random uuid as nbt to it
+ UUID uuid = UUID.randomUUID();
+ NBTTagCompound nbtTagCompound = new NBTTagCompound();
+
+ nbtTagCompound.set("uuid", new NBTTagLongArray(new long [] {
+ uuid.getLeastSignificantBits(),
+ uuid.getMostSignificantBits()
+ }));
+
+ this.uniqueItem.setTag(nbtTagCompound);
+ }
+
+ /**
+ * Forcefully updates the client state, sending all items, container properties and the held item.
+ *
+ * @since 0.10.8
+ */
+ public void forceUpdate() {
+ /*
+ The server will not send the items when they haven't changed, so we will overwrite every item with a unique
+ item first to ensure the server is going to send our items.
+ */
+ Collections.fill(this.items, this.uniqueItem);
+
+ notifyListeners();
+
+ List extends ICrafting> listeners;
+
+ try {
+ //noinspection unchecked
+ listeners = (List extends ICrafting>) listenersField.get(this);
+ } catch (IllegalAccessException exception) {
+ throw new RuntimeException("Unable to access field 'listeners'", exception);
+ }
+
+ for (ICrafting listener : listeners) {
+ if (!(listener instanceof EntityPlayer)) {
+ continue;
+ }
+
+ EntityPlayer player = (EntityPlayer) listener;
+
+ player.e = false;
+ player.broadcastCarriedItem();
+ }
+ }
+
+ @Override
+ public ItemStack a(int i, int j, InventoryClickType inventoryclicktype, EntityHuman entityhuman) {
+ ItemStack itemStack = super.a(i, j, inventoryclicktype, entityhuman);
+
+ //the client predicts the allowed movement of the item, so we broadcast the state again to override it
+ forceUpdate();
+
+ return itemStack;
+ }
+
+ @Contract(pure = true, value = "_ -> true")
+ @Override
+ public boolean canUse(@Nullable EntityHuman entityHuman) {
+ return true;
+ }
+
+ @Override
+ public void a(IInventory inventory) {}
+
+ @Override
+ public void b(EntityHuman entityHuman) {}
+
+ public int getWindowId() {
+ return this.windowId;
+ }
+ }
+}
diff --git a/nms/1_16_4-5/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_4_5/MerchantInventoryImpl.java b/nms/1_16_4-5/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_4_5/MerchantInventoryImpl.java
new file mode 100644
index 000000000..1f48e76d2
--- /dev/null
+++ b/nms/1_16_4-5/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_4_5/MerchantInventoryImpl.java
@@ -0,0 +1,95 @@
+package com.github.stefvanschie.inventoryframework.nms.v1_16_4_5;
+
+import com.github.stefvanschie.inventoryframework.abstraction.MerchantInventory;
+import net.minecraft.server.v1_16_R3.EntityPlayer;
+import net.minecraft.server.v1_16_R3.MerchantRecipeList;
+import org.bukkit.craftbukkit.v1_16_R3.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftItemStack;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.MerchantRecipe;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Internal merchant inventory for 1.16.4 - 1.16.5
+ *
+ * @since 0.10.1
+ */
+public class MerchantInventoryImpl extends MerchantInventory {
+
+ @Override
+ public void sendMerchantOffers(@NotNull Player player,
+ @NotNull List extends Map.Entry extends MerchantRecipe, ? extends Integer>> trades,
+ int level, int experience) {
+ MerchantRecipeList offers = new MerchantRecipeList();
+
+ for (Map.Entry extends MerchantRecipe, ? extends Integer> entry : trades) {
+ MerchantRecipe recipe = entry.getKey();
+ List ingredients = recipe.getIngredients();
+
+ if (ingredients.size() < 1) {
+ throw new IllegalStateException("Merchant recipe has no ingredients");
+ }
+
+ ItemStack itemA = ingredients.get(0);
+ ItemStack itemB = null;
+
+ if (ingredients.size() >= 2) {
+ itemB = ingredients.get(1);
+ }
+
+ net.minecraft.server.v1_16_R3.ItemStack nmsItemA = CraftItemStack.asNMSCopy(itemA);
+ net.minecraft.server.v1_16_R3.ItemStack nmsItemB = net.minecraft.server.v1_16_R3.ItemStack.b;
+ net.minecraft.server.v1_16_R3.ItemStack nmsItemResult = CraftItemStack.asNMSCopy(recipe.getResult());
+
+ if (itemB != null) {
+ nmsItemB = CraftItemStack.asNMSCopy(itemB);
+ }
+
+ int uses = recipe.getUses();
+ int maxUses = recipe.getMaxUses();
+ int exp = recipe.getVillagerExperience();
+ float multiplier = recipe.getPriceMultiplier();
+
+ net.minecraft.server.v1_16_R3.MerchantRecipe merchantOffer = new net.minecraft.server.v1_16_R3.MerchantRecipe(
+ nmsItemA, nmsItemB, nmsItemResult, uses, maxUses, exp, multiplier
+ );
+ merchantOffer.setSpecialPrice(entry.getValue());
+
+ offers.add(merchantOffer);
+ }
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ entityPlayer.openTrade(getWindowId(entityPlayer), offers, level, experience, true, false);
+ }
+
+ /**
+ * Gets the entity player associated to this player
+ *
+ * @param player the player to get the entity player from
+ * @return the entity player
+ * @since 0.10.1
+ */
+ @NotNull
+ @Contract(pure = true)
+ private EntityPlayer getEntityPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * Gets the window id for the inventory view the player currently has open
+ *
+ * @param entityPlayer the player to get the window id for
+ * @return the window id
+ * @since 0.10.1
+ */
+ @Contract(pure = true)
+ private int getWindowId(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.activeContainer.windowId;
+ }
+}
diff --git a/nms/1_16_R3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R3/SmithingTableInventoryImpl.java b/nms/1_16_4-5/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_4_5/SmithingTableInventoryImpl.java
similarity index 91%
rename from nms/1_16_R3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R3/SmithingTableInventoryImpl.java
rename to nms/1_16_4-5/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_4_5/SmithingTableInventoryImpl.java
index a9e9e5d60..a1d178405 100644
--- a/nms/1_16_R3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R3/SmithingTableInventoryImpl.java
+++ b/nms/1_16_4-5/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_4_5/SmithingTableInventoryImpl.java
@@ -1,227 +1,234 @@
-package com.github.stefvanschie.inventoryframework.nms.v1_16_R3;
-
-import com.github.stefvanschie.inventoryframework.abstraction.SmithingTableInventory;
-import net.minecraft.server.v1_16_R3.*;
-import org.bukkit.craftbukkit.v1_16_R3.entity.CraftPlayer;
-import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftInventory;
-import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftInventorySmithing;
-import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftInventoryView;
-import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftItemStack;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.InventoryHolder;
-import org.jetbrains.annotations.Contract;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-/**
- * Internal smithing table inventory for 1.16 R3
- *
- * @since 0.8.0
- */
-public class SmithingTableInventoryImpl extends SmithingTableInventory {
-
- public SmithingTableInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
- super(inventoryHolder);
- }
-
- @Override
- public void openInventory(@NotNull Player player, @NotNull String title,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- int itemAmount = items.length;
-
- if (itemAmount != 3) {
- throw new IllegalArgumentException(
- "The amount of items for a smithing table should be 3, but is '" + itemAmount + "'"
- );
- }
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
- ContainerSmithingTableImpl containerSmithingTable = new ContainerSmithingTableImpl(entityPlayer, items);
-
- entityPlayer.activeContainer = containerSmithingTable;
-
- int id = containerSmithingTable.windowId;
- ChatMessage message = new ChatMessage(title);
- PacketPlayOutOpenWindow packet = new PacketPlayOutOpenWindow(id, Containers.SMITHING, message);
-
- entityPlayer.playerConnection.sendPacket(packet);
-
- sendItems(player, items);
- }
-
- @Override
- public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
- NonNullList nmsItems = NonNullList.a(
- ItemStack.b,
- CraftItemStack.asNMSCopy(items[0]),
- CraftItemStack.asNMSCopy(items[1]),
- CraftItemStack.asNMSCopy(items[2])
- );
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
- }
-
- @Override
- public void sendFirstItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
- EntityPlayer entityPlayer = getEntityPlayer(player);
- ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutSetSlot(getWindowId(entityPlayer), 0, nmsItem));
- }
-
- @Override
- public void sendSecondItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
- EntityPlayer entityPlayer = getEntityPlayer(player);
- ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutSetSlot(getWindowId(entityPlayer), 1, nmsItem));
- }
-
- @Override
- public void sendResultItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
- sendResultItem(player, CraftItemStack.asNMSCopy(item));
- }
-
- @Override
- public void clearResultItem(@NotNull Player player) {
- sendResultItem(player, ItemStack.b);
- }
-
- @Override
- public void setCursor(@NotNull Player player, @NotNull org.bukkit.inventory.ItemStack item) {
- setCursor(player, CraftItemStack.asNMSCopy(item));
- }
-
- @Override
- public void clearCursor(@NotNull Player player) {
- getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.b));
- }
-
- /**
- * Sets the cursor of the given player
- *
- * @param player the player to set the cursor
- * @param item the item to set the cursor to
- * @since 0.8.0
- */
- private void setCursor(@NotNull Player player, @NotNull ItemStack item) {
- getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, item));
- }
-
- /**
- * Sends the result item to the specified player with the given item
- *
- * @param player the player to send the result item to
- * @param item the result item
- * @since 0.8.0
- */
- private void sendResultItem(@NotNull Player player, @NotNull ItemStack item) {
- EntityPlayer entityPlayer = getEntityPlayer(player);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutSetSlot(getWindowId(entityPlayer), 2, item));
- }
-
- /**
- * Gets the window id for the inventory view the player currently has open
- *
- * @param entityPlayer the player to get the window id for
- * @return the window id
- * @since 0.8.0
- */
- @Contract(pure = true)
- private int getWindowId(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.activeContainer.windowId;
- }
-
- /**
- * Gets the player connection for the specified player
- *
- * @param entityPlayer the player to get the player connection from
- * @return the player connection
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.playerConnection;
- }
-
- /**
- * Gets the entity player associated to this player
- *
- * @param player the player to get the entity player from
- * @return the entity player
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private EntityPlayer getEntityPlayer(@NotNull Player player) {
- return ((CraftPlayer) player).getHandle();
- }
-
- /**
- * A custom container smithing table
- *
- * @since 0.8.0
- */
- private class ContainerSmithingTableImpl extends ContainerSmithing {
-
- /**
- * The player for this smithing table container
- */
- @NotNull
- private final Player player;
-
- /**
- * The internal bukkit entity for this container smithing table
- */
- @Nullable
- private CraftInventoryView bukkitEntity;
-
- public ContainerSmithingTableImpl(@NotNull EntityPlayer entityPlayer,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- super(entityPlayer.nextContainerCounter(), entityPlayer.inventory,
- ContainerAccess.at(entityPlayer.getWorld(), new BlockPosition(0, 0, 0)));
-
- this.player = entityPlayer.getBukkitEntity();
-
- repairInventory.setItem(0, CraftItemStack.asNMSCopy(items[0]));
- repairInventory.setItem(1, CraftItemStack.asNMSCopy(items[1]));
- resultInventory.setItem(0, CraftItemStack.asNMSCopy(items[2]));
- }
-
- @NotNull
- @Override
- public CraftInventoryView getBukkitView() {
- if (bukkitEntity == null) {
- CraftInventory inventory = new CraftInventorySmithing(containerAccess.getLocation(), repairInventory,
- resultInventory) {
- @NotNull
- @Contract(pure = true)
- @Override
- public InventoryHolder getHolder() {
- return inventoryHolder;
- }
- };
-
- bukkitEntity = new CraftInventoryView(player, inventory, this);
- }
-
- return bukkitEntity;
- }
-
- @Contract(pure = true, value = "_ -> true")
- @Override
- public boolean canUse(@Nullable EntityHuman entityhuman) {
- return true;
- }
-
- @Override
- public void a(IInventory inventory) {}
-
- @Override
- public void b(EntityHuman entityhuman) {}
- }
-}
+package com.github.stefvanschie.inventoryframework.nms.v1_16_4_5;
+
+import com.github.stefvanschie.inventoryframework.abstraction.SmithingTableInventory;
+import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
+import com.github.stefvanschie.inventoryframework.nms.v1_16_4_5.util.TextHolderUtil;
+import net.minecraft.server.v1_16_R3.*;
+import org.bukkit.craftbukkit.v1_16_R3.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftInventory;
+import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftInventorySmithing;
+import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftInventoryView;
+import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftItemStack;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.InventoryHolder;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Internal smithing table inventory for 1.16 R3
+ *
+ * @since 0.8.0
+ */
+public class SmithingTableInventoryImpl extends SmithingTableInventory {
+
+ public SmithingTableInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
+ super(inventoryHolder);
+ }
+
+ @Nullable
+ @Override
+ public Inventory openInventory(@NotNull Player player, @NotNull TextHolder title,
+ @Nullable org.bukkit.inventory.ItemStack[] items) {
+ int itemAmount = items.length;
+
+ if (itemAmount != 3) {
+ throw new IllegalArgumentException(
+ "The amount of items for a smithing table should be 3, but is '" + itemAmount + "'"
+ );
+ }
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+ ContainerSmithingTableImpl containerSmithingTable = new ContainerSmithingTableImpl(entityPlayer, items);
+
+ entityPlayer.activeContainer = containerSmithingTable;
+
+ int id = containerSmithingTable.windowId;
+ IChatBaseComponent message = TextHolderUtil.toComponent(title);
+ PacketPlayOutOpenWindow packet = new PacketPlayOutOpenWindow(id, Containers.SMITHING, message);
+
+ entityPlayer.playerConnection.sendPacket(packet);
+
+ sendItems(player, items, null);
+
+ return null;
+ }
+
+ @Override
+ public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items,
+ @Nullable org.bukkit.inventory.ItemStack cursor) {
+ NonNullList nmsItems = NonNullList.a(
+ ItemStack.b,
+ CraftItemStack.asNMSCopy(items[0]),
+ CraftItemStack.asNMSCopy(items[1]),
+ CraftItemStack.asNMSCopy(items[2])
+ );
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
+ }
+
+ @Override
+ public void sendFirstItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+ ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutSetSlot(getWindowId(entityPlayer), 0, nmsItem));
+ }
+
+ @Override
+ public void sendSecondItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+ ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutSetSlot(getWindowId(entityPlayer), 1, nmsItem));
+ }
+
+ @Override
+ public void sendResultItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
+ sendResultItem(player, CraftItemStack.asNMSCopy(item));
+ }
+
+ @Override
+ public void clearResultItem(@NotNull Player player) {
+ sendResultItem(player, ItemStack.b);
+ }
+
+ @Override
+ public void setCursor(@NotNull Player player, @NotNull org.bukkit.inventory.ItemStack item) {
+ setCursor(player, CraftItemStack.asNMSCopy(item));
+ }
+
+ @Override
+ public void clearCursor(@NotNull Player player) {
+ getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.b));
+ }
+
+ /**
+ * Sets the cursor of the given player
+ *
+ * @param player the player to set the cursor
+ * @param item the item to set the cursor to
+ * @since 0.8.0
+ */
+ private void setCursor(@NotNull Player player, @NotNull ItemStack item) {
+ getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, item));
+ }
+
+ /**
+ * Sends the result item to the specified player with the given item
+ *
+ * @param player the player to send the result item to
+ * @param item the result item
+ * @since 0.8.0
+ */
+ private void sendResultItem(@NotNull Player player, @NotNull ItemStack item) {
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutSetSlot(getWindowId(entityPlayer), 2, item));
+ }
+
+ /**
+ * Gets the window id for the inventory view the player currently has open
+ *
+ * @param entityPlayer the player to get the window id for
+ * @return the window id
+ * @since 0.8.0
+ */
+ @Contract(pure = true)
+ private int getWindowId(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.activeContainer.windowId;
+ }
+
+ /**
+ * Gets the player connection for the specified player
+ *
+ * @param entityPlayer the player to get the player connection from
+ * @return the player connection
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.playerConnection;
+ }
+
+ /**
+ * Gets the entity player associated to this player
+ *
+ * @param player the player to get the entity player from
+ * @return the entity player
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private EntityPlayer getEntityPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * A custom container smithing table
+ *
+ * @since 0.8.0
+ */
+ private class ContainerSmithingTableImpl extends ContainerSmithing {
+
+ /**
+ * The player for this smithing table container
+ */
+ @NotNull
+ private final Player player;
+
+ /**
+ * The internal bukkit entity for this container smithing table
+ */
+ @Nullable
+ private CraftInventoryView bukkitEntity;
+
+ public ContainerSmithingTableImpl(@NotNull EntityPlayer entityPlayer,
+ @Nullable org.bukkit.inventory.ItemStack[] items) {
+ super(entityPlayer.nextContainerCounter(), entityPlayer.inventory,
+ ContainerAccess.at(entityPlayer.getWorld(), new BlockPosition(0, 0, 0)));
+
+ this.player = entityPlayer.getBukkitEntity();
+
+ repairInventory.setItem(0, CraftItemStack.asNMSCopy(items[0]));
+ repairInventory.setItem(1, CraftItemStack.asNMSCopy(items[1]));
+ resultInventory.setItem(0, CraftItemStack.asNMSCopy(items[2]));
+ }
+
+ @NotNull
+ @Override
+ public CraftInventoryView getBukkitView() {
+ if (bukkitEntity == null) {
+ CraftInventory inventory = new CraftInventorySmithing(containerAccess.getLocation(), repairInventory,
+ resultInventory) {
+ @NotNull
+ @Contract(pure = true)
+ @Override
+ public InventoryHolder getHolder() {
+ return inventoryHolder;
+ }
+ };
+
+ bukkitEntity = new CraftInventoryView(player, inventory, this);
+ }
+
+ return bukkitEntity;
+ }
+
+ @Contract(pure = true, value = "_ -> true")
+ @Override
+ public boolean canUse(@Nullable EntityHuman entityhuman) {
+ return true;
+ }
+
+ @Override
+ public void a(IInventory inventory) {}
+
+ @Override
+ public void b(EntityHuman entityhuman) {}
+ }
+}
diff --git a/nms/1_16_R3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R3/StonecutterInventoryImpl.java b/nms/1_16_4-5/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_4_5/StonecutterInventoryImpl.java
similarity index 94%
rename from nms/1_16_R3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R3/StonecutterInventoryImpl.java
rename to nms/1_16_4-5/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_4_5/StonecutterInventoryImpl.java
index 2e9db691e..0d44d97c9 100644
--- a/nms/1_16_R3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R3/StonecutterInventoryImpl.java
+++ b/nms/1_16_4-5/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_4_5/StonecutterInventoryImpl.java
@@ -1,199 +1,201 @@
-package com.github.stefvanschie.inventoryframework.nms.v1_16_R3;
-
-import com.github.stefvanschie.inventoryframework.abstraction.StonecutterInventory;
-import net.minecraft.server.v1_16_R3.*;
-import org.bukkit.craftbukkit.v1_16_R3.entity.CraftPlayer;
-import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftInventory;
-import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftInventoryStonecutter;
-import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftInventoryView;
-import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftItemStack;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.InventoryHolder;
-import org.jetbrains.annotations.Contract;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.lang.reflect.Field;
-
-/**
- * Internal stonecutter inventory for 1.16 R3
- *
- * @since 0.8.0
- */
-public class StonecutterInventoryImpl extends StonecutterInventory {
-
- public StonecutterInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
- super(inventoryHolder);
- }
-
- @Override
- public void openInventory(@NotNull Player player, @NotNull String title,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- int itemAmount = items.length;
-
- if (itemAmount != 2) {
- throw new IllegalArgumentException(
- "The amount of items for a stonecutter should be 2, but is '" + itemAmount + "'"
- );
- }
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
- ContainerStonecutterImpl containerEnchantmentTable = new ContainerStonecutterImpl(entityPlayer, items);
-
- entityPlayer.activeContainer = containerEnchantmentTable;
-
- int id = containerEnchantmentTable.windowId;
- ChatMessage message = new ChatMessage(title);
- PacketPlayOutOpenWindow packet = new PacketPlayOutOpenWindow(id, Containers.STONECUTTER, message);
-
- entityPlayer.playerConnection.sendPacket(packet);
-
- sendItems(player, items);
- }
-
- @Override
- public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
- NonNullList nmsItems = NonNullList.a(
- ItemStack.b,
- CraftItemStack.asNMSCopy(items[0]),
- CraftItemStack.asNMSCopy(items[1])
- );
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
- }
-
- @Override
- public void clearCursor(@NotNull Player player) {
- getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.b));
- }
-
- /**
- * Gets the window id for the inventory view the player currently has open
- *
- * @param entityPlayer the player to get the window id for
- * @return the window id
- * @since 0.8.0
- */
- @Contract(pure = true)
- private int getWindowId(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.activeContainer.windowId;
- }
-
- /**
- * Gets the player connection for the specified player
- *
- * @param entityPlayer the player to get the player connection from
- * @return the player connection
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.playerConnection;
- }
-
- /**
- * Gets the entity player associated to this player
- *
- * @param player the player to get the entity player from
- * @return the entity player
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private EntityPlayer getEntityPlayer(@NotNull Player player) {
- return ((CraftPlayer) player).getHandle();
- }
-
- /**
- * A custom container enchanting table
- *
- * @since 0.8.0
- */
- private class ContainerStonecutterImpl extends ContainerStonecutter {
-
- /**
- * The player for this enchanting table container
- */
- @NotNull
- private final Player player;
-
- /**
- * The internal bukkit entity for this container enchanting table
- */
- @Nullable
- private CraftInventoryView bukkitEntity;
-
- /**
- * Field for accessing the result inventory field
- */
- @NotNull
- private final Field resultInventoryField;
-
- public ContainerStonecutterImpl(@NotNull EntityPlayer entityPlayer,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
-
- this.player = entityPlayer.getBukkitEntity();
-
- try {
- this.resultInventoryField = ContainerStonecutter.class.getDeclaredField("resultInventory");
- this.resultInventoryField.setAccessible(true);
- } catch (NoSuchFieldException exception) {
- throw new RuntimeException(exception);
- }
-
- inventory.setItem(0, CraftItemStack.asNMSCopy(items[0]));
- getResultInventory().setItem(0, CraftItemStack.asNMSCopy(items[1]));
- }
-
- @NotNull
- @Override
- public CraftInventoryView getBukkitView() {
- if (bukkitEntity == null) {
- CraftInventory inventory = new CraftInventoryStonecutter(this.inventory, getResultInventory()) {
- @NotNull
- @Contract(pure = true)
- @Override
- public InventoryHolder getHolder() {
- return inventoryHolder;
- }
- };
-
- bukkitEntity = new CraftInventoryView(player, inventory, this);
- }
-
- return bukkitEntity;
- }
-
- @Contract(pure = true, value = "_ -> true")
- @Override
- public boolean canUse(@Nullable EntityHuman entityhuman) {
- return true;
- }
-
- @Override
- public void a(IInventory inventory) {}
-
- @Override
- public void b(EntityHuman entityhuman) {}
-
- /**
- * Gets the result inventory
- *
- * @return the result inventory
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- public IInventory getResultInventory() {
- try {
- return (IInventory) resultInventoryField.get(this);
- } catch (IllegalAccessException exception) {
- throw new RuntimeException(exception);
- }
- }
- }
-}
+package com.github.stefvanschie.inventoryframework.nms.v1_16_4_5;
+
+import com.github.stefvanschie.inventoryframework.abstraction.StonecutterInventory;
+import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
+import com.github.stefvanschie.inventoryframework.nms.v1_16_4_5.util.TextHolderUtil;
+import net.minecraft.server.v1_16_R3.*;
+import org.bukkit.craftbukkit.v1_16_R3.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftInventory;
+import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftInventoryStonecutter;
+import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftInventoryView;
+import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftItemStack;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.InventoryHolder;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.lang.reflect.Field;
+
+/**
+ * Internal stonecutter inventory for 1.16 R3
+ *
+ * @since 0.8.0
+ */
+public class StonecutterInventoryImpl extends StonecutterInventory {
+
+ public StonecutterInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
+ super(inventoryHolder);
+ }
+
+ @Override
+ public void openInventory(@NotNull Player player, @NotNull TextHolder title,
+ @Nullable org.bukkit.inventory.ItemStack[] items) {
+ int itemAmount = items.length;
+
+ if (itemAmount != 2) {
+ throw new IllegalArgumentException(
+ "The amount of items for a stonecutter should be 2, but is '" + itemAmount + "'"
+ );
+ }
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+ ContainerStonecutterImpl containerEnchantmentTable = new ContainerStonecutterImpl(entityPlayer, items);
+
+ entityPlayer.activeContainer = containerEnchantmentTable;
+
+ int id = containerEnchantmentTable.windowId;
+ IChatBaseComponent message = TextHolderUtil.toComponent(title);
+ PacketPlayOutOpenWindow packet = new PacketPlayOutOpenWindow(id, Containers.STONECUTTER, message);
+
+ entityPlayer.playerConnection.sendPacket(packet);
+
+ sendItems(player, items);
+ }
+
+ @Override
+ public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
+ NonNullList nmsItems = NonNullList.a(
+ ItemStack.b,
+ CraftItemStack.asNMSCopy(items[0]),
+ CraftItemStack.asNMSCopy(items[1])
+ );
+
+ EntityPlayer entityPlayer = getEntityPlayer(player);
+
+ getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
+ }
+
+ @Override
+ public void clearCursor(@NotNull Player player) {
+ getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.b));
+ }
+
+ /**
+ * Gets the window id for the inventory view the player currently has open
+ *
+ * @param entityPlayer the player to get the window id for
+ * @return the window id
+ * @since 0.8.0
+ */
+ @Contract(pure = true)
+ private int getWindowId(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.activeContainer.windowId;
+ }
+
+ /**
+ * Gets the player connection for the specified player
+ *
+ * @param entityPlayer the player to get the player connection from
+ * @return the player connection
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
+ return entityPlayer.playerConnection;
+ }
+
+ /**
+ * Gets the entity player associated to this player
+ *
+ * @param player the player to get the entity player from
+ * @return the entity player
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private EntityPlayer getEntityPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * A custom container enchanting table
+ *
+ * @since 0.8.0
+ */
+ private class ContainerStonecutterImpl extends ContainerStonecutter {
+
+ /**
+ * The player for this enchanting table container
+ */
+ @NotNull
+ private final Player player;
+
+ /**
+ * The internal bukkit entity for this container enchanting table
+ */
+ @Nullable
+ private CraftInventoryView bukkitEntity;
+
+ /**
+ * Field for accessing the result inventory field
+ */
+ @NotNull
+ private final Field resultInventoryField;
+
+ public ContainerStonecutterImpl(@NotNull EntityPlayer entityPlayer,
+ @Nullable org.bukkit.inventory.ItemStack[] items) {
+ super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
+
+ this.player = entityPlayer.getBukkitEntity();
+
+ try {
+ this.resultInventoryField = ContainerStonecutter.class.getDeclaredField("resultInventory");
+ this.resultInventoryField.setAccessible(true);
+ } catch (NoSuchFieldException exception) {
+ throw new RuntimeException(exception);
+ }
+
+ inventory.setItem(0, CraftItemStack.asNMSCopy(items[0]));
+ getResultInventory().setItem(0, CraftItemStack.asNMSCopy(items[1]));
+ }
+
+ @NotNull
+ @Override
+ public CraftInventoryView getBukkitView() {
+ if (bukkitEntity == null) {
+ CraftInventory inventory = new CraftInventoryStonecutter(this.inventory, getResultInventory()) {
+ @NotNull
+ @Contract(pure = true)
+ @Override
+ public InventoryHolder getHolder() {
+ return inventoryHolder;
+ }
+ };
+
+ bukkitEntity = new CraftInventoryView(player, inventory, this);
+ }
+
+ return bukkitEntity;
+ }
+
+ @Contract(pure = true, value = "_ -> true")
+ @Override
+ public boolean canUse(@Nullable EntityHuman entityhuman) {
+ return true;
+ }
+
+ @Override
+ public void a(IInventory inventory) {}
+
+ @Override
+ public void b(EntityHuman entityhuman) {}
+
+ /**
+ * Gets the result inventory
+ *
+ * @return the result inventory
+ * @since 0.8.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ public IInventory getResultInventory() {
+ try {
+ return (IInventory) resultInventoryField.get(this);
+ } catch (IllegalAccessException exception) {
+ throw new RuntimeException(exception);
+ }
+ }
+ }
+}
diff --git a/nms/1_16_4-5/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_4_5/util/TextHolderUtil.java b/nms/1_16_4-5/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_4_5/util/TextHolderUtil.java
new file mode 100644
index 000000000..506d10d9b
--- /dev/null
+++ b/nms/1_16_4-5/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_4_5/util/TextHolderUtil.java
@@ -0,0 +1,66 @@
+package com.github.stefvanschie.inventoryframework.nms.v1_16_4_5.util;
+
+import com.github.stefvanschie.inventoryframework.adventuresupport.ComponentHolder;
+import com.github.stefvanschie.inventoryframework.adventuresupport.StringHolder;
+import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
+import net.minecraft.server.v1_16_R3.ChatComponentText;
+import net.minecraft.server.v1_16_R3.IChatBaseComponent;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Objects;
+
+/**
+ * A utility class for adding {@link TextHolder} support.
+ *
+ * @since 0.10.0
+ */
+public final class TextHolderUtil {
+
+ private TextHolderUtil() {
+ //private constructor to prevent construction
+ }
+
+ /**
+ * Converts the specified value to a vanilla component.
+ *
+ * @param holder the value to convert
+ * @return the value as a vanilla component
+ * @since 0.10.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ public static IChatBaseComponent toComponent(@NotNull TextHolder holder) {
+ if (holder instanceof StringHolder) {
+ return toComponent((StringHolder) holder);
+ } else {
+ return toComponent((ComponentHolder) holder);
+ }
+ }
+
+ /**
+ * Converts the specified legacy string holder to a vanilla component.
+ *
+ * @param holder the value to convert
+ * @return the value as a vanilla component
+ * @since 0.10.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private static IChatBaseComponent toComponent(@NotNull StringHolder holder) {
+ return new ChatComponentText(holder.asLegacyString());
+ }
+
+ /**
+ * Converts the specified Adventure component holder to a vanilla component.
+ *
+ * @param holder the value to convert
+ * @return the value as a vanilla component
+ * @since 0.10.0
+ */
+ @NotNull
+ @Contract(pure = true)
+ private static IChatBaseComponent toComponent(@NotNull ComponentHolder holder) {
+ return Objects.requireNonNull(IChatBaseComponent.ChatSerializer.a(holder.asJson()));
+ }
+}
diff --git a/nms/1_16_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R1/AnvilInventoryImpl.java b/nms/1_16_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R1/AnvilInventoryImpl.java
deleted file mode 100644
index 5da3e3f29..000000000
--- a/nms/1_16_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R1/AnvilInventoryImpl.java
+++ /dev/null
@@ -1,241 +0,0 @@
-package com.github.stefvanschie.inventoryframework.nms.v1_16_R1;
-
-import com.github.stefvanschie.inventoryframework.abstraction.AnvilInventory;
-import net.minecraft.server.v1_16_R1.*;
-import org.bukkit.Location;
-import org.bukkit.craftbukkit.v1_16_R1.entity.CraftPlayer;
-import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftInventory;
-import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftInventoryAnvil;
-import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftInventoryView;
-import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftItemStack;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.InventoryHolder;
-import org.jetbrains.annotations.Contract;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-/**
- * Internal anvil inventory for 1.16 R1
- *
- * @since 0.8.0
- */
-public class AnvilInventoryImpl extends AnvilInventory {
-
- public AnvilInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
- super(inventoryHolder);
- }
-
- @Override
- public void openInventory(@NotNull Player player, @NotNull String title,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- int itemAmount = items.length;
-
- if (itemAmount != 3) {
- throw new IllegalArgumentException(
- "The amount of items for an anvil should be 3, but is '" + itemAmount + "'"
- );
- }
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
- ContainerAnvilImpl containerAnvil = new ContainerAnvilImpl(entityPlayer, items);
-
- entityPlayer.activeContainer = containerAnvil;
-
- int id = containerAnvil.windowId;
- ChatMessage message = new ChatMessage(title);
-
- entityPlayer.playerConnection.sendPacket(new PacketPlayOutOpenWindow(id, Containers.ANVIL, message));
-
- sendItems(player, items);
- }
-
- @Override
- public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
- NonNullList nmsItems = NonNullList.a(
- ItemStack.b,
- CraftItemStack.asNMSCopy(items[0]),
- CraftItemStack.asNMSCopy(items[1]),
- CraftItemStack.asNMSCopy(items[2])
- );
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
- }
-
- @Override
- public void sendFirstItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
- EntityPlayer entityPlayer = getEntityPlayer(player);
- ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutSetSlot(getWindowId(entityPlayer), 0, nmsItem));
- }
-
- @Override
- public void sendSecondItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
- EntityPlayer entityPlayer = getEntityPlayer(player);
- ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutSetSlot(getWindowId(entityPlayer), 1, nmsItem));
- }
-
- @Override
- public void sendResultItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
- sendResultItem(player, CraftItemStack.asNMSCopy(item));
- }
-
- @Override
- public void clearResultItem(@NotNull Player player) {
- sendResultItem(player, ItemStack.b);
- }
-
- @Override
- public void setCursor(@NotNull Player player, @NotNull org.bukkit.inventory.ItemStack item) {
- setCursor(player, CraftItemStack.asNMSCopy(item));
- }
-
- @Override
- public void clearCursor(@NotNull Player player) {
- getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.b));
- }
-
- /**
- * Sets the cursor of the given player
- *
- * @param player the player to set the cursor
- * @param item the item to set the cursor to
- * @since 0.8.0
- */
- private void setCursor(@NotNull Player player, @NotNull ItemStack item) {
- getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, item));
- }
-
- /**
- * Sends the result item to the specified player with the given item
- *
- * @param player the player to send the result item to
- * @param item the result item
- * @since 0.8.0
- */
- private void sendResultItem(@NotNull Player player, @NotNull ItemStack item) {
- EntityPlayer entityPlayer = getEntityPlayer(player);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutSetSlot(getWindowId(entityPlayer), 2, item));
- }
-
- /**
- * Gets the window id for the inventory view the player currently has open
- *
- * @param entityPlayer the player to get the window id for
- * @return the window id
- * @since 0.8.0
- */
- @Contract(pure = true)
- private int getWindowId(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.activeContainer.windowId;
- }
-
- /**
- * Gets the player connection for the specified player
- *
- * @param entityPlayer the player to get the player connection from
- * @return the player connection
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.playerConnection;
- }
-
- /**
- * Gets the entity player associated to this player
- *
- * @param player the player to get the entity player from
- * @return the entity player
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private EntityPlayer getEntityPlayer(@NotNull Player player) {
- return ((CraftPlayer) player).getHandle();
- }
-
- /**
- * A custom container anvil for responding to item renaming
- *
- * @since 0.8.0
- */
- private class ContainerAnvilImpl extends ContainerAnvil {
-
- /**
- * The player for whom this anvil container is
- */
- @NotNull
- private final Player player;
-
- /**
- * The internal bukkit entity for this container anvil
- */
- @Nullable
- private CraftInventoryView bukkitEntity;
-
- /**
- * Creates a new custom anvil container for the specified player
- *
- * @param entityPlayer the player for who this anvil container is
- * @since 0.8.0
- */
- public ContainerAnvilImpl(@NotNull EntityPlayer entityPlayer,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- super(entityPlayer.nextContainerCounter(), entityPlayer.inventory,
- ContainerAccess.at(entityPlayer.getWorld(), new BlockPosition(0, 0, 0)));
-
- this.player = entityPlayer.getBukkitEntity();
-
- repairInventory.setItem(0, CraftItemStack.asNMSCopy(items[0]));
- repairInventory.setItem(1, CraftItemStack.asNMSCopy(items[1]));
- resultInventory.setItem(0, CraftItemStack.asNMSCopy(items[2]));
- }
-
- @NotNull
- @Override
- public CraftInventoryView getBukkitView() {
- if (bukkitEntity == null) {
- Location location = containerAccess.getLocation();
- CraftInventory inventory = new CraftInventoryAnvil(location, repairInventory, resultInventory,
- this) {
- @NotNull
- @Contract(pure = true)
- @Override
- public InventoryHolder getHolder() {
- return inventoryHolder;
- }
- };
-
- bukkitEntity = new CraftInventoryView(player, inventory, this);
- }
-
- return bukkitEntity;
- }
-
- @Override
- public void a(@Nullable String name) {
- text = name == null ? "" : name;
-
- sendResultItem(player, resultInventory.getItem(0));
- }
-
- @Contract(pure = true, value = "_ -> true")
- @Override
- public boolean canUse(@Nullable EntityHuman entityhuman) {
- return true;
- }
-
- @Override
- public void a(IInventory inventory) {}
-
- @Override
- public void b(EntityHuman entityhuman) {}
- }
-}
diff --git a/nms/1_16_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R1/GrindstoneInventoryImpl.java b/nms/1_16_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R1/GrindstoneInventoryImpl.java
deleted file mode 100644
index 291db39c1..000000000
--- a/nms/1_16_R1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R1/GrindstoneInventoryImpl.java
+++ /dev/null
@@ -1,227 +0,0 @@
-package com.github.stefvanschie.inventoryframework.nms.v1_16_R1;
-
-import com.github.stefvanschie.inventoryframework.abstraction.GrindstoneInventory;
-import net.minecraft.server.v1_16_R1.*;
-import org.bukkit.craftbukkit.v1_16_R1.entity.CraftPlayer;
-import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftInventory;
-import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftInventoryGrindstone;
-import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftInventoryView;
-import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftItemStack;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.InventoryHolder;
-import org.jetbrains.annotations.Contract;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.lang.reflect.Field;
-
-/**
- * Internal grindstone inventory for 1.16 R1
- *
- * @since 0.8.0
- */
-public class GrindstoneInventoryImpl extends GrindstoneInventory {
-
- public GrindstoneInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
- super(inventoryHolder);
- }
-
- @Override
- public void openInventory(@NotNull Player player, @NotNull String title,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- int itemAmount = items.length;
-
- if (itemAmount != 3) {
- throw new IllegalArgumentException(
- "The amount of items for a grindstone should be 3, but is '" + itemAmount + "'"
- );
- }
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
- ContainerGrindstoneImpl containerGrindstone = new ContainerGrindstoneImpl(entityPlayer, items);
-
- entityPlayer.activeContainer = containerGrindstone;
-
- int id = containerGrindstone.windowId;
- ChatMessage message = new ChatMessage(title);
- PacketPlayOutOpenWindow packet = new PacketPlayOutOpenWindow(id, Containers.GRINDSTONE, message);
-
- entityPlayer.playerConnection.sendPacket(packet);
-
- sendItems(player, items);
- }
-
- @Override
- public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
- NonNullList nmsItems = NonNullList.a(
- ItemStack.b,
- CraftItemStack.asNMSCopy(items[0]),
- CraftItemStack.asNMSCopy(items[1]),
- CraftItemStack.asNMSCopy(items[2])
- );
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
- }
-
- @Override
- public void clearCursor(@NotNull Player player) {
- getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.b));
- }
-
- /**
- * Gets the window id for the inventory view the player currently has open
- *
- * @param entityPlayer the player to get the window id for
- * @return the window id
- * @since 0.8.0
- */
- @Contract(pure = true)
- private int getWindowId(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.activeContainer.windowId;
- }
-
- /**
- * Gets the player connection for the specified player
- *
- * @param entityPlayer the player to get the player connection from
- * @return the player connection
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.playerConnection;
- }
-
- /**
- * Gets the entity player associated to this player
- *
- * @param player the player to get the entity player from
- * @return the entity player
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private EntityPlayer getEntityPlayer(@NotNull Player player) {
- return ((CraftPlayer) player).getHandle();
- }
-
- /**
- * A custom container grindstone
- *
- * @since 0.8.0
- */
- private class ContainerGrindstoneImpl extends ContainerGrindstone {
-
- /**
- * The player for this grindstone container
- */
- @NotNull
- private final Player player;
-
- /**
- * The internal bukkit entity for this container grindstone
- */
- @Nullable
- private CraftInventoryView bukkitEntity;
-
- /**
- * Field for accessing the craft inventory field
- */
- @NotNull
- private final Field craftInventoryField;
-
- /**
- * Field for accessing the result inventory field
- */
- @NotNull
- private final Field resultInventoryField;
-
- public ContainerGrindstoneImpl(@NotNull EntityPlayer entityPlayer,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
-
- this.player = entityPlayer.getBukkitEntity();
-
- try {
- this.craftInventoryField = ContainerGrindstone.class.getDeclaredField("craftInventory");
- this.craftInventoryField.setAccessible(true);
-
- this.resultInventoryField = ContainerGrindstone.class.getDeclaredField("resultInventory");
- this.resultInventoryField.setAccessible(true);
- } catch (NoSuchFieldException exception) {
- throw new RuntimeException(exception);
- }
-
- getCraftInventory().setItem(0, CraftItemStack.asNMSCopy(items[0]));
- getCraftInventory().setItem(1, CraftItemStack.asNMSCopy(items[1]));
-
- getResultInventory().setItem(2, CraftItemStack.asNMSCopy(items[2]));
- }
-
- @NotNull
- @Override
- public CraftInventoryView getBukkitView() {
- if (bukkitEntity == null) {
- CraftInventory inventory = new CraftInventoryGrindstone(getCraftInventory(), getResultInventory()) {
- @NotNull
- @Contract(pure = true)
- @Override
- public InventoryHolder getHolder() {
- return inventoryHolder;
- }
- };
-
- bukkitEntity = new CraftInventoryView(player, inventory, this);
- }
-
- return bukkitEntity;
- }
-
- @Contract(pure = true, value = "_ -> true")
- @Override
- public boolean canUse(@Nullable EntityHuman entityhuman) {
- return true;
- }
-
- @Override
- public void a(IInventory inventory) {}
-
- @Override
- public void b(EntityHuman entityhuman) {}
-
- /**
- * Gets the craft inventory
- *
- * @return the craft inventory
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private IInventory getCraftInventory() {
- try {
- return (IInventory) craftInventoryField.get(this);
- } catch (IllegalAccessException exception) {
- throw new RuntimeException(exception);
- }
- }
-
- /**
- * Gets the result inventory
- *
- * @return the result inventory
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private IInventory getResultInventory() {
- try {
- return (IInventory) resultInventoryField.get(this);
- } catch (IllegalAccessException exception) {
- throw new RuntimeException(exception);
- }
- }
- }
-}
diff --git a/nms/1_16_R2/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R2/AnvilInventoryImpl.java b/nms/1_16_R2/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R2/AnvilInventoryImpl.java
deleted file mode 100644
index b0fc4bd74..000000000
--- a/nms/1_16_R2/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R2/AnvilInventoryImpl.java
+++ /dev/null
@@ -1,241 +0,0 @@
-package com.github.stefvanschie.inventoryframework.nms.v1_16_R2;
-
-import com.github.stefvanschie.inventoryframework.abstraction.AnvilInventory;
-import net.minecraft.server.v1_16_R2.*;
-import org.bukkit.Location;
-import org.bukkit.craftbukkit.v1_16_R2.entity.CraftPlayer;
-import org.bukkit.craftbukkit.v1_16_R2.inventory.CraftInventory;
-import org.bukkit.craftbukkit.v1_16_R2.inventory.CraftInventoryAnvil;
-import org.bukkit.craftbukkit.v1_16_R2.inventory.CraftInventoryView;
-import org.bukkit.craftbukkit.v1_16_R2.inventory.CraftItemStack;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.InventoryHolder;
-import org.jetbrains.annotations.Contract;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-/**
- * Internal anvil inventory for 1.16 R2
- *
- * @since 0.8.0
- */
-public class AnvilInventoryImpl extends AnvilInventory {
-
- public AnvilInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
- super(inventoryHolder);
- }
-
- @Override
- public void openInventory(@NotNull Player player, @NotNull String title,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- int itemAmount = items.length;
-
- if (itemAmount != 3) {
- throw new IllegalArgumentException(
- "The amount of items for an anvil should be 3, but is '" + itemAmount + "'"
- );
- }
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
- ContainerAnvilImpl containerAnvil = new ContainerAnvilImpl(entityPlayer, items);
-
- entityPlayer.activeContainer = containerAnvil;
-
- int id = containerAnvil.windowId;
- ChatMessage message = new ChatMessage(title);
-
- entityPlayer.playerConnection.sendPacket(new PacketPlayOutOpenWindow(id, Containers.ANVIL, message));
-
- sendItems(player, items);
- }
-
- @Override
- public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
- NonNullList nmsItems = NonNullList.a(
- ItemStack.b,
- CraftItemStack.asNMSCopy(items[0]),
- CraftItemStack.asNMSCopy(items[1]),
- CraftItemStack.asNMSCopy(items[2])
- );
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
- }
-
- @Override
- public void sendFirstItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
- EntityPlayer entityPlayer = getEntityPlayer(player);
- ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutSetSlot(getWindowId(entityPlayer), 0, nmsItem));
- }
-
- @Override
- public void sendSecondItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
- EntityPlayer entityPlayer = getEntityPlayer(player);
- ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutSetSlot(getWindowId(entityPlayer), 1, nmsItem));
- }
-
- @Override
- public void sendResultItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
- sendResultItem(player, CraftItemStack.asNMSCopy(item));
- }
-
- @Override
- public void clearResultItem(@NotNull Player player) {
- sendResultItem(player, ItemStack.b);
- }
-
- @Override
- public void setCursor(@NotNull Player player, @NotNull org.bukkit.inventory.ItemStack item) {
- setCursor(player, CraftItemStack.asNMSCopy(item));
- }
-
- @Override
- public void clearCursor(@NotNull Player player) {
- getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.b));
- }
-
- /**
- * Sets the cursor of the given player
- *
- * @param player the player to set the cursor
- * @param item the item to set the cursor to
- * @since 0.8.0
- */
- private void setCursor(@NotNull Player player, @NotNull ItemStack item) {
- getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, item));
- }
-
- /**
- * Sends the result item to the specified player with the given item
- *
- * @param player the player to send the result item to
- * @param item the result item
- * @since 0.8.0
- */
- private void sendResultItem(@NotNull Player player, @NotNull ItemStack item) {
- EntityPlayer entityPlayer = getEntityPlayer(player);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutSetSlot(getWindowId(entityPlayer), 2, item));
- }
-
- /**
- * Gets the window id for the inventory view the player currently has open
- *
- * @param entityPlayer the player to get the window id for
- * @return the window id
- * @since 0.8.0
- */
- @Contract(pure = true)
- private int getWindowId(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.activeContainer.windowId;
- }
-
- /**
- * Gets the player connection for the specified player
- *
- * @param entityPlayer the player to get the player connection from
- * @return the player connection
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.playerConnection;
- }
-
- /**
- * Gets the entity player associated to this player
- *
- * @param player the player to get the entity player from
- * @return the entity player
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private EntityPlayer getEntityPlayer(@NotNull Player player) {
- return ((CraftPlayer) player).getHandle();
- }
-
- /**
- * A custom container anvil for responding to item renaming
- *
- * @since 0.8.0
- */
- private class ContainerAnvilImpl extends ContainerAnvil {
-
- /**
- * The player for whom this anvil container is
- */
- @NotNull
- private final Player player;
-
- /**
- * The internal bukkit entity for this container anvil
- */
- @Nullable
- private CraftInventoryView bukkitEntity;
-
- /**
- * Creates a new custom anvil container for the specified player
- *
- * @param entityPlayer the player for who this anvil container is
- * @since 0.8.0
- */
- public ContainerAnvilImpl(@NotNull EntityPlayer entityPlayer,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- super(entityPlayer.nextContainerCounter(), entityPlayer.inventory,
- ContainerAccess.at(entityPlayer.getWorld(), new BlockPosition(0, 0, 0)));
-
- this.player = entityPlayer.getBukkitEntity();
-
- repairInventory.setItem(0, CraftItemStack.asNMSCopy(items[0]));
- repairInventory.setItem(1, CraftItemStack.asNMSCopy(items[1]));
- resultInventory.setItem(0, CraftItemStack.asNMSCopy(items[2]));
- }
-
- @NotNull
- @Override
- public CraftInventoryView getBukkitView() {
- if (bukkitEntity == null) {
- Location location = containerAccess.getLocation();
- CraftInventory inventory = new CraftInventoryAnvil(location, repairInventory, resultInventory,
- this) {
- @NotNull
- @Contract(pure = true)
- @Override
- public InventoryHolder getHolder() {
- return inventoryHolder;
- }
- };
-
- bukkitEntity = new CraftInventoryView(player, inventory, this);
- }
-
- return bukkitEntity;
- }
-
- @Override
- public void a(@Nullable String name) {
- text = name == null ? "" : name;
-
- sendResultItem(player, resultInventory.getItem(0));
- }
-
- @Contract(pure = true, value = "_ -> true")
- @Override
- public boolean canUse(@Nullable EntityHuman entityhuman) {
- return true;
- }
-
- @Override
- public void a(IInventory inventory) {}
-
- @Override
- public void b(EntityHuman entityhuman) {}
- }
-}
diff --git a/nms/1_16_R2/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R2/GrindstoneInventoryImpl.java b/nms/1_16_R2/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R2/GrindstoneInventoryImpl.java
deleted file mode 100644
index 48bf2f02e..000000000
--- a/nms/1_16_R2/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R2/GrindstoneInventoryImpl.java
+++ /dev/null
@@ -1,224 +0,0 @@
-package com.github.stefvanschie.inventoryframework.nms.v1_16_R2;
-
-import com.github.stefvanschie.inventoryframework.abstraction.GrindstoneInventory;
-import net.minecraft.server.v1_16_R2.*;
-import org.bukkit.craftbukkit.v1_16_R2.entity.CraftPlayer;
-import org.bukkit.craftbukkit.v1_16_R2.inventory.*;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.InventoryHolder;
-import org.jetbrains.annotations.Contract;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.lang.reflect.Field;
-
-/**
- * Internal grindstone inventory for 1.16 R2
- *
- * @since 0.8.0
- */
-public class GrindstoneInventoryImpl extends GrindstoneInventory {
-
- public GrindstoneInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
- super(inventoryHolder);
- }
-
- @Override
- public void openInventory(@NotNull Player player, @NotNull String title,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- int itemAmount = items.length;
-
- if (itemAmount != 3) {
- throw new IllegalArgumentException(
- "The amount of items for a grindstone should be 3, but is '" + itemAmount + "'"
- );
- }
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
- ContainerGrindstoneImpl containerGrindstone = new ContainerGrindstoneImpl(entityPlayer, items);
-
- entityPlayer.activeContainer = containerGrindstone;
-
- int id = containerGrindstone.windowId;
- ChatMessage message = new ChatMessage(title);
- PacketPlayOutOpenWindow packet = new PacketPlayOutOpenWindow(id, Containers.GRINDSTONE, message);
-
- entityPlayer.playerConnection.sendPacket(packet);
-
- sendItems(player, items);
- }
-
- @Override
- public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
- NonNullList nmsItems = NonNullList.a(
- ItemStack.b,
- CraftItemStack.asNMSCopy(items[0]),
- CraftItemStack.asNMSCopy(items[1]),
- CraftItemStack.asNMSCopy(items[2])
- );
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
- }
-
- @Override
- public void clearCursor(@NotNull Player player) {
- getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.b));
- }
-
- /**
- * Gets the window id for the inventory view the player currently has open
- *
- * @param entityPlayer the player to get the window id for
- * @return the window id
- * @since 0.8.0
- */
- @Contract(pure = true)
- private int getWindowId(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.activeContainer.windowId;
- }
-
- /**
- * Gets the player connection for the specified player
- *
- * @param entityPlayer the player to get the player connection from
- * @return the player connection
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.playerConnection;
- }
-
- /**
- * Gets the entity player associated to this player
- *
- * @param player the player to get the entity player from
- * @return the entity player
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private EntityPlayer getEntityPlayer(@NotNull Player player) {
- return ((CraftPlayer) player).getHandle();
- }
-
- /**
- * A custom container grindstone
- *
- * @since 0.8.0
- */
- private class ContainerGrindstoneImpl extends ContainerGrindstone {
-
- /**
- * The player for this grindstone container
- */
- @NotNull
- private final Player player;
-
- /**
- * The internal bukkit entity for this container grindstone
- */
- @Nullable
- private CraftInventoryView bukkitEntity;
-
- /**
- * Field for accessing the craft inventory field
- */
- @NotNull
- private final Field craftInventoryField;
-
- /**
- * Field for accessing the result inventory field
- */
- @NotNull
- private final Field resultInventoryField;
-
- public ContainerGrindstoneImpl(@NotNull EntityPlayer entityPlayer,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
-
- this.player = entityPlayer.getBukkitEntity();
-
- try {
- this.craftInventoryField = ContainerGrindstone.class.getDeclaredField("craftInventory");
- this.craftInventoryField.setAccessible(true);
-
- this.resultInventoryField = ContainerGrindstone.class.getDeclaredField("resultInventory");
- this.resultInventoryField.setAccessible(true);
- } catch (NoSuchFieldException exception) {
- throw new RuntimeException(exception);
- }
-
- getCraftInventory().setItem(0, CraftItemStack.asNMSCopy(items[0]));
- getCraftInventory().setItem(1, CraftItemStack.asNMSCopy(items[1]));
-
- getResultInventory().setItem(2, CraftItemStack.asNMSCopy(items[2]));
- }
-
- @NotNull
- @Override
- public CraftInventoryView getBukkitView() {
- if (bukkitEntity == null) {
- CraftInventory inventory = new CraftInventoryGrindstone(getCraftInventory(), getResultInventory()) {
- @NotNull
- @Contract(pure = true)
- @Override
- public InventoryHolder getHolder() {
- return inventoryHolder;
- }
- };
-
- bukkitEntity = new CraftInventoryView(player, inventory, this);
- }
-
- return bukkitEntity;
- }
-
- @Contract(pure = true, value = "_ -> true")
- @Override
- public boolean canUse(@Nullable EntityHuman entityhuman) {
- return true;
- }
-
- @Override
- public void a(IInventory inventory) {}
-
- @Override
- public void b(EntityHuman entityhuman) {}
-
- /**
- * Gets the craft inventory
- *
- * @return the craft inventory
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private IInventory getCraftInventory() {
- try {
- return (IInventory) craftInventoryField.get(this);
- } catch (IllegalAccessException exception) {
- throw new RuntimeException(exception);
- }
- }
-
- /**
- * Gets the result inventory
- *
- * @return the result inventory
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private IInventory getResultInventory() {
- try {
- return (IInventory) resultInventoryField.get(this);
- } catch (IllegalAccessException exception) {
- throw new RuntimeException(exception);
- }
- }
- }
-}
diff --git a/nms/1_16_R3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R3/AnvilInventoryImpl.java b/nms/1_16_R3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R3/AnvilInventoryImpl.java
deleted file mode 100644
index 636d6ce51..000000000
--- a/nms/1_16_R3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R3/AnvilInventoryImpl.java
+++ /dev/null
@@ -1,241 +0,0 @@
-package com.github.stefvanschie.inventoryframework.nms.v1_16_R3;
-
-import com.github.stefvanschie.inventoryframework.abstraction.AnvilInventory;
-import net.minecraft.server.v1_16_R3.*;
-import org.bukkit.Location;
-import org.bukkit.craftbukkit.v1_16_R3.entity.CraftPlayer;
-import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftInventory;
-import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftInventoryAnvil;
-import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftInventoryView;
-import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftItemStack;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.InventoryHolder;
-import org.jetbrains.annotations.Contract;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-/**
- * Internal anvil inventory for 1.16 R3
- *
- * @since 0.8.0
- */
-public class AnvilInventoryImpl extends AnvilInventory {
-
- public AnvilInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
- super(inventoryHolder);
- }
-
- @Override
- public void openInventory(@NotNull Player player, @NotNull String title,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- int itemAmount = items.length;
-
- if (itemAmount != 3) {
- throw new IllegalArgumentException(
- "The amount of items for an anvil should be 3, but is '" + itemAmount + "'"
- );
- }
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
- ContainerAnvilImpl containerAnvil = new ContainerAnvilImpl(entityPlayer, items);
-
- entityPlayer.activeContainer = containerAnvil;
-
- int id = containerAnvil.windowId;
- ChatMessage message = new ChatMessage(title);
-
- entityPlayer.playerConnection.sendPacket(new PacketPlayOutOpenWindow(id, Containers.ANVIL, message));
-
- sendItems(player, items);
- }
-
- @Override
- public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
- NonNullList nmsItems = NonNullList.a(
- ItemStack.b,
- CraftItemStack.asNMSCopy(items[0]),
- CraftItemStack.asNMSCopy(items[1]),
- CraftItemStack.asNMSCopy(items[2])
- );
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
- }
-
- @Override
- public void sendFirstItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
- EntityPlayer entityPlayer = getEntityPlayer(player);
- ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutSetSlot(getWindowId(entityPlayer), 0, nmsItem));
- }
-
- @Override
- public void sendSecondItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
- EntityPlayer entityPlayer = getEntityPlayer(player);
- ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutSetSlot(getWindowId(entityPlayer), 1, nmsItem));
- }
-
- @Override
- public void sendResultItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
- sendResultItem(player, CraftItemStack.asNMSCopy(item));
- }
-
- @Override
- public void clearResultItem(@NotNull Player player) {
- sendResultItem(player, ItemStack.b);
- }
-
- @Override
- public void setCursor(@NotNull Player player, @NotNull org.bukkit.inventory.ItemStack item) {
- setCursor(player, CraftItemStack.asNMSCopy(item));
- }
-
- @Override
- public void clearCursor(@NotNull Player player) {
- getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.b));
- }
-
- /**
- * Sets the cursor of the given player
- *
- * @param player the player to set the cursor
- * @param item the item to set the cursor to
- * @since 0.8.0
- */
- private void setCursor(@NotNull Player player, @NotNull ItemStack item) {
- getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, item));
- }
-
- /**
- * Sends the result item to the specified player with the given item
- *
- * @param player the player to send the result item to
- * @param item the result item
- * @since 0.8.0
- */
- private void sendResultItem(@NotNull Player player, @NotNull ItemStack item) {
- EntityPlayer entityPlayer = getEntityPlayer(player);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutSetSlot(getWindowId(entityPlayer), 2, item));
- }
-
- /**
- * Gets the window id for the inventory view the player currently has open
- *
- * @param entityPlayer the player to get the window id for
- * @return the window id
- * @since 0.8.0
- */
- @Contract(pure = true)
- private int getWindowId(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.activeContainer.windowId;
- }
-
- /**
- * Gets the player connection for the specified player
- *
- * @param entityPlayer the player to get the player connection from
- * @return the player connection
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.playerConnection;
- }
-
- /**
- * Gets the entity player associated to this player
- *
- * @param player the player to get the entity player from
- * @return the entity player
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private EntityPlayer getEntityPlayer(@NotNull Player player) {
- return ((CraftPlayer) player).getHandle();
- }
-
- /**
- * A custom container anvil for responding to item renaming
- *
- * @since 0.8.0
- */
- private class ContainerAnvilImpl extends ContainerAnvil {
-
- /**
- * The player for whom this anvil container is
- */
- @NotNull
- private final Player player;
-
- /**
- * The internal bukkit entity for this container anvil
- */
- @Nullable
- private CraftInventoryView bukkitEntity;
-
- /**
- * Creates a new custom anvil container for the specified player
- *
- * @param entityPlayer the player for who this anvil container is
- * @since 0.8.0
- */
- public ContainerAnvilImpl(@NotNull EntityPlayer entityPlayer,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- super(entityPlayer.nextContainerCounter(), entityPlayer.inventory,
- ContainerAccess.at(entityPlayer.getWorld(), new BlockPosition(0, 0, 0)));
-
- this.player = entityPlayer.getBukkitEntity();
-
- repairInventory.setItem(0, CraftItemStack.asNMSCopy(items[0]));
- repairInventory.setItem(1, CraftItemStack.asNMSCopy(items[1]));
- resultInventory.setItem(0, CraftItemStack.asNMSCopy(items[2]));
- }
-
- @NotNull
- @Override
- public CraftInventoryView getBukkitView() {
- if (bukkitEntity == null) {
- Location location = containerAccess.getLocation();
- CraftInventory inventory = new CraftInventoryAnvil(location, repairInventory, resultInventory,
- this) {
- @NotNull
- @Contract(pure = true)
- @Override
- public InventoryHolder getHolder() {
- return inventoryHolder;
- }
- };
-
- bukkitEntity = new CraftInventoryView(player, inventory, this);
- }
-
- return bukkitEntity;
- }
-
- @Override
- public void a(@Nullable String name) {
- text = name == null ? "" : name;
-
- sendResultItem(player, resultInventory.getItem(0));
- }
-
- @Contract(pure = true, value = "_ -> true")
- @Override
- public boolean canUse(@Nullable EntityHuman entityhuman) {
- return true;
- }
-
- @Override
- public void a(IInventory inventory) {}
-
- @Override
- public void b(EntityHuman entityhuman) {}
- }
-}
diff --git a/nms/1_16_R3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R3/GrindstoneInventoryImpl.java b/nms/1_16_R3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R3/GrindstoneInventoryImpl.java
deleted file mode 100644
index 140cf4d7b..000000000
--- a/nms/1_16_R3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_16_R3/GrindstoneInventoryImpl.java
+++ /dev/null
@@ -1,227 +0,0 @@
-package com.github.stefvanschie.inventoryframework.nms.v1_16_R3;
-
-import com.github.stefvanschie.inventoryframework.abstraction.GrindstoneInventory;
-import net.minecraft.server.v1_16_R3.*;
-import org.bukkit.craftbukkit.v1_16_R3.entity.CraftPlayer;
-import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftInventory;
-import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftInventoryGrindstone;
-import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftInventoryView;
-import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftItemStack;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.InventoryHolder;
-import org.jetbrains.annotations.Contract;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.lang.reflect.Field;
-
-/**
- * Internal grindstone inventory for 1.16 R3
- *
- * @since 0.8.0
- */
-public class GrindstoneInventoryImpl extends GrindstoneInventory {
-
- public GrindstoneInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
- super(inventoryHolder);
- }
-
- @Override
- public void openInventory(@NotNull Player player, @NotNull String title,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- int itemAmount = items.length;
-
- if (itemAmount != 3) {
- throw new IllegalArgumentException(
- "The amount of items for a grindstone should be 3, but is '" + itemAmount + "'"
- );
- }
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
- ContainerGrindstoneImpl containerGrindstone = new ContainerGrindstoneImpl(entityPlayer, items);
-
- entityPlayer.activeContainer = containerGrindstone;
-
- int id = containerGrindstone.windowId;
- ChatMessage message = new ChatMessage(title);
- PacketPlayOutOpenWindow packet = new PacketPlayOutOpenWindow(id, Containers.GRINDSTONE, message);
-
- entityPlayer.playerConnection.sendPacket(packet);
-
- sendItems(player, items);
- }
-
- @Override
- public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
- NonNullList nmsItems = NonNullList.a(
- ItemStack.b,
- CraftItemStack.asNMSCopy(items[0]),
- CraftItemStack.asNMSCopy(items[1]),
- CraftItemStack.asNMSCopy(items[2])
- );
-
- EntityPlayer entityPlayer = getEntityPlayer(player);
-
- getPlayerConnection(entityPlayer).sendPacket(new PacketPlayOutWindowItems(getWindowId(entityPlayer), nmsItems));
- }
-
- @Override
- public void clearCursor(@NotNull Player player) {
- getPlayerConnection(getEntityPlayer(player)).sendPacket(new PacketPlayOutSetSlot(-1, -1, ItemStack.b));
- }
-
- /**
- * Gets the window id for the inventory view the player currently has open
- *
- * @param entityPlayer the player to get the window id for
- * @return the window id
- * @since 0.8.0
- */
- @Contract(pure = true)
- private int getWindowId(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.activeContainer.windowId;
- }
-
- /**
- * Gets the player connection for the specified player
- *
- * @param entityPlayer the player to get the player connection from
- * @return the player connection
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private PlayerConnection getPlayerConnection(@NotNull EntityPlayer entityPlayer) {
- return entityPlayer.playerConnection;
- }
-
- /**
- * Gets the entity player associated to this player
- *
- * @param player the player to get the entity player from
- * @return the entity player
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private EntityPlayer getEntityPlayer(@NotNull Player player) {
- return ((CraftPlayer) player).getHandle();
- }
-
- /**
- * A custom container grindstone
- *
- * @since 0.8.0
- */
- private class ContainerGrindstoneImpl extends ContainerGrindstone {
-
- /**
- * The player for this grindstone container
- */
- @NotNull
- private final Player player;
-
- /**
- * The internal bukkit entity for this container grindstone
- */
- @Nullable
- private CraftInventoryView bukkitEntity;
-
- /**
- * Field for accessing the craft inventory field
- */
- @NotNull
- private final Field craftInventoryField;
-
- /**
- * Field for accessing the result inventory field
- */
- @NotNull
- private final Field resultInventoryField;
-
- public ContainerGrindstoneImpl(@NotNull EntityPlayer entityPlayer,
- @Nullable org.bukkit.inventory.ItemStack[] items) {
- super(entityPlayer.nextContainerCounter(), entityPlayer.inventory);
-
- this.player = entityPlayer.getBukkitEntity();
-
- try {
- this.craftInventoryField = ContainerGrindstone.class.getDeclaredField("craftInventory");
- this.craftInventoryField.setAccessible(true);
-
- this.resultInventoryField = ContainerGrindstone.class.getDeclaredField("resultInventory");
- this.resultInventoryField.setAccessible(true);
- } catch (NoSuchFieldException exception) {
- throw new RuntimeException(exception);
- }
-
- getCraftInventory().setItem(0, CraftItemStack.asNMSCopy(items[0]));
- getCraftInventory().setItem(1, CraftItemStack.asNMSCopy(items[1]));
-
- getResultInventory().setItem(2, CraftItemStack.asNMSCopy(items[2]));
- }
-
- @NotNull
- @Override
- public CraftInventoryView getBukkitView() {
- if (bukkitEntity == null) {
- CraftInventory inventory = new CraftInventoryGrindstone(getCraftInventory(), getResultInventory()) {
- @NotNull
- @Contract(pure = true)
- @Override
- public InventoryHolder getHolder() {
- return inventoryHolder;
- }
- };
-
- bukkitEntity = new CraftInventoryView(player, inventory, this);
- }
-
- return bukkitEntity;
- }
-
- @Contract(pure = true, value = "_ -> true")
- @Override
- public boolean canUse(@Nullable EntityHuman entityhuman) {
- return true;
- }
-
- @Override
- public void a(IInventory inventory) {}
-
- @Override
- public void b(EntityHuman entityhuman) {}
-
- /**
- * Gets the craft inventory
- *
- * @return the craft inventory
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private IInventory getCraftInventory() {
- try {
- return (IInventory) craftInventoryField.get(this);
- } catch (IllegalAccessException exception) {
- throw new RuntimeException(exception);
- }
- }
-
- /**
- * Gets the result inventory
- *
- * @return the result inventory
- * @since 0.8.0
- */
- @NotNull
- @Contract(pure = true)
- private IInventory getResultInventory() {
- try {
- return (IInventory) resultInventoryField.get(this);
- } catch (IllegalAccessException exception) {
- throw new RuntimeException(exception);
- }
- }
- }
-}
diff --git a/nms/1_17_0/pom.xml b/nms/1_17_0/pom.xml
new file mode 100644
index 000000000..9ed5e1571
--- /dev/null
+++ b/nms/1_17_0/pom.xml
@@ -0,0 +1,59 @@
+
+
+
+ IF-parent
+ com.github.stefvanschie.inventoryframework
+ 0.10.18
+ ../../pom.xml
+
+ 4.0.0
+
+ 1_17_0
+
+
+ true
+
+
+
+
+ com.github.stefvanschie.inventoryframework
+ abstraction
+ ${project.version}
+ compile
+
+
+ ca.bkaw
+ paper-nms
+ 1.17-SNAPSHOT
+ provided
+
+
+
+
+
+
+ ca.bkaw
+ paper-nms-maven-plugin
+ 1.4.4
+
+