Skip to content

Commit

Permalink
Merge pull request #137 from Ingrim4/feat/support-1.21
Browse files Browse the repository at this point in the history
Add support for 1.20.6/1.21
  • Loading branch information
josemmo authored Oct 13, 2024
2 parents 0e678dd + 955c7c2 commit 055eced
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 36 deletions.
14 changes: 7 additions & 7 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.20.6-R0.1-SNAPSHOT</version>
<version>1.21.1-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>

Expand All @@ -66,7 +66,7 @@
<dependency>
<groupId>org.bstats</groupId>
<artifactId>bstats-bukkit</artifactId>
<version>3.0.2</version>
<version>3.1.0</version>
</dependency>

<!-- https://central.sonatype.com/artifact/net.luckperms/api -->
Expand Down Expand Up @@ -103,25 +103,25 @@

<!-- https://jitpack.io/com/github/TownyAdvanced/towny/ -->
<dependency>
<groupId>com.github.TownyAdvanced</groupId>
<groupId>com.github.TownyAdvanced.Towny</groupId>
<artifactId>towny</artifactId>
<version>0.100.2.11</version>
<version>0.100.4.4</version>
<scope>provided</scope>
</dependency>

<!-- https://jitpack.io/com/github/Angeschossen/LandsAPI/ -->
<dependency>
<groupId>com.github.angeschossen</groupId>
<groupId>com.github.Angeschossen</groupId>
<artifactId>LandsAPI</artifactId>
<version>7.1.12</version>
<version>7.9.17</version>
<scope>provided</scope>
</dependency>

<!-- https://central.sonatype.com/artifact/org.jetbrains/annotations -->
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId>
<version>24.1.0</version>
<version>26.0.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
Expand Down
39 changes: 34 additions & 5 deletions src/main/java/io/josemmo/bukkit/plugin/packets/MapDataPacket.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,65 @@

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() {
super(PacketType.Play.Server.MAP);
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;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
42 changes: 19 additions & 23 deletions src/main/java/io/josemmo/bukkit/plugin/utils/Internals.java
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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");
Expand Down

0 comments on commit 055eced

Please sign in to comment.