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;
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 java.util.ArrayList;
@ -32,7 +35,7 @@ public class ReflectionBuilder {
}
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;
}
@ -98,4 +101,16 @@ public class ReflectionBuilder {
public String getFieldName() {
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 {
private static final boolean flattened = !VersionUtil.isNewerThan(17);
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
* 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 ENTITY = flattened ? MINECRAFT : join(MINECRAFT, "world.entity");
public static final String MINECRAFT = joinWithDot("net.minecraft", flattened ? "server." + VersionUtil.getBukkitPackage() : "");
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 join(String... parts) {
public static String joinWithDot(String... parts) {
return Arrays.stream(parts)
.filter(Objects::nonNull)
.filter(p -> p.length() != 0)

@ -1,9 +1,7 @@
package lol.pyr.znpcsplus.reflection;
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.MethodReflection;
import lol.pyr.znpcsplus.util.FoliaUtil;
import lol.pyr.znpcsplus.util.VersionUtil;
import org.bukkit.Bukkit;
@ -18,101 +16,111 @@ import java.util.function.Consumer;
/**
* 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 static final Class<?> ENTITY_CLASS = new ClassReflection(
public static final Class<?> ENTITY_CLASS =
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)
.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)
.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)
.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)
.withClassName(ENTITY_CLASS)
.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)
.withClassName(ENTITY_CLASS)
.withFieldName("entityCount")
.withFieldName("d")
.withFieldName("c")
.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")
.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")
.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")
.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)
.withMethodName("getAsyncScheduler")
.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)
.withMethodName("getGlobalRegionScheduler")
.withExpectResult(GLOBAL_REGION_SCHEDULER_CLASS)
.setStrict(FoliaUtil.isFolia()));
.setStrict(FoliaUtil.isFolia())
.toMethodReflection();
public static final ReflectionLazyLoader<Method> FOLIA_RUN_NOW = new MethodReflection(
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(
public static final ReflectionLazyLoader<Method> FOLIA_RUN_DELAYED =
new ReflectionBuilder(ASYNC_SCHEDULER_CLASS)
.withMethodName("runDelayed")
.withParameterTypes(Plugin.class, Consumer.class, long.class, TimeUnit.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)
.withMethodName("runAtFixedRate")
.withParameterTypes(Plugin.class, Consumer.class, long.class, long.class, TimeUnit.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)
.withMethodName("runNow")
.withParameterTypes(Plugin.class, Consumer.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)
.withMethodName("teleportAsync")
.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 Class<?> expectType;
public FieldReflection(ReflectionBuilder reflectionBuilder) {
super(reflectionBuilder);
this.fieldName = reflectionBuilder.getFieldName();
this.expectType = reflectionBuilder.getExpectType();
public FieldReflection(ReflectionBuilder builder) {
super(builder);
this.fieldName = builder.getFieldName();
this.expectType = builder.getExpectType();
}
protected Field load() {
@ -53,27 +53,27 @@ public class FieldReflection extends ReflectionLazyLoader<Field> {
logger.accept("Field Type: " + expectType);
}
public ValueReflection<Object> staticValueLoader() {
return staticValueLoader(Object.class);
public ValueReflection<Object> toStaticValueLoader() {
return toStaticValueLoader(Object.class);
}
@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);
}
@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);
}
@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);
}
@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);
}