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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,6 @@ src/libs
*/google-java-format.xml

dependency-reduced-pom.xml

# paper-nms:init task temporary folder
.paper-nms/
56 changes: 56 additions & 0 deletions Mojang1_21_R4/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>net.wesjd</groupId>
<artifactId>anvilgui-parent</artifactId>
<version>1.10.6-SNAPSHOT</version>
</parent>

<artifactId>anvilgui-1_21_R4-mojang</artifactId>

<dependencies>
<dependency>
<groupId>ca.bkaw</groupId>
<artifactId>paper-nms</artifactId>
<version>1.21.5-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.wesjd</groupId>
<artifactId>anvilgui-abstraction</artifactId>
<version>${project.parent.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>

<pluginRepositories>
<pluginRepository>
<id>bytecode.space</id>
<url>https://repo.bytecode.space/repository/maven-public/</url>
</pluginRepository>
</pluginRepositories>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>21</source>
<target>21</target>
</configuration>
</plugin>
<!-- plugins -> paper-nms -> init-->
<plugin>
<groupId>ca.bkaw</groupId>
<artifactId>paper-nms-maven-plugin</artifactId>
<version>1.4.8-SNAPSHOT</version>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -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();
}
}
}
6 changes: 6 additions & 0 deletions api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,12 @@
<version>${project.parent.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.wesjd</groupId>
<artifactId>anvilgui-1_21_R4-mojang</artifactId>
<version>${project.parent.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.geysermc.geyser</groupId>
<artifactId>api</artifactId>
Expand Down
34 changes: 31 additions & 3 deletions api/src/main/java/net/wesjd/anvilgui/version/VersionMatcher.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,42 @@ public VersionWrapper match() {
rVersion = craftBukkitPackage.split("\\.")[3].substring(1);
}

boolean isMojMap = isMojangMapped(rVersion);

try {
return (VersionWrapper) Class.forName(getClass().getPackage().getName() + ".Wrapper" + rVersion)
.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) {
throw new IllegalStateException("Failed to instantiate version wrapper for version " + rVersion, exception);
}
}

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) {
// 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;
if (major == 20 && minor == 4) return true; // 1.20.5/6
return major > 20; // >= 1.21
}
}
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
<module>1_21_R3</module>
<module>1_21_R4</module>
<module>1_21_R5</module>
<module>Mojang1_21_R4</module>
</modules>

<repositories>
Expand Down