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");