diff --git a/pom.xml b/pom.xml
index 892a65b..ca26e6d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -42,7 +42,7 @@
org.spigotmc
spigot-api
- 1.20.6-R0.1-SNAPSHOT
+ 1.21.1-R0.1-SNAPSHOT
provided
@@ -66,7 +66,7 @@
org.bstats
bstats-bukkit
- 3.0.2
+ 3.1.0
@@ -103,17 +103,17 @@
- com.github.TownyAdvanced
+ com.github.TownyAdvanced.Towny
towny
- 0.100.2.11
+ 0.100.4.4
provided
- com.github.angeschossen
+ com.github.Angeschossen
LandsAPI
- 7.1.12
+ 7.9.17
provided
@@ -121,7 +121,7 @@
org.jetbrains
annotations
- 24.1.0
+ 26.0.0
provided
diff --git a/src/main/java/io/josemmo/bukkit/plugin/packets/MapDataPacket.java b/src/main/java/io/josemmo/bukkit/plugin/packets/MapDataPacket.java
index 734e16f..1fb3496 100644
--- a/src/main/java/io/josemmo/bukkit/plugin/packets/MapDataPacket.java
+++ b/src/main/java/io/josemmo/bukkit/plugin/packets/MapDataPacket.java
@@ -2,17 +2,30 @@
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.events.PacketContainer;
+import com.comphenix.protocol.injector.StructureCache;
+import com.comphenix.protocol.reflect.ExactReflection;
import com.comphenix.protocol.reflect.StructureModifier;
+import com.comphenix.protocol.utility.MinecraftReflection;
import io.josemmo.bukkit.plugin.utils.Internals;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.ParameterizedType;
+import java.util.Optional;
public class MapDataPacket extends PacketContainer {
private static final int LOCKED_INDEX;
+ private static final @Nullable Constructor> MAP_ID_CONSTRUCTOR;
private @Nullable StructureModifier> mapDataModifier;
static {
LOCKED_INDEX = (Internals.MINECRAFT_VERSION < 17) ? 1 : 0;
+ if (Internals.MINECRAFT_VERSION < 20.5) {
+ MAP_ID_CONSTRUCTOR = null;
+ } else {
+ Class> mapIdClass = MinecraftReflection.getNullableNMS("world.level.saveddata.maps.MapId");
+ MAP_ID_CONSTRUCTOR = ExactReflection.fromClass(mapIdClass, true).findConstructor(int.class);
+ }
}
public MapDataPacket() {
@@ -20,18 +33,34 @@ public MapDataPacket() {
getModifier().writeDefaults();
if (Internals.MINECRAFT_VERSION < 17) {
- // Disable tracking position
- getBooleans().write(0, false);
- } else {
- // Create modifier for map data instance
+ getBooleans().write(0, false); // Disable tracking position
+ } else if (Internals.MINECRAFT_VERSION < 20.5) {
Class> mapDataType = getModifier().getField(4).getType();
Object mapDataInstance = getModifier().read(4);
mapDataModifier = new StructureModifier<>(mapDataType).withTarget(mapDataInstance);
+ } else {
+ ParameterizedType genericType = (ParameterizedType) getModifier().getField(4).getGenericType();
+ Class> mapDataType = (Class>) genericType.getActualTypeArguments()[0];
+ Object mapDataInstance = StructureCache.newInstance(mapDataType);
+ getModifier().write(3, Optional.empty());
+ getModifier().write(4, Optional.of(mapDataInstance));
+ mapDataModifier = new StructureModifier<>(mapDataType).withTarget(mapDataInstance);
}
}
+ @SuppressWarnings({"unchecked", "rawtypes"})
public @NotNull MapDataPacket setId(int id) {
- getIntegers().write(0, id);
+ if (MAP_ID_CONSTRUCTOR == null) {
+ getIntegers().write(0, id);
+ } else {
+ try {
+ Class> mapIdClass = MAP_ID_CONSTRUCTOR.getDeclaringClass();
+ Object mapIdInstance = MAP_ID_CONSTRUCTOR.newInstance(id);
+ ((StructureModifier) getSpecificModifier(mapIdClass)).write(0, mapIdInstance);
+ } catch (Exception e) {
+ throw new RuntimeException("Failed to instantiate MapId for map #" + id);
+ }
+ }
return this;
}
diff --git a/src/main/java/io/josemmo/bukkit/plugin/renderer/FakeEntity.java b/src/main/java/io/josemmo/bukkit/plugin/renderer/FakeEntity.java
index a503653..f39783b 100644
--- a/src/main/java/io/josemmo/bukkit/plugin/renderer/FakeEntity.java
+++ b/src/main/java/io/josemmo/bukkit/plugin/renderer/FakeEntity.java
@@ -88,7 +88,11 @@ protected static void tryToSendPacket(@NotNull Player player, @NotNull PacketCon
if (NETWORK_MANAGER_INJECTOR == null) { // Use single-threaded packet sending if reflection failed
CONNECTION.sendServerPacket(player, packet);
} else { // Use non-blocking packet sending if available (faster, the expected case)
- NETWORK_MANAGER_INJECTOR.getInjector(player).sendClientboundPacket(packet, null, false);
+ NETWORK_MANAGER_INJECTOR.getInjector(player).sendClientboundPacket(
+ packet.getHandle(),
+ null,
+ false
+ );
}
} catch (IllegalStateException e) {
// Server is shutting down and cannot send the packet, ignore
diff --git a/src/main/java/io/josemmo/bukkit/plugin/utils/Internals.java b/src/main/java/io/josemmo/bukkit/plugin/utils/Internals.java
index 4bcb955..bb13820 100644
--- a/src/main/java/io/josemmo/bukkit/plugin/utils/Internals.java
+++ b/src/main/java/io/josemmo/bukkit/plugin/utils/Internals.java
@@ -1,14 +1,16 @@
package io.josemmo.bukkit.plugin.utils;
-import com.mojang.brigadier.CommandDispatcher;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
import org.bukkit.Bukkit;
import org.bukkit.Server;
import org.bukkit.command.CommandMap;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
+import com.comphenix.protocol.reflect.FuzzyReflection;
+import com.comphenix.protocol.utility.MinecraftReflection;
+import com.mojang.brigadier.CommandDispatcher;
public class Internals {
public static final float MINECRAFT_VERSION;
@@ -28,28 +30,22 @@ public class Internals {
Class> obcClass = obcInstance.getClass();
// Get "net.minecraft.server.MinecraftServer" references
- Object nmsInstance = obcClass.getDeclaredMethod("getServer").invoke(obcInstance);
- Class> nmsClass = nmsInstance.getClass().getSuperclass();
+ Object nmsServerInstance = obcClass.getDeclaredMethod("getServer").invoke(obcInstance);
- if (MINECRAFT_VERSION >= 20.5) {
- // Get "net.minecraft.commands.Commands" references
- Object nmsCommandsInstance = nmsClass.getDeclaredMethod("getCommands").invoke(nmsInstance);
- Class> nmsCommandsClass = nmsCommandsInstance.getClass();
+ // Get "net.minecraft.server.CommandDispatcher" references
+ Class> nmsDispatcherClass = MinecraftReflection.getMinecraftClass(
+ "CommandDispatcher", // Spigot <1.17
+ "commands.CommandDispatcher", // Spigot >=1.17
+ "commands.Commands" // PaperMC
+ );
+ Object nmsDispatcherInstance = FuzzyReflection.fromObject(nmsServerInstance, true)
+ .getMethodByReturnTypeAndParameters("getDispatcher", nmsDispatcherClass)
+ .invoke(nmsServerInstance);
- // Get "com.mojang.brigadier.CommandDispatcher" instance
- Field nmsDispatcherField = nmsCommandsClass.getDeclaredField("dispatcher");
- nmsDispatcherField.setAccessible(true);
- DISPATCHER = (CommandDispatcher>) nmsDispatcherField.get(nmsCommandsInstance);
- } else {
- // Get "net.minecraft.server.CommandDispatcher" references
- Object nmsDispatcherInstance = nmsClass.getDeclaredField("vanillaCommandDispatcher").get(nmsInstance);
- Class> nmsDispatcherClass = nmsDispatcherInstance.getClass();
-
- // Get "com.mojang.brigadier.CommandDispatcher" instance
- Method getDispatcherMethod = nmsDispatcherClass.getDeclaredMethod("a");
- getDispatcherMethod.setAccessible(true);
- DISPATCHER = (CommandDispatcher>) getDispatcherMethod.invoke(nmsDispatcherInstance);
- }
+ // Get "com.mojang.brigadier.CommandDispatcher" instance
+ DISPATCHER = (CommandDispatcher>) FuzzyReflection.fromObject(nmsDispatcherInstance, true)
+ .getMethodByReturnTypeAndParameters("getDispatcher", CommandDispatcher.class)
+ .invoke(nmsDispatcherInstance);
// Get command map instance
Field commandMapField = obcClass.getDeclaredField("commandMap");