mirror of
https://github.com/GeyserMC/Floodgate.git
synced 2025-12-28 02:59:16 +00:00
Works on 1.21.9
This commit is contained in:
@@ -151,6 +151,15 @@ public final class ReflectionUtils {
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static <T> T newInstanceOrThrow(Constructor<T> constructor, Object... parameters) {
|
||||
try {
|
||||
return constructor.newInstance(parameters);
|
||||
} catch (IllegalAccessException | InstantiationException | InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static <T> T newInstance(Constructor<T> constructor, Object... parameters) {
|
||||
try {
|
||||
|
||||
@@ -28,8 +28,6 @@ package org.geysermc.floodgate.addon.data;
|
||||
import static org.geysermc.floodgate.util.ReflectionUtils.getCastedValue;
|
||||
import static org.geysermc.floodgate.util.ReflectionUtils.setValue;
|
||||
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.MultimapBuilder;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.authlib.properties.Property;
|
||||
import io.netty.channel.Channel;
|
||||
@@ -181,16 +179,15 @@ public final class SpigotDataHandler extends CommonDataHandler {
|
||||
}
|
||||
}
|
||||
|
||||
Multimap<String, Property> properties = MultimapBuilder.hashKeys().arrayListValues().build();
|
||||
|
||||
Property texturesProperty = null;
|
||||
if (!player.isLinked()) {
|
||||
// Otherwise game server will try to fetch the skin from Mojang.
|
||||
// No need to worry that this overrides proxy data, because those won't reach this
|
||||
// method / are already removed (in the case of username validation)
|
||||
properties.put("textures", DEFAULT_TEXTURE_PROPERTY);
|
||||
texturesProperty = DEFAULT_TEXTURE_PROPERTY;
|
||||
}
|
||||
GameProfile gameProfile = versionSpecificMethods.createGameProfile(
|
||||
player.getCorrectUniqueId(), player.getCorrectUsername(), properties);
|
||||
player.getCorrectUniqueId(), player.getCorrectUsername(), texturesProperty);
|
||||
|
||||
// we have to fake the offline player (login) cycle
|
||||
|
||||
|
||||
@@ -99,10 +99,9 @@ public final class SpigotSkinApplier implements SkinApplier {
|
||||
}
|
||||
|
||||
private void replaceSkin(Player player, FloodgatePlayer floodgatePlayer, SkinData skinData) {
|
||||
Multimap<String, Property> newProperties = MultimapBuilder.hashKeys().arrayListValues().build();
|
||||
newProperties.put("textures", new Property("textures", skinData.value(), skinData.signature()));
|
||||
Property skinProperty = new Property("textures", skinData.value(), skinData.signature());
|
||||
GameProfile profile = versionSpecificMethods.createGameProfile(floodgatePlayer.getCorrectUniqueId(),
|
||||
floodgatePlayer.getCorrectUsername(), newProperties);
|
||||
floodgatePlayer.getCorrectUsername(), skinProperty);
|
||||
Object entityHuman = ReflectionUtils.invoke(player, ClassNames.GET_ENTITY_HUMAN_METHOD);
|
||||
ReflectionUtils.setValue(entityHuman, ClassNames.GAME_PROFILE_FIELD, profile);
|
||||
}
|
||||
|
||||
@@ -124,7 +124,8 @@ public class ClassNames {
|
||||
Class<?> entityHumanClass = getClassOrFallback("net.minecraft.world.entity.player.EntityHuman",
|
||||
"net.minecraft.world.entity.player.Player");
|
||||
checkNotNull(entityHumanClass, "EntityHuman class");
|
||||
GAME_PROFILE_FIELD = getField(entityHumanClass, "gameProfile");
|
||||
// Since 1.21.9: Spigot obfuscates field name
|
||||
GAME_PROFILE_FIELD = getFieldOfType(entityHumanClass, GameProfile.class);
|
||||
checkNotNull(GAME_PROFILE_FIELD, "EntityHuman.gameProfile field");
|
||||
|
||||
// SpigotInjector
|
||||
|
||||
@@ -25,12 +25,13 @@
|
||||
|
||||
package org.geysermc.floodgate.util;
|
||||
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.authlib.properties.Property;
|
||||
import com.mojang.authlib.properties.PropertyMap;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.bukkit.entity.Player;
|
||||
@@ -49,6 +50,7 @@ public final class SpigotVersionSpecificMethods {
|
||||
private static final Method NEW_GAME_PROFILE_PROPERTIES;
|
||||
private static final Constructor<GameProfile> RECORD_GAME_PROFILE_CONSTRUCTOR;
|
||||
private static final Constructor<PropertyMap> IMMUTABLE_PROPERTY_MAP_CONSTRUCTOR;
|
||||
private static final Method MULTIMAP_FROM_MAP;
|
||||
|
||||
static {
|
||||
GET_SPIGOT = ReflectionUtils.getMethod(Player.class, "spigot");
|
||||
@@ -61,11 +63,16 @@ public final class SpigotVersionSpecificMethods {
|
||||
|
||||
NEW_PROPERTY_VALUE = ReflectionUtils.getMethod(Property.class, "value");
|
||||
NEW_PROPERTY_SIGNATURE = ReflectionUtils.getMethod(Property.class, "signature");
|
||||
NEW_GAME_PROFILE_PROPERTIES = ReflectionUtils.getMethod(GameProfile.class, "properties");
|
||||
RECORD_GAME_PROFILE_CONSTRUCTOR = ReflectionUtils.getConstructor(GameProfile.class, true, UUID.class, String.class, PropertyMap.class);
|
||||
// TODO have to do this here because if we get constructor using Multimap.class we try to look for one that takes our
|
||||
// TODO relocated Multimap, which doesn't exist
|
||||
IMMUTABLE_PROPERTY_MAP_CONSTRUCTOR = (Constructor<PropertyMap>) PropertyMap.class.getConstructors()[0];
|
||||
NEW_GAME_PROFILE_PROPERTIES = ReflectionUtils.getMethod(
|
||||
GameProfile.class, "properties");
|
||||
RECORD_GAME_PROFILE_CONSTRUCTOR = ReflectionUtils.getConstructor(
|
||||
GameProfile.class, true, UUID.class, String.class, PropertyMap.class);
|
||||
IMMUTABLE_PROPERTY_MAP_CONSTRUCTOR = (Constructor<PropertyMap>)
|
||||
PropertyMap.class.getConstructors()[0];
|
||||
// Avoid relocation for this class.
|
||||
Class<?> multimaps = ReflectionUtils.getClass(String.join(".", "com",
|
||||
"google", "common", "collect", "Multimaps"));
|
||||
MULTIMAP_FROM_MAP = ReflectionUtils.getMethod(multimaps, "forMap", Map.class);
|
||||
}
|
||||
|
||||
private final SpigotPlugin plugin;
|
||||
@@ -74,15 +81,22 @@ public final class SpigotVersionSpecificMethods {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public GameProfile createGameProfile(UUID uuid, String name, Multimap<String, Property> properties) {
|
||||
public GameProfile createGameProfile(UUID uuid, String name, Property texturesProperty) {
|
||||
if (RECORD_GAME_PROFILE_CONSTRUCTOR != null && IMMUTABLE_PROPERTY_MAP_CONSTRUCTOR != null) {
|
||||
// TODO this breaks, as the passed properties to the IMMUTABLE_PROPERTY_MAP_CONSTRUCTOR
|
||||
// TODO is of our relocated Multimap, and not the one PropertyMap uses
|
||||
return ReflectionUtils.newInstance(RECORD_GAME_PROFILE_CONSTRUCTOR, uuid, name,
|
||||
ReflectionUtils.newInstance(IMMUTABLE_PROPERTY_MAP_CONSTRUCTOR, properties));
|
||||
if (texturesProperty != null) {
|
||||
Map<String, Property> properties = new HashMap<>();
|
||||
properties.put("textures", texturesProperty);
|
||||
Object multimap = ReflectionUtils.invoke(null, MULTIMAP_FROM_MAP, properties);
|
||||
return ReflectionUtils.newInstanceOrThrow(RECORD_GAME_PROFILE_CONSTRUCTOR, uuid,
|
||||
name,
|
||||
ReflectionUtils.newInstanceOrThrow(IMMUTABLE_PROPERTY_MAP_CONSTRUCTOR,
|
||||
multimap));
|
||||
}
|
||||
}
|
||||
GameProfile profile = new GameProfile(uuid, name);
|
||||
profile.getProperties().putAll(properties);
|
||||
if (texturesProperty != null) {
|
||||
profile.getProperties().put("textures", texturesProperty);
|
||||
}
|
||||
return profile;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user