diff --git a/spigot/src/main/java/org/geysermc/floodgate/util/ClassNames.java b/spigot/src/main/java/org/geysermc/floodgate/util/ClassNames.java index 52be11ea..14072a64 100644 --- a/spigot/src/main/java/org/geysermc/floodgate/util/ClassNames.java +++ b/spigot/src/main/java/org/geysermc/floodgate/util/ClassNames.java @@ -60,7 +60,9 @@ public class ClassNames { public static final Class LOGIN_LISTENER; @Nullable public static final Class CLIENT_INTENT; - public static final Constructor CRAFT_OFFLINE_PLAYER_CONSTRUCTOR; + @Nullable public static final Constructor CRAFT_OFFLINE_PLAYER_CONSTRUCTOR; + @Nullable public static final Constructor CRAFT_NEW_OFFLINE_PLAYER_CONSTRUCTOR; + @Nullable public static final Constructor NAME_AND_ID_CONSTRUCTOR; @Nullable public static final Constructor LOGIN_HANDLER_CONSTRUCTOR; @Nullable public static final Constructor HANDSHAKE_PACKET_CONSTRUCTOR; @@ -159,6 +161,18 @@ public class ClassNames { CRAFT_OFFLINE_PLAYER_CONSTRUCTOR = ReflectionUtils.getConstructor( craftOfflinePlayerClass, true, craftServerClass, GameProfile.class); + if (CRAFT_OFFLINE_PLAYER_CONSTRUCTOR == null) { // Changed in 1.21.9 + Class nameAndIdClass = getClassSilently("net.minecraft.server.players.NameAndId"); + + CRAFT_NEW_OFFLINE_PLAYER_CONSTRUCTOR = ReflectionUtils.getConstructor( + craftOfflinePlayerClass, true, craftServerClass, nameAndIdClass); + + NAME_AND_ID_CONSTRUCTOR = ReflectionUtils.getConstructor(nameAndIdClass, true, GameProfile.class); + } else { + CRAFT_NEW_OFFLINE_PLAYER_CONSTRUCTOR = null; + NAME_AND_ID_CONSTRUCTOR = null; + } + // SpigotDataHandler Class networkManager = getClassOrFallback( "net.minecraft.network.Connection", diff --git a/spigot/src/main/java/org/geysermc/floodgate/util/WhitelistUtils.java b/spigot/src/main/java/org/geysermc/floodgate/util/WhitelistUtils.java index 3e675d64..9ddedd28 100644 --- a/spigot/src/main/java/org/geysermc/floodgate/util/WhitelistUtils.java +++ b/spigot/src/main/java/org/geysermc/floodgate/util/WhitelistUtils.java @@ -29,6 +29,7 @@ import com.mojang.authlib.GameProfile; import java.util.UUID; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; +import org.bukkit.Server; @SuppressWarnings("ConstantConditions") public final class WhitelistUtils { @@ -44,10 +45,7 @@ public final class WhitelistUtils { public static boolean addPlayer(UUID uuid, String username, SpigotVersionSpecificMethods versionSpecificMethods) { GameProfile profile = new GameProfile(uuid, username); - OfflinePlayer player = ReflectionUtils.newInstance( - ClassNames.CRAFT_OFFLINE_PLAYER_CONSTRUCTOR, - Bukkit.getServer(), profile - ); + OfflinePlayer player = getOfflinePlayer(profile); if (player.isWhitelisted()) { return false; } @@ -67,10 +65,7 @@ public final class WhitelistUtils { public static boolean removePlayer(UUID uuid, String username, SpigotVersionSpecificMethods versionSpecificMethods) { GameProfile profile = new GameProfile(uuid, username); - OfflinePlayer player = ReflectionUtils.newInstance( - ClassNames.CRAFT_OFFLINE_PLAYER_CONSTRUCTOR, - Bukkit.getServer(), profile - ); + OfflinePlayer player = getOfflinePlayer(profile); if (!player.isWhitelisted()) { return false; } @@ -81,4 +76,23 @@ public final class WhitelistUtils { static void setWhitelist(OfflinePlayer player, boolean whitelist, SpigotVersionSpecificMethods versionSpecificMethods) { versionSpecificMethods.maybeSchedule(() -> player.setWhitelisted(whitelist), true); // Whitelisting is on the global thread } + + static OfflinePlayer getOfflinePlayer(GameProfile profile) { + if (ClassNames.CRAFT_NEW_OFFLINE_PLAYER_CONSTRUCTOR != null) { + Object nameAndId = ReflectionUtils.newInstance( + ClassNames.NAME_AND_ID_CONSTRUCTOR, + profile + ); + + return ReflectionUtils.newInstance( + ClassNames.CRAFT_NEW_OFFLINE_PLAYER_CONSTRUCTOR, + Bukkit.getServer(), nameAndId + ); + } else { + return ReflectionUtils.newInstance( + ClassNames.CRAFT_OFFLINE_PLAYER_CONSTRUCTOR, + Bukkit.getServer(), profile + ); + } + } }