1
0
mirror of https://github.com/GeyserMC/Floodgate.git synced 2025-12-19 14:59:20 +00:00

Merge master

This commit is contained in:
Aurora
2025-10-03 17:04:02 +01:00
3 changed files with 46 additions and 31 deletions

View File

@@ -30,6 +30,7 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.Arrays;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
@@ -135,31 +136,31 @@ public final class ReflectionUtils {
return clazz; return clazz;
} }
public static Class<?> getClassOrFallback(String className, String fallbackClassName1, String fallbackClassName2) { public static Class<?> getClassOrFallback(String... classNames) {
Class<?> clazz = getClassSilently(className); for (String className : classNames) {
Class<?> clazz = getClassSilently(className);
if (clazz != null) { if (clazz != null) {
if (Constants.DEBUG_MODE) { if (Constants.DEBUG_MODE) {
System.out.println("Found class (primary): " + clazz.getName()); System.out.println("Found class: " + clazz.getName() + " for choices: " +
Arrays.toString(classNames));
}
return clazz;
} }
return clazz;
} }
clazz = getClassSilently(fallbackClassName1); throw new IllegalStateException("Could not find class between these choices: " +
Arrays.toString(classNames));
}
if (clazz != null) { @Nullable
if (Constants.DEBUG_MODE) { public static Class<?> getClassOrFallbackSilently(String... classNames) {
System.out.println("Found class (fallback1): " + clazz.getName()); for (String className : classNames) {
Class<?> clazz = getClassSilently(className);
if (clazz != null) {
return clazz;
} }
return clazz;
} }
return null;
// do throw an exception when both classes couldn't be found
clazz = ReflectionUtils.getClassOrThrow(fallbackClassName2);
if (Constants.DEBUG_MODE) {
System.out.println("Found class (fallback2): " + clazz.getName());
}
return clazz;
} }
@Nullable @Nullable

View File

@@ -25,12 +25,11 @@
package org.geysermc.floodgate.pluginmessage; package org.geysermc.floodgate.pluginmessage;
import com.google.common.collect.Multimap;
import com.google.common.collect.MultimapBuilder;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.Singleton; import com.google.inject.Singleton;
import com.mojang.authlib.GameProfile; import com.mojang.authlib.GameProfile;
import com.mojang.authlib.properties.Property; import com.mojang.authlib.properties.Property;
import com.mojang.authlib.properties.PropertyMap;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
@@ -87,7 +86,12 @@ public final class SpigotSkinApplier implements SkinApplier {
return; return;
} }
replaceSkin(player, floodgatePlayer, event.newSkin()); if (ClassNames.GAME_PROFILE_FIELD != null) {
replaceSkin(player, floodgatePlayer, event.newSkin());
} else {
// We're on a version with mutable GameProfiles
replaceSkinOld(profile.getProperties(), event.newSkin());
}
versionSpecificMethods.maybeSchedule(() -> { versionSpecificMethods.maybeSchedule(() -> {
for (Player p : Bukkit.getOnlinePlayers()) { for (Player p : Bukkit.getOnlinePlayers()) {
@@ -105,4 +109,10 @@ public final class SpigotSkinApplier implements SkinApplier {
Object entityHuman = ReflectionUtils.invoke(player, ClassNames.GET_ENTITY_HUMAN_METHOD); Object entityHuman = ReflectionUtils.invoke(player, ClassNames.GET_ENTITY_HUMAN_METHOD);
ReflectionUtils.setValue(entityHuman, ClassNames.GAME_PROFILE_FIELD, profile); ReflectionUtils.setValue(entityHuman, ClassNames.GAME_PROFILE_FIELD, profile);
} }
private void replaceSkinOld(PropertyMap properties, SkinData skinData) {
properties.removeAll("textures");
Property property = new Property("textures", skinData.value(), skinData.signature());
properties.put("textures", property);
}
} }

View File

@@ -28,6 +28,7 @@ package org.geysermc.floodgate.util;
import static org.geysermc.floodgate.util.ReflectionUtils.castedStaticBooleanValue; import static org.geysermc.floodgate.util.ReflectionUtils.castedStaticBooleanValue;
import static org.geysermc.floodgate.util.ReflectionUtils.getBooleanValue; import static org.geysermc.floodgate.util.ReflectionUtils.getBooleanValue;
import static org.geysermc.floodgate.util.ReflectionUtils.getClassOrFallback; import static org.geysermc.floodgate.util.ReflectionUtils.getClassOrFallback;
import static org.geysermc.floodgate.util.ReflectionUtils.getClassOrFallbackSilently;
import static org.geysermc.floodgate.util.ReflectionUtils.getClassSilently; import static org.geysermc.floodgate.util.ReflectionUtils.getClassSilently;
import static org.geysermc.floodgate.util.ReflectionUtils.getConstructor; import static org.geysermc.floodgate.util.ReflectionUtils.getConstructor;
import static org.geysermc.floodgate.util.ReflectionUtils.getField; import static org.geysermc.floodgate.util.ReflectionUtils.getField;
@@ -77,8 +78,8 @@ public class ClassNames {
public static final Method GET_PROFILE_METHOD; public static final Method GET_PROFILE_METHOD;
public static final Method GET_ENTITY_HUMAN_METHOD; @Nullable public static final Method GET_ENTITY_HUMAN_METHOD;
public static final Field GAME_PROFILE_FIELD; @Nullable public static final Field GAME_PROFILE_FIELD;
public static final Method LOGIN_DISCONNECT; public static final Method LOGIN_DISCONNECT;
public static final Method NETWORK_EXCEPTION_CAUGHT; public static final Method NETWORK_EXCEPTION_CAUGHT;
@@ -122,13 +123,16 @@ public class ClassNames {
checkNotNull(GET_PROFILE_METHOD, "Get profile method"); checkNotNull(GET_PROFILE_METHOD, "Get profile method");
GET_ENTITY_HUMAN_METHOD = getMethod(craftPlayerClass, "getHandle"); GET_ENTITY_HUMAN_METHOD = getMethod(craftPlayerClass, "getHandle");
checkNotNull(GET_ENTITY_HUMAN_METHOD, "getHandle method"); Class<?> entityHumanClass = getClassOrFallbackSilently(
Class<?> entityHumanClass = getClassOrFallback("net.minecraft.world.entity.player.EntityHuman", "net.minecraft.world.entity.player.EntityHuman",
"net.minecraft.world.entity.player.Player"); "net.minecraft.world.entity.player.Player"
checkNotNull(entityHumanClass, "EntityHuman class"); );
// Since 1.21.9: Spigot obfuscates field name if (entityHumanClass != null) {
GAME_PROFILE_FIELD = getFieldOfType(entityHumanClass, GameProfile.class); // Spigot obfuscates field name
checkNotNull(GAME_PROFILE_FIELD, "EntityHuman.gameProfile field"); GAME_PROFILE_FIELD = getFieldOfType(entityHumanClass, GameProfile.class);
} else {
GAME_PROFILE_FIELD = null;
}
// SpigotInjector // SpigotInjector
MINECRAFT_SERVER = getClassOrFallback( MINECRAFT_SERVER = getClassOrFallback(