move GameProfile manipulation to reflection

This commit is contained in:
Pyrbu 2023-07-01 00:15:10 +02:00
parent f438d50808
commit 488d098f79
3 changed files with 95 additions and 20 deletions

@ -19,6 +19,10 @@ public class ReflectionBuilder {
private Class<?> expectType; private Class<?> expectType;
private boolean strict = true; private boolean strict = true;
public ReflectionBuilder() {
this("");
}
public ReflectionBuilder(Class<?> clazz) { public ReflectionBuilder(Class<?> clazz) {
this(""); this("");
withClassName(clazz); withClassName(clazz);
@ -40,6 +44,11 @@ public class ReflectionBuilder {
return this; return this;
} }
public ReflectionBuilder withRawClassName(String className) {
this.className.add(className);
return this;
}
public ReflectionBuilder withClassName(Class<?> clazz) { public ReflectionBuilder withClassName(Class<?> clazz) {
if (clazz != null) className.add(clazz.getName()); if (clazz != null) className.add(clazz.getName());
return this; return this;

@ -2,7 +2,6 @@ package lol.pyr.znpcsplus.reflection;
import com.github.retrooper.packetevents.PacketEvents; import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.manager.server.ServerVersion; import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.mojang.authlib.GameProfile;
import lol.pyr.znpcsplus.reflection.types.FieldReflection; import lol.pyr.znpcsplus.reflection.types.FieldReflection;
import lol.pyr.znpcsplus.util.FoliaUtil; import lol.pyr.znpcsplus.util.FoliaUtil;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@ -11,6 +10,7 @@ import org.bukkit.entity.Entity;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.Collection;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer; import java.util.function.Consumer;
@ -20,9 +20,14 @@ import java.util.function.Consumer;
* uses to access inaccessible components of the server jar. * uses to access inaccessible components of the server jar.
*/ */
public final class Reflections { public final class Reflections {
public static final Class<?> ENTITY_CLASS =
new ReflectionBuilder(ReflectionPackage.ENTITY) /*
.withClassName("Entity") * Game profile methods used for obtaining raw skin data of online players
*/
public static final Class<?> GAME_PROFILE_CLASS =
new ReflectionBuilder()
.withRawClassName("com.mojang.authlib.GameProfile")
.toClassReflection().get(); .toClassReflection().get();
public static final Class<?> ENTITY_HUMAN_CLASS = public static final Class<?> ENTITY_HUMAN_CLASS =
@ -31,18 +36,70 @@ public final class Reflections {
.withClassName("EntityHuman") .withClassName("EntityHuman")
.toClassReflection().get(); .toClassReflection().get();
public static final ReflectionLazyLoader<Method> GET_PLAYER_HANDLE_METHOD =
new ReflectionBuilder(ReflectionPackage.BUKKIT)
.withClassName("entity.CraftPlayer")
.withClassName("entity.CraftHumanEntity")
.withMethodName("getHandle")
.withExpectResult(ENTITY_HUMAN_CLASS)
.toMethodReflection();
public static final ReflectionLazyLoader<Method> GET_PROFILE_METHOD = public static final ReflectionLazyLoader<Method> GET_PROFILE_METHOD =
new ReflectionBuilder(ReflectionPackage.ENTITY) new ReflectionBuilder(ReflectionPackage.ENTITY)
.withClassName(ENTITY_HUMAN_CLASS) .withClassName(ENTITY_HUMAN_CLASS)
.withExpectResult(GameProfile.class) .withExpectResult(GAME_PROFILE_CLASS)
.toMethodReflection(); .toMethodReflection();
public static final ReflectionLazyLoader<Method> GET_HANDLE_PLAYER_METHOD = public static final Class<?> PROPERTY_MAP_CLASS =
new ReflectionBuilder(ReflectionPackage.BUKKIT) new ReflectionBuilder()
.withClassName("entity.CraftPlayer").withClassName("entity.CraftHumanEntity") .withRawClassName("com.mojang.authlib.properties.PropertyMap")
.withMethodName("getHandle") .toClassReflection().get();
public static final ReflectionLazyLoader<Method> GET_PROPERTY_MAP_METHOD =
new ReflectionBuilder(GAME_PROFILE_CLASS)
.withMethodName("getProperties")
.withExpectResult(PROPERTY_MAP_CLASS)
.toMethodReflection(); .toMethodReflection();
public static final ReflectionLazyLoader<Method> PROPERTY_MAP_VALUES_METHOD =
new ReflectionBuilder()
.withClassName(PROPERTY_MAP_CLASS.getSuperclass())
.withMethodName("values")
.withExpectResult(Collection.class)
.toMethodReflection();
public static final Class<?> PROPERTY_CLASS =
new ReflectionBuilder()
.withRawClassName("com.mojang.authlib.properties.Property")
.toClassReflection().get();
public static final ReflectionLazyLoader<Method> PROPERTY_GET_NAME_METHOD =
new ReflectionBuilder(PROPERTY_CLASS)
.withMethodName("getName")
.withExpectResult(String.class)
.toMethodReflection();
public static final ReflectionLazyLoader<Method> PROPERTY_GET_VALUE_METHOD =
new ReflectionBuilder(PROPERTY_CLASS)
.withMethodName("getValue")
.withExpectResult(String.class)
.toMethodReflection();
public static final ReflectionLazyLoader<Method> PROPERTY_GET_SIGNATURE_METHOD =
new ReflectionBuilder(PROPERTY_CLASS)
.withMethodName("getSignature")
.withExpectResult(String.class)
.toMethodReflection();
/*
* These methods are used for reserving entity ids so regular Minecraft
* entity packets don't interfere with our packet-based entities
*/
public static final Class<?> ENTITY_CLASS =
new ReflectionBuilder(ReflectionPackage.ENTITY)
.withClassName("Entity")
.toClassReflection().get();
public static final FieldReflection.ValueModifier<Integer> ENTITY_ID_MODIFIER = public static final FieldReflection.ValueModifier<Integer> ENTITY_ID_MODIFIER =
new ReflectionBuilder(ReflectionPackage.ENTITY) new ReflectionBuilder(ReflectionPackage.ENTITY)
.withClassName(ENTITY_CLASS) .withClassName(ENTITY_CLASS)
@ -62,6 +119,11 @@ public final class Reflections {
.toFieldReflection() .toFieldReflection()
.toStaticValueLoader(AtomicInteger.class); .toStaticValueLoader(AtomicInteger.class);
/*
* All of these folia methods need to be reflected because folia is strictly
* available on the newest java versions but we need to keep support for Java 8
*/
public static final Class<?> ASYNC_SCHEDULER_CLASS = public static final Class<?> ASYNC_SCHEDULER_CLASS =
new ReflectionBuilder("io.papermc.paper.threadedregions.scheduler") new ReflectionBuilder("io.papermc.paper.threadedregions.scheduler")
.withClassName("AsyncScheduler") .withClassName("AsyncScheduler")

@ -4,13 +4,12 @@ import com.github.retrooper.packetevents.protocol.player.TextureProperty;
import com.github.retrooper.packetevents.protocol.player.UserProfile; import com.github.retrooper.packetevents.protocol.player.UserProfile;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.mojang.authlib.properties.PropertyMap; import lol.pyr.znpcsplus.reflection.Reflections;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
public class Skin { public class Skin {
private final long timestamp = System.currentTimeMillis(); private final long timestamp = System.currentTimeMillis();
@ -21,18 +20,23 @@ public class Skin {
properties.add(new TextureProperty("textures", texture, signature)); properties.add(new TextureProperty("textures", texture, signature));
} }
public Skin(TextureProperty... properties) {
this.properties = Arrays.asList(properties);
}
public Skin(Collection<TextureProperty> properties) { public Skin(Collection<TextureProperty> properties) {
this.properties = new ArrayList<>(properties); this.properties = new ArrayList<>(properties);
} }
public Skin(PropertyMap properties) { public Skin(Object propertyMap) {
this.properties = properties.values().stream() this.properties = new ArrayList<>();
.map(property -> new TextureProperty(property.getName(), property.getValue(), property.getSignature())) try {
.collect(Collectors.toList()); Collection<?> properties = (Collection<?>) Reflections.PROPERTY_MAP_VALUES_METHOD.get().invoke(propertyMap);
for (Object property : properties) {
String name = (String) Reflections.PROPERTY_GET_NAME_METHOD.get().invoke(property);
String value = (String) Reflections.PROPERTY_GET_VALUE_METHOD.get().invoke(property);
String signature = (String) Reflections.PROPERTY_GET_SIGNATURE_METHOD.get().invoke(property);
this.properties.add(new TextureProperty(name, value, signature));
}
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
} }
public Skin(JsonObject obj) { public Skin(JsonObject obj) {