From c5ff860b2870e8a7c6ae592a73cb49f1bd5003f7 Mon Sep 17 00:00:00 2001
From: BoBkiNN <78136575+BoBkiNN@users.noreply.github.com>
Date: Sun, 22 Jun 2025 21:33:02 +0500
Subject: [PATCH 1/8] add support for mojmapped 1.21.5
---
Mojang1_21_R4/pom.xml | 56 +++++++
.../version/MojangWrapper1_21_R4.java | 158 ++++++++++++++++++
.../anvilgui/version/VersionMatcher.java | 19 ++-
pom.xml | 1 +
4 files changed, 233 insertions(+), 1 deletion(-)
create mode 100644 Mojang1_21_R4/pom.xml
create mode 100644 Mojang1_21_R4/src/main/java/net/wesjd/anvilgui/version/MojangWrapper1_21_R4.java
diff --git a/Mojang1_21_R4/pom.xml b/Mojang1_21_R4/pom.xml
new file mode 100644
index 00000000..57152a04
--- /dev/null
+++ b/Mojang1_21_R4/pom.xml
@@ -0,0 +1,56 @@
+
+
+ 4.0.0
+
+
+ net.wesjd
+ anvilgui-parent
+ 1.10.5-SNAPSHOT
+
+
+ anvilgui-1_21_R4-mojang
+
+
+
+ ca.bkaw
+ paper-nms
+ 1.21.5-SNAPSHOT
+ provided
+
+
+ net.wesjd
+ anvilgui-abstraction
+ ${project.parent.version}
+ provided
+
+
+
+
+
+ bytecode.space
+ https://repo.bytecode.space/repository/maven-public/
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.8.1
+
+ 21
+ 21
+
+
+
+
+ ca.bkaw
+ paper-nms-maven-plugin
+ 1.4.7
+
+
+
+
diff --git a/Mojang1_21_R4/src/main/java/net/wesjd/anvilgui/version/MojangWrapper1_21_R4.java b/Mojang1_21_R4/src/main/java/net/wesjd/anvilgui/version/MojangWrapper1_21_R4.java
new file mode 100644
index 00000000..e47b5b6a
--- /dev/null
+++ b/Mojang1_21_R4/src/main/java/net/wesjd/anvilgui/version/MojangWrapper1_21_R4.java
@@ -0,0 +1,158 @@
+package net.wesjd.anvilgui.version;
+
+import net.minecraft.core.BlockPos;
+import net.minecraft.core.RegistryAccess;
+import net.minecraft.core.component.DataComponents;
+import net.minecraft.network.chat.Component;
+import net.minecraft.network.protocol.game.ClientboundContainerClosePacket;
+import net.minecraft.network.protocol.game.ClientboundOpenScreenPacket;
+import net.minecraft.network.protocol.game.ClientboundSetExperiencePacket;
+import net.minecraft.server.level.ServerPlayer;
+import net.minecraft.world.Container;
+import net.minecraft.world.inventory.*;
+import org.bukkit.craftbukkit.CraftWorld;
+import org.bukkit.craftbukkit.entity.CraftPlayer;
+import org.bukkit.craftbukkit.event.CraftEventFactory;
+import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.InventoryCloseEvent;
+import org.bukkit.inventory.Inventory;
+import org.jetbrains.annotations.NotNull;
+
+public final class MojangWrapper1_21_R4 implements VersionWrapper {
+ private int getRealNextContainerId(Player player) {
+ return toNMS(player).nextContainerCounter();
+ }
+
+ /**
+ * Turns a {@link Player} into an NMS one
+ *
+ * @param player The player to be converted
+ * @return the NMS EntityPlayer
+ */
+ private ServerPlayer toNMS(Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ @Override
+ public int getNextContainerId(Player player, AnvilContainerWrapper container) {
+ return ((AnvilContainer) container).getContainerId();
+ }
+
+ @Override
+ public void handleInventoryCloseEvent(Player player) {
+ CraftEventFactory.handleInventoryCloseEvent(toNMS(player), InventoryCloseEvent.Reason.UNKNOWN);
+ toNMS(player).doCloseContainer(); // p -> doCloseContainer
+ }
+
+ @Override
+ public void sendPacketOpenWindow(Player player, int containerId, Object inventoryTitle) {
+ toNMS(player).connection.send(new ClientboundOpenScreenPacket(containerId, MenuType.ANVIL, (Component)
+ inventoryTitle));
+ }
+
+ @Override
+ public void sendPacketCloseWindow(Player player, int containerId) {
+ toNMS(player).connection.send(new ClientboundContainerClosePacket(containerId));
+ }
+
+ @Override
+ public void sendPacketExperienceChange(Player player, int experienceLevel) {
+ toNMS(player).connection.send(new ClientboundSetExperiencePacket(0f, 0, experienceLevel));
+ }
+
+ @Override
+ public void setActiveContainerDefault(Player player) {
+ toNMS(player).containerMenu = toNMS(player).inventoryMenu; // bR -> containerMenu, bQ -> inventoryMenu
+ }
+
+ @Override
+ public void setActiveContainer(Player player, AnvilContainerWrapper container) {
+ toNMS(player).containerMenu = (AbstractContainerMenu) container;
+ }
+
+ @Override
+ public void setActiveContainerId(AnvilContainerWrapper container, int containerId) {}
+
+ @Override
+ public void addActiveContainerSlotListener(AnvilContainerWrapper container, Player player) {
+ toNMS(player).initMenu((AbstractContainerMenu) container);
+ }
+
+ @Override
+ public AnvilContainerWrapper newContainerAnvil(Player player, Object title) {
+ return new AnvilContainer(player, getRealNextContainerId(player), (Component) title);
+ }
+
+ @Override
+ public Object literalChatComponent(String content) {
+ return Component.literal(content); // IChatBaseComponent.b -> Component.literal
+ }
+
+ @Override
+ public Object jsonChatComponent(String json) {
+ return Component.Serializer.fromJson(json, RegistryAccess.EMPTY);
+ }
+
+ private static class AnvilContainer extends AnvilMenu implements AnvilContainerWrapper {
+ public AnvilContainer(Player player, int containerId, Component guiTitle) {
+ super(
+ containerId,
+ ((CraftPlayer) player).getHandle().getInventory(),
+ ContainerLevelAccess.create(((CraftWorld) player.getWorld()).getHandle(), new BlockPos(0, 0, 0)));
+ this.checkReachable = false;
+ setTitle(guiTitle);
+ }
+
+ @Override
+ public void createResult() {
+ // If the output is empty copy the left input into the output
+ Slot output = this.getSlot(2); // b -> getSlot
+ if (!output.hasItem()) { // h -> hasItem
+ output.set(this.getSlot(0).getItem().copy()); // f -> set, g -> getItem, v -> copy
+ }
+
+ this.cost.set(0); // y -> cost, a -> set
+
+ // Sync to the client
+ this.sendAllDataToRemote(); // b -> sendAllDataToRemote
+ this.broadcastChanges(); // d -> broadcastChanges
+ }
+
+ @Override
+ public void removed(net.minecraft.world.entity.player.@NotNull Player player) {}
+
+ @Override
+ protected void clearContainer(
+ net.minecraft.world.entity.player.@NotNull Player player, @NotNull Container container) {}
+
+ public int getContainerId() {
+ return this.containerId;
+ }
+
+ @Override
+ public String getRenameText() {
+ return this.itemName;
+ }
+
+ @Override
+ public void setRenameText(String text) {
+ // If an item is present in the left input slot change its hover name to the literal text.
+ Slot inputLeft = getSlot(0);
+ if (inputLeft.hasItem()) {
+ inputLeft
+ .getItem()
+ .set(
+ DataComponents.CUSTOM_NAME,
+ Component.literal(text)); // DataComponents.g -> DataComponents.CUSTOM_NAME
+ }
+ }
+
+ @Override
+ public Inventory getBukkitInventory() {
+ // NOTE: We need to call Container#getBukkitView() instead of ContainerAnvil#getBukkitView()
+ // because ContainerAnvil#getBukkitView() had an ABI breakage in the middle of the Minecraft 1.21
+ // development cycle for Spigot. For more info, see: https://github.com/WesJD/AnvilGUI/issues/342
+ return ((AbstractContainerMenu) this).getBukkitView().getTopInventory();
+ }
+ }
+}
diff --git a/api/src/main/java/net/wesjd/anvilgui/version/VersionMatcher.java b/api/src/main/java/net/wesjd/anvilgui/version/VersionMatcher.java
index e0c9feca..c996b0cf 100644
--- a/api/src/main/java/net/wesjd/anvilgui/version/VersionMatcher.java
+++ b/api/src/main/java/net/wesjd/anvilgui/version/VersionMatcher.java
@@ -49,8 +49,11 @@ public VersionWrapper match() {
rVersion = craftBukkitPackage.split("\\.")[3].substring(1);
}
+ boolean isMojMap = isMojangMapped(rVersion);
+ String wrapperPrefix = isMojMap ? "MojangWrapper" : "Wrapper";
+
try {
- return (VersionWrapper) Class.forName(getClass().getPackage().getName() + ".Wrapper" + rVersion)
+ return (VersionWrapper) Class.forName(getClass().getPackage().getName() + "." + wrapperPrefix + rVersion)
.getDeclaredConstructor()
.newInstance();
} catch (ClassNotFoundException exception) {
@@ -59,4 +62,18 @@ public VersionWrapper match() {
throw new IllegalStateException("Failed to instantiate version wrapper for version " + rVersion, exception);
}
}
+
+ private static boolean isMojangMapped(String version) {
+ try {
+ Class.forName("com.destroystokyo.paper.ParticleBuilder");
+ } catch (ClassNotFoundException ignored) {
+ return false;
+ }
+
+ final String[] versionNumbers = version.replace("R", "").split("_");
+ int major = Integer.parseInt(versionNumbers[1]);
+ int minor = versionNumbers.length > 2 ? Integer.parseInt(versionNumbers[2]) : 0;
+ if (major == 20 && minor == 4) return true; // 1.20.5/6
+ return major > 20; // >= 1.21
+ }
}
diff --git a/pom.xml b/pom.xml
index 9d39c944..3fea6ea8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -49,6 +49,7 @@
1_21_R2
1_21_R3
1_21_R4
+ Mojang1_21_R4
From 33c5a8b748e20a210de01c6f1da2ebd03d726c3f Mon Sep 17 00:00:00 2001
From: BoBkiNN <78136575+BoBkiNN@users.noreply.github.com>
Date: Sun, 22 Jun 2025 22:59:10 +0500
Subject: [PATCH 2/8] use normal wrapper if failed to find mojang
---
.../wesjd/anvilgui/version/VersionMatcher.java | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/api/src/main/java/net/wesjd/anvilgui/version/VersionMatcher.java b/api/src/main/java/net/wesjd/anvilgui/version/VersionMatcher.java
index c996b0cf..f2810172 100644
--- a/api/src/main/java/net/wesjd/anvilgui/version/VersionMatcher.java
+++ b/api/src/main/java/net/wesjd/anvilgui/version/VersionMatcher.java
@@ -50,10 +50,9 @@ public VersionWrapper match() {
}
boolean isMojMap = isMojangMapped(rVersion);
- String wrapperPrefix = isMojMap ? "MojangWrapper" : "Wrapper";
try {
- return (VersionWrapper) Class.forName(getClass().getPackage().getName() + "." + wrapperPrefix + rVersion)
+ return (VersionWrapper) getWrapperClass(rVersion, isMojMap)
.getDeclaredConstructor()
.newInstance();
} catch (ClassNotFoundException exception) {
@@ -63,6 +62,18 @@ public VersionWrapper match() {
}
}
+ private Class> getWrapperClass(String version, boolean isMojMap) throws ClassNotFoundException {
+ String pkg = getClass().getPackage().getName();
+ if (isMojMap) { // if mojang-mapped server, use MojangWrapper
+ try {
+ return Class.forName(pkg+".MojangWrapper"+version);
+ } catch (ClassNotFoundException ignored) {
+ }
+ }
+ // then try usual wrapper
+ return Class.forName(pkg+".Wrapper"+version);
+ }
+
private static boolean isMojangMapped(String version) {
try {
Class.forName("com.destroystokyo.paper.ParticleBuilder");
From 0072e53564a1222736569d255f8a30992fb1feed Mon Sep 17 00:00:00 2001
From: BoBkiNN <78136575+BoBkiNN@users.noreply.github.com>
Date: Sun, 22 Jun 2025 23:00:21 +0500
Subject: [PATCH 3/8] add comments
---
.../main/java/net/wesjd/anvilgui/version/VersionMatcher.java | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/api/src/main/java/net/wesjd/anvilgui/version/VersionMatcher.java b/api/src/main/java/net/wesjd/anvilgui/version/VersionMatcher.java
index f2810172..aa746e66 100644
--- a/api/src/main/java/net/wesjd/anvilgui/version/VersionMatcher.java
+++ b/api/src/main/java/net/wesjd/anvilgui/version/VersionMatcher.java
@@ -75,12 +75,13 @@ private Class> getWrapperClass(String version, boolean isMojMap) throws ClassN
}
private static boolean isMojangMapped(String version) {
+ // firstly check for paper
try {
Class.forName("com.destroystokyo.paper.ParticleBuilder");
} catch (ClassNotFoundException ignored) {
return false;
}
-
+ // then check version
final String[] versionNumbers = version.replace("R", "").split("_");
int major = Integer.parseInt(versionNumbers[1]);
int minor = versionNumbers.length > 2 ? Integer.parseInt(versionNumbers[2]) : 0;
From d551d8547aded28fff97b6671cc70c272d17341c Mon Sep 17 00:00:00 2001
From: BoBkiNN <78136575+BoBkiNN@users.noreply.github.com>
Date: Sun, 22 Jun 2025 23:02:17 +0500
Subject: [PATCH 4/8] apply spotless
---
.../java/net/wesjd/anvilgui/version/VersionMatcher.java | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/api/src/main/java/net/wesjd/anvilgui/version/VersionMatcher.java b/api/src/main/java/net/wesjd/anvilgui/version/VersionMatcher.java
index aa746e66..c06caf3e 100644
--- a/api/src/main/java/net/wesjd/anvilgui/version/VersionMatcher.java
+++ b/api/src/main/java/net/wesjd/anvilgui/version/VersionMatcher.java
@@ -52,9 +52,8 @@ public VersionWrapper match() {
boolean isMojMap = isMojangMapped(rVersion);
try {
- return (VersionWrapper) getWrapperClass(rVersion, isMojMap)
- .getDeclaredConstructor()
- .newInstance();
+ return (VersionWrapper)
+ getWrapperClass(rVersion, isMojMap).getDeclaredConstructor().newInstance();
} catch (ClassNotFoundException exception) {
throw new IllegalStateException("AnvilGUI does not support server version \"" + rVersion + "\"", exception);
} catch (ReflectiveOperationException exception) {
@@ -66,12 +65,12 @@ private Class> getWrapperClass(String version, boolean isMojMap) throws ClassN
String pkg = getClass().getPackage().getName();
if (isMojMap) { // if mojang-mapped server, use MojangWrapper
try {
- return Class.forName(pkg+".MojangWrapper"+version);
+ return Class.forName(pkg + ".MojangWrapper" + version);
} catch (ClassNotFoundException ignored) {
}
}
// then try usual wrapper
- return Class.forName(pkg+".Wrapper"+version);
+ return Class.forName(pkg + ".Wrapper" + version);
}
private static boolean isMojangMapped(String version) {
From a4aabb5483d775f63cdb436221e6295a831464a1 Mon Sep 17 00:00:00 2001
From: BoBkiNN <78136575+BoBkiNN@users.noreply.github.com>
Date: Sun, 22 Jun 2025 23:14:33 +0500
Subject: [PATCH 5/8] include 1.21.4 mojang artifact
---
api/pom.xml | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/api/pom.xml b/api/pom.xml
index ff04ccfb..1fabef7b 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -223,6 +223,12 @@
${project.parent.version}
compile
+
+ net.wesjd
+ anvilgui-1_21_R4-mojang
+ ${project.parent.version}
+ compile
+
org.geysermc.geyser
api
From 4aff78f130f2ffe63006c7674350961e4d763fba Mon Sep 17 00:00:00 2001
From: BoBkiNN <78136575+BoBkiNN@users.noreply.github.com>
Date: Sun, 22 Jun 2025 23:33:55 +0500
Subject: [PATCH 6/8] update version of mojang 1.21.5
---
Mojang1_21_R4/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Mojang1_21_R4/pom.xml b/Mojang1_21_R4/pom.xml
index 57152a04..7609ab76 100644
--- a/Mojang1_21_R4/pom.xml
+++ b/Mojang1_21_R4/pom.xml
@@ -7,7 +7,7 @@
net.wesjd
anvilgui-parent
- 1.10.5-SNAPSHOT
+ 1.10.6-SNAPSHOT
anvilgui-1_21_R4-mojang
From 1629106ba1505b0c1e1038527263452bc7f08933 Mon Sep 17 00:00:00 2001
From: BoBkiNN <78136575+BoBkiNN@users.noreply.github.com>
Date: Sun, 22 Jun 2025 23:54:11 +0500
Subject: [PATCH 7/8] update gitignore to include .paper-nms
---
.gitignore | 3 +++
1 file changed, 3 insertions(+)
diff --git a/.gitignore b/.gitignore
index a528356f..e2c8d4ac 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,3 +17,6 @@ src/libs
*/google-java-format.xml
dependency-reduced-pom.xml
+
+# paper-nms:init task temporary folder
+.paper-nms/
\ No newline at end of file
From 71db8ccb9289af3bf8ef4257257fbb4a6adb3df1 Mon Sep 17 00:00:00 2001
From: BoBkiNN <78136575+BoBkiNN@users.noreply.github.com>
Date: Mon, 23 Jun 2025 00:01:31 +0500
Subject: [PATCH 8/8] update paper-nms maven plugin to support dev bundle ver 7
---
Mojang1_21_R4/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Mojang1_21_R4/pom.xml b/Mojang1_21_R4/pom.xml
index 7609ab76..3c25ed71 100644
--- a/Mojang1_21_R4/pom.xml
+++ b/Mojang1_21_R4/pom.xml
@@ -49,7 +49,7 @@
ca.bkaw
paper-nms-maven-plugin
- 1.4.7
+ 1.4.8-SNAPSHOT