improve reflection system

This commit is contained in:
Pyrbu 2023-05-16 15:01:45 +01:00
parent a08e973319
commit 2194faba0b
4 changed files with 77 additions and 56 deletions

@ -1,6 +1,9 @@
package lol.pyr.znpcsplus.reflection; package lol.pyr.znpcsplus.reflection;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import lol.pyr.znpcsplus.reflection.types.ClassReflection;
import lol.pyr.znpcsplus.reflection.types.FieldReflection;
import lol.pyr.znpcsplus.reflection.types.MethodReflection;
import lol.pyr.znpcsplus.util.VersionUtil; import lol.pyr.znpcsplus.util.VersionUtil;
import java.util.ArrayList; import java.util.ArrayList;
@ -32,7 +35,7 @@ public class ReflectionBuilder {
} }
public ReflectionBuilder withClassName(String className) { public ReflectionBuilder withClassName(String className) {
this.className.add(ReflectionPackage.join(reflectionPackage, VersionUtil.isNewerThan(17) ? additionalData : "", className)); this.className.add(ReflectionPackage.joinWithDot(reflectionPackage, VersionUtil.isNewerThan(17) ? additionalData : "", className));
return this; return this;
} }
@ -98,4 +101,16 @@ public class ReflectionBuilder {
public String getFieldName() { public String getFieldName() {
return fieldName; return fieldName;
} }
public MethodReflection toMethodReflection() {
return new MethodReflection(this);
}
public ClassReflection toClassReflection() {
return new ClassReflection(this);
}
public FieldReflection toFieldReflection() {
return new FieldReflection(this);
}
} }

@ -13,18 +13,16 @@ import java.util.stream.Collectors;
*/ */
public class ReflectionPackage { public class ReflectionPackage {
private static final boolean flattened = !VersionUtil.isNewerThan(17); private static final boolean flattened = !VersionUtil.isNewerThan(17);
public static final String BUKKIT = "org.bukkit.craftbukkit." + VersionUtil.getBukkitPackage(); public static final String BUKKIT = "org.bukkit.craftbukkit." + VersionUtil.getBukkitPackage();
/** /**
* Check if the classes are flattened, if so we need to add the version string into the * Check if the classes are flattened, if so we need to add the version string into the
* package string which is another quirk of the old server jars. * package string which is another quirk of the old server jars.
*/ */
public static final String MINECRAFT = join("net.minecraft", flattened ? "server." + VersionUtil.getBukkitPackage() : ""); public static final String MINECRAFT = joinWithDot("net.minecraft", flattened ? "server." + VersionUtil.getBukkitPackage() : "");
public static final String ENTITY = flattened ? MINECRAFT : join(MINECRAFT, "world.entity"); public static final String ENTITY = flattened ? MINECRAFT : joinWithDot(MINECRAFT, "world.entity");
// Simple method that joins all the non-null & non-empty arguments with a dot and returns the result public static String joinWithDot(String... parts) {
public static String join(String... parts) {
return Arrays.stream(parts) return Arrays.stream(parts)
.filter(Objects::nonNull) .filter(Objects::nonNull)
.filter(p -> p.length() != 0) .filter(p -> p.length() != 0)

@ -1,9 +1,7 @@
package lol.pyr.znpcsplus.reflection; package lol.pyr.znpcsplus.reflection;
import com.mojang.authlib.GameProfile; import com.mojang.authlib.GameProfile;
import lol.pyr.znpcsplus.reflection.types.ClassReflection;
import lol.pyr.znpcsplus.reflection.types.FieldReflection; import lol.pyr.znpcsplus.reflection.types.FieldReflection;
import lol.pyr.znpcsplus.reflection.types.MethodReflection;
import lol.pyr.znpcsplus.util.FoliaUtil; import lol.pyr.znpcsplus.util.FoliaUtil;
import lol.pyr.znpcsplus.util.VersionUtil; import lol.pyr.znpcsplus.util.VersionUtil;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@ -18,101 +16,111 @@ import java.util.function.Consumer;
/** /**
* Class containing all of the lazy-loaded reflections that the plugin * Class containing all of the lazy-loaded reflections that the plugin
* uses to accessinaccessible things from 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 ClassReflection( public static final Class<?> ENTITY_CLASS =
new ReflectionBuilder(ReflectionPackage.ENTITY) new ReflectionBuilder(ReflectionPackage.ENTITY)
.withClassName("Entity")).get(); .withClassName("Entity")
.toClassReflection().get();
public static final Class<?> ENTITY_HUMAN_CLASS = new ClassReflection( public static final Class<?> ENTITY_HUMAN_CLASS =
new ReflectionBuilder(ReflectionPackage.ENTITY) new ReflectionBuilder(ReflectionPackage.ENTITY)
.withSubClass("player") .withSubClass("player")
.withClassName("EntityHuman")).get(); .withClassName("EntityHuman")
.toClassReflection().get();
public static final ReflectionLazyLoader<Method> GET_PROFILE_METHOD = new MethodReflection( 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(GameProfile.class)
.toMethodReflection();
public static final ReflectionLazyLoader<Method> GET_HANDLE_PLAYER_METHOD = new MethodReflection( public static final ReflectionLazyLoader<Method> GET_HANDLE_PLAYER_METHOD =
new ReflectionBuilder(ReflectionPackage.BUKKIT) new ReflectionBuilder(ReflectionPackage.BUKKIT)
.withClassName("entity.CraftPlayer").withClassName("entity.CraftHumanEntity") .withClassName("entity.CraftPlayer").withClassName("entity.CraftHumanEntity")
.withMethodName("getHandle")); .withMethodName("getHandle")
.toMethodReflection();
public static final FieldReflection.ValueModifier<Integer> ENTITY_ID_MODIFIER = new FieldReflection( public static final FieldReflection.ValueModifier<Integer> ENTITY_ID_MODIFIER =
new ReflectionBuilder(ReflectionPackage.ENTITY) new ReflectionBuilder(ReflectionPackage.ENTITY)
.withClassName(ENTITY_CLASS) .withClassName(ENTITY_CLASS)
.withFieldName("entityCount") .withFieldName("entityCount")
.setStrict(!VersionUtil.isNewerThan(14))).staticValueModifier(int.class); .setStrict(!VersionUtil.isNewerThan(14))
.toFieldReflection()
.toStaticValueModifier(int.class);
public static final ReflectionLazyLoader<AtomicInteger> ATOMIC_ENTITY_ID_FIELD = new FieldReflection( public static final ReflectionLazyLoader<AtomicInteger> ATOMIC_ENTITY_ID_FIELD =
new ReflectionBuilder(ReflectionPackage.ENTITY) new ReflectionBuilder(ReflectionPackage.ENTITY)
.withClassName(ENTITY_CLASS) .withClassName(ENTITY_CLASS)
.withFieldName("entityCount") .withFieldName("entityCount")
.withFieldName("d") .withFieldName("d")
.withFieldName("c") .withFieldName("c")
.withExpectResult(AtomicInteger.class) .withExpectResult(AtomicInteger.class)
.setStrict(VersionUtil.isNewerThan(14))).staticValueLoader(AtomicInteger.class); .setStrict(VersionUtil.isNewerThan(14))
.toFieldReflection()
.toStaticValueLoader(AtomicInteger.class);
public static final Class<?> ASYNC_SCHEDULER_CLASS = new ClassReflection( 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")
.setStrict(FoliaUtil.isFolia())).get(); .setStrict(FoliaUtil.isFolia())
.toClassReflection().get();
public static final Class<?> GLOBAL_REGION_SCHEDULER_CLASS = new ClassReflection( public static final Class<?> GLOBAL_REGION_SCHEDULER_CLASS =
new ReflectionBuilder("io.papermc.paper.threadedregions.scheduler") new ReflectionBuilder("io.papermc.paper.threadedregions.scheduler")
.withClassName("GlobalRegionScheduler") .withClassName("GlobalRegionScheduler")
.setStrict(FoliaUtil.isFolia())).get(); .setStrict(FoliaUtil.isFolia())
.toClassReflection().get();
public static final Class<?> SCHEDULED_TASK_CLASS = new ClassReflection( public static final Class<?> SCHEDULED_TASK_CLASS =
new ReflectionBuilder("io.papermc.paper.threadedregions.scheduler") new ReflectionBuilder("io.papermc.paper.threadedregions.scheduler")
.withClassName("ScheduledTask") .withClassName("ScheduledTask")
.setStrict(FoliaUtil.isFolia())).get(); .setStrict(FoliaUtil.isFolia())
.toClassReflection().get();
public static final ReflectionLazyLoader<Method> FOLIA_GET_ASYNC_SCHEDULER = new MethodReflection( public static final ReflectionLazyLoader<Method> FOLIA_GET_ASYNC_SCHEDULER =
new ReflectionBuilder(Bukkit.class) new ReflectionBuilder(Bukkit.class)
.withMethodName("getAsyncScheduler") .withMethodName("getAsyncScheduler")
.withExpectResult(ASYNC_SCHEDULER_CLASS) .withExpectResult(ASYNC_SCHEDULER_CLASS)
.setStrict(FoliaUtil.isFolia())); .setStrict(FoliaUtil.isFolia())
.toMethodReflection();
public static final ReflectionLazyLoader<Method> FOLIA_GET_GLOBAL_REGION_SCHEDULER = new MethodReflection( public static final ReflectionLazyLoader<Method> FOLIA_GET_GLOBAL_REGION_SCHEDULER =
new ReflectionBuilder(Bukkit.class) new ReflectionBuilder(Bukkit.class)
.withMethodName("getGlobalRegionScheduler") .withMethodName("getGlobalRegionScheduler")
.withExpectResult(GLOBAL_REGION_SCHEDULER_CLASS) .withExpectResult(GLOBAL_REGION_SCHEDULER_CLASS)
.setStrict(FoliaUtil.isFolia())); .setStrict(FoliaUtil.isFolia())
.toMethodReflection();
public static final ReflectionLazyLoader<Method> FOLIA_RUN_NOW = new MethodReflection( public static final ReflectionLazyLoader<Method> FOLIA_RUN_DELAYED =
new ReflectionBuilder(ASYNC_SCHEDULER_CLASS)
.withMethodName("runNow")
.withParameterTypes(Plugin.class, Consumer.class)
.withExpectResult(SCHEDULED_TASK_CLASS)
.setStrict(FoliaUtil.isFolia()));
public static final ReflectionLazyLoader<Method> FOLIA_RUN_DELAYED = new MethodReflection(
new ReflectionBuilder(ASYNC_SCHEDULER_CLASS) new ReflectionBuilder(ASYNC_SCHEDULER_CLASS)
.withMethodName("runDelayed") .withMethodName("runDelayed")
.withParameterTypes(Plugin.class, Consumer.class, long.class, TimeUnit.class) .withParameterTypes(Plugin.class, Consumer.class, long.class, TimeUnit.class)
.withExpectResult(SCHEDULED_TASK_CLASS) .withExpectResult(SCHEDULED_TASK_CLASS)
.setStrict(FoliaUtil.isFolia())); .setStrict(FoliaUtil.isFolia())
.toMethodReflection();
public static final ReflectionLazyLoader<Method> FOLIA_RUN_AT_FIXED_RATE = new MethodReflection( public static final ReflectionLazyLoader<Method> FOLIA_RUN_AT_FIXED_RATE =
new ReflectionBuilder(ASYNC_SCHEDULER_CLASS) new ReflectionBuilder(ASYNC_SCHEDULER_CLASS)
.withMethodName("runAtFixedRate") .withMethodName("runAtFixedRate")
.withParameterTypes(Plugin.class, Consumer.class, long.class, long.class, TimeUnit.class) .withParameterTypes(Plugin.class, Consumer.class, long.class, long.class, TimeUnit.class)
.withExpectResult(SCHEDULED_TASK_CLASS) .withExpectResult(SCHEDULED_TASK_CLASS)
.setStrict(FoliaUtil.isFolia())); .setStrict(FoliaUtil.isFolia())
.toMethodReflection();
public static final ReflectionLazyLoader<Method> FOLIA_RUN_NOW_GLOBAL = new MethodReflection( public static final ReflectionLazyLoader<Method> FOLIA_RUN_NOW_GLOBAL =
new ReflectionBuilder(GLOBAL_REGION_SCHEDULER_CLASS) new ReflectionBuilder(GLOBAL_REGION_SCHEDULER_CLASS)
.withMethodName("runNow") .withMethodName("runNow")
.withParameterTypes(Plugin.class, Consumer.class) .withParameterTypes(Plugin.class, Consumer.class)
.withExpectResult(SCHEDULED_TASK_CLASS) .withExpectResult(SCHEDULED_TASK_CLASS)
.setStrict(FoliaUtil.isFolia())); .setStrict(FoliaUtil.isFolia())
.toMethodReflection();
public static final ReflectionLazyLoader<Method> FOLIA_TELEPORT_ASYNC = new MethodReflection( public static final ReflectionLazyLoader<Method> FOLIA_TELEPORT_ASYNC =
new ReflectionBuilder(Entity.class) new ReflectionBuilder(Entity.class)
.withMethodName("teleportAsync") .withMethodName("teleportAsync")
.withParameterTypes(Location.class) .withParameterTypes(Location.class)
.setStrict(FoliaUtil.isFolia())); .setStrict(FoliaUtil.isFolia())
.toMethodReflection();
} }

@ -11,10 +11,10 @@ public class FieldReflection extends ReflectionLazyLoader<Field> {
private final String fieldName; private final String fieldName;
private final Class<?> expectType; private final Class<?> expectType;
public FieldReflection(ReflectionBuilder reflectionBuilder) { public FieldReflection(ReflectionBuilder builder) {
super(reflectionBuilder); super(builder);
this.fieldName = reflectionBuilder.getFieldName(); this.fieldName = builder.getFieldName();
this.expectType = reflectionBuilder.getExpectType(); this.expectType = builder.getExpectType();
} }
protected Field load() { protected Field load() {
@ -53,27 +53,27 @@ public class FieldReflection extends ReflectionLazyLoader<Field> {
logger.accept("Field Type: " + expectType); logger.accept("Field Type: " + expectType);
} }
public ValueReflection<Object> staticValueLoader() { public ValueReflection<Object> toStaticValueLoader() {
return staticValueLoader(Object.class); return toStaticValueLoader(Object.class);
} }
@SuppressWarnings("unused") @SuppressWarnings("unused")
public <T> ValueReflection<T> staticValueLoader(Class<T> valueType) { public <T> ValueReflection<T> toStaticValueLoader(Class<T> valueType) {
return new ValueReflection<>(this, possibleClassNames, null, strict); return new ValueReflection<>(this, possibleClassNames, null, strict);
} }
@SuppressWarnings("unused") @SuppressWarnings("unused")
public <T> ValueReflection<T> valueLoader(Object obj, Class<T> valueType) { public <T> ValueReflection<T> toValueLoader(Object obj, Class<T> valueType) {
return new ValueReflection<>(this, possibleClassNames, obj, strict); return new ValueReflection<>(this, possibleClassNames, obj, strict);
} }
@SuppressWarnings("unused") @SuppressWarnings("unused")
public <T> ValueModifier<T> staticValueModifier(Class<T> valueType) { public <T> ValueModifier<T> toStaticValueModifier(Class<T> valueType) {
return new ValueModifier<>(this, possibleClassNames, null, strict); return new ValueModifier<>(this, possibleClassNames, null, strict);
} }
@SuppressWarnings("unused") @SuppressWarnings("unused")
public <T> ValueModifier<T> valueModifier(Object obj, Class<T> valueType) { public <T> ValueModifier<T> toValueModifier(Object obj, Class<T> valueType) {
return new ValueModifier<>(this, possibleClassNames, obj, strict); return new ValueModifier<>(this, possibleClassNames, obj, strict);
} }