diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 18ab4d3d..2472e19a 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -97,7 +97,15 @@ updates:
schedule:
interval: "daily"
- package-ecosystem: "maven"
- directory: "/nms/1_21"
+ directory: "/nms/1_21_0"
+ schedule:
+ interval: "daily"
+ - package-ecosystem: "maven"
+ directory: "/nms/1_21_1"
+ schedule:
+ interval: "daily"
+ - package-ecosystem: "maven"
+ directory: "/nms/1_21_2-3"
schedule:
interval: "daily"
- package-ecosystem: "maven"
diff --git a/.github/workflows/auto-deploy.yml b/.github/workflows/auto-deploy.yml
index 721bab50..0ec441f2 100644
--- a/.github/workflows/auto-deploy.yml
+++ b/.github/workflows/auto-deploy.yml
@@ -76,7 +76,7 @@ jobs:
mvn paper-nms:init -pl nms/1_20_1
mvn paper-nms:init -pl nms/1_20_2
mvn paper-nms:init -pl nms/1_20_3-4
- - name: 'Run BuildTools 1.20.5-1.20.6, 1.21.1'
+ - name: 'Run BuildTools 1.20.5-1.20.6, 1.21'
if: steps.cache-paperclip-jars.outputs.cache-hit != 'true'
run: |
mkdir -p build
@@ -105,7 +105,27 @@ jobs:
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
+
cd ../
- name: Setup GPG keys
run: cat <(echo -e "${{ secrets.GPG_KEY }}") | gpg --batch --import
diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml
index 05f7da27..ae799f8a 100644
--- a/.github/workflows/maven.yml
+++ b/.github/workflows/maven.yml
@@ -82,7 +82,7 @@ jobs:
mvn paper-nms:init -pl nms/1_20_1
mvn paper-nms:init -pl nms/1_20_2
mvn paper-nms:init -pl nms/1_20_3-4
- - name: 'Run BuildTools 1.20.5-1.20.6, 1.21.1'
+ - name: 'Run BuildTools 1.20.5-1.20.6, 1.21'
if: steps.cache-paperclip-jars.outputs.cache-hit != 'true'
run: |
mkdir -p build
@@ -111,7 +111,27 @@ jobs:
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
+
cd ../
- name: Build with Maven
run: mvn -B package --file pom.xml
diff --git a/IF/pom.xml b/IF/pom.xml
index 5f0c3399..e14f5591 100644
--- a/IF/pom.xml
+++ b/IF/pom.xml
@@ -5,7 +5,7 @@
IF-parent
com.github.stefvanschie.inventoryframework
- 0.10.17
+ 0.10.18
../pom.xml
4.0.0
@@ -169,7 +169,19 @@
com.github.stefvanschie.inventoryframework
- 1_21
+ 1_21_0
+ ${project.version}
+ compile
+
+
+ com.github.stefvanschie.inventoryframework
+ 1_21_1
+ ${project.version}
+ compile
+
+
+ com.github.stefvanschie.inventoryframework
+ 1_21_2-3
${project.version}
compile
@@ -267,12 +279,12 @@
org.apache.maven.plugins
maven-surefire-plugin
- 3.2.5
+ 3.5.0
org.apache.maven.surefire
surefire-junit-platform
- 3.5.0
+ 3.5.2
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 fa8fe3d6..93ddce44 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
@@ -164,11 +164,25 @@ public enum Version {
V1_20_6,
/**
- * Version 1.21
+ * Version 1.21.0
*
- * @since 0.10.15
+ * @since 0.10.18
*/
- V1_21;
+ 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.
@@ -176,7 +190,7 @@ public enum Version {
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
+ V1_21_0, V1_21_1, V1_21_2_3
);
/**
@@ -192,6 +206,14 @@ public enum Version {
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.
*
@@ -200,7 +222,7 @@ public enum Version {
*/
@Contract(pure = true)
public boolean isInventoryViewInterface() {
- return this == Version.V1_21;
+ return INTERFACE_INVENTORY_VIEW.contains(this);
}
/**
@@ -289,8 +311,12 @@ public static Version getVersion() {
case "1.20.6":
return V1_20_6;
case "1.21":
+ return V1_21_0;
case "1.21.1":
- return V1_21;
+ 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 eceb0e85..5ef83680 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
@@ -317,8 +317,12 @@ public static StonecutterInventory newStonecutterInventory(@NotNull Version vers
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,
- com.github.stefvanschie.inventoryframework.nms.v1_21.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,
@@ -363,8 +367,12 @@ public static StonecutterInventory newStonecutterInventory(@NotNull Version vers
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,
- com.github.stefvanschie.inventoryframework.nms.v1_21.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,
@@ -409,8 +417,12 @@ public static StonecutterInventory newStonecutterInventory(@NotNull Version vers
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,
- com.github.stefvanschie.inventoryframework.nms.v1_21.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,
@@ -455,8 +467,12 @@ public static StonecutterInventory newStonecutterInventory(@NotNull Version vers
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,
- com.github.stefvanschie.inventoryframework.nms.v1_21.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,
@@ -501,8 +517,12 @@ public static StonecutterInventory newStonecutterInventory(@NotNull Version vers
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,
- com.github.stefvanschie.inventoryframework.nms.v1_21.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,
@@ -547,8 +567,12 @@ public static StonecutterInventory newStonecutterInventory(@NotNull Version vers
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,
- com.github.stefvanschie.inventoryframework.nms.v1_21.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_19_4,
@@ -565,8 +589,12 @@ public static StonecutterInventory newStonecutterInventory(@NotNull Version vers
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,
- com.github.stefvanschie.inventoryframework.nms.v1_21.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,
@@ -639,7 +667,11 @@ public static StonecutterInventory newStonecutterInventory(@NotNull Version vers
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,
- com.github.stefvanschie.inventoryframework.nms.v1_21.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/README.md b/README.md
index 18109e57..66687244 100644
--- a/README.md
+++ b/README.md
@@ -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.10.17
+ 0.10.18
```
The project is in the Central Repository, so specifying a repository is not needed.
@@ -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 {
- implementation 'com.github.stefvanschie.inventoryframework:IF:0.10.17'
+ implementation 'com.github.stefvanschie.inventoryframework:IF:0.10.18'
// ...
}
```
@@ -142,10 +142,10 @@ mvn paper-nms:init -pl nms/1_20_3-4
```
### Installing Spigot via BuildTools
-For versions 1.20.5-1.20.6, we use BuildTools. To install these versions, we run the following commands.
+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
@@ -167,9 +167,27 @@ 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.
diff --git a/adventure-support/pom.xml b/adventure-support/pom.xml
index 18a87595..3d4bb888 100644
--- a/adventure-support/pom.xml
+++ b/adventure-support/pom.xml
@@ -5,7 +5,7 @@
IF-parent
com.github.stefvanschie.inventoryframework
- 0.10.17
+ 0.10.18
4.0.0
diff --git a/inventory-view/iv-abstract-class/pom.xml b/inventory-view/iv-abstract-class/pom.xml
index 7e93aa5e..ea1a52a8 100644
--- a/inventory-view/iv-abstract-class/pom.xml
+++ b/inventory-view/iv-abstract-class/pom.xml
@@ -6,7 +6,7 @@
com.github.stefvanschie.inventoryframework
IF-parent
- 0.10.17
+ 0.10.18
../../pom.xml
diff --git a/inventory-view/iv-abstraction/pom.xml b/inventory-view/iv-abstraction/pom.xml
index e8c41e99..c03fa67b 100644
--- a/inventory-view/iv-abstraction/pom.xml
+++ b/inventory-view/iv-abstraction/pom.xml
@@ -6,7 +6,7 @@
com.github.stefvanschie.inventoryframework
IF-parent
- 0.10.17
+ 0.10.18
../../pom.xml
diff --git a/inventory-view/iv-interface/pom.xml b/inventory-view/iv-interface/pom.xml
index d79270a6..cd6e8cf4 100644
--- a/inventory-view/iv-interface/pom.xml
+++ b/inventory-view/iv-interface/pom.xml
@@ -6,7 +6,7 @@
com.github.stefvanschie.inventoryframework
IF-parent
- 0.10.17
+ 0.10.18
../../pom.xml
diff --git a/nms/1_14/pom.xml b/nms/1_14/pom.xml
index 4d8035bf..dad32016 100644
--- a/nms/1_14/pom.xml
+++ b/nms/1_14/pom.xml
@@ -5,7 +5,7 @@
IF-parent
com.github.stefvanschie.inventoryframework
- 0.10.17
+ 0.10.18
../../pom.xml
4.0.0
diff --git a/nms/1_15/pom.xml b/nms/1_15/pom.xml
index 78de6860..c85530eb 100644
--- a/nms/1_15/pom.xml
+++ b/nms/1_15/pom.xml
@@ -5,7 +5,7 @@
IF-parent
com.github.stefvanschie.inventoryframework
- 0.10.17
+ 0.10.18
../../pom.xml
4.0.0
diff --git a/nms/1_16_1/pom.xml b/nms/1_16_1/pom.xml
index 96402109..6ad0fba2 100644
--- a/nms/1_16_1/pom.xml
+++ b/nms/1_16_1/pom.xml
@@ -5,7 +5,7 @@
IF-parent
com.github.stefvanschie.inventoryframework
- 0.10.17
+ 0.10.18
../../pom.xml
4.0.0
diff --git a/nms/1_16_2-3/pom.xml b/nms/1_16_2-3/pom.xml
index ace906da..147afb07 100644
--- a/nms/1_16_2-3/pom.xml
+++ b/nms/1_16_2-3/pom.xml
@@ -5,7 +5,7 @@
IF-parent
com.github.stefvanschie.inventoryframework
- 0.10.17
+ 0.10.18
../../pom.xml
4.0.0
diff --git a/nms/1_16_4-5/pom.xml b/nms/1_16_4-5/pom.xml
index e6372f49..8f5722fb 100644
--- a/nms/1_16_4-5/pom.xml
+++ b/nms/1_16_4-5/pom.xml
@@ -5,7 +5,7 @@
IF-parent
com.github.stefvanschie.inventoryframework
- 0.10.17
+ 0.10.18
../../pom.xml
4.0.0
diff --git a/nms/1_17_0/pom.xml b/nms/1_17_0/pom.xml
index 7d523f9f..9ed5e157 100644
--- a/nms/1_17_0/pom.xml
+++ b/nms/1_17_0/pom.xml
@@ -5,7 +5,7 @@
IF-parent
com.github.stefvanschie.inventoryframework
- 0.10.17
+ 0.10.18
../../pom.xml
4.0.0
diff --git a/nms/1_17_1/pom.xml b/nms/1_17_1/pom.xml
index 0ab843dd..76b1958b 100644
--- a/nms/1_17_1/pom.xml
+++ b/nms/1_17_1/pom.xml
@@ -5,7 +5,7 @@
IF-parent
com.github.stefvanschie.inventoryframework
- 0.10.17
+ 0.10.18
../../pom.xml
4.0.0
diff --git a/nms/1_18_0/pom.xml b/nms/1_18_0/pom.xml
index 92549d97..26911cff 100644
--- a/nms/1_18_0/pom.xml
+++ b/nms/1_18_0/pom.xml
@@ -5,7 +5,7 @@
IF-parent
com.github.stefvanschie.inventoryframework
- 0.10.17
+ 0.10.18
../../pom.xml
4.0.0
diff --git a/nms/1_18_1/pom.xml b/nms/1_18_1/pom.xml
index 3db1fd53..cfa85309 100644
--- a/nms/1_18_1/pom.xml
+++ b/nms/1_18_1/pom.xml
@@ -5,7 +5,7 @@
IF-parent
com.github.stefvanschie.inventoryframework
- 0.10.17
+ 0.10.18
../../pom.xml
4.0.0
diff --git a/nms/1_18_2/pom.xml b/nms/1_18_2/pom.xml
index 9cb915bd..09e12156 100644
--- a/nms/1_18_2/pom.xml
+++ b/nms/1_18_2/pom.xml
@@ -5,7 +5,7 @@
IF-parent
com.github.stefvanschie.inventoryframework
- 0.10.17
+ 0.10.18
../../pom.xml
4.0.0
diff --git a/nms/1_19_0/pom.xml b/nms/1_19_0/pom.xml
index 49ee1600..db868d97 100644
--- a/nms/1_19_0/pom.xml
+++ b/nms/1_19_0/pom.xml
@@ -5,7 +5,7 @@
IF-parent
com.github.stefvanschie.inventoryframework
- 0.10.17
+ 0.10.18
../../pom.xml
4.0.0
diff --git a/nms/1_19_1/pom.xml b/nms/1_19_1/pom.xml
index 3b7b6d8e..2510e437 100644
--- a/nms/1_19_1/pom.xml
+++ b/nms/1_19_1/pom.xml
@@ -5,7 +5,7 @@
IF-parent
com.github.stefvanschie.inventoryframework
- 0.10.17
+ 0.10.18
../../pom.xml
4.0.0
diff --git a/nms/1_19_2/pom.xml b/nms/1_19_2/pom.xml
index 2526e1c1..a9d1888f 100644
--- a/nms/1_19_2/pom.xml
+++ b/nms/1_19_2/pom.xml
@@ -5,7 +5,7 @@
IF-parent
com.github.stefvanschie.inventoryframework
- 0.10.17
+ 0.10.18
../../pom.xml
4.0.0
diff --git a/nms/1_19_3/pom.xml b/nms/1_19_3/pom.xml
index da030c6b..1f792479 100644
--- a/nms/1_19_3/pom.xml
+++ b/nms/1_19_3/pom.xml
@@ -5,7 +5,7 @@
IF-parent
com.github.stefvanschie.inventoryframework
- 0.10.17
+ 0.10.18
../../pom.xml
4.0.0
diff --git a/nms/1_19_4/pom.xml b/nms/1_19_4/pom.xml
index 5c059349..9d84bb3b 100644
--- a/nms/1_19_4/pom.xml
+++ b/nms/1_19_4/pom.xml
@@ -5,7 +5,7 @@
IF-parent
com.github.stefvanschie.inventoryframework
- 0.10.17
+ 0.10.18
../../pom.xml
4.0.0
diff --git a/nms/1_20_0/pom.xml b/nms/1_20_0/pom.xml
index 6f111cb8..4197a5b5 100644
--- a/nms/1_20_0/pom.xml
+++ b/nms/1_20_0/pom.xml
@@ -6,7 +6,7 @@
com.github.stefvanschie.inventoryframework
IF-parent
- 0.10.17
+ 0.10.18
../../pom.xml
diff --git a/nms/1_20_1/pom.xml b/nms/1_20_1/pom.xml
index b575179c..d6231fee 100644
--- a/nms/1_20_1/pom.xml
+++ b/nms/1_20_1/pom.xml
@@ -6,7 +6,7 @@
com.github.stefvanschie.inventoryframework
IF-parent
- 0.10.17
+ 0.10.18
../../pom.xml
diff --git a/nms/1_20_2/pom.xml b/nms/1_20_2/pom.xml
index b85178e1..7e531ea4 100644
--- a/nms/1_20_2/pom.xml
+++ b/nms/1_20_2/pom.xml
@@ -6,7 +6,7 @@
com.github.stefvanschie.inventoryframework
IF-parent
- 0.10.17
+ 0.10.18
../../pom.xml
diff --git a/nms/1_20_3-4/pom.xml b/nms/1_20_3-4/pom.xml
index 232dd395..a3084721 100644
--- a/nms/1_20_3-4/pom.xml
+++ b/nms/1_20_3-4/pom.xml
@@ -6,7 +6,7 @@
com.github.stefvanschie.inventoryframework
IF-parent
- 0.10.17
+ 0.10.18
../../pom.xml
@@ -62,12 +62,12 @@
net.kyori
adventure-text-serializer-gson
- 4.15.0
+ 4.17.0
net.kyori
adventure-text-serializer-json
- 4.15.0
+ 4.17.0
net.kyori
@@ -77,7 +77,7 @@
net.kyori
adventure-text-serializer-plain
- 4.15.0
+ 4.17.0
diff --git a/nms/1_20_5/pom.xml b/nms/1_20_5/pom.xml
index 7a7863a2..ed3a0704 100644
--- a/nms/1_20_5/pom.xml
+++ b/nms/1_20_5/pom.xml
@@ -6,7 +6,7 @@
com.github.stefvanschie.inventoryframework
IF-parent
- 0.10.17
+ 0.10.18
../../pom.xml
diff --git a/nms/1_20_6/pom.xml b/nms/1_20_6/pom.xml
index 182ed06d..0a522e95 100644
--- a/nms/1_20_6/pom.xml
+++ b/nms/1_20_6/pom.xml
@@ -6,7 +6,7 @@
com.github.stefvanschie.inventoryframework
IF-parent
- 0.10.17
+ 0.10.18
../../pom.xml
diff --git a/nms/1_21_0/pom.xml b/nms/1_21_0/pom.xml
new file mode 100644
index 00000000..662ae335
--- /dev/null
+++ b/nms/1_21_0/pom.xml
@@ -0,0 +1,72 @@
+
+
+ 4.0.0
+
+ com.github.stefvanschie.inventoryframework
+ IF-parent
+ 0.10.18
+ ../../pom.xml
+
+
+ 1_21_0
+
+
+ true
+
+
+
+
+ com.github.stefvanschie.inventoryframework
+ abstraction
+ ${project.version}
+ compile
+
+
+ org.spigotmc
+ spigot
+ 1.21-R0.1-SNAPSHOT
+ remapped-mojang
+ provided
+
+
+
+
+
+
+ net.md-5
+ specialsource-maven-plugin
+ 2.0.3
+
+
+ package
+
+ remap
+
+ remap-obf
+
+ org.spigotmc:minecraft-server:1.21-R0.1-SNAPSHOT:txt:maps-mojang
+ true
+ org.spigotmc:spigot:1.21-R0.1-SNAPSHOT:jar:remapped-mojang
+ true
+ remapped-obf
+
+
+
+ package
+
+ remap
+
+ remap-spigot
+
+ ${project.build.directory}/${project.artifactId}-${project.version}-remapped-obf.jar
+ org.spigotmc:minecraft-server:1.21-R0.1-SNAPSHOT:csrg:maps-spigot
+ org.spigotmc:spigot:1.21-R0.1-SNAPSHOT:jar:remapped-obf
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/nms/1_21/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21/AnvilInventoryImpl.java b/nms/1_21_0/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_0/AnvilInventoryImpl.java
similarity index 95%
rename from nms/1_21/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21/AnvilInventoryImpl.java
rename to nms/1_21_0/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_0/AnvilInventoryImpl.java
index 82e0192d..b40c0243 100644
--- a/nms/1_21/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21/AnvilInventoryImpl.java
+++ b/nms/1_21_0/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_0/AnvilInventoryImpl.java
@@ -1,9 +1,9 @@
-package com.github.stefvanschie.inventoryframework.nms.v1_21;
+package com.github.stefvanschie.inventoryframework.nms.v1_21_0;
import com.github.stefvanschie.inventoryframework.abstraction.AnvilInventory;
import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
-import com.github.stefvanschie.inventoryframework.nms.v1_21.util.CustomInventoryUtil;
-import com.github.stefvanschie.inventoryframework.nms.v1_21.util.TextHolderUtil;
+import com.github.stefvanschie.inventoryframework.nms.v1_21_0.util.CustomInventoryUtil;
+import com.github.stefvanschie.inventoryframework.nms.v1_21_0.util.TextHolderUtil;
import net.minecraft.core.BlockPos;
import net.minecraft.core.NonNullList;
import net.minecraft.network.chat.Component;
@@ -29,9 +29,9 @@
import org.jetbrains.annotations.Nullable;
/**
- * Internal anvil inventory for 1.21
+ * Internal anvil inventory for 1.21.0
*
- * @since 0.10.15
+ * @since 0.10.18
*/
public class AnvilInventoryImpl extends AnvilInventory {
@@ -136,7 +136,7 @@ public void clearCursor(@NotNull Player player) {
*
* @param player the player to set the cursor
* @param item the item to set the cursor to
- * @since 0.10.15
+ * @since 0.10.18
* @deprecated no longer used internally
*/
@Deprecated
@@ -152,7 +152,7 @@ private void setCursor(@NotNull Player player, @NotNull ItemStack item) {
*
* @param player the player to send the result item to
* @param item the result item
- * @since 0.10.15
+ * @since 0.10.18
* @deprecated no longer used internally
*/
@Deprecated
@@ -169,7 +169,7 @@ private void sendResultItem(@NotNull Player player, @NotNull ItemStack item) {
*
* @param nmsPlayer the player to get the container id for
* @return the container id
- * @since 0.10.15
+ * @since 0.10.18
* @deprecated no longer used internally
*/
@Contract(pure = true)
@@ -183,7 +183,7 @@ private int getContainerId(@NotNull net.minecraft.world.entity.player.Player nms
*
* @param serverPlayer the player to get the player connection from
* @return the player connection
- * @since 0.10.15
+ * @since 0.10.18
* @deprecated no longer used internally
*/
@NotNull
@@ -198,7 +198,7 @@ private ServerPlayerConnection getPlayerConnection(@NotNull ServerPlayer serverP
*
* @param player the player to get the server player from
* @return the server player
- * @since 0.10.15
+ * @since 0.10.18
*/
@NotNull
@Contract(pure = true)
@@ -209,7 +209,7 @@ private ServerPlayer getServerPlayer(@NotNull Player player) {
/**
* A custom container anvil for responding to item renaming
*
- * @since 0.10.15
+ * @since 0.10.18
*/
private class ContainerAnvilImpl extends AnvilMenu {
@@ -218,7 +218,7 @@ private class ContainerAnvilImpl extends AnvilMenu {
*
* @param serverPlayer the player for whom this anvil container is
* @param title the title of the inventory
- * @since 0.10.15
+ * @since 0.10.18
*/
public ContainerAnvilImpl(@NotNull ServerPlayer serverPlayer, @NotNull Component title) {
super(serverPlayer.nextContainerCounter(), serverPlayer.getInventory(),
diff --git a/nms/1_21_0/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_0/BeaconInventoryImpl.java b/nms/1_21_0/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_0/BeaconInventoryImpl.java
new file mode 100644
index 00000000..90981e03
--- /dev/null
+++ b/nms/1_21_0/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_0/BeaconInventoryImpl.java
@@ -0,0 +1,202 @@
+package com.github.stefvanschie.inventoryframework.nms.v1_21_0;
+
+import com.github.stefvanschie.inventoryframework.abstraction.BeaconInventory;
+import net.minecraft.core.NonNullList;
+import net.minecraft.network.chat.Component;
+import net.minecraft.network.protocol.game.ClientboundContainerSetContentPacket;
+import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket;
+import net.minecraft.network.protocol.game.ClientboundOpenScreenPacket;
+import net.minecraft.server.level.ServerPlayer;
+import net.minecraft.server.network.ServerPlayerConnection;
+import net.minecraft.world.Container;
+import net.minecraft.world.inventory.BeaconMenu;
+import net.minecraft.world.inventory.MenuType;
+import net.minecraft.world.item.ItemStack;
+import org.bukkit.craftbukkit.v1_21_R1.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_21_R1.inventory.CraftInventoryBeacon;
+import org.bukkit.craftbukkit.v1_21_R1.inventory.CraftItemStack;
+import org.bukkit.craftbukkit.v1_21_R1.inventory.view.CraftBeaconView;
+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;
+
+/**
+ * Internal beacon inventory for 1.21.0
+ *
+ * @since 0.10.18
+ */
+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) {
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ ContainerBeaconImpl containerBeacon = new ContainerBeaconImpl(serverPlayer, item);
+
+ serverPlayer.containerMenu = containerBeacon;
+
+ int id = containerBeacon.containerId;
+ Component beacon = Component.literal("Beacon");
+
+ serverPlayer.connection.send(new ClientboundOpenScreenPacket(id, MenuType.BEACON, beacon));
+
+ sendItem(player, item);
+ }
+
+ @Override
+ public void sendItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
+ NonNullList items = NonNullList.of(
+ ItemStack.EMPTY, //the first item doesn't count for some reason, so send a dummy item
+ CraftItemStack.asNMSCopy(item)
+ );
+
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ int containerId = getContainerId(serverPlayer);
+ int state = serverPlayer.containerMenu.incrementStateId();
+ ItemStack cursor = CraftItemStack.asNMSCopy(player.getItemOnCursor());
+ ServerPlayerConnection playerConnection = getPlayerConnection(serverPlayer);
+
+ playerConnection.send(new ClientboundContainerSetContentPacket(containerId, state, items, cursor));
+ }
+
+ @Override
+ public void clearCursor(@NotNull Player player) {
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ int state = serverPlayer.containerMenu.incrementStateId();
+
+ getPlayerConnection(serverPlayer).send(new ClientboundContainerSetSlotPacket(-1, state, -1, ItemStack.EMPTY));
+ }
+
+ /**
+ * Gets the container id for the inventory view the player currently has open
+ *
+ * @param nmsPlayer the player to get the container id for
+ * @return the container id
+ * @since 0.10.18
+ */
+ @Contract(pure = true)
+ private int getContainerId(@NotNull net.minecraft.world.entity.player.Player nmsPlayer) {
+ return nmsPlayer.containerMenu.containerId;
+ }
+
+ /**
+ * Gets the player connection for the specified player
+ *
+ * @param serverPlayer the player to get the player connection from
+ * @return the player connection
+ * @since 0.10.18
+ */
+ @NotNull
+ @Contract(pure = true)
+ private ServerPlayerConnection getPlayerConnection(@NotNull ServerPlayer serverPlayer) {
+ return serverPlayer.connection;
+ }
+
+ /**
+ * Gets the server player associated to this player
+ *
+ * @param player the player to get the server player from
+ * @return the server player
+ * @since 0.10.18
+ */
+ @NotNull
+ @Contract(pure = true)
+ private ServerPlayer getServerPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * A custom container beacon
+ *
+ * @since 0.10.18
+ */
+ private class ContainerBeaconImpl extends BeaconMenu {
+
+ /**
+ * The player for this beacon container
+ */
+ @NotNull
+ private final Player player;
+
+ /**
+ * The internal bukkit entity for this container beacon
+ */
+ @Nullable
+ private CraftBeaconView bukkitEntity;
+
+ /**
+ * Field for accessing the beacon field
+ */
+ @NotNull
+ private final Field beaconField;
+
+ public ContainerBeaconImpl(@NotNull ServerPlayer serverPlayer, @Nullable org.bukkit.inventory.ItemStack item) {
+ super(serverPlayer.nextContainerCounter(), serverPlayer.getInventory());
+
+ this.player = serverPlayer.getBukkitEntity();
+ setTitle(Component.empty());
+
+ try {
+ //noinspection JavaReflectionMemberAccess
+ this.beaconField = BeaconMenu.class.getDeclaredField("s"); //beacon
+ this.beaconField.setAccessible(true);
+ } catch (NoSuchFieldException exception) {
+ throw new RuntimeException(exception);
+ }
+
+ try {
+ ItemStack itemStack = CraftItemStack.asNMSCopy(item);
+
+ ((Container) beaconField.get(this)).setItem(0, itemStack);
+ } catch (IllegalAccessException exception) {
+ throw new RuntimeException(exception);
+ }
+ }
+
+ @NotNull
+ @Override
+ public CraftBeaconView getBukkitView() {
+ if (bukkitEntity == null) {
+ try {
+ Container container = (Container) beaconField.get(this);
+
+ Inventory inventory = new CraftInventoryBeacon(container) {
+ @NotNull
+ @Contract(pure = true)
+ @Override
+ public InventoryHolder getHolder() {
+ return inventoryHolder;
+ }
+ };
+
+ this.bukkitEntity = new CraftBeaconView(player, inventory, this);
+ } catch (IllegalAccessException exception) {
+ throw new RuntimeException(exception);
+ }
+ }
+
+ return bukkitEntity;
+ }
+
+ @Contract(pure = true, value = "_ -> true")
+ @Override
+ public boolean stillValid(@Nullable net.minecraft.world.entity.player.Player nmsPlayer) {
+ return true;
+ }
+
+ @Override
+ public void slotsChanged(Container container) {}
+
+ @Override
+ public void removed(net.minecraft.world.entity.player.Player nmsPlayer) {}
+
+ }
+}
diff --git a/nms/1_21/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21/CartographyTableInventoryImpl.java b/nms/1_21_0/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_0/CartographyTableInventoryImpl.java
similarity index 95%
rename from nms/1_21/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21/CartographyTableInventoryImpl.java
rename to nms/1_21_0/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_0/CartographyTableInventoryImpl.java
index 37216c68..ee1d9a23 100644
--- a/nms/1_21/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21/CartographyTableInventoryImpl.java
+++ b/nms/1_21_0/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_0/CartographyTableInventoryImpl.java
@@ -1,9 +1,9 @@
-package com.github.stefvanschie.inventoryframework.nms.v1_21;
+package com.github.stefvanschie.inventoryframework.nms.v1_21_0;
import com.github.stefvanschie.inventoryframework.abstraction.CartographyTableInventory;
import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
-import com.github.stefvanschie.inventoryframework.nms.v1_21.util.CustomInventoryUtil;
-import com.github.stefvanschie.inventoryframework.nms.v1_21.util.TextHolderUtil;
+import com.github.stefvanschie.inventoryframework.nms.v1_21_0.util.CustomInventoryUtil;
+import com.github.stefvanschie.inventoryframework.nms.v1_21_0.util.TextHolderUtil;
import net.minecraft.core.NonNullList;
import net.minecraft.network.chat.Component;
import net.minecraft.network.protocol.game.ClientboundContainerSetContentPacket;
@@ -29,9 +29,9 @@
import java.lang.reflect.Field;
/**
- * Internal cartography table inventory for 1.21
+ * Internal cartography table inventory for 1.21.0
*
- * @since 0.10.15
+ * @since 0.10.18
*/
public class CartographyTableInventoryImpl extends CartographyTableInventory {
@@ -92,7 +92,7 @@ public void clearCursor(@NotNull Player player) {
*
* @param nmsPlayer the player to get the container id for
* @return the container id
- * @since 0.10.15
+ * @since 0.10.18
*/
@Contract(pure = true)
private int getContainerId(@NotNull net.minecraft.world.entity.player.Player nmsPlayer) {
@@ -104,7 +104,7 @@ private int getContainerId(@NotNull net.minecraft.world.entity.player.Player nms
*
* @param serverPlayer the player to get the player connection from
* @return the player connection
- * @since 0.10.15
+ * @since 0.10.18
*/
@NotNull
@Contract(pure = true)
@@ -117,7 +117,7 @@ private ServerPlayerConnection getPlayerConnection(@NotNull ServerPlayer serverP
*
* @param player the player to get the server player from
* @return the server player
- * @since 0.10.15
+ * @since 0.10.18
*/
@NotNull
@Contract(pure = true)
@@ -128,7 +128,7 @@ private ServerPlayer getServerPlayer(@NotNull Player player) {
/**
* A custom container cartography table
*
- * @since 0.10.15
+ * @since 0.10.18
*/
private class ContainerCartographyTableImpl extends CartographyTableMenu {
diff --git a/nms/1_21/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21/EnchantingTableInventoryImpl.java b/nms/1_21_0/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_0/EnchantingTableInventoryImpl.java
similarity index 93%
rename from nms/1_21/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21/EnchantingTableInventoryImpl.java
rename to nms/1_21_0/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_0/EnchantingTableInventoryImpl.java
index 9bfd901a..01de8a79 100644
--- a/nms/1_21/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21/EnchantingTableInventoryImpl.java
+++ b/nms/1_21_0/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_0/EnchantingTableInventoryImpl.java
@@ -1,8 +1,8 @@
-package com.github.stefvanschie.inventoryframework.nms.v1_21;
+package com.github.stefvanschie.inventoryframework.nms.v1_21_0;
import com.github.stefvanschie.inventoryframework.abstraction.EnchantingTableInventory;
import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
-import com.github.stefvanschie.inventoryframework.nms.v1_21.util.TextHolderUtil;
+import com.github.stefvanschie.inventoryframework.nms.v1_21_0.util.TextHolderUtil;
import net.minecraft.core.NonNullList;
import net.minecraft.network.chat.Component;
import net.minecraft.network.protocol.game.ClientboundContainerSetContentPacket;
@@ -15,11 +15,11 @@
import net.minecraft.world.inventory.MenuType;
import net.minecraft.world.item.ItemStack;
import org.bukkit.craftbukkit.v1_21_R1.entity.CraftPlayer;
-import org.bukkit.craftbukkit.v1_21_R1.inventory.CraftInventory;
import org.bukkit.craftbukkit.v1_21_R1.inventory.CraftInventoryEnchanting;
import org.bukkit.craftbukkit.v1_21_R1.inventory.CraftItemStack;
import org.bukkit.craftbukkit.v1_21_R1.inventory.view.CraftEnchantmentView;
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;
@@ -28,9 +28,9 @@
import java.lang.reflect.Field;
/**
- * Internal enchanting table inventory for 1.21
+ * Internal enchanting table inventory for 1.21.0
*
- * @since 0.10.15
+ * @since 0.10.18
*/
public class EnchantingTableInventoryImpl extends EnchantingTableInventory {
@@ -94,7 +94,7 @@ public void clearCursor(@NotNull Player player) {
*
* @param nmsPlayer the player to get the containerId id for
* @return the containerId id
- * @since 0.10.15
+ * @since 0.10.18
*/
@Contract(pure = true)
private int getContainerId(@NotNull net.minecraft.world.entity.player.Player nmsPlayer) {
@@ -106,7 +106,7 @@ private int getContainerId(@NotNull net.minecraft.world.entity.player.Player nms
*
* @param serverPlayer the player to get the player connection from
* @return the player connection
- * @since 0.10.15
+ * @since 0.10.18
*/
@NotNull
@Contract(pure = true)
@@ -119,7 +119,7 @@ private ServerPlayerConnection getPlayerConnection(@NotNull ServerPlayer serverP
*
* @param player the player to get the server player from
* @return the server player
- * @since 0.10.15
+ * @since 0.10.18
*/
@NotNull
@Contract(pure = true)
@@ -130,7 +130,7 @@ private ServerPlayer getServerPlayer(@NotNull Player player) {
/**
* A custom container enchanting table
*
- * @since 0.10.15
+ * @since 0.10.18
*/
private class ContainerEnchantingTableImpl extends EnchantmentMenu {
@@ -184,7 +184,9 @@ public ContainerEnchantingTableImpl(@NotNull ServerPlayer serverPlayer,
public CraftEnchantmentView getBukkitView() {
if (bukkitEntity == null) {
try {
- CraftInventory inventory = new CraftInventoryEnchanting((Container) enchantSlotsField.get(this)) {
+ Container container = (Container) enchantSlotsField.get(this);
+
+ Inventory inventory = new CraftInventoryEnchanting(container) {
@NotNull
@Contract(pure = true)
@Override
diff --git a/nms/1_21/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21/GrindstoneInventoryImpl.java b/nms/1_21_0/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_0/GrindstoneInventoryImpl.java
similarity index 94%
rename from nms/1_21/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21/GrindstoneInventoryImpl.java
rename to nms/1_21_0/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_0/GrindstoneInventoryImpl.java
index 34f2883e..59d5f89a 100644
--- a/nms/1_21/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21/GrindstoneInventoryImpl.java
+++ b/nms/1_21_0/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_0/GrindstoneInventoryImpl.java
@@ -1,9 +1,9 @@
-package com.github.stefvanschie.inventoryframework.nms.v1_21;
+package com.github.stefvanschie.inventoryframework.nms.v1_21_0;
import com.github.stefvanschie.inventoryframework.abstraction.GrindstoneInventory;
import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
-import com.github.stefvanschie.inventoryframework.nms.v1_21.util.CustomInventoryUtil;
-import com.github.stefvanschie.inventoryframework.nms.v1_21.util.TextHolderUtil;
+import com.github.stefvanschie.inventoryframework.nms.v1_21_0.util.CustomInventoryUtil;
+import com.github.stefvanschie.inventoryframework.nms.v1_21_0.util.TextHolderUtil;
import net.minecraft.core.NonNullList;
import net.minecraft.network.chat.Component;
import net.minecraft.network.protocol.game.ClientboundContainerSetContentPacket;
@@ -27,9 +27,9 @@
import org.jetbrains.annotations.Nullable;
/**
- * Internal grindstone inventory for 1.21
+ * Internal grindstone inventory for 1.21.0
*
- * @since 0.10.15
+ * @since 0.10.18
*/
public class GrindstoneInventoryImpl extends GrindstoneInventory {
@@ -104,7 +104,7 @@ public void clearCursor(@NotNull Player player) {
*
* @param nmsPlayer the player to get the containerId id for
* @return the containerId id
- * @since 0.10.15
+ * @since 0.10.18
* @deprecated no longer used internally
*/
@Contract(pure = true)
@@ -118,7 +118,7 @@ private int getContainerId(@NotNull net.minecraft.world.entity.player.Player nms
*
* @param serverPlayer the player to get the player connection from
* @return the player connection
- * @since 0.10.15
+ * @since 0.10.18
* @deprecated no longer used internally
*/
@NotNull
@@ -133,7 +133,7 @@ private ServerPlayerConnection getPlayerConnection(@NotNull ServerPlayer serverP
*
* @param player the player to get the server player from
* @return the server player
- * @since 0.10.15
+ * @since 0.10.18
*/
@NotNull
@Contract(pure = true)
@@ -144,7 +144,7 @@ private ServerPlayer getServerPlayer(@NotNull Player player) {
/**
* A custom container grindstone
*
- * @since 0.10.15
+ * @since 0.10.18
*/
private static class ContainerGrindstoneImpl extends GrindstoneMenu {
@@ -153,7 +153,7 @@ private static class ContainerGrindstoneImpl extends GrindstoneMenu {
*
* @param serverPlayer the player for whom this container should be opened
* @param title the title of the gui
- * @since 0.10.15
+ * @since 0.10.18
*/
public ContainerGrindstoneImpl(@NotNull ServerPlayer serverPlayer, @NotNull Component title) {
super(serverPlayer.nextContainerCounter(), serverPlayer.getInventory());
diff --git a/nms/1_21/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21/MerchantInventoryImpl.java b/nms/1_21_0/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_0/MerchantInventoryImpl.java
similarity index 95%
rename from nms/1_21/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21/MerchantInventoryImpl.java
rename to nms/1_21_0/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_0/MerchantInventoryImpl.java
index b04be99e..489a02e5 100644
--- a/nms/1_21/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21/MerchantInventoryImpl.java
+++ b/nms/1_21_0/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_0/MerchantInventoryImpl.java
@@ -1,4 +1,4 @@
-package com.github.stefvanschie.inventoryframework.nms.v1_21;
+package com.github.stefvanschie.inventoryframework.nms.v1_21_0;
import com.github.stefvanschie.inventoryframework.abstraction.MerchantInventory;
import net.minecraft.core.component.DataComponentPredicate;
@@ -19,9 +19,9 @@
import java.util.Optional;
/**
- * Internal merchant inventory for 1.21
+ * Internal merchant inventory for 1.21.0
*
- * @since 0.10.15
+ * @since 0.10.18
*/
public class MerchantInventoryImpl extends MerchantInventory {
@@ -81,7 +81,7 @@ public void sendMerchantOffers(@NotNull Player player,
*
* @param itemStack the item stack to convert
* @return the item cost
- * @since 0.10.15
+ * @since 0.10.18
*/
@NotNull
@Contract(value = "_ -> new", pure = true)
@@ -96,7 +96,7 @@ private ItemCost convertItemStackToItemCost(@NotNull net.minecraft.world.item.It
*
* @param player the player to get the server player from
* @return the server player
- * @since 0.10.15
+ * @since 0.10.18
*/
@NotNull
@Contract(pure = true)
@@ -109,7 +109,7 @@ private ServerPlayer getServerPlayer(@NotNull Player player) {
*
* @param nmsPlayer the player to get the containerId id for
* @return the containerId id
- * @since 0.10.15
+ * @since 0.10.18
*/
@Contract(pure = true)
private int getContainerId(@NotNull net.minecraft.world.entity.player.Player nmsPlayer) {
diff --git a/nms/1_21/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21/SmithingTableInventoryImpl.java b/nms/1_21_0/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_0/SmithingTableInventoryImpl.java
similarity index 96%
rename from nms/1_21/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21/SmithingTableInventoryImpl.java
rename to nms/1_21_0/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_0/SmithingTableInventoryImpl.java
index 8e44a969..b3cb1100 100644
--- a/nms/1_21/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21/SmithingTableInventoryImpl.java
+++ b/nms/1_21_0/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_0/SmithingTableInventoryImpl.java
@@ -1,9 +1,9 @@
-package com.github.stefvanschie.inventoryframework.nms.v1_21;
+package com.github.stefvanschie.inventoryframework.nms.v1_21_0;
import com.github.stefvanschie.inventoryframework.abstraction.SmithingTableInventory;
import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
-import com.github.stefvanschie.inventoryframework.nms.v1_21.util.CustomInventoryUtil;
-import com.github.stefvanschie.inventoryframework.nms.v1_21.util.TextHolderUtil;
+import com.github.stefvanschie.inventoryframework.nms.v1_21_0.util.CustomInventoryUtil;
+import com.github.stefvanschie.inventoryframework.nms.v1_21_0.util.TextHolderUtil;
import net.minecraft.core.BlockPos;
import net.minecraft.core.NonNullList;
import net.minecraft.network.chat.Component;
@@ -29,9 +29,9 @@
import org.jetbrains.annotations.Nullable;
/**
- * Internal smithing table inventory for 1.21. This is only available for Minecraft 1.20 and higher.
+ * Internal smithing table inventory for 1.21.0. This is only available for Minecraft 1.20 and higher.
*
- * @since 0.10.15
+ * @since 0.10.18
*/
public class SmithingTableInventoryImpl extends SmithingTableInventory {
@@ -139,7 +139,7 @@ public void clearCursor(@NotNull Player player) {
*
* @param player the player to set the cursor
* @param item the item to set the cursor to
- * @since 0.10.15
+ * @since 0.10.18
* @deprecated no longer used internally
*/
@Deprecated
@@ -155,7 +155,7 @@ private void setCursor(@NotNull Player player, @NotNull ItemStack item) {
*
* @param player the player to send the result item to
* @param item the result item
- * @since 0.10.15
+ * @since 0.10.18
* @deprecated no longer used internally
*/
@Deprecated
@@ -172,7 +172,7 @@ private void sendResultItem(@NotNull Player player, @NotNull ItemStack item) {
*
* @param nmsPlayer the player to get the container id for
* @return the container id
- * @since 0.10.15
+ * @since 0.10.18
* @deprecated no longer used internally
*/
@Contract(pure = true)
@@ -186,7 +186,7 @@ private int getContainerId(@NotNull net.minecraft.world.entity.player.Player nms
*
* @param serverPlayer the player to get the player connection from
* @return the player connection
- * @since 0.10.15
+ * @since 0.10.18
* @deprecated no longer used internally
*/
@NotNull
@@ -201,7 +201,7 @@ private ServerPlayerConnection getPlayerConnection(@NotNull ServerPlayer serverP
*
* @param player the player to get the server player from
* @return the server player
- * @since 0.10.15
+ * @since 0.10.18
*/
@NotNull
@Contract(pure = true)
@@ -212,7 +212,7 @@ private ServerPlayer getServerPlayer(@NotNull Player player) {
/**
* A custom container smithing table
*
- * @since 0.10.15
+ * @since 0.10.18
*/
private static class ContainerSmithingTableImpl extends SmithingMenu {
@@ -221,7 +221,7 @@ private static class ContainerSmithingTableImpl extends SmithingMenu {
*
* @param serverPlayer the player for whom this anvil container is
* @param title the title of the inventory
- * @since 0.10.15
+ * @since 0.10.18
*/
public ContainerSmithingTableImpl(@NotNull ServerPlayer serverPlayer, @NotNull Component title) {
super(serverPlayer.nextContainerCounter(), serverPlayer.getInventory(),
diff --git a/nms/1_21/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21/StonecutterInventoryImpl.java b/nms/1_21_0/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_0/StonecutterInventoryImpl.java
similarity index 93%
rename from nms/1_21/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21/StonecutterInventoryImpl.java
rename to nms/1_21_0/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_0/StonecutterInventoryImpl.java
index 9cadfe56..d12e3e7f 100644
--- a/nms/1_21/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21/StonecutterInventoryImpl.java
+++ b/nms/1_21_0/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_0/StonecutterInventoryImpl.java
@@ -1,8 +1,8 @@
-package com.github.stefvanschie.inventoryframework.nms.v1_21;
+package com.github.stefvanschie.inventoryframework.nms.v1_21_0;
import com.github.stefvanschie.inventoryframework.abstraction.StonecutterInventory;
import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
-import com.github.stefvanschie.inventoryframework.nms.v1_21.util.TextHolderUtil;
+import com.github.stefvanschie.inventoryframework.nms.v1_21_0.util.TextHolderUtil;
import net.minecraft.core.NonNullList;
import net.minecraft.network.chat.Component;
import net.minecraft.network.protocol.game.ClientboundContainerSetContentPacket;
@@ -15,11 +15,11 @@
import net.minecraft.world.inventory.StonecutterMenu;
import net.minecraft.world.item.ItemStack;
import org.bukkit.craftbukkit.v1_21_R1.entity.CraftPlayer;
-import org.bukkit.craftbukkit.v1_21_R1.inventory.CraftInventory;
import org.bukkit.craftbukkit.v1_21_R1.inventory.CraftInventoryStonecutter;
import org.bukkit.craftbukkit.v1_21_R1.inventory.CraftItemStack;
import org.bukkit.craftbukkit.v1_21_R1.inventory.view.CraftStonecutterView;
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;
@@ -28,9 +28,9 @@
import java.lang.reflect.Field;
/**
- * Internal stonecutter inventory for 1.21
+ * Internal stonecutter inventory for 1.21.0
*
- * @since 0.10.15
+ * @since 0.10.18
*/
public class StonecutterInventoryImpl extends StonecutterInventory {
@@ -93,7 +93,7 @@ public void clearCursor(@NotNull Player player) {
*
* @param nmsPlayer the player to get the container id for
* @return the container id
- * @since 0.10.15
+ * @since 0.10.18
*/
@Contract(pure = true)
private int getContainerId(@NotNull net.minecraft.world.entity.player.Player nmsPlayer) {
@@ -105,7 +105,7 @@ private int getContainerId(@NotNull net.minecraft.world.entity.player.Player nms
*
* @param serverPlayer the player to get the player connection from
* @return the player connection
- * @since 0.10.15
+ * @since 0.10.18
*/
@NotNull
@Contract(pure = true)
@@ -118,7 +118,7 @@ private ServerPlayerConnection getPlayerConnection(@NotNull ServerPlayer serverP
*
* @param player the player to get the server player from
* @return the server player
- * @since 0.10.15
+ * @since 0.10.18
*/
@NotNull
@Contract(pure = true)
@@ -129,7 +129,7 @@ private ServerPlayer getServerPlayer(@NotNull Player player) {
/**
* A custom container enchanting table
*
- * @since 0.10.15
+ * @since 0.10.18
*/
private class ContainerStonecutterImpl extends StonecutterMenu {
@@ -175,7 +175,7 @@ public ContainerStonecutterImpl(@NotNull ServerPlayer entityPlayer,
@Override
public CraftStonecutterView getBukkitView() {
if (bukkitEntity == null) {
- CraftInventory inventory = new CraftInventoryStonecutter(this.container, getResultInventory()) {
+ Inventory inventory = new CraftInventoryStonecutter(this.container, getResultInventory()) {
@NotNull
@Contract(pure = true)
@Override
@@ -206,7 +206,7 @@ public void removed(net.minecraft.world.entity.player.Player nmsPlayer) {}
* Gets the result inventory
*
* @return the result inventory
- * @since 0.10.15
+ * @since 0.10.18
*/
@NotNull
@Contract(pure = true)
diff --git a/nms/1_21/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21/util/CustomInventoryUtil.java b/nms/1_21_0/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_0/util/CustomInventoryUtil.java
similarity index 91%
rename from nms/1_21/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21/util/CustomInventoryUtil.java
rename to nms/1_21_0/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_0/util/CustomInventoryUtil.java
index 0d1e7354..364fd9bc 100644
--- a/nms/1_21/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21/util/CustomInventoryUtil.java
+++ b/nms/1_21_0/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_0/util/CustomInventoryUtil.java
@@ -1,4 +1,4 @@
-package com.github.stefvanschie.inventoryframework.nms.v1_21.util;
+package com.github.stefvanschie.inventoryframework.nms.v1_21_0.util;
import net.minecraft.core.NonNullList;
import net.minecraft.world.item.ItemStack;
@@ -10,7 +10,7 @@
/**
* A utility class for custom inventories
*
- * @since 0.10.15
+ * @since 0.10.18
*/
public final class CustomInventoryUtil {
@@ -25,7 +25,7 @@ private CustomInventoryUtil() {}
*
* @param items the items to convert
* @return a list of converted items
- * @since 0.10.15
+ * @since 0.10.18
*/
@NotNull
@Contract(pure = true)
diff --git a/nms/1_21/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21/util/TextHolderUtil.java b/nms/1_21_0/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_0/util/TextHolderUtil.java
similarity index 92%
rename from nms/1_21/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21/util/TextHolderUtil.java
rename to nms/1_21_0/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_0/util/TextHolderUtil.java
index 07864c3d..b0757a95 100644
--- a/nms/1_21/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21/util/TextHolderUtil.java
+++ b/nms/1_21_0/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_0/util/TextHolderUtil.java
@@ -1,4 +1,4 @@
-package com.github.stefvanschie.inventoryframework.nms.v1_21.util;
+package com.github.stefvanschie.inventoryframework.nms.v1_21_0.util;
import com.github.stefvanschie.inventoryframework.adventuresupport.ComponentHolder;
import com.github.stefvanschie.inventoryframework.adventuresupport.StringHolder;
@@ -14,7 +14,7 @@
/**
* A utility class for adding {@link TextHolder} support.
*
- * @since 0.10.15
+ * @since 0.10.18
*/
public final class TextHolderUtil {
@@ -27,7 +27,7 @@ private TextHolderUtil() {
*
* @param holder the value to convert
* @return the value as a vanilla component
- * @since 0.10.15
+ * @since 0.10.18
*/
@NotNull
@Contract(pure = true)
@@ -44,7 +44,7 @@ public static Component toComponent(@NotNull TextHolder holder) {
*
* @param holder the value to convert
* @return the value as a vanilla component
- * @since 0.10.15
+ * @since 0.10.18
*/
@NotNull
@Contract(pure = true)
@@ -57,7 +57,7 @@ private static Component toComponent(@NotNull StringHolder holder) {
*
* @param holder the value to convert
* @return the value as a vanilla component
- * @since 0.10.15
+ * @since 0.10.18
*/
@NotNull
@Contract(pure = true)
diff --git a/nms/1_21/pom.xml b/nms/1_21_1/pom.xml
similarity index 97%
rename from nms/1_21/pom.xml
rename to nms/1_21_1/pom.xml
index 3ad1e532..a70e9df9 100644
--- a/nms/1_21/pom.xml
+++ b/nms/1_21_1/pom.xml
@@ -6,11 +6,11 @@
com.github.stefvanschie.inventoryframework
IF-parent
- 0.10.17
+ 0.10.18
../../pom.xml
- 1_21
+ 1_21_1
true
diff --git a/nms/1_21_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_1/AnvilInventoryImpl.java b/nms/1_21_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_1/AnvilInventoryImpl.java
new file mode 100644
index 00000000..807fb052
--- /dev/null
+++ b/nms/1_21_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_1/AnvilInventoryImpl.java
@@ -0,0 +1,284 @@
+package com.github.stefvanschie.inventoryframework.nms.v1_21_1;
+
+import com.github.stefvanschie.inventoryframework.abstraction.AnvilInventory;
+import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
+import com.github.stefvanschie.inventoryframework.nms.v1_21_1.util.CustomInventoryUtil;
+import com.github.stefvanschie.inventoryframework.nms.v1_21_1.util.TextHolderUtil;
+import net.minecraft.core.BlockPos;
+import net.minecraft.core.NonNullList;
+import net.minecraft.network.chat.Component;
+import net.minecraft.network.protocol.game.ClientboundContainerSetContentPacket;
+import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket;
+import net.minecraft.network.protocol.game.ClientboundOpenScreenPacket;
+import net.minecraft.server.level.ServerPlayer;
+import net.minecraft.server.network.ServerPlayerConnection;
+import net.minecraft.world.Container;
+import net.minecraft.world.inventory.AnvilMenu;
+import net.minecraft.world.inventory.ContainerLevelAccess;
+import net.minecraft.world.inventory.MenuType;
+import net.minecraft.world.inventory.Slot;
+import net.minecraft.world.item.ItemStack;
+import org.bukkit.craftbukkit.v1_21_R1.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_21_R1.event.CraftEventFactory;
+import org.bukkit.craftbukkit.v1_21_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 anvil inventory for 1.21.1
+ *
+ * @since 0.10.18
+ */
+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 + "'"
+ );
+ }
+
+ ServerPlayer serverPlayer = getServerPlayer(player);
+
+ //ignore deprecation: superseding method is only available on Paper
+ //noinspection deprecation
+ CraftEventFactory.handleInventoryCloseEvent(serverPlayer);
+
+ serverPlayer.containerMenu = serverPlayer.inventoryMenu;
+
+ Component message = TextHolderUtil.toComponent(title);
+ ContainerAnvilImpl containerAnvil = new ContainerAnvilImpl(serverPlayer, 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();
+
+ serverPlayer.connection.send(new ClientboundOpenScreenPacket(containerId, MenuType.ANVIL, message));
+ serverPlayer.containerMenu = containerAnvil;
+ serverPlayer.initMenu(containerAnvil);
+
+ return inventory;
+ }
+
+ @Override
+ public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
+ NonNullList nmsItems = CustomInventoryUtil.convertToNMSItems(items);
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ int containerId = getContainerId(serverPlayer);
+ int state = serverPlayer.containerMenu.incrementStateId();
+ ItemStack cursor = CraftItemStack.asNMSCopy(player.getItemOnCursor());
+ ServerPlayerConnection playerConnection = getPlayerConnection(serverPlayer);
+
+ playerConnection.send(new ClientboundContainerSetContentPacket(containerId, state, nmsItems, cursor));
+ }
+
+ @Override
+ public void sendFirstItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ int containerId = getContainerId(serverPlayer);
+ ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
+ int state = serverPlayer.containerMenu.incrementStateId();
+
+ getPlayerConnection(serverPlayer).send(new ClientboundContainerSetSlotPacket(containerId, state, 0, nmsItem));
+ }
+
+ @Override
+ public void sendSecondItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ int containerId = getContainerId(serverPlayer);
+ ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
+ int state = serverPlayer.containerMenu.incrementStateId();
+
+ getPlayerConnection(serverPlayer).send(new ClientboundContainerSetSlotPacket(containerId, state, 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.EMPTY);
+ }
+
+ @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) {
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ int state = serverPlayer.containerMenu.incrementStateId();
+
+ getPlayerConnection(serverPlayer).send(new ClientboundContainerSetSlotPacket(-1, state, -1, ItemStack.EMPTY));
+ }
+
+ /**
+ * 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.10.18
+ * @deprecated no longer used internally
+ */
+ @Deprecated
+ private void setCursor(@NotNull Player player, @NotNull ItemStack item) {
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ int state = serverPlayer.containerMenu.incrementStateId();
+
+ getPlayerConnection(serverPlayer).send(new ClientboundContainerSetSlotPacket(-1, state, -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.10.18
+ * @deprecated no longer used internally
+ */
+ @Deprecated
+ private void sendResultItem(@NotNull Player player, @NotNull ItemStack item) {
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ int containerId = getContainerId(serverPlayer);
+ int state = serverPlayer.containerMenu.incrementStateId();
+
+ getPlayerConnection(serverPlayer).send(new ClientboundContainerSetSlotPacket(containerId, state, 2, item));
+ }
+
+ /**
+ * Gets the container id for the inventory view the player currently has open
+ *
+ * @param nmsPlayer the player to get the container id for
+ * @return the container id
+ * @since 0.10.18
+ * @deprecated no longer used internally
+ */
+ @Contract(pure = true)
+ @Deprecated
+ private int getContainerId(@NotNull net.minecraft.world.entity.player.Player nmsPlayer) {
+ return nmsPlayer.containerMenu.containerId;
+ }
+
+ /**
+ * Gets the player connection for the specified player
+ *
+ * @param serverPlayer the player to get the player connection from
+ * @return the player connection
+ * @since 0.10.18
+ * @deprecated no longer used internally
+ */
+ @NotNull
+ @Contract(pure = true)
+ @Deprecated
+ private ServerPlayerConnection getPlayerConnection(@NotNull ServerPlayer serverPlayer) {
+ return serverPlayer.connection;
+ }
+
+ /**
+ * Gets the server player associated to this player
+ *
+ * @param player the player to get the server player from
+ * @return the server player
+ * @since 0.10.18
+ */
+ @NotNull
+ @Contract(pure = true)
+ private ServerPlayer getServerPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * A custom container anvil for responding to item renaming
+ *
+ * @since 0.10.18
+ */
+ private class ContainerAnvilImpl extends AnvilMenu {
+
+ /**
+ * Creates a new custom anvil container for the specified player
+ *
+ * @param serverPlayer the player for whom this anvil container is
+ * @param title the title of the inventory
+ * @since 0.10.18
+ */
+ public ContainerAnvilImpl(@NotNull ServerPlayer serverPlayer, @NotNull Component title) {
+ super(serverPlayer.nextContainerCounter(), serverPlayer.getInventory(),
+ ContainerLevelAccess.create(serverPlayer.getCommandSenderWorld(), new BlockPos(0, 0, 0)));
+
+ this.checkReachable = false;
+ this.cost.set(AnvilInventoryImpl.super.cost);
+
+ setTitle(title);
+
+ Slot originalSlot = this.slots.get(2);
+
+ this.slots.set(2, new Slot(originalSlot.container, originalSlot.index, originalSlot.x, originalSlot.y) {
+ @Override
+ public boolean mayPlace(@NotNull ItemStack stack) {
+ return true;
+ }
+
+ @Override
+ public boolean mayPickup(net.minecraft.world.entity.player.@NotNull Player playerEntity) {
+ return true;
+ }
+
+ @Override
+ public void onTake(net.minecraft.world.entity.player.@NotNull Player player, @NotNull ItemStack stack) {
+ originalSlot.onTake(player, stack);
+ }
+ });
+ }
+
+ @Override
+ public boolean setItemName(@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
+ broadcastFullState();
+ return true; //no idea what this is for
+ }
+
+ @Override
+ public void createResult() {}
+
+ @Override
+ public void removed(net.minecraft.world.entity.player.@NotNull Player nmsPlayer) {}
+
+ @Override
+ protected void clearContainer(net.minecraft.world.entity.player.@NotNull Player player,
+ @NotNull Container inventory) {}
+
+ @Override
+ protected void onTake(net.minecraft.world.entity.player.@NotNull Player player, @NotNull ItemStack stack) {}
+
+ public int getContainerId() {
+ return this.containerId;
+ }
+ }
+}
diff --git a/nms/1_21/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21/BeaconInventoryImpl.java b/nms/1_21_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_1/BeaconInventoryImpl.java
similarity index 94%
rename from nms/1_21/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21/BeaconInventoryImpl.java
rename to nms/1_21_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_1/BeaconInventoryImpl.java
index 0a8f689f..676d6064 100644
--- a/nms/1_21/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21/BeaconInventoryImpl.java
+++ b/nms/1_21_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_1/BeaconInventoryImpl.java
@@ -1,4 +1,4 @@
-package com.github.stefvanschie.inventoryframework.nms.v1_21;
+package com.github.stefvanschie.inventoryframework.nms.v1_21_1;
import com.github.stefvanschie.inventoryframework.abstraction.BeaconInventory;
import net.minecraft.core.NonNullList;
@@ -13,7 +13,6 @@
import net.minecraft.world.inventory.MenuType;
import net.minecraft.world.item.ItemStack;
import org.bukkit.craftbukkit.v1_21_R1.entity.CraftPlayer;
-import org.bukkit.craftbukkit.v1_21_R1.inventory.CraftInventory;
import org.bukkit.craftbukkit.v1_21_R1.inventory.CraftInventoryBeacon;
import org.bukkit.craftbukkit.v1_21_R1.inventory.CraftItemStack;
import org.bukkit.craftbukkit.v1_21_R1.inventory.view.CraftBeaconView;
@@ -26,9 +25,9 @@
import java.lang.reflect.Field;
/**
- * Internal beacon inventory for 1.21
+ * Internal beacon inventory for 1.21.1
*
- * @since 0.10.15
+ * @since 0.10.18
*/
public class BeaconInventoryImpl extends BeaconInventory {
@@ -80,7 +79,7 @@ public void clearCursor(@NotNull Player player) {
*
* @param nmsPlayer the player to get the container id for
* @return the container id
- * @since 0.10.15
+ * @since 0.10.18
*/
@Contract(pure = true)
private int getContainerId(@NotNull net.minecraft.world.entity.player.Player nmsPlayer) {
@@ -92,7 +91,7 @@ private int getContainerId(@NotNull net.minecraft.world.entity.player.Player nms
*
* @param serverPlayer the player to get the player connection from
* @return the player connection
- * @since 0.10.15
+ * @since 0.10.18
*/
@NotNull
@Contract(pure = true)
@@ -105,7 +104,7 @@ private ServerPlayerConnection getPlayerConnection(@NotNull ServerPlayer serverP
*
* @param player the player to get the server player from
* @return the server player
- * @since 0.10.15
+ * @since 0.10.18
*/
@NotNull
@Contract(pure = true)
@@ -116,7 +115,7 @@ private ServerPlayer getServerPlayer(@NotNull Player player) {
/**
* A custom container beacon
*
- * @since 0.10.15
+ * @since 0.10.18
*/
private class ContainerBeaconImpl extends BeaconMenu {
@@ -166,7 +165,9 @@ public ContainerBeaconImpl(@NotNull ServerPlayer serverPlayer, @Nullable org.buk
public CraftBeaconView getBukkitView() {
if (bukkitEntity == null) {
try {
- CraftInventory inventory = new CraftInventoryBeacon((Container) beaconField.get(this)) {
+ Container container = (Container) beaconField.get(this);
+
+ org.bukkit.inventory.BeaconInventory inventory = new CraftInventoryBeacon(container) {
@NotNull
@Contract(pure = true)
@Override
diff --git a/nms/1_21_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_1/CartographyTableInventoryImpl.java b/nms/1_21_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_1/CartographyTableInventoryImpl.java
new file mode 100644
index 00000000..f9a79e83
--- /dev/null
+++ b/nms/1_21_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_1/CartographyTableInventoryImpl.java
@@ -0,0 +1,218 @@
+package com.github.stefvanschie.inventoryframework.nms.v1_21_1;
+
+import com.github.stefvanschie.inventoryframework.abstraction.CartographyTableInventory;
+import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
+import com.github.stefvanschie.inventoryframework.nms.v1_21_1.util.CustomInventoryUtil;
+import com.github.stefvanschie.inventoryframework.nms.v1_21_1.util.TextHolderUtil;
+import net.minecraft.core.NonNullList;
+import net.minecraft.network.chat.Component;
+import net.minecraft.network.protocol.game.ClientboundContainerSetContentPacket;
+import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket;
+import net.minecraft.network.protocol.game.ClientboundOpenScreenPacket;
+import net.minecraft.server.level.ServerPlayer;
+import net.minecraft.server.network.ServerPlayerConnection;
+import net.minecraft.world.Container;
+import net.minecraft.world.inventory.CartographyTableMenu;
+import net.minecraft.world.inventory.MenuType;
+import net.minecraft.world.item.ItemStack;
+import org.bukkit.craftbukkit.v1_21_R1.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_21_R1.inventory.CraftInventory;
+import org.bukkit.craftbukkit.v1_21_R1.inventory.CraftInventoryCartography;
+import org.bukkit.craftbukkit.v1_21_R1.inventory.CraftInventoryView;
+import org.bukkit.craftbukkit.v1_21_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.21.1
+ *
+ * @since 0.10.18
+ */
+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 + "'"
+ );
+ }
+
+
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ Component message = TextHolderUtil.toComponent(title);
+
+ ContainerCartographyTableImpl containerCartographyTable = new ContainerCartographyTableImpl(
+ serverPlayer, items, message
+ );
+
+ serverPlayer.containerMenu = containerCartographyTable;
+
+ int id = containerCartographyTable.containerId;
+
+ serverPlayer.connection.send(new ClientboundOpenScreenPacket(id, MenuType.CARTOGRAPHY_TABLE, message));
+
+ sendItems(player, items);
+ }
+
+ @Override
+ public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
+ NonNullList nmsItems = CustomInventoryUtil.convertToNMSItems(items);
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ int containerId = getContainerId(serverPlayer);
+ int state = serverPlayer.containerMenu.incrementStateId();
+ ItemStack cursor = CraftItemStack.asNMSCopy(player.getItemOnCursor());
+ ServerPlayerConnection playerConnection = getPlayerConnection(serverPlayer);
+
+ playerConnection.send(new ClientboundContainerSetContentPacket(containerId, state, nmsItems, cursor));
+ }
+
+ @Override
+ public void clearCursor(@NotNull Player player) {
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ int state = serverPlayer.containerMenu.incrementStateId();
+
+ getPlayerConnection(serverPlayer).send(new ClientboundContainerSetSlotPacket(-1, state, -1, ItemStack.EMPTY));
+ }
+
+ /**
+ * Gets the container id for the inventory view the player currently has open
+ *
+ * @param nmsPlayer the player to get the container id for
+ * @return the container id
+ * @since 0.10.18
+ */
+ @Contract(pure = true)
+ private int getContainerId(@NotNull net.minecraft.world.entity.player.Player nmsPlayer) {
+ return nmsPlayer.containerMenu.containerId;
+ }
+
+ /**
+ * Gets the player connection for the specified player
+ *
+ * @param serverPlayer the player to get the player connection from
+ * @return the player connection
+ * @since 0.10.18
+ */
+ @NotNull
+ @Contract(pure = true)
+ private ServerPlayerConnection getPlayerConnection(@NotNull ServerPlayer serverPlayer) {
+ return serverPlayer.connection;
+ }
+
+ /**
+ * Gets the server player associated to this player
+ *
+ * @param player the player to get the server player from
+ * @return the server player
+ * @since 0.10.18
+ */
+ @NotNull
+ @Contract(pure = true)
+ private ServerPlayer getServerPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * A custom container cartography table
+ *
+ * @since 0.10.18
+ */
+ private class ContainerCartographyTableImpl extends CartographyTableMenu {
+
+ /**
+ * 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 resultContainerField;
+
+ public ContainerCartographyTableImpl(@NotNull ServerPlayer serverPlayer,
+ @Nullable org.bukkit.inventory.ItemStack[] items,
+ @NotNull Component title) {
+ super(serverPlayer.nextContainerCounter(), serverPlayer.getInventory());
+
+ this.player = serverPlayer.getBukkitEntity();
+
+ setTitle(title);
+
+ try {
+ //noinspection JavaReflectionMemberAccess
+ this.resultContainerField = CartographyTableMenu.class.getDeclaredField("u"); //resultContainer
+ this.resultContainerField.setAccessible(true);
+ } catch (NoSuchFieldException exception) {
+ throw new RuntimeException(exception);
+ }
+
+ container.setItem(0, CraftItemStack.asNMSCopy(items[0]));
+ container.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.container, 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 stillValid(@Nullable net.minecraft.world.entity.player.Player nmsPlayer) {
+ return true;
+ }
+
+ @Override
+ public void slotsChanged(Container container) {}
+
+ @Override
+ public void removed(net.minecraft.world.entity.player.Player nmsPlayer) {}
+
+ @NotNull
+ @Contract(pure = true)
+ private Container getResultInventory() {
+ try {
+ return (Container) resultContainerField.get(this);
+ } catch (IllegalAccessException exception) {
+ throw new RuntimeException(exception);
+ }
+ }
+
+ }
+}
diff --git a/nms/1_21_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_1/EnchantingTableInventoryImpl.java b/nms/1_21_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_1/EnchantingTableInventoryImpl.java
new file mode 100644
index 00000000..0e29d26b
--- /dev/null
+++ b/nms/1_21_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_1/EnchantingTableInventoryImpl.java
@@ -0,0 +1,220 @@
+package com.github.stefvanschie.inventoryframework.nms.v1_21_1;
+
+import com.github.stefvanschie.inventoryframework.abstraction.EnchantingTableInventory;
+import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
+import com.github.stefvanschie.inventoryframework.nms.v1_21_1.util.TextHolderUtil;
+import net.minecraft.core.NonNullList;
+import net.minecraft.network.chat.Component;
+import net.minecraft.network.protocol.game.ClientboundContainerSetContentPacket;
+import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket;
+import net.minecraft.network.protocol.game.ClientboundOpenScreenPacket;
+import net.minecraft.server.level.ServerPlayer;
+import net.minecraft.server.network.ServerPlayerConnection;
+import net.minecraft.world.Container;
+import net.minecraft.world.inventory.EnchantmentMenu;
+import net.minecraft.world.inventory.MenuType;
+import net.minecraft.world.item.ItemStack;
+import org.bukkit.craftbukkit.v1_21_R1.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_21_R1.inventory.CraftInventoryEnchanting;
+import org.bukkit.craftbukkit.v1_21_R1.inventory.CraftItemStack;
+import org.bukkit.craftbukkit.v1_21_R1.inventory.view.CraftEnchantmentView;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.EnchantingInventory;
+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.21.1
+ *
+ * @since 0.10.18
+ */
+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 + "'"
+ );
+ }
+
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ Component message = TextHolderUtil.toComponent(title);
+ ContainerEnchantingTableImpl containerEnchantmentTable = new ContainerEnchantingTableImpl(
+ serverPlayer, items, message
+ );
+
+ serverPlayer.containerMenu = containerEnchantmentTable;
+
+ int id = containerEnchantmentTable.containerId;
+
+ serverPlayer.connection.send(new ClientboundOpenScreenPacket(id, MenuType.ENCHANTMENT, message));
+
+ sendItems(player, items);
+ }
+
+ @Override
+ public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
+ NonNullList nmsItems = NonNullList.of(
+ ItemStack.EMPTY,
+ CraftItemStack.asNMSCopy(items[0]),
+ CraftItemStack.asNMSCopy(items[1])
+ );
+
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ int containerId = getContainerId(serverPlayer);
+ int state = serverPlayer.containerMenu.incrementStateId();
+ ItemStack cursor = CraftItemStack.asNMSCopy(player.getItemOnCursor());
+ ServerPlayerConnection playerConnection = getPlayerConnection(serverPlayer);
+
+ playerConnection.send(new ClientboundContainerSetContentPacket(containerId, state, nmsItems, cursor));
+ }
+
+ @Override
+ public void clearCursor(@NotNull Player player) {
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ int state = serverPlayer.containerMenu.incrementStateId();
+
+ getPlayerConnection(serverPlayer).send(new ClientboundContainerSetSlotPacket(-1, state, -1, ItemStack.EMPTY));
+ }
+
+ /**
+ * Gets the containerId id for the inventory view the player currently has open
+ *
+ * @param nmsPlayer the player to get the containerId id for
+ * @return the containerId id
+ * @since 0.10.18
+ */
+ @Contract(pure = true)
+ private int getContainerId(@NotNull net.minecraft.world.entity.player.Player nmsPlayer) {
+ return nmsPlayer.containerMenu.containerId;
+ }
+
+ /**
+ * Gets the player connection for the specified player
+ *
+ * @param serverPlayer the player to get the player connection from
+ * @return the player connection
+ * @since 0.10.18
+ */
+ @NotNull
+ @Contract(pure = true)
+ private ServerPlayerConnection getPlayerConnection(@NotNull ServerPlayer serverPlayer) {
+ return serverPlayer.connection;
+ }
+
+ /**
+ * Gets the server player associated to this player
+ *
+ * @param player the player to get the server player from
+ * @return the server player
+ * @since 0.10.18
+ */
+ @NotNull
+ @Contract(pure = true)
+ private ServerPlayer getServerPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * A custom container enchanting table
+ *
+ * @since 0.10.18
+ */
+ private class ContainerEnchantingTableImpl extends EnchantmentMenu {
+
+ /**
+ * The player for this enchanting table container
+ */
+ @NotNull
+ private final Player player;
+
+ /**
+ * The internal bukkit entity for this container enchanting table
+ */
+ @Nullable
+ private CraftEnchantmentView bukkitEntity;
+
+ /**
+ * Field for accessing the enchant slots field
+ */
+ @NotNull
+ private final Field enchantSlotsField;
+
+ public ContainerEnchantingTableImpl(@NotNull ServerPlayer serverPlayer,
+ @Nullable org.bukkit.inventory.ItemStack[] items,
+ @NotNull Component title) {
+ super(serverPlayer.nextContainerCounter(), serverPlayer.getInventory());
+
+ this.player = serverPlayer.getBukkitEntity();
+
+ setTitle(title);
+
+ try {
+ //noinspection JavaReflectionMemberAccess
+ this.enchantSlotsField = EnchantmentMenu.class.getDeclaredField("o"); //enchantSlots
+ this.enchantSlotsField.setAccessible(true);
+ } catch (NoSuchFieldException exception) {
+ throw new RuntimeException(exception);
+ }
+
+ try {
+ Container input = (Container) 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 CraftEnchantmentView getBukkitView() {
+ if (bukkitEntity == null) {
+ try {
+ Container container = (Container) enchantSlotsField.get(this);
+
+ EnchantingInventory inventory = new CraftInventoryEnchanting(container) {
+ @NotNull
+ @Contract(pure = true)
+ @Override
+ public InventoryHolder getHolder() {
+ return inventoryHolder;
+ }
+ };
+
+ this.bukkitEntity = new CraftEnchantmentView(player, inventory, this);
+ } catch (IllegalAccessException exception) {
+ exception.printStackTrace();
+ }
+ }
+
+ return bukkitEntity;
+ }
+
+ @Contract(pure = true, value = "_ -> true")
+ @Override
+ public boolean stillValid(@Nullable net.minecraft.world.entity.player.Player nmsPlayer) {
+ return true;
+ }
+
+ @Override
+ public void slotsChanged(Container container) {}
+
+ @Override
+ public void removed(net.minecraft.world.entity.player.Player nmsPlayer) {}
+
+ }
+}
diff --git a/nms/1_21_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_1/GrindstoneInventoryImpl.java b/nms/1_21_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_1/GrindstoneInventoryImpl.java
new file mode 100644
index 00000000..ba8297b7
--- /dev/null
+++ b/nms/1_21_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_1/GrindstoneInventoryImpl.java
@@ -0,0 +1,208 @@
+package com.github.stefvanschie.inventoryframework.nms.v1_21_1;
+
+import com.github.stefvanschie.inventoryframework.abstraction.GrindstoneInventory;
+import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
+import com.github.stefvanschie.inventoryframework.nms.v1_21_1.util.CustomInventoryUtil;
+import com.github.stefvanschie.inventoryframework.nms.v1_21_1.util.TextHolderUtil;
+import net.minecraft.core.NonNullList;
+import net.minecraft.network.chat.Component;
+import net.minecraft.network.protocol.game.ClientboundContainerSetContentPacket;
+import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket;
+import net.minecraft.network.protocol.game.ClientboundOpenScreenPacket;
+import net.minecraft.server.level.ServerPlayer;
+import net.minecraft.server.network.ServerPlayerConnection;
+import net.minecraft.world.Container;
+import net.minecraft.world.inventory.GrindstoneMenu;
+import net.minecraft.world.inventory.MenuType;
+import net.minecraft.world.inventory.Slot;
+import net.minecraft.world.item.ItemStack;
+import org.bukkit.craftbukkit.v1_21_R1.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_21_R1.event.CraftEventFactory;
+import org.bukkit.craftbukkit.v1_21_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 grindstone inventory for 1.21.1
+ *
+ * @since 0.10.18
+ */
+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 + "'"
+ );
+ }
+
+ ServerPlayer serverPlayer = getServerPlayer(player);
+
+ //ignore deprecation: superseding method is only available on Paper
+ //noinspection deprecation
+ CraftEventFactory.handleInventoryCloseEvent(serverPlayer);
+
+ serverPlayer.containerMenu = serverPlayer.inventoryMenu;
+
+ Component message = TextHolderUtil.toComponent(title);
+ ContainerGrindstoneImpl containerGrindstone = new ContainerGrindstoneImpl(serverPlayer, message);
+
+ Inventory inventory = containerGrindstone.getBukkitView().getTopInventory();
+
+ inventory.setItem(0, items[0]);
+ inventory.setItem(1, items[1]);
+ inventory.setItem(2, items[2]);
+
+ int containerId = containerGrindstone.getContainerId();
+
+ serverPlayer.connection.send(new ClientboundOpenScreenPacket(containerId, MenuType.GRINDSTONE, message));
+ serverPlayer.containerMenu = containerGrindstone;
+ serverPlayer.initMenu(containerGrindstone);
+
+ return inventory;
+ }
+
+ @Override
+ public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items,
+ @Nullable org.bukkit.inventory.ItemStack cursor) {
+ if (cursor == null) {
+ throw new IllegalArgumentException("Cursor may not be null on version 1.19.2");
+ }
+
+ NonNullList nmsItems = CustomInventoryUtil.convertToNMSItems(items);
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ int containerId = getContainerId(serverPlayer);
+ int state = serverPlayer.containerMenu.incrementStateId();
+ ItemStack nmsCursor = CraftItemStack.asNMSCopy(cursor);
+ ServerPlayerConnection playerConnection = getPlayerConnection(serverPlayer);
+
+ playerConnection.send(new ClientboundContainerSetContentPacket(containerId, state, nmsItems, nmsCursor));
+ }
+
+ @Override
+ public void clearCursor(@NotNull Player player) {
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ int state = serverPlayer.containerMenu.incrementStateId();
+
+ getPlayerConnection(serverPlayer).send(new ClientboundContainerSetSlotPacket(-1, state, -1, ItemStack.EMPTY));
+ }
+
+ /**
+ * Gets the containerId id for the inventory view the player currently has open
+ *
+ * @param nmsPlayer the player to get the containerId id for
+ * @return the containerId id
+ * @since 0.10.18
+ * @deprecated no longer used internally
+ */
+ @Contract(pure = true)
+ @Deprecated
+ private int getContainerId(@NotNull net.minecraft.world.entity.player.Player nmsPlayer) {
+ return nmsPlayer.containerMenu.containerId;
+ }
+
+ /**
+ * Gets the player connection for the specified player
+ *
+ * @param serverPlayer the player to get the player connection from
+ * @return the player connection
+ * @since 0.10.18
+ * @deprecated no longer used internally
+ */
+ @NotNull
+ @Contract(pure = true)
+ @Deprecated
+ private ServerPlayerConnection getPlayerConnection(@NotNull ServerPlayer serverPlayer) {
+ return serverPlayer.connection;
+ }
+
+ /**
+ * Gets the server player associated to this player
+ *
+ * @param player the player to get the server player from
+ * @return the server player
+ * @since 0.10.18
+ */
+ @NotNull
+ @Contract(pure = true)
+ private ServerPlayer getServerPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * A custom container grindstone
+ *
+ * @since 0.10.18
+ */
+ private static class ContainerGrindstoneImpl extends GrindstoneMenu {
+
+ /**
+ * Creates a new grindstone container
+ *
+ * @param serverPlayer the player for whom this container should be opened
+ * @param title the title of the gui
+ * @since 0.10.18
+ */
+ public ContainerGrindstoneImpl(@NotNull ServerPlayer serverPlayer, @NotNull Component title) {
+ super(serverPlayer.nextContainerCounter(), serverPlayer.getInventory());
+
+ setTitle(title);
+
+ 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.container, firstSlot.index, firstSlot.x, firstSlot.y) {
+ @Override
+ public boolean mayPlace(ItemStack stack) {
+ return true;
+ }
+ });
+
+ this.slots.set(1, new Slot(secondSlot.container, secondSlot.index, secondSlot.x, secondSlot.y) {
+ @Override
+ public boolean mayPlace(ItemStack stack) {
+ return true;
+ }
+ });
+
+ this.slots.set(2, new Slot(thirdSlot.container, thirdSlot.index, thirdSlot.x, thirdSlot.y) {
+ @Override
+ public boolean mayPlace(ItemStack stack) {
+ return true;
+ }
+
+ @Override
+ public void onTake(net.minecraft.world.entity.player.Player player, ItemStack stack) {}
+ });
+ }
+
+ @Contract(pure = true, value = "_ -> true")
+ @Override
+ public boolean stillValid(@Nullable net.minecraft.world.entity.player.Player nmsPlayer) {
+ return true;
+ }
+
+ @Override
+ public void slotsChanged(Container container) {}
+
+ @Override
+ public void removed(net.minecraft.world.entity.player.Player nmsPlayer) {}
+
+ public int getContainerId() {
+ return this.containerId;
+ }
+ }
+}
diff --git a/nms/1_21_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_1/MerchantInventoryImpl.java b/nms/1_21_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_1/MerchantInventoryImpl.java
new file mode 100644
index 00000000..97aed260
--- /dev/null
+++ b/nms/1_21_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_1/MerchantInventoryImpl.java
@@ -0,0 +1,118 @@
+package com.github.stefvanschie.inventoryframework.nms.v1_21_1;
+
+import com.github.stefvanschie.inventoryframework.abstraction.MerchantInventory;
+import net.minecraft.core.component.DataComponentPredicate;
+import net.minecraft.server.level.ServerPlayer;
+import net.minecraft.world.item.trading.ItemCost;
+import net.minecraft.world.item.trading.MerchantOffer;
+import net.minecraft.world.item.trading.MerchantOffers;
+import org.bukkit.craftbukkit.v1_21_R1.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_21_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;
+import java.util.Optional;
+
+/**
+ * Internal merchant inventory for 1.21.1
+ *
+ * @since 0.10.18
+ */
+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) {
+ MerchantOffers offers = new MerchantOffers();
+
+ 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.world.item.ItemStack nmsItemA = CraftItemStack.asNMSCopy(itemA);
+ net.minecraft.world.item.ItemStack nmsItemB = net.minecraft.world.item.ItemStack.EMPTY;
+ net.minecraft.world.item.ItemStack nmsItemResult = CraftItemStack.asNMSCopy(recipe.getResult());
+
+ if (itemB != null) {
+ nmsItemB = CraftItemStack.asNMSCopy(itemB);
+ }
+
+ ItemCost itemCostA = convertItemStackToItemCost(nmsItemA);
+ ItemCost itemCostB = convertItemStackToItemCost(nmsItemB);
+
+ int uses = recipe.getUses();
+ int maxUses = recipe.getMaxUses();
+ int exp = recipe.getVillagerExperience();
+ float multiplier = recipe.getPriceMultiplier();
+
+ MerchantOffer merchantOffer = new MerchantOffer(
+ itemCostA, Optional.of(itemCostB), nmsItemResult, uses, maxUses, exp, multiplier
+ );
+ merchantOffer.setSpecialPriceDiff(entry.getValue());
+
+ offers.add(merchantOffer);
+ }
+
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ int containerId = getContainerId(serverPlayer);
+
+ serverPlayer.sendMerchantOffers(containerId, offers, level, experience, true, false);
+ }
+
+ /**
+ * Converts an NMS item stack to an item cost.
+ *
+ * @param itemStack the item stack to convert
+ * @return the item cost
+ * @since 0.10.18
+ */
+ @NotNull
+ @Contract(value = "_ -> new", pure = true)
+ private ItemCost convertItemStackToItemCost(@NotNull net.minecraft.world.item.ItemStack itemStack) {
+ DataComponentPredicate predicate = DataComponentPredicate.allOf(itemStack.getComponents());
+
+ return new ItemCost(itemStack.getItemHolder(), itemStack.getCount(), predicate, itemStack);
+ }
+
+ /**
+ * Gets the server player associated to this player
+ *
+ * @param player the player to get the server player from
+ * @return the server player
+ * @since 0.10.18
+ */
+ @NotNull
+ @Contract(pure = true)
+ private ServerPlayer getServerPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * Gets the containerId id for the inventory view the player currently has open
+ *
+ * @param nmsPlayer the player to get the containerId id for
+ * @return the containerId id
+ * @since 0.10.18
+ */
+ @Contract(pure = true)
+ private int getContainerId(@NotNull net.minecraft.world.entity.player.Player nmsPlayer) {
+ return nmsPlayer.containerMenu.containerId;
+ }
+}
diff --git a/nms/1_21_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_1/SmithingTableInventoryImpl.java b/nms/1_21_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_1/SmithingTableInventoryImpl.java
new file mode 100644
index 00000000..1e1cdb77
--- /dev/null
+++ b/nms/1_21_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_1/SmithingTableInventoryImpl.java
@@ -0,0 +1,335 @@
+package com.github.stefvanschie.inventoryframework.nms.v1_21_1;
+
+import com.github.stefvanschie.inventoryframework.abstraction.SmithingTableInventory;
+import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
+import com.github.stefvanschie.inventoryframework.nms.v1_21_1.util.CustomInventoryUtil;
+import com.github.stefvanschie.inventoryframework.nms.v1_21_1.util.TextHolderUtil;
+import net.minecraft.core.BlockPos;
+import net.minecraft.core.NonNullList;
+import net.minecraft.network.chat.Component;
+import net.minecraft.network.protocol.game.ClientboundContainerSetContentPacket;
+import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket;
+import net.minecraft.network.protocol.game.ClientboundOpenScreenPacket;
+import net.minecraft.server.level.ServerPlayer;
+import net.minecraft.server.network.ServerPlayerConnection;
+import net.minecraft.world.Container;
+import net.minecraft.world.inventory.ContainerLevelAccess;
+import net.minecraft.world.inventory.MenuType;
+import net.minecraft.world.inventory.Slot;
+import net.minecraft.world.inventory.SmithingMenu;
+import net.minecraft.world.item.ItemStack;
+import org.bukkit.craftbukkit.v1_21_R1.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_21_R1.event.CraftEventFactory;
+import org.bukkit.craftbukkit.v1_21_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.21.1. This is only available for Minecraft 1.20 and higher.
+ *
+ * @since 0.10.18
+ */
+public class SmithingTableInventoryImpl extends SmithingTableInventory {
+
+ public SmithingTableInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
+ super(inventoryHolder);
+ }
+
+ @NotNull
+ @Override
+ public Inventory openInventory(@NotNull Player player, @NotNull TextHolder title,
+ @Nullable org.bukkit.inventory.ItemStack[] items) {
+ int itemAmount = items.length;
+
+ if (itemAmount != 4) {
+ throw new IllegalArgumentException(
+ "The amount of items for a smithing table should be 4, but is '" + itemAmount + "'"
+ );
+ }
+
+ ServerPlayer serverPlayer = getServerPlayer(player);
+
+ //ignore deprecation: superseding method is only available on Paper
+ //noinspection deprecation
+ CraftEventFactory.handleInventoryCloseEvent(serverPlayer);
+
+ serverPlayer.containerMenu = serverPlayer.inventoryMenu;
+
+ Component message = TextHolderUtil.toComponent(title);
+ ContainerSmithingTableImpl containerSmithingTable = new ContainerSmithingTableImpl(serverPlayer, message);
+
+ Inventory inventory = containerSmithingTable.getBukkitView().getTopInventory();
+
+ inventory.setItem(0, items[0]);
+ inventory.setItem(1, items[1]);
+ inventory.setItem(2, items[2]);
+ inventory.setItem(3, items[3]);
+
+ int containerId = containerSmithingTable.getContainerId();
+
+ serverPlayer.connection.send(new ClientboundOpenScreenPacket(containerId, MenuType.SMITHING, message));
+ serverPlayer.containerMenu = containerSmithingTable;
+ serverPlayer.initMenu(containerSmithingTable);
+
+ return inventory;
+ }
+
+ @Override
+ public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items,
+ @Nullable org.bukkit.inventory.ItemStack cursor) {
+ NonNullList nmsItems = CustomInventoryUtil.convertToNMSItems(items);
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ int containerId = getContainerId(serverPlayer);
+ int state = serverPlayer.containerMenu.incrementStateId();
+ ItemStack nmsCursor = CraftItemStack.asNMSCopy(cursor);
+ ServerPlayerConnection playerConnection = getPlayerConnection(serverPlayer);
+
+ playerConnection.send(new ClientboundContainerSetContentPacket(containerId, state, nmsItems, nmsCursor));
+ }
+
+ @Override
+ public void sendFirstItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
+ int containerId = getContainerId(serverPlayer);
+ int state = serverPlayer.containerMenu.incrementStateId();
+
+ getPlayerConnection(serverPlayer).send(new ClientboundContainerSetSlotPacket(containerId, state, 0, nmsItem));
+ }
+
+ @Override
+ public void sendSecondItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
+ int containerId = getContainerId(serverPlayer);
+ int state = serverPlayer.containerMenu.incrementStateId();
+
+ getPlayerConnection(serverPlayer).send(new ClientboundContainerSetSlotPacket(containerId, state, 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.EMPTY);
+ }
+
+ @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) {
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ int state = serverPlayer.containerMenu.incrementStateId();
+
+ getPlayerConnection(serverPlayer).send(new ClientboundContainerSetSlotPacket(-1, state, -1, ItemStack.EMPTY));
+ }
+
+ /**
+ * 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.10.18
+ * @deprecated no longer used internally
+ */
+ @Deprecated
+ private void setCursor(@NotNull Player player, @NotNull ItemStack item) {
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ int state = serverPlayer.containerMenu.incrementStateId();
+
+ getPlayerConnection(serverPlayer).send(new ClientboundContainerSetSlotPacket(-1, state, -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.10.18
+ * @deprecated no longer used internally
+ */
+ @Deprecated
+ private void sendResultItem(@NotNull Player player, @NotNull ItemStack item) {
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ int containerId = getContainerId(serverPlayer);
+ int state = serverPlayer.containerMenu.incrementStateId();
+
+ getPlayerConnection(serverPlayer).send(new ClientboundContainerSetSlotPacket(containerId, state, 2, item));
+ }
+
+ /**
+ * Gets the container id for the inventory view the player currently has open
+ *
+ * @param nmsPlayer the player to get the container id for
+ * @return the container id
+ * @since 0.10.18
+ * @deprecated no longer used internally
+ */
+ @Contract(pure = true)
+ @Deprecated
+ private int getContainerId(@NotNull net.minecraft.world.entity.player.Player nmsPlayer) {
+ return nmsPlayer.containerMenu.containerId;
+ }
+
+ /**
+ * Gets the player connection for the specified player
+ *
+ * @param serverPlayer the player to get the player connection from
+ * @return the player connection
+ * @since 0.10.18
+ * @deprecated no longer used internally
+ */
+ @NotNull
+ @Contract(pure = true)
+ @Deprecated
+ private ServerPlayerConnection getPlayerConnection(@NotNull ServerPlayer serverPlayer) {
+ return serverPlayer.connection;
+ }
+
+ /**
+ * Gets the server player associated to this player
+ *
+ * @param player the player to get the server player from
+ * @return the server player
+ * @since 0.10.18
+ */
+ @NotNull
+ @Contract(pure = true)
+ private ServerPlayer getServerPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * A custom container smithing table
+ *
+ * @since 0.10.18
+ */
+ private static class ContainerSmithingTableImpl extends SmithingMenu {
+
+ /**
+ * Creates a new custom smithing table container for the specified player
+ *
+ * @param serverPlayer the player for whom this anvil container is
+ * @param title the title of the inventory
+ * @since 0.10.18
+ */
+ public ContainerSmithingTableImpl(@NotNull ServerPlayer serverPlayer, @NotNull Component title) {
+ super(serverPlayer.nextContainerCounter(), serverPlayer.getInventory(),
+ ContainerLevelAccess.create(serverPlayer.getCommandSenderWorld(), new BlockPos(0, 0, 0)));
+
+ setTitle(title);
+
+ this.checkReachable = false;
+
+ Slot slotOne = this.slots.get(0);
+ Slot slotTwo = this.slots.get(1);
+ Slot slotThree = this.slots.get(2);
+ Slot slotFour = this.slots.get(3);
+
+ this.slots.set(0, new Slot(slotOne.container, slotOne.index, slotOne.x, slotOne.y) {
+ @Override
+ public boolean mayPlace(@NotNull ItemStack stack) {
+ return true;
+ }
+
+ @Override
+ public boolean mayPickup(net.minecraft.world.entity.player.@NotNull Player playerEntity) {
+ return true;
+ }
+
+ @Override
+ public void onTake(net.minecraft.world.entity.player.@NotNull Player player, @NotNull ItemStack stack) {
+ slotOne.onTake(player, stack);
+ }
+ });
+
+ this.slots.set(1, new Slot(slotTwo.container, slotTwo.index, slotTwo.x, slotTwo.y) {
+ @Override
+ public boolean mayPlace(@NotNull ItemStack stack) {
+ return true;
+ }
+
+ @Override
+ public boolean mayPickup(net.minecraft.world.entity.player.@NotNull Player playerEntity) {
+ return true;
+ }
+
+ @Override
+ public void onTake(net.minecraft.world.entity.player.@NotNull Player player, @NotNull ItemStack stack) {
+ slotTwo.onTake(player, stack);
+ }
+ });
+
+ this.slots.set(2, new Slot(slotThree.container, slotThree.index, slotThree.x, slotThree.y) {
+ @Override
+ public boolean mayPlace(@NotNull ItemStack stack) {
+ return true;
+ }
+
+ @Override
+ public boolean mayPickup(net.minecraft.world.entity.player.@NotNull Player playerEntity) {
+ return true;
+ }
+
+ @Override
+ public void onTake(net.minecraft.world.entity.player.@NotNull Player player, @NotNull ItemStack stack) {
+ slotThree.onTake(player, stack);
+ }
+ });
+
+ this.slots.set(3, new Slot(slotFour.container, slotFour.index, slotFour.x, slotFour.y) {
+ @Override
+ public boolean mayPlace(@NotNull ItemStack stack) {
+ return true;
+ }
+
+ @Override
+ public boolean mayPickup(net.minecraft.world.entity.player.@NotNull Player playerEntity) {
+ return true;
+ }
+
+ @Override
+ public void onTake(net.minecraft.world.entity.player.@NotNull Player player, @NotNull ItemStack stack) {
+ slotFour.onTake(player, stack);
+ }
+ });
+ }
+
+ @Contract(pure = true, value = "_ -> true")
+ @Override
+ public boolean stillValid(@Nullable net.minecraft.world.entity.player.Player nmsPlayer) {
+ return true;
+ }
+
+ @Override
+ public void slotsChanged(Container container) {}
+
+ @Override
+ public void removed(net.minecraft.world.entity.player.Player nmsPlayer) {}
+
+ @Override
+ public void createResult() {}
+
+ @Override
+ protected void onTake(net.minecraft.world.entity.player.Player player, ItemStack stack) {}
+
+ @Override
+ protected boolean mayPickup(net.minecraft.world.entity.player.Player player, boolean present) {
+ return true;
+ }
+
+ public int getContainerId() {
+ return this.containerId;
+ }
+ }
+}
diff --git a/nms/1_21_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_1/StonecutterInventoryImpl.java b/nms/1_21_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_1/StonecutterInventoryImpl.java
new file mode 100644
index 00000000..85f43a7e
--- /dev/null
+++ b/nms/1_21_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_1/StonecutterInventoryImpl.java
@@ -0,0 +1,222 @@
+package com.github.stefvanschie.inventoryframework.nms.v1_21_1;
+
+import com.github.stefvanschie.inventoryframework.abstraction.StonecutterInventory;
+import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
+import com.github.stefvanschie.inventoryframework.nms.v1_21_1.util.TextHolderUtil;
+import net.minecraft.core.NonNullList;
+import net.minecraft.network.chat.Component;
+import net.minecraft.network.protocol.game.ClientboundContainerSetContentPacket;
+import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket;
+import net.minecraft.network.protocol.game.ClientboundOpenScreenPacket;
+import net.minecraft.server.level.ServerPlayer;
+import net.minecraft.server.network.ServerPlayerConnection;
+import net.minecraft.world.Container;
+import net.minecraft.world.inventory.MenuType;
+import net.minecraft.world.inventory.StonecutterMenu;
+import net.minecraft.world.item.ItemStack;
+import org.bukkit.craftbukkit.v1_21_R1.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_21_R1.inventory.CraftInventoryStonecutter;
+import org.bukkit.craftbukkit.v1_21_R1.inventory.CraftItemStack;
+import org.bukkit.craftbukkit.v1_21_R1.inventory.view.CraftStonecutterView;
+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.21.1
+ *
+ * @since 0.10.18
+ */
+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 + "'"
+ );
+ }
+
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ Component message = TextHolderUtil.toComponent(title);
+ ContainerStonecutterImpl containerEnchantmentTable = new ContainerStonecutterImpl(serverPlayer, items, message);
+
+ serverPlayer.containerMenu = containerEnchantmentTable;
+
+ int id = containerEnchantmentTable.containerId;
+ ClientboundOpenScreenPacket packet = new ClientboundOpenScreenPacket(id, MenuType.STONECUTTER, message);
+
+ serverPlayer.connection.send(packet);
+
+ sendItems(player, items);
+ }
+
+ @Override
+ public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
+ NonNullList nmsItems = NonNullList.of(
+ ItemStack.EMPTY,
+ CraftItemStack.asNMSCopy(items[0]),
+ CraftItemStack.asNMSCopy(items[1])
+ );
+
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ int containerId = getContainerId(serverPlayer);
+ int state = serverPlayer.containerMenu.incrementStateId();
+ ItemStack cursor = CraftItemStack.asNMSCopy(player.getItemOnCursor());
+ ServerPlayerConnection playerConnection = getPlayerConnection(serverPlayer);
+
+ playerConnection.send(new ClientboundContainerSetContentPacket(containerId, state, nmsItems, cursor));
+ }
+
+ @Override
+ public void clearCursor(@NotNull Player player) {
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ int state = serverPlayer.containerMenu.incrementStateId();
+
+ getPlayerConnection(serverPlayer).send(new ClientboundContainerSetSlotPacket(-1, state, -1, ItemStack.EMPTY));
+ }
+
+ /**
+ * Gets the container id for the inventory view the player currently has open
+ *
+ * @param nmsPlayer the player to get the container id for
+ * @return the container id
+ * @since 0.10.18
+ */
+ @Contract(pure = true)
+ private int getContainerId(@NotNull net.minecraft.world.entity.player.Player nmsPlayer) {
+ return nmsPlayer.containerMenu.containerId;
+ }
+
+ /**
+ * Gets the player connection for the specified player
+ *
+ * @param serverPlayer the player to get the player connection from
+ * @return the player connection
+ * @since 0.10.18
+ */
+ @NotNull
+ @Contract(pure = true)
+ private ServerPlayerConnection getPlayerConnection(@NotNull ServerPlayer serverPlayer) {
+ return serverPlayer.connection;
+ }
+
+ /**
+ * Gets the server player associated to this player
+ *
+ * @param player the player to get the server player from
+ * @return the server player
+ * @since 0.10.18
+ */
+ @NotNull
+ @Contract(pure = true)
+ private ServerPlayer getServerPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * A custom container enchanting table
+ *
+ * @since 0.10.18
+ */
+ private class ContainerStonecutterImpl extends StonecutterMenu {
+
+ /**
+ * The player for this enchanting table container
+ */
+ @NotNull
+ private final Player player;
+
+ /**
+ * The internal bukkit entity for this container enchanting table
+ */
+ @Nullable
+ private CraftStonecutterView bukkitEntity;
+
+ /**
+ * Field for accessing the result inventory field
+ */
+ @NotNull
+ private final Field resultContainerField;
+
+ public ContainerStonecutterImpl(@NotNull ServerPlayer entityPlayer,
+ @Nullable org.bukkit.inventory.ItemStack[] items, @NotNull Component title) {
+ super(entityPlayer.nextContainerCounter(), entityPlayer.getInventory());
+
+ this.player = entityPlayer.getBukkitEntity();
+
+ setTitle(title);
+
+ try {
+ //noinspection JavaReflectionMemberAccess
+ this.resultContainerField = StonecutterMenu.class.getDeclaredField("A"); //resultContainer
+ this.resultContainerField.setAccessible(true);
+ } catch (NoSuchFieldException exception) {
+ throw new RuntimeException(exception);
+ }
+
+ container.setItem(0, CraftItemStack.asNMSCopy(items[0]));
+ getResultInventory().setItem(0, CraftItemStack.asNMSCopy(items[1]));
+ }
+
+ @NotNull
+ @Override
+ public CraftStonecutterView getBukkitView() {
+ if (bukkitEntity == null) {
+ org.bukkit.inventory.StonecutterInventory inventory = new CraftInventoryStonecutter(
+ this.container, getResultInventory()
+ ) {
+ @NotNull
+ @Contract(pure = true)
+ @Override
+ public InventoryHolder getHolder() {
+ return inventoryHolder;
+ }
+ };
+
+ this.bukkitEntity = new CraftStonecutterView(player, inventory, this);
+ }
+
+ return bukkitEntity;
+ }
+
+ @Contract(pure = true, value = "_ -> true")
+ @Override
+ public boolean stillValid(@Nullable net.minecraft.world.entity.player.Player nmsPlayer) {
+ return true;
+ }
+
+ @Override
+ public void slotsChanged(Container container) {}
+
+ @Override
+ public void removed(net.minecraft.world.entity.player.Player nmsPlayer) {}
+
+ /**
+ * Gets the result inventory
+ *
+ * @return the result inventory
+ * @since 0.10.18
+ */
+ @NotNull
+ @Contract(pure = true)
+ public Container getResultInventory() {
+ try {
+ return (Container) resultContainerField.get(this);
+ } catch (IllegalAccessException exception) {
+ throw new RuntimeException(exception);
+ }
+ }
+ }
+}
diff --git a/nms/1_21_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_1/util/CustomInventoryUtil.java b/nms/1_21_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_1/util/CustomInventoryUtil.java
new file mode 100644
index 00000000..e1d0af6d
--- /dev/null
+++ b/nms/1_21_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_1/util/CustomInventoryUtil.java
@@ -0,0 +1,41 @@
+package com.github.stefvanschie.inventoryframework.nms.v1_21_1.util;
+
+import net.minecraft.core.NonNullList;
+import net.minecraft.world.item.ItemStack;
+import org.bukkit.craftbukkit.v1_21_R1.inventory.CraftItemStack;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * A utility class for custom inventories
+ *
+ * @since 0.10.18
+ */
+public final class CustomInventoryUtil {
+
+ /**
+ * A private constructor to prevent construction.
+ */
+ private CustomInventoryUtil() {}
+
+ /**
+ * Converts an array of Bukkit items into a non-null list of NMS items. The returned list is modifiable. If no items
+ * were specified, this returns an empty list.
+ *
+ * @param items the items to convert
+ * @return a list of converted items
+ * @since 0.10.18
+ */
+ @NotNull
+ @Contract(pure = true)
+ public static NonNullList convertToNMSItems(@Nullable org.bukkit.inventory.ItemStack @NotNull [] items) {
+ NonNullList nmsItems = NonNullList.create();
+
+ for (org.bukkit.inventory.ItemStack item : items) {
+ nmsItems.add(CraftItemStack.asNMSCopy(item));
+ }
+
+ return nmsItems;
+ }
+}
diff --git a/nms/1_21_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_1/util/TextHolderUtil.java b/nms/1_21_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_1/util/TextHolderUtil.java
new file mode 100644
index 00000000..16d0416f
--- /dev/null
+++ b/nms/1_21_1/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_1/util/TextHolderUtil.java
@@ -0,0 +1,67 @@
+package com.github.stefvanschie.inventoryframework.nms.v1_21_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.core.HolderLookup;
+import net.minecraft.network.chat.Component;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Objects;
+import java.util.stream.Stream;
+
+/**
+ * A utility class for adding {@link TextHolder} support.
+ *
+ * @since 0.10.18
+ */
+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.18
+ */
+ @NotNull
+ @Contract(pure = true)
+ public static Component 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.18
+ */
+ @NotNull
+ @Contract(pure = true)
+ private static Component toComponent(@NotNull StringHolder holder) {
+ return Component.literal(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.18
+ */
+ @NotNull
+ @Contract(pure = true)
+ private static Component toComponent(@NotNull ComponentHolder holder) {
+ return Objects.requireNonNull(Component.Serializer.fromJson(holder.asJson(), HolderLookup.Provider.create(Stream.empty())));
+ }
+}
diff --git a/nms/1_21_2-3/pom.xml b/nms/1_21_2-3/pom.xml
new file mode 100644
index 00000000..a042895c
--- /dev/null
+++ b/nms/1_21_2-3/pom.xml
@@ -0,0 +1,72 @@
+
+
+ 4.0.0
+
+ com.github.stefvanschie.inventoryframework
+ IF-parent
+ 0.10.18
+ ../../pom.xml
+
+
+ 1_21_2-3
+
+
+ true
+
+
+
+
+ com.github.stefvanschie.inventoryframework
+ abstraction
+ ${project.version}
+ compile
+
+
+ org.spigotmc
+ spigot
+ 1.21.3-R0.1-SNAPSHOT
+ remapped-mojang
+ provided
+
+
+
+
+
+
+ net.md-5
+ specialsource-maven-plugin
+ 2.0.3
+
+
+ package
+
+ remap
+
+ remap-obf
+
+ org.spigotmc:minecraft-server:1.21.3-R0.1-SNAPSHOT:txt:maps-mojang
+ true
+ org.spigotmc:spigot:1.21.3-R0.1-SNAPSHOT:jar:remapped-mojang
+ true
+ remapped-obf
+
+
+
+ package
+
+ remap
+
+ remap-spigot
+
+ ${project.build.directory}/${project.artifactId}-${project.version}-remapped-obf.jar
+ org.spigotmc:minecraft-server:1.21.3-R0.1-SNAPSHOT:csrg:maps-spigot
+ org.spigotmc:spigot:1.21.3-R0.1-SNAPSHOT:jar:remapped-obf
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/nms/1_21_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_2_3/AnvilInventoryImpl.java b/nms/1_21_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_2_3/AnvilInventoryImpl.java
new file mode 100644
index 00000000..0b3aa092
--- /dev/null
+++ b/nms/1_21_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_2_3/AnvilInventoryImpl.java
@@ -0,0 +1,284 @@
+package com.github.stefvanschie.inventoryframework.nms.v1_21_2_3;
+
+import com.github.stefvanschie.inventoryframework.abstraction.AnvilInventory;
+import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
+import com.github.stefvanschie.inventoryframework.nms.v1_21_2_3.util.CustomInventoryUtil;
+import com.github.stefvanschie.inventoryframework.nms.v1_21_2_3.util.TextHolderUtil;
+import net.minecraft.core.BlockPos;
+import net.minecraft.core.NonNullList;
+import net.minecraft.network.chat.Component;
+import net.minecraft.network.protocol.game.ClientboundContainerSetContentPacket;
+import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket;
+import net.minecraft.network.protocol.game.ClientboundOpenScreenPacket;
+import net.minecraft.server.level.ServerPlayer;
+import net.minecraft.server.network.ServerPlayerConnection;
+import net.minecraft.world.Container;
+import net.minecraft.world.inventory.AnvilMenu;
+import net.minecraft.world.inventory.ContainerLevelAccess;
+import net.minecraft.world.inventory.MenuType;
+import net.minecraft.world.inventory.Slot;
+import net.minecraft.world.item.ItemStack;
+import org.bukkit.craftbukkit.v1_21_R2.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_21_R2.event.CraftEventFactory;
+import org.bukkit.craftbukkit.v1_21_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;
+
+/**
+ * Internal anvil inventory for 1.21.2
+ *
+ * @since 0.10.18
+ */
+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 + "'"
+ );
+ }
+
+ ServerPlayer serverPlayer = getServerPlayer(player);
+
+ //ignore deprecation: superseding method is only available on Paper
+ //noinspection deprecation
+ CraftEventFactory.handleInventoryCloseEvent(serverPlayer);
+
+ serverPlayer.containerMenu = serverPlayer.inventoryMenu;
+
+ Component message = TextHolderUtil.toComponent(title);
+ ContainerAnvilImpl containerAnvil = new ContainerAnvilImpl(serverPlayer, 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();
+
+ serverPlayer.connection.send(new ClientboundOpenScreenPacket(containerId, MenuType.ANVIL, message));
+ serverPlayer.containerMenu = containerAnvil;
+ serverPlayer.initMenu(containerAnvil);
+
+ return inventory;
+ }
+
+ @Override
+ public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
+ NonNullList nmsItems = CustomInventoryUtil.convertToNMSItems(items);
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ int containerId = getContainerId(serverPlayer);
+ int state = serverPlayer.containerMenu.incrementStateId();
+ ItemStack cursor = CraftItemStack.asNMSCopy(player.getItemOnCursor());
+ ServerPlayerConnection playerConnection = getPlayerConnection(serverPlayer);
+
+ playerConnection.send(new ClientboundContainerSetContentPacket(containerId, state, nmsItems, cursor));
+ }
+
+ @Override
+ public void sendFirstItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ int containerId = getContainerId(serverPlayer);
+ ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
+ int state = serverPlayer.containerMenu.incrementStateId();
+
+ getPlayerConnection(serverPlayer).send(new ClientboundContainerSetSlotPacket(containerId, state, 0, nmsItem));
+ }
+
+ @Override
+ public void sendSecondItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ int containerId = getContainerId(serverPlayer);
+ ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
+ int state = serverPlayer.containerMenu.incrementStateId();
+
+ getPlayerConnection(serverPlayer).send(new ClientboundContainerSetSlotPacket(containerId, state, 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.EMPTY);
+ }
+
+ @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) {
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ int state = serverPlayer.containerMenu.incrementStateId();
+
+ getPlayerConnection(serverPlayer).send(new ClientboundContainerSetSlotPacket(-1, state, -1, ItemStack.EMPTY));
+ }
+
+ /**
+ * 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.10.18
+ * @deprecated no longer used internally
+ */
+ @Deprecated
+ private void setCursor(@NotNull Player player, @NotNull ItemStack item) {
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ int state = serverPlayer.containerMenu.incrementStateId();
+
+ getPlayerConnection(serverPlayer).send(new ClientboundContainerSetSlotPacket(-1, state, -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.10.18
+ * @deprecated no longer used internally
+ */
+ @Deprecated
+ private void sendResultItem(@NotNull Player player, @NotNull ItemStack item) {
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ int containerId = getContainerId(serverPlayer);
+ int state = serverPlayer.containerMenu.incrementStateId();
+
+ getPlayerConnection(serverPlayer).send(new ClientboundContainerSetSlotPacket(containerId, state, 2, item));
+ }
+
+ /**
+ * Gets the container id for the inventory view the player currently has open
+ *
+ * @param nmsPlayer the player to get the container id for
+ * @return the container id
+ * @since 0.10.18
+ * @deprecated no longer used internally
+ */
+ @Contract(pure = true)
+ @Deprecated
+ private int getContainerId(@NotNull net.minecraft.world.entity.player.Player nmsPlayer) {
+ return nmsPlayer.containerMenu.containerId;
+ }
+
+ /**
+ * Gets the player connection for the specified player
+ *
+ * @param serverPlayer the player to get the player connection from
+ * @return the player connection
+ * @since 0.10.18
+ * @deprecated no longer used internally
+ */
+ @NotNull
+ @Contract(pure = true)
+ @Deprecated
+ private ServerPlayerConnection getPlayerConnection(@NotNull ServerPlayer serverPlayer) {
+ return serverPlayer.connection;
+ }
+
+ /**
+ * Gets the server player associated to this player
+ *
+ * @param player the player to get the server player from
+ * @return the server player
+ * @since 0.10.18
+ */
+ @NotNull
+ @Contract(pure = true)
+ private ServerPlayer getServerPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * A custom container anvil for responding to item renaming
+ *
+ * @since 0.10.18
+ */
+ private class ContainerAnvilImpl extends AnvilMenu {
+
+ /**
+ * Creates a new custom anvil container for the specified player
+ *
+ * @param serverPlayer the player for whom this anvil container is
+ * @param title the title of the inventory
+ * @since 0.10.18
+ */
+ public ContainerAnvilImpl(@NotNull ServerPlayer serverPlayer, @NotNull Component title) {
+ super(serverPlayer.nextContainerCounter(), serverPlayer.getInventory(),
+ ContainerLevelAccess.create(serverPlayer.getCommandSenderWorld(), new BlockPos(0, 0, 0)));
+
+ this.checkReachable = false;
+ this.cost.set(AnvilInventoryImpl.super.cost);
+
+ setTitle(title);
+
+ Slot originalSlot = this.slots.get(2);
+
+ this.slots.set(2, new Slot(originalSlot.container, originalSlot.index, originalSlot.x, originalSlot.y) {
+ @Override
+ public boolean mayPlace(@NotNull ItemStack stack) {
+ return true;
+ }
+
+ @Override
+ public boolean mayPickup(net.minecraft.world.entity.player.@NotNull Player playerEntity) {
+ return true;
+ }
+
+ @Override
+ public void onTake(net.minecraft.world.entity.player.@NotNull Player player, @NotNull ItemStack stack) {
+ originalSlot.onTake(player, stack);
+ }
+ });
+ }
+
+ @Override
+ public boolean setItemName(@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
+ broadcastFullState();
+ return true; //no idea what this is for
+ }
+
+ @Override
+ public void createResult() {}
+
+ @Override
+ public void removed(net.minecraft.world.entity.player.@NotNull Player nmsPlayer) {}
+
+ @Override
+ protected void clearContainer(net.minecraft.world.entity.player.@NotNull Player player,
+ @NotNull Container inventory) {}
+
+ @Override
+ protected void onTake(net.minecraft.world.entity.player.@NotNull Player player, @NotNull ItemStack stack) {}
+
+ public int getContainerId() {
+ return this.containerId;
+ }
+ }
+}
diff --git a/nms/1_21_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_2_3/BeaconInventoryImpl.java b/nms/1_21_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_2_3/BeaconInventoryImpl.java
new file mode 100644
index 00000000..34faf64c
--- /dev/null
+++ b/nms/1_21_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_2_3/BeaconInventoryImpl.java
@@ -0,0 +1,201 @@
+package com.github.stefvanschie.inventoryframework.nms.v1_21_2_3;
+
+import com.github.stefvanschie.inventoryframework.abstraction.BeaconInventory;
+import net.minecraft.core.NonNullList;
+import net.minecraft.network.chat.Component;
+import net.minecraft.network.protocol.game.ClientboundContainerSetContentPacket;
+import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket;
+import net.minecraft.network.protocol.game.ClientboundOpenScreenPacket;
+import net.minecraft.server.level.ServerPlayer;
+import net.minecraft.server.network.ServerPlayerConnection;
+import net.minecraft.world.Container;
+import net.minecraft.world.inventory.BeaconMenu;
+import net.minecraft.world.inventory.MenuType;
+import net.minecraft.world.item.ItemStack;
+import org.bukkit.craftbukkit.v1_21_R2.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_21_R2.inventory.CraftInventoryBeacon;
+import org.bukkit.craftbukkit.v1_21_R2.inventory.CraftItemStack;
+import org.bukkit.craftbukkit.v1_21_R2.inventory.view.CraftBeaconView;
+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.21.2
+ *
+ * @since 0.10.18
+ */
+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) {
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ ContainerBeaconImpl containerBeacon = new ContainerBeaconImpl(serverPlayer, item);
+
+ serverPlayer.containerMenu = containerBeacon;
+
+ int id = containerBeacon.containerId;
+ Component beacon = Component.literal("Beacon");
+
+ serverPlayer.connection.send(new ClientboundOpenScreenPacket(id, MenuType.BEACON, beacon));
+
+ sendItem(player, item);
+ }
+
+ @Override
+ public void sendItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
+ NonNullList items = NonNullList.of(
+ ItemStack.EMPTY, //the first item doesn't count for some reason, so send a dummy item
+ CraftItemStack.asNMSCopy(item)
+ );
+
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ int containerId = getContainerId(serverPlayer);
+ int state = serverPlayer.containerMenu.incrementStateId();
+ ItemStack cursor = CraftItemStack.asNMSCopy(player.getItemOnCursor());
+ ServerPlayerConnection playerConnection = getPlayerConnection(serverPlayer);
+
+ playerConnection.send(new ClientboundContainerSetContentPacket(containerId, state, items, cursor));
+ }
+
+ @Override
+ public void clearCursor(@NotNull Player player) {
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ int state = serverPlayer.containerMenu.incrementStateId();
+
+ getPlayerConnection(serverPlayer).send(new ClientboundContainerSetSlotPacket(-1, state, -1, ItemStack.EMPTY));
+ }
+
+ /**
+ * Gets the container id for the inventory view the player currently has open
+ *
+ * @param nmsPlayer the player to get the container id for
+ * @return the container id
+ * @since 0.10.18
+ */
+ @Contract(pure = true)
+ private int getContainerId(@NotNull net.minecraft.world.entity.player.Player nmsPlayer) {
+ return nmsPlayer.containerMenu.containerId;
+ }
+
+ /**
+ * Gets the player connection for the specified player
+ *
+ * @param serverPlayer the player to get the player connection from
+ * @return the player connection
+ * @since 0.10.18
+ */
+ @NotNull
+ @Contract(pure = true)
+ private ServerPlayerConnection getPlayerConnection(@NotNull ServerPlayer serverPlayer) {
+ return serverPlayer.connection;
+ }
+
+ /**
+ * Gets the server player associated to this player
+ *
+ * @param player the player to get the server player from
+ * @return the server player
+ * @since 0.10.18
+ */
+ @NotNull
+ @Contract(pure = true)
+ private ServerPlayer getServerPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * A custom container beacon
+ *
+ * @since 0.10.18
+ */
+ private class ContainerBeaconImpl extends BeaconMenu {
+
+ /**
+ * The player for this beacon container
+ */
+ @NotNull
+ private final Player player;
+
+ /**
+ * The internal bukkit entity for this container beacon
+ */
+ @Nullable
+ private CraftBeaconView bukkitEntity;
+
+ /**
+ * Field for accessing the beacon field
+ */
+ @NotNull
+ private final Field beaconField;
+
+ public ContainerBeaconImpl(@NotNull ServerPlayer serverPlayer, @Nullable org.bukkit.inventory.ItemStack item) {
+ super(serverPlayer.nextContainerCounter(), serverPlayer.getInventory());
+
+ this.player = serverPlayer.getBukkitEntity();
+ setTitle(Component.empty());
+
+ try {
+ //noinspection JavaReflectionMemberAccess
+ this.beaconField = BeaconMenu.class.getDeclaredField("u"); //beacon
+ this.beaconField.setAccessible(true);
+ } catch (NoSuchFieldException exception) {
+ throw new RuntimeException(exception);
+ }
+
+ try {
+ ItemStack itemStack = CraftItemStack.asNMSCopy(item);
+
+ ((Container) beaconField.get(this)).setItem(0, itemStack);
+ } catch (IllegalAccessException exception) {
+ throw new RuntimeException(exception);
+ }
+ }
+
+ @NotNull
+ @Override
+ public CraftBeaconView getBukkitView() {
+ if (bukkitEntity == null) {
+ try {
+ Container container = (Container) beaconField.get(this);
+
+ org.bukkit.inventory.BeaconInventory inventory = new CraftInventoryBeacon(container) {
+ @NotNull
+ @Contract(pure = true)
+ @Override
+ public InventoryHolder getHolder() {
+ return inventoryHolder;
+ }
+ };
+
+ this.bukkitEntity = new CraftBeaconView(player, inventory, this);
+ } catch (IllegalAccessException exception) {
+ throw new RuntimeException(exception);
+ }
+ }
+
+ return bukkitEntity;
+ }
+
+ @Contract(pure = true, value = "_ -> true")
+ @Override
+ public boolean stillValid(@Nullable net.minecraft.world.entity.player.Player nmsPlayer) {
+ return true;
+ }
+
+ @Override
+ public void slotsChanged(Container container) {}
+
+ @Override
+ public void removed(net.minecraft.world.entity.player.Player nmsPlayer) {}
+
+ }
+}
diff --git a/nms/1_21_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_2_3/CartographyTableInventoryImpl.java b/nms/1_21_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_2_3/CartographyTableInventoryImpl.java
new file mode 100644
index 00000000..ef2b9a2b
--- /dev/null
+++ b/nms/1_21_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_2_3/CartographyTableInventoryImpl.java
@@ -0,0 +1,218 @@
+package com.github.stefvanschie.inventoryframework.nms.v1_21_2_3;
+
+import com.github.stefvanschie.inventoryframework.abstraction.CartographyTableInventory;
+import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
+import com.github.stefvanschie.inventoryframework.nms.v1_21_2_3.util.CustomInventoryUtil;
+import com.github.stefvanschie.inventoryframework.nms.v1_21_2_3.util.TextHolderUtil;
+import net.minecraft.core.NonNullList;
+import net.minecraft.network.chat.Component;
+import net.minecraft.network.protocol.game.ClientboundContainerSetContentPacket;
+import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket;
+import net.minecraft.network.protocol.game.ClientboundOpenScreenPacket;
+import net.minecraft.server.level.ServerPlayer;
+import net.minecraft.server.network.ServerPlayerConnection;
+import net.minecraft.world.Container;
+import net.minecraft.world.inventory.CartographyTableMenu;
+import net.minecraft.world.inventory.MenuType;
+import net.minecraft.world.item.ItemStack;
+import org.bukkit.craftbukkit.v1_21_R2.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_21_R2.inventory.CraftInventory;
+import org.bukkit.craftbukkit.v1_21_R2.inventory.CraftInventoryCartography;
+import org.bukkit.craftbukkit.v1_21_R2.inventory.CraftInventoryView;
+import org.bukkit.craftbukkit.v1_21_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;
+
+import java.lang.reflect.Field;
+
+/**
+ * Internal cartography table inventory for 1.21.2
+ *
+ * @since 0.10.18
+ */
+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 + "'"
+ );
+ }
+
+
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ Component message = TextHolderUtil.toComponent(title);
+
+ ContainerCartographyTableImpl containerCartographyTable = new ContainerCartographyTableImpl(
+ serverPlayer, items, message
+ );
+
+ serverPlayer.containerMenu = containerCartographyTable;
+
+ int id = containerCartographyTable.containerId;
+
+ serverPlayer.connection.send(new ClientboundOpenScreenPacket(id, MenuType.CARTOGRAPHY_TABLE, message));
+
+ sendItems(player, items);
+ }
+
+ @Override
+ public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
+ NonNullList nmsItems = CustomInventoryUtil.convertToNMSItems(items);
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ int containerId = getContainerId(serverPlayer);
+ int state = serverPlayer.containerMenu.incrementStateId();
+ ItemStack cursor = CraftItemStack.asNMSCopy(player.getItemOnCursor());
+ ServerPlayerConnection playerConnection = getPlayerConnection(serverPlayer);
+
+ playerConnection.send(new ClientboundContainerSetContentPacket(containerId, state, nmsItems, cursor));
+ }
+
+ @Override
+ public void clearCursor(@NotNull Player player) {
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ int state = serverPlayer.containerMenu.incrementStateId();
+
+ getPlayerConnection(serverPlayer).send(new ClientboundContainerSetSlotPacket(-1, state, -1, ItemStack.EMPTY));
+ }
+
+ /**
+ * Gets the container id for the inventory view the player currently has open
+ *
+ * @param nmsPlayer the player to get the container id for
+ * @return the container id
+ * @since 0.10.18
+ */
+ @Contract(pure = true)
+ private int getContainerId(@NotNull net.minecraft.world.entity.player.Player nmsPlayer) {
+ return nmsPlayer.containerMenu.containerId;
+ }
+
+ /**
+ * Gets the player connection for the specified player
+ *
+ * @param serverPlayer the player to get the player connection from
+ * @return the player connection
+ * @since 0.10.18
+ */
+ @NotNull
+ @Contract(pure = true)
+ private ServerPlayerConnection getPlayerConnection(@NotNull ServerPlayer serverPlayer) {
+ return serverPlayer.connection;
+ }
+
+ /**
+ * Gets the server player associated to this player
+ *
+ * @param player the player to get the server player from
+ * @return the server player
+ * @since 0.10.18
+ */
+ @NotNull
+ @Contract(pure = true)
+ private ServerPlayer getServerPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * A custom container cartography table
+ *
+ * @since 0.10.18
+ */
+ private class ContainerCartographyTableImpl extends CartographyTableMenu {
+
+ /**
+ * 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 resultContainerField;
+
+ public ContainerCartographyTableImpl(@NotNull ServerPlayer serverPlayer,
+ @Nullable org.bukkit.inventory.ItemStack[] items,
+ @NotNull Component title) {
+ super(serverPlayer.nextContainerCounter(), serverPlayer.getInventory());
+
+ this.player = serverPlayer.getBukkitEntity();
+
+ setTitle(title);
+
+ try {
+ //noinspection JavaReflectionMemberAccess
+ this.resultContainerField = CartographyTableMenu.class.getDeclaredField("w"); //resultContainer
+ this.resultContainerField.setAccessible(true);
+ } catch (NoSuchFieldException exception) {
+ throw new RuntimeException(exception);
+ }
+
+ container.setItem(0, CraftItemStack.asNMSCopy(items[0]));
+ container.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.container, 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 stillValid(@Nullable net.minecraft.world.entity.player.Player nmsPlayer) {
+ return true;
+ }
+
+ @Override
+ public void slotsChanged(Container container) {}
+
+ @Override
+ public void removed(net.minecraft.world.entity.player.Player nmsPlayer) {}
+
+ @NotNull
+ @Contract(pure = true)
+ private Container getResultInventory() {
+ try {
+ return (Container) resultContainerField.get(this);
+ } catch (IllegalAccessException exception) {
+ throw new RuntimeException(exception);
+ }
+ }
+
+ }
+}
diff --git a/nms/1_21_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_2_3/EnchantingTableInventoryImpl.java b/nms/1_21_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_2_3/EnchantingTableInventoryImpl.java
new file mode 100644
index 00000000..c4cec265
--- /dev/null
+++ b/nms/1_21_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_2_3/EnchantingTableInventoryImpl.java
@@ -0,0 +1,220 @@
+package com.github.stefvanschie.inventoryframework.nms.v1_21_2_3;
+
+import com.github.stefvanschie.inventoryframework.abstraction.EnchantingTableInventory;
+import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
+import com.github.stefvanschie.inventoryframework.nms.v1_21_2_3.util.TextHolderUtil;
+import net.minecraft.core.NonNullList;
+import net.minecraft.network.chat.Component;
+import net.minecraft.network.protocol.game.ClientboundContainerSetContentPacket;
+import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket;
+import net.minecraft.network.protocol.game.ClientboundOpenScreenPacket;
+import net.minecraft.server.level.ServerPlayer;
+import net.minecraft.server.network.ServerPlayerConnection;
+import net.minecraft.world.Container;
+import net.minecraft.world.inventory.EnchantmentMenu;
+import net.minecraft.world.inventory.MenuType;
+import net.minecraft.world.item.ItemStack;
+import org.bukkit.craftbukkit.v1_21_R2.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_21_R2.inventory.CraftInventoryEnchanting;
+import org.bukkit.craftbukkit.v1_21_R2.inventory.CraftItemStack;
+import org.bukkit.craftbukkit.v1_21_R2.inventory.view.CraftEnchantmentView;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.EnchantingInventory;
+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.21.2
+ *
+ * @since 0.10.18
+ */
+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 + "'"
+ );
+ }
+
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ Component message = TextHolderUtil.toComponent(title);
+ ContainerEnchantingTableImpl containerEnchantmentTable = new ContainerEnchantingTableImpl(
+ serverPlayer, items, message
+ );
+
+ serverPlayer.containerMenu = containerEnchantmentTable;
+
+ int id = containerEnchantmentTable.containerId;
+
+ serverPlayer.connection.send(new ClientboundOpenScreenPacket(id, MenuType.ENCHANTMENT, message));
+
+ sendItems(player, items);
+ }
+
+ @Override
+ public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
+ NonNullList nmsItems = NonNullList.of(
+ ItemStack.EMPTY,
+ CraftItemStack.asNMSCopy(items[0]),
+ CraftItemStack.asNMSCopy(items[1])
+ );
+
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ int containerId = getContainerId(serverPlayer);
+ int state = serverPlayer.containerMenu.incrementStateId();
+ ItemStack cursor = CraftItemStack.asNMSCopy(player.getItemOnCursor());
+ ServerPlayerConnection playerConnection = getPlayerConnection(serverPlayer);
+
+ playerConnection.send(new ClientboundContainerSetContentPacket(containerId, state, nmsItems, cursor));
+ }
+
+ @Override
+ public void clearCursor(@NotNull Player player) {
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ int state = serverPlayer.containerMenu.incrementStateId();
+
+ getPlayerConnection(serverPlayer).send(new ClientboundContainerSetSlotPacket(-1, state, -1, ItemStack.EMPTY));
+ }
+
+ /**
+ * Gets the containerId id for the inventory view the player currently has open
+ *
+ * @param nmsPlayer the player to get the containerId id for
+ * @return the containerId id
+ * @since 0.10.18
+ */
+ @Contract(pure = true)
+ private int getContainerId(@NotNull net.minecraft.world.entity.player.Player nmsPlayer) {
+ return nmsPlayer.containerMenu.containerId;
+ }
+
+ /**
+ * Gets the player connection for the specified player
+ *
+ * @param serverPlayer the player to get the player connection from
+ * @return the player connection
+ * @since 0.10.18
+ */
+ @NotNull
+ @Contract(pure = true)
+ private ServerPlayerConnection getPlayerConnection(@NotNull ServerPlayer serverPlayer) {
+ return serverPlayer.connection;
+ }
+
+ /**
+ * Gets the server player associated to this player
+ *
+ * @param player the player to get the server player from
+ * @return the server player
+ * @since 0.10.18
+ */
+ @NotNull
+ @Contract(pure = true)
+ private ServerPlayer getServerPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * A custom container enchanting table
+ *
+ * @since 0.10.18
+ */
+ private class ContainerEnchantingTableImpl extends EnchantmentMenu {
+
+ /**
+ * The player for this enchanting table container
+ */
+ @NotNull
+ private final Player player;
+
+ /**
+ * The internal bukkit entity for this container enchanting table
+ */
+ @Nullable
+ private CraftEnchantmentView bukkitEntity;
+
+ /**
+ * Field for accessing the enchant slots field
+ */
+ @NotNull
+ private final Field enchantSlotsField;
+
+ public ContainerEnchantingTableImpl(@NotNull ServerPlayer serverPlayer,
+ @Nullable org.bukkit.inventory.ItemStack[] items,
+ @NotNull Component title) {
+ super(serverPlayer.nextContainerCounter(), serverPlayer.getInventory());
+
+ this.player = serverPlayer.getBukkitEntity();
+
+ setTitle(title);
+
+ try {
+ //noinspection JavaReflectionMemberAccess
+ this.enchantSlotsField = EnchantmentMenu.class.getDeclaredField("q"); //enchantSlots
+ this.enchantSlotsField.setAccessible(true);
+ } catch (NoSuchFieldException exception) {
+ throw new RuntimeException(exception);
+ }
+
+ try {
+ Container input = (Container) 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 CraftEnchantmentView getBukkitView() {
+ if (bukkitEntity == null) {
+ try {
+ Container container = (Container) enchantSlotsField.get(this);
+
+ EnchantingInventory inventory = new CraftInventoryEnchanting(container) {
+ @NotNull
+ @Contract(pure = true)
+ @Override
+ public InventoryHolder getHolder() {
+ return inventoryHolder;
+ }
+ };
+
+ this.bukkitEntity = new CraftEnchantmentView(player, inventory, this);
+ } catch (IllegalAccessException exception) {
+ exception.printStackTrace();
+ }
+ }
+
+ return bukkitEntity;
+ }
+
+ @Contract(pure = true, value = "_ -> true")
+ @Override
+ public boolean stillValid(@Nullable net.minecraft.world.entity.player.Player nmsPlayer) {
+ return true;
+ }
+
+ @Override
+ public void slotsChanged(Container container) {}
+
+ @Override
+ public void removed(net.minecraft.world.entity.player.Player nmsPlayer) {}
+
+ }
+}
diff --git a/nms/1_21_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_2_3/GrindstoneInventoryImpl.java b/nms/1_21_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_2_3/GrindstoneInventoryImpl.java
new file mode 100644
index 00000000..c9796f49
--- /dev/null
+++ b/nms/1_21_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_2_3/GrindstoneInventoryImpl.java
@@ -0,0 +1,208 @@
+package com.github.stefvanschie.inventoryframework.nms.v1_21_2_3;
+
+import com.github.stefvanschie.inventoryframework.abstraction.GrindstoneInventory;
+import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
+import com.github.stefvanschie.inventoryframework.nms.v1_21_2_3.util.CustomInventoryUtil;
+import com.github.stefvanschie.inventoryframework.nms.v1_21_2_3.util.TextHolderUtil;
+import net.minecraft.core.NonNullList;
+import net.minecraft.network.chat.Component;
+import net.minecraft.network.protocol.game.ClientboundContainerSetContentPacket;
+import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket;
+import net.minecraft.network.protocol.game.ClientboundOpenScreenPacket;
+import net.minecraft.server.level.ServerPlayer;
+import net.minecraft.server.network.ServerPlayerConnection;
+import net.minecraft.world.Container;
+import net.minecraft.world.inventory.GrindstoneMenu;
+import net.minecraft.world.inventory.MenuType;
+import net.minecraft.world.inventory.Slot;
+import net.minecraft.world.item.ItemStack;
+import org.bukkit.craftbukkit.v1_21_R2.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_21_R2.event.CraftEventFactory;
+import org.bukkit.craftbukkit.v1_21_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;
+
+/**
+ * Internal grindstone inventory for 1.21.1
+ *
+ * @since 0.10.18
+ */
+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 + "'"
+ );
+ }
+
+ ServerPlayer serverPlayer = getServerPlayer(player);
+
+ //ignore deprecation: superseding method is only available on Paper
+ //noinspection deprecation
+ CraftEventFactory.handleInventoryCloseEvent(serverPlayer);
+
+ serverPlayer.containerMenu = serverPlayer.inventoryMenu;
+
+ Component message = TextHolderUtil.toComponent(title);
+ ContainerGrindstoneImpl containerGrindstone = new ContainerGrindstoneImpl(serverPlayer, message);
+
+ Inventory inventory = containerGrindstone.getBukkitView().getTopInventory();
+
+ inventory.setItem(0, items[0]);
+ inventory.setItem(1, items[1]);
+ inventory.setItem(2, items[2]);
+
+ int containerId = containerGrindstone.getContainerId();
+
+ serverPlayer.connection.send(new ClientboundOpenScreenPacket(containerId, MenuType.GRINDSTONE, message));
+ serverPlayer.containerMenu = containerGrindstone;
+ serverPlayer.initMenu(containerGrindstone);
+
+ return inventory;
+ }
+
+ @Override
+ public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items,
+ @Nullable org.bukkit.inventory.ItemStack cursor) {
+ if (cursor == null) {
+ throw new IllegalArgumentException("Cursor may not be null on version 1.19.2");
+ }
+
+ NonNullList nmsItems = CustomInventoryUtil.convertToNMSItems(items);
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ int containerId = getContainerId(serverPlayer);
+ int state = serverPlayer.containerMenu.incrementStateId();
+ ItemStack nmsCursor = CraftItemStack.asNMSCopy(cursor);
+ ServerPlayerConnection playerConnection = getPlayerConnection(serverPlayer);
+
+ playerConnection.send(new ClientboundContainerSetContentPacket(containerId, state, nmsItems, nmsCursor));
+ }
+
+ @Override
+ public void clearCursor(@NotNull Player player) {
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ int state = serverPlayer.containerMenu.incrementStateId();
+
+ getPlayerConnection(serverPlayer).send(new ClientboundContainerSetSlotPacket(-1, state, -1, ItemStack.EMPTY));
+ }
+
+ /**
+ * Gets the containerId id for the inventory view the player currently has open
+ *
+ * @param nmsPlayer the player to get the containerId id for
+ * @return the containerId id
+ * @since 0.10.18
+ * @deprecated no longer used internally
+ */
+ @Contract(pure = true)
+ @Deprecated
+ private int getContainerId(@NotNull net.minecraft.world.entity.player.Player nmsPlayer) {
+ return nmsPlayer.containerMenu.containerId;
+ }
+
+ /**
+ * Gets the player connection for the specified player
+ *
+ * @param serverPlayer the player to get the player connection from
+ * @return the player connection
+ * @since 0.10.18
+ * @deprecated no longer used internally
+ */
+ @NotNull
+ @Contract(pure = true)
+ @Deprecated
+ private ServerPlayerConnection getPlayerConnection(@NotNull ServerPlayer serverPlayer) {
+ return serverPlayer.connection;
+ }
+
+ /**
+ * Gets the server player associated to this player
+ *
+ * @param player the player to get the server player from
+ * @return the server player
+ * @since 0.10.18
+ */
+ @NotNull
+ @Contract(pure = true)
+ private ServerPlayer getServerPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * A custom container grindstone
+ *
+ * @since 0.10.18
+ */
+ private static class ContainerGrindstoneImpl extends GrindstoneMenu {
+
+ /**
+ * Creates a new grindstone container
+ *
+ * @param serverPlayer the player for whom this container should be opened
+ * @param title the title of the gui
+ * @since 0.10.18
+ */
+ public ContainerGrindstoneImpl(@NotNull ServerPlayer serverPlayer, @NotNull Component title) {
+ super(serverPlayer.nextContainerCounter(), serverPlayer.getInventory());
+
+ setTitle(title);
+
+ 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.container, firstSlot.index, firstSlot.x, firstSlot.y) {
+ @Override
+ public boolean mayPlace(ItemStack stack) {
+ return true;
+ }
+ });
+
+ this.slots.set(1, new Slot(secondSlot.container, secondSlot.index, secondSlot.x, secondSlot.y) {
+ @Override
+ public boolean mayPlace(ItemStack stack) {
+ return true;
+ }
+ });
+
+ this.slots.set(2, new Slot(thirdSlot.container, thirdSlot.index, thirdSlot.x, thirdSlot.y) {
+ @Override
+ public boolean mayPlace(ItemStack stack) {
+ return true;
+ }
+
+ @Override
+ public void onTake(net.minecraft.world.entity.player.Player player, ItemStack stack) {}
+ });
+ }
+
+ @Contract(pure = true, value = "_ -> true")
+ @Override
+ public boolean stillValid(@Nullable net.minecraft.world.entity.player.Player nmsPlayer) {
+ return true;
+ }
+
+ @Override
+ public void slotsChanged(Container container) {}
+
+ @Override
+ public void removed(net.minecraft.world.entity.player.Player nmsPlayer) {}
+
+ public int getContainerId() {
+ return this.containerId;
+ }
+ }
+}
diff --git a/nms/1_21_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_2_3/MerchantInventoryImpl.java b/nms/1_21_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_2_3/MerchantInventoryImpl.java
new file mode 100644
index 00000000..7f64c878
--- /dev/null
+++ b/nms/1_21_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_2_3/MerchantInventoryImpl.java
@@ -0,0 +1,118 @@
+package com.github.stefvanschie.inventoryframework.nms.v1_21_2_3;
+
+import com.github.stefvanschie.inventoryframework.abstraction.MerchantInventory;
+import net.minecraft.core.component.DataComponentPredicate;
+import net.minecraft.server.level.ServerPlayer;
+import net.minecraft.world.item.trading.ItemCost;
+import net.minecraft.world.item.trading.MerchantOffer;
+import net.minecraft.world.item.trading.MerchantOffers;
+import org.bukkit.craftbukkit.v1_21_R2.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_21_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;
+import java.util.Optional;
+
+/**
+ * Internal merchant inventory for 1.21.2
+ *
+ * @since 0.10.18
+ */
+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) {
+ MerchantOffers offers = new MerchantOffers();
+
+ 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.world.item.ItemStack nmsItemA = CraftItemStack.asNMSCopy(itemA);
+ net.minecraft.world.item.ItemStack nmsItemB = net.minecraft.world.item.ItemStack.EMPTY;
+ net.minecraft.world.item.ItemStack nmsItemResult = CraftItemStack.asNMSCopy(recipe.getResult());
+
+ if (itemB != null) {
+ nmsItemB = CraftItemStack.asNMSCopy(itemB);
+ }
+
+ ItemCost itemCostA = convertItemStackToItemCost(nmsItemA);
+ ItemCost itemCostB = convertItemStackToItemCost(nmsItemB);
+
+ int uses = recipe.getUses();
+ int maxUses = recipe.getMaxUses();
+ int exp = recipe.getVillagerExperience();
+ float multiplier = recipe.getPriceMultiplier();
+
+ MerchantOffer merchantOffer = new MerchantOffer(
+ itemCostA, Optional.of(itemCostB), nmsItemResult, uses, maxUses, exp, multiplier
+ );
+ merchantOffer.setSpecialPriceDiff(entry.getValue());
+
+ offers.add(merchantOffer);
+ }
+
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ int containerId = getContainerId(serverPlayer);
+
+ serverPlayer.sendMerchantOffers(containerId, offers, level, experience, true, false);
+ }
+
+ /**
+ * Converts an NMS item stack to an item cost.
+ *
+ * @param itemStack the item stack to convert
+ * @return the item cost
+ * @since 0.10.18
+ */
+ @NotNull
+ @Contract(value = "_ -> new", pure = true)
+ private ItemCost convertItemStackToItemCost(@NotNull net.minecraft.world.item.ItemStack itemStack) {
+ DataComponentPredicate predicate = DataComponentPredicate.allOf(itemStack.getComponents());
+
+ return new ItemCost(itemStack.getItemHolder(), itemStack.getCount(), predicate, itemStack);
+ }
+
+ /**
+ * Gets the server player associated to this player
+ *
+ * @param player the player to get the server player from
+ * @return the server player
+ * @since 0.10.18
+ */
+ @NotNull
+ @Contract(pure = true)
+ private ServerPlayer getServerPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * Gets the containerId id for the inventory view the player currently has open
+ *
+ * @param nmsPlayer the player to get the containerId id for
+ * @return the containerId id
+ * @since 0.10.18
+ */
+ @Contract(pure = true)
+ private int getContainerId(@NotNull net.minecraft.world.entity.player.Player nmsPlayer) {
+ return nmsPlayer.containerMenu.containerId;
+ }
+}
diff --git a/nms/1_21_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_2_3/SmithingTableInventoryImpl.java b/nms/1_21_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_2_3/SmithingTableInventoryImpl.java
new file mode 100644
index 00000000..03457ad7
--- /dev/null
+++ b/nms/1_21_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_2_3/SmithingTableInventoryImpl.java
@@ -0,0 +1,335 @@
+package com.github.stefvanschie.inventoryframework.nms.v1_21_2_3;
+
+import com.github.stefvanschie.inventoryframework.abstraction.SmithingTableInventory;
+import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
+import com.github.stefvanschie.inventoryframework.nms.v1_21_2_3.util.CustomInventoryUtil;
+import com.github.stefvanschie.inventoryframework.nms.v1_21_2_3.util.TextHolderUtil;
+import net.minecraft.core.BlockPos;
+import net.minecraft.core.NonNullList;
+import net.minecraft.network.chat.Component;
+import net.minecraft.network.protocol.game.ClientboundContainerSetContentPacket;
+import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket;
+import net.minecraft.network.protocol.game.ClientboundOpenScreenPacket;
+import net.minecraft.server.level.ServerPlayer;
+import net.minecraft.server.network.ServerPlayerConnection;
+import net.minecraft.world.Container;
+import net.minecraft.world.inventory.ContainerLevelAccess;
+import net.minecraft.world.inventory.MenuType;
+import net.minecraft.world.inventory.Slot;
+import net.minecraft.world.inventory.SmithingMenu;
+import net.minecraft.world.item.ItemStack;
+import org.bukkit.craftbukkit.v1_21_R2.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_21_R2.event.CraftEventFactory;
+import org.bukkit.craftbukkit.v1_21_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;
+
+/**
+ * Internal smithing table inventory for 1.21.2. This is only available for Minecraft 1.20 and higher.
+ *
+ * @since 0.10.18
+ */
+public class SmithingTableInventoryImpl extends SmithingTableInventory {
+
+ public SmithingTableInventoryImpl(@NotNull InventoryHolder inventoryHolder) {
+ super(inventoryHolder);
+ }
+
+ @NotNull
+ @Override
+ public Inventory openInventory(@NotNull Player player, @NotNull TextHolder title,
+ @Nullable org.bukkit.inventory.ItemStack[] items) {
+ int itemAmount = items.length;
+
+ if (itemAmount != 4) {
+ throw new IllegalArgumentException(
+ "The amount of items for a smithing table should be 4, but is '" + itemAmount + "'"
+ );
+ }
+
+ ServerPlayer serverPlayer = getServerPlayer(player);
+
+ //ignore deprecation: superseding method is only available on Paper
+ //noinspection deprecation
+ CraftEventFactory.handleInventoryCloseEvent(serverPlayer);
+
+ serverPlayer.containerMenu = serverPlayer.inventoryMenu;
+
+ Component message = TextHolderUtil.toComponent(title);
+ ContainerSmithingTableImpl containerSmithingTable = new ContainerSmithingTableImpl(serverPlayer, message);
+
+ Inventory inventory = containerSmithingTable.getBukkitView().getTopInventory();
+
+ inventory.setItem(0, items[0]);
+ inventory.setItem(1, items[1]);
+ inventory.setItem(2, items[2]);
+ inventory.setItem(3, items[3]);
+
+ int containerId = containerSmithingTable.getContainerId();
+
+ serverPlayer.connection.send(new ClientboundOpenScreenPacket(containerId, MenuType.SMITHING, message));
+ serverPlayer.containerMenu = containerSmithingTable;
+ serverPlayer.initMenu(containerSmithingTable);
+
+ return inventory;
+ }
+
+ @Override
+ public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items,
+ @Nullable org.bukkit.inventory.ItemStack cursor) {
+ NonNullList nmsItems = CustomInventoryUtil.convertToNMSItems(items);
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ int containerId = getContainerId(serverPlayer);
+ int state = serverPlayer.containerMenu.incrementStateId();
+ ItemStack nmsCursor = CraftItemStack.asNMSCopy(cursor);
+ ServerPlayerConnection playerConnection = getPlayerConnection(serverPlayer);
+
+ playerConnection.send(new ClientboundContainerSetContentPacket(containerId, state, nmsItems, nmsCursor));
+ }
+
+ @Override
+ public void sendFirstItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
+ int containerId = getContainerId(serverPlayer);
+ int state = serverPlayer.containerMenu.incrementStateId();
+
+ getPlayerConnection(serverPlayer).send(new ClientboundContainerSetSlotPacket(containerId, state, 0, nmsItem));
+ }
+
+ @Override
+ public void sendSecondItem(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack item) {
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
+ int containerId = getContainerId(serverPlayer);
+ int state = serverPlayer.containerMenu.incrementStateId();
+
+ getPlayerConnection(serverPlayer).send(new ClientboundContainerSetSlotPacket(containerId, state, 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.EMPTY);
+ }
+
+ @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) {
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ int state = serverPlayer.containerMenu.incrementStateId();
+
+ getPlayerConnection(serverPlayer).send(new ClientboundContainerSetSlotPacket(-1, state, -1, ItemStack.EMPTY));
+ }
+
+ /**
+ * 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.10.18
+ * @deprecated no longer used internally
+ */
+ @Deprecated
+ private void setCursor(@NotNull Player player, @NotNull ItemStack item) {
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ int state = serverPlayer.containerMenu.incrementStateId();
+
+ getPlayerConnection(serverPlayer).send(new ClientboundContainerSetSlotPacket(-1, state, -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.10.18
+ * @deprecated no longer used internally
+ */
+ @Deprecated
+ private void sendResultItem(@NotNull Player player, @NotNull ItemStack item) {
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ int containerId = getContainerId(serverPlayer);
+ int state = serverPlayer.containerMenu.incrementStateId();
+
+ getPlayerConnection(serverPlayer).send(new ClientboundContainerSetSlotPacket(containerId, state, 2, item));
+ }
+
+ /**
+ * Gets the container id for the inventory view the player currently has open
+ *
+ * @param nmsPlayer the player to get the container id for
+ * @return the container id
+ * @since 0.10.18
+ * @deprecated no longer used internally
+ */
+ @Contract(pure = true)
+ @Deprecated
+ private int getContainerId(@NotNull net.minecraft.world.entity.player.Player nmsPlayer) {
+ return nmsPlayer.containerMenu.containerId;
+ }
+
+ /**
+ * Gets the player connection for the specified player
+ *
+ * @param serverPlayer the player to get the player connection from
+ * @return the player connection
+ * @since 0.10.18
+ * @deprecated no longer used internally
+ */
+ @NotNull
+ @Contract(pure = true)
+ @Deprecated
+ private ServerPlayerConnection getPlayerConnection(@NotNull ServerPlayer serverPlayer) {
+ return serverPlayer.connection;
+ }
+
+ /**
+ * Gets the server player associated to this player
+ *
+ * @param player the player to get the server player from
+ * @return the server player
+ * @since 0.10.18
+ */
+ @NotNull
+ @Contract(pure = true)
+ private ServerPlayer getServerPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * A custom container smithing table
+ *
+ * @since 0.10.18
+ */
+ private static class ContainerSmithingTableImpl extends SmithingMenu {
+
+ /**
+ * Creates a new custom smithing table container for the specified player
+ *
+ * @param serverPlayer the player for whom this anvil container is
+ * @param title the title of the inventory
+ * @since 0.10.18
+ */
+ public ContainerSmithingTableImpl(@NotNull ServerPlayer serverPlayer, @NotNull Component title) {
+ super(serverPlayer.nextContainerCounter(), serverPlayer.getInventory(),
+ ContainerLevelAccess.create(serverPlayer.getCommandSenderWorld(), new BlockPos(0, 0, 0)));
+
+ setTitle(title);
+
+ this.checkReachable = false;
+
+ Slot slotOne = this.slots.get(0);
+ Slot slotTwo = this.slots.get(1);
+ Slot slotThree = this.slots.get(2);
+ Slot slotFour = this.slots.get(3);
+
+ this.slots.set(0, new Slot(slotOne.container, slotOne.index, slotOne.x, slotOne.y) {
+ @Override
+ public boolean mayPlace(@NotNull ItemStack stack) {
+ return true;
+ }
+
+ @Override
+ public boolean mayPickup(net.minecraft.world.entity.player.@NotNull Player playerEntity) {
+ return true;
+ }
+
+ @Override
+ public void onTake(net.minecraft.world.entity.player.@NotNull Player player, @NotNull ItemStack stack) {
+ slotOne.onTake(player, stack);
+ }
+ });
+
+ this.slots.set(1, new Slot(slotTwo.container, slotTwo.index, slotTwo.x, slotTwo.y) {
+ @Override
+ public boolean mayPlace(@NotNull ItemStack stack) {
+ return true;
+ }
+
+ @Override
+ public boolean mayPickup(net.minecraft.world.entity.player.@NotNull Player playerEntity) {
+ return true;
+ }
+
+ @Override
+ public void onTake(net.minecraft.world.entity.player.@NotNull Player player, @NotNull ItemStack stack) {
+ slotTwo.onTake(player, stack);
+ }
+ });
+
+ this.slots.set(2, new Slot(slotThree.container, slotThree.index, slotThree.x, slotThree.y) {
+ @Override
+ public boolean mayPlace(@NotNull ItemStack stack) {
+ return true;
+ }
+
+ @Override
+ public boolean mayPickup(net.minecraft.world.entity.player.@NotNull Player playerEntity) {
+ return true;
+ }
+
+ @Override
+ public void onTake(net.minecraft.world.entity.player.@NotNull Player player, @NotNull ItemStack stack) {
+ slotThree.onTake(player, stack);
+ }
+ });
+
+ this.slots.set(3, new Slot(slotFour.container, slotFour.index, slotFour.x, slotFour.y) {
+ @Override
+ public boolean mayPlace(@NotNull ItemStack stack) {
+ return true;
+ }
+
+ @Override
+ public boolean mayPickup(net.minecraft.world.entity.player.@NotNull Player playerEntity) {
+ return true;
+ }
+
+ @Override
+ public void onTake(net.minecraft.world.entity.player.@NotNull Player player, @NotNull ItemStack stack) {
+ slotFour.onTake(player, stack);
+ }
+ });
+ }
+
+ @Contract(pure = true, value = "_ -> true")
+ @Override
+ public boolean stillValid(@Nullable net.minecraft.world.entity.player.Player nmsPlayer) {
+ return true;
+ }
+
+ @Override
+ public void slotsChanged(Container container) {}
+
+ @Override
+ public void removed(net.minecraft.world.entity.player.Player nmsPlayer) {}
+
+ @Override
+ public void createResult() {}
+
+ @Override
+ protected void onTake(net.minecraft.world.entity.player.Player player, ItemStack stack) {}
+
+ @Override
+ protected boolean mayPickup(net.minecraft.world.entity.player.Player player, boolean present) {
+ return true;
+ }
+
+ public int getContainerId() {
+ return this.containerId;
+ }
+ }
+}
diff --git a/nms/1_21_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_2_3/StonecutterInventoryImpl.java b/nms/1_21_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_2_3/StonecutterInventoryImpl.java
new file mode 100644
index 00000000..18d57027
--- /dev/null
+++ b/nms/1_21_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_2_3/StonecutterInventoryImpl.java
@@ -0,0 +1,222 @@
+package com.github.stefvanschie.inventoryframework.nms.v1_21_2_3;
+
+import com.github.stefvanschie.inventoryframework.abstraction.StonecutterInventory;
+import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
+import com.github.stefvanschie.inventoryframework.nms.v1_21_2_3.util.TextHolderUtil;
+import net.minecraft.core.NonNullList;
+import net.minecraft.network.chat.Component;
+import net.minecraft.network.protocol.game.ClientboundContainerSetContentPacket;
+import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket;
+import net.minecraft.network.protocol.game.ClientboundOpenScreenPacket;
+import net.minecraft.server.level.ServerPlayer;
+import net.minecraft.server.network.ServerPlayerConnection;
+import net.minecraft.world.Container;
+import net.minecraft.world.inventory.MenuType;
+import net.minecraft.world.inventory.StonecutterMenu;
+import net.minecraft.world.item.ItemStack;
+import org.bukkit.craftbukkit.v1_21_R2.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_21_R2.inventory.CraftInventoryStonecutter;
+import org.bukkit.craftbukkit.v1_21_R2.inventory.CraftItemStack;
+import org.bukkit.craftbukkit.v1_21_R2.inventory.view.CraftStonecutterView;
+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.21.2
+ *
+ * @since 0.10.18
+ */
+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 + "'"
+ );
+ }
+
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ Component message = TextHolderUtil.toComponent(title);
+ ContainerStonecutterImpl containerEnchantmentTable = new ContainerStonecutterImpl(serverPlayer, items, message);
+
+ serverPlayer.containerMenu = containerEnchantmentTable;
+
+ int id = containerEnchantmentTable.containerId;
+ ClientboundOpenScreenPacket packet = new ClientboundOpenScreenPacket(id, MenuType.STONECUTTER, message);
+
+ serverPlayer.connection.send(packet);
+
+ sendItems(player, items);
+ }
+
+ @Override
+ public void sendItems(@NotNull Player player, @Nullable org.bukkit.inventory.ItemStack[] items) {
+ NonNullList nmsItems = NonNullList.of(
+ ItemStack.EMPTY,
+ CraftItemStack.asNMSCopy(items[0]),
+ CraftItemStack.asNMSCopy(items[1])
+ );
+
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ int containerId = getContainerId(serverPlayer);
+ int state = serverPlayer.containerMenu.incrementStateId();
+ ItemStack cursor = CraftItemStack.asNMSCopy(player.getItemOnCursor());
+ ServerPlayerConnection playerConnection = getPlayerConnection(serverPlayer);
+
+ playerConnection.send(new ClientboundContainerSetContentPacket(containerId, state, nmsItems, cursor));
+ }
+
+ @Override
+ public void clearCursor(@NotNull Player player) {
+ ServerPlayer serverPlayer = getServerPlayer(player);
+ int state = serverPlayer.containerMenu.incrementStateId();
+
+ getPlayerConnection(serverPlayer).send(new ClientboundContainerSetSlotPacket(-1, state, -1, ItemStack.EMPTY));
+ }
+
+ /**
+ * Gets the container id for the inventory view the player currently has open
+ *
+ * @param nmsPlayer the player to get the container id for
+ * @return the container id
+ * @since 0.10.18
+ */
+ @Contract(pure = true)
+ private int getContainerId(@NotNull net.minecraft.world.entity.player.Player nmsPlayer) {
+ return nmsPlayer.containerMenu.containerId;
+ }
+
+ /**
+ * Gets the player connection for the specified player
+ *
+ * @param serverPlayer the player to get the player connection from
+ * @return the player connection
+ * @since 0.10.18
+ */
+ @NotNull
+ @Contract(pure = true)
+ private ServerPlayerConnection getPlayerConnection(@NotNull ServerPlayer serverPlayer) {
+ return serverPlayer.connection;
+ }
+
+ /**
+ * Gets the server player associated to this player
+ *
+ * @param player the player to get the server player from
+ * @return the server player
+ * @since 0.10.18
+ */
+ @NotNull
+ @Contract(pure = true)
+ private ServerPlayer getServerPlayer(@NotNull Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ /**
+ * A custom container enchanting table
+ *
+ * @since 0.10.18
+ */
+ private class ContainerStonecutterImpl extends StonecutterMenu {
+
+ /**
+ * The player for this enchanting table container
+ */
+ @NotNull
+ private final Player player;
+
+ /**
+ * The internal bukkit entity for this container enchanting table
+ */
+ @Nullable
+ private CraftStonecutterView bukkitEntity;
+
+ /**
+ * Field for accessing the result inventory field
+ */
+ @NotNull
+ private final Field resultContainerField;
+
+ public ContainerStonecutterImpl(@NotNull ServerPlayer entityPlayer,
+ @Nullable org.bukkit.inventory.ItemStack[] items, @NotNull Component title) {
+ super(entityPlayer.nextContainerCounter(), entityPlayer.getInventory());
+
+ this.player = entityPlayer.getBukkitEntity();
+
+ setTitle(title);
+
+ try {
+ //noinspection JavaReflectionMemberAccess
+ this.resultContainerField = StonecutterMenu.class.getDeclaredField("C"); //resultContainer
+ this.resultContainerField.setAccessible(true);
+ } catch (NoSuchFieldException exception) {
+ throw new RuntimeException(exception);
+ }
+
+ container.setItem(0, CraftItemStack.asNMSCopy(items[0]));
+ getResultInventory().setItem(0, CraftItemStack.asNMSCopy(items[1]));
+ }
+
+ @NotNull
+ @Override
+ public CraftStonecutterView getBukkitView() {
+ if (bukkitEntity == null) {
+ org.bukkit.inventory.StonecutterInventory inventory = new CraftInventoryStonecutter(
+ this.container, getResultInventory()
+ ) {
+ @NotNull
+ @Contract(pure = true)
+ @Override
+ public InventoryHolder getHolder() {
+ return inventoryHolder;
+ }
+ };
+
+ this.bukkitEntity = new CraftStonecutterView(player, inventory, this);
+ }
+
+ return bukkitEntity;
+ }
+
+ @Contract(pure = true, value = "_ -> true")
+ @Override
+ public boolean stillValid(@Nullable net.minecraft.world.entity.player.Player nmsPlayer) {
+ return true;
+ }
+
+ @Override
+ public void slotsChanged(Container container) {}
+
+ @Override
+ public void removed(net.minecraft.world.entity.player.Player nmsPlayer) {}
+
+ /**
+ * Gets the result inventory
+ *
+ * @return the result inventory
+ * @since 0.10.18
+ */
+ @NotNull
+ @Contract(pure = true)
+ public Container getResultInventory() {
+ try {
+ return (Container) resultContainerField.get(this);
+ } catch (IllegalAccessException exception) {
+ throw new RuntimeException(exception);
+ }
+ }
+ }
+}
diff --git a/nms/1_21_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_2_3/util/CustomInventoryUtil.java b/nms/1_21_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_2_3/util/CustomInventoryUtil.java
new file mode 100644
index 00000000..eb2257b9
--- /dev/null
+++ b/nms/1_21_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_2_3/util/CustomInventoryUtil.java
@@ -0,0 +1,41 @@
+package com.github.stefvanschie.inventoryframework.nms.v1_21_2_3.util;
+
+import net.minecraft.core.NonNullList;
+import net.minecraft.world.item.ItemStack;
+import org.bukkit.craftbukkit.v1_21_R2.inventory.CraftItemStack;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * A utility class for custom inventories
+ *
+ * @since 0.10.18
+ */
+public final class CustomInventoryUtil {
+
+ /**
+ * A private constructor to prevent construction.
+ */
+ private CustomInventoryUtil() {}
+
+ /**
+ * Converts an array of Bukkit items into a non-null list of NMS items. The returned list is modifiable. If no items
+ * were specified, this returns an empty list.
+ *
+ * @param items the items to convert
+ * @return a list of converted items
+ * @since 0.10.18
+ */
+ @NotNull
+ @Contract(pure = true)
+ public static NonNullList convertToNMSItems(@Nullable org.bukkit.inventory.ItemStack @NotNull [] items) {
+ NonNullList nmsItems = NonNullList.create();
+
+ for (org.bukkit.inventory.ItemStack item : items) {
+ nmsItems.add(CraftItemStack.asNMSCopy(item));
+ }
+
+ return nmsItems;
+ }
+}
diff --git a/nms/1_21_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_2_3/util/TextHolderUtil.java b/nms/1_21_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_2_3/util/TextHolderUtil.java
new file mode 100644
index 00000000..4f807583
--- /dev/null
+++ b/nms/1_21_2-3/src/main/java/com/github/stefvanschie/inventoryframework/nms/v1_21_2_3/util/TextHolderUtil.java
@@ -0,0 +1,67 @@
+package com.github.stefvanschie.inventoryframework.nms.v1_21_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.core.HolderLookup;
+import net.minecraft.network.chat.Component;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Objects;
+import java.util.stream.Stream;
+
+/**
+ * A utility class for adding {@link TextHolder} support.
+ *
+ * @since 0.10.18
+ */
+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.18
+ */
+ @NotNull
+ @Contract(pure = true)
+ public static Component 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.18
+ */
+ @NotNull
+ @Contract(pure = true)
+ private static Component toComponent(@NotNull StringHolder holder) {
+ return Component.literal(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.18
+ */
+ @NotNull
+ @Contract(pure = true)
+ private static Component toComponent(@NotNull ComponentHolder holder) {
+ return Objects.requireNonNull(Component.Serializer.fromJson(holder.asJson(), HolderLookup.Provider.create(Stream.empty())));
+ }
+}
diff --git a/nms/abstraction/pom.xml b/nms/abstraction/pom.xml
index 1e7aa466..3d194bfe 100644
--- a/nms/abstraction/pom.xml
+++ b/nms/abstraction/pom.xml
@@ -5,7 +5,7 @@
IF-parent
com.github.stefvanschie.inventoryframework
- 0.10.17
+ 0.10.18
../../pom.xml
4.0.0
diff --git a/pom.xml b/pom.xml
index 3ac4df64..7050fa7b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -7,7 +7,9 @@
IF
nms/abstraction
- nms/1_21
+ nms/1_21_2-3
+ nms/1_21_1
+ nms/1_21_0
nms/1_20_6
nms/1_20_5
nms/1_20_3-4
@@ -45,7 +47,7 @@
com.github.stefvanschie.inventoryframework
IF-parent
- 0.10.17
+ 0.10.18
pom
IF
@@ -120,12 +122,12 @@
org.apache.maven.plugins
maven-surefire-plugin
- 3.5.0
+ 3.5.2
org.apache.maven.surefire
surefire-junit-platform
- 3.5.0
+ 3.5.2
org.junit.jupiter