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