major reflection improvements (fixes #12)

This commit is contained in:
Pyrbu 2023-04-22 04:32:17 +01:00
parent dfbd9bebce
commit 5395094063
11 changed files with 199 additions and 101 deletions

@ -6,7 +6,6 @@ import io.github.znetworkw.znpcservers.commands.exception.CommandExecuteExceptio
import io.github.znetworkw.znpcservers.commands.exception.CommandPermissionException; import io.github.znetworkw.znpcservers.commands.exception.CommandPermissionException;
import io.github.znetworkw.znpcservers.reflection.Reflections; import io.github.znetworkw.znpcservers.reflection.Reflections;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.command.CommandMap;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.command.defaults.BukkitCommand; import org.bukkit.command.defaults.BukkitCommand;
@ -23,7 +22,7 @@ public class Command extends BukkitCommand {
} }
private void load() { private void load() {
((CommandMap) Reflections.COMMAND_MAP_FIELD.get()).register(getName(), this); Reflections.COMMAND_MAP_FIELD.get().register(getName(), this);
for (Method method : getClass().getMethods()) { for (Method method : getClass().getMethods()) {
if (method.isAnnotationPresent(CommandInformation.class)) { if (method.isAnnotationPresent(CommandInformation.class)) {
CommandInformation cmdInfo = method.getAnnotation(CommandInformation.class); CommandInformation cmdInfo = method.getAnnotation(CommandInformation.class);

@ -11,7 +11,7 @@ public class PacketV19 extends PacketV18 {
public Object getPlayerPacket(Object nmsWorld, GameProfile gameProfile) throws ReflectiveOperationException { public Object getPlayerPacket(Object nmsWorld, GameProfile gameProfile) throws ReflectiveOperationException {
try { try {
return Reflections.PLAYER_CONSTRUCTOR_NEW_1.get(true).newInstance(Reflections.GET_SERVER_METHOD.get().invoke(Bukkit.getServer()), nmsWorld, gameProfile, null); return Reflections.PLAYER_CONSTRUCTOR_NEW_1.get().newInstance(Reflections.GET_SERVER_METHOD.get().invoke(Bukkit.getServer()), nmsWorld, gameProfile, null);
} catch (Throwable e) { } catch (Throwable e) {
return Reflections.PLAYER_CONSTRUCTOR_NEW_2.get().newInstance(Reflections.GET_SERVER_METHOD.get().invoke(Bukkit.getServer()), nmsWorld, gameProfile); return Reflections.PLAYER_CONSTRUCTOR_NEW_2.get().newInstance(Reflections.GET_SERVER_METHOD.get().invoke(Bukkit.getServer()), nmsWorld, gameProfile);
} }

@ -39,7 +39,7 @@ public class PacketV8 implements Packet {
public Object getMetadataPacket(int entityId, Object nmsEntity) throws ReflectiveOperationException { public Object getMetadataPacket(int entityId, Object nmsEntity) throws ReflectiveOperationException {
Object dataWatcher = Reflections.GET_DATA_WATCHER_METHOD.get().invoke(nmsEntity); Object dataWatcher = Reflections.GET_DATA_WATCHER_METHOD.get().invoke(nmsEntity);
try { try {
return Reflections.PACKET_PLAY_OUT_ENTITY_META_DATA_CONSTRUCTOR.get(true).newInstance(entityId, dataWatcher, true); return Reflections.PACKET_PLAY_OUT_ENTITY_META_DATA_CONSTRUCTOR.get().newInstance(entityId, dataWatcher, true);
} catch (Exception e2) { } catch (Exception e2) {
return Reflections.PACKET_PLAY_OUT_ENTITY_META_DATA_CONSTRUCTOR_V1.get().newInstance(entityId, Reflections.GET_DATAWATCHER_B_LIST.get().invoke(dataWatcher)); return Reflections.PACKET_PLAY_OUT_ENTITY_META_DATA_CONSTRUCTOR_V1.get().newInstance(entityId, Reflections.GET_DATAWATCHER_B_LIST.get().invoke(dataWatcher));
} }

@ -13,6 +13,7 @@ public class ReflectionBuilder {
private final ArrayList<String> methods = new ArrayList<>(); private final ArrayList<String> methods = new ArrayList<>();
private final ArrayList<Class<?>[]> parameterTypes = new ArrayList<>(); private final ArrayList<Class<?>[]> parameterTypes = new ArrayList<>();
private Class<?> expectType; private Class<?> expectType;
private boolean strict = true;
public ReflectionBuilder(String reflectionPackage) { public ReflectionBuilder(String reflectionPackage) {
this(reflectionPackage, "", "", null); this(reflectionPackage, "", "", null);
@ -60,6 +61,15 @@ public class ReflectionBuilder {
return this; return this;
} }
public ReflectionBuilder setStrict(boolean strict) {
this.strict = strict;
return this;
}
public boolean isStrict() {
return strict;
}
public Class<?> getExpectType() { public Class<?> getExpectType() {
return expectType; return expectType;
} }

@ -3,50 +3,46 @@ package io.github.znetworkw.znpcservers.reflection;
import io.github.znetworkw.znpcservers.utility.Utils; import io.github.znetworkw.znpcservers.utility.Utils;
import lol.pyr.znpcsplus.ZNPCsPlus; import lol.pyr.znpcsplus.ZNPCsPlus;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.function.Consumer;
public abstract class ReflectionLazyLoader<T> { public abstract class ReflectionLazyLoader<T> {
protected final List<String> possibleClassNames; protected final List<String> possibleClassNames;
protected List<Class<?>> reflectionClasses = new ArrayList<>();
protected Class<?> reflectionClass; protected final boolean strict;
private T cached; private T cached;
private boolean loaded = false; private boolean loaded = false;
protected ReflectionLazyLoader(ReflectionBuilder builder) { protected ReflectionLazyLoader(ReflectionBuilder builder) {
this(builder.getClassNames()); this(builder.getClassNames(), builder.isStrict());
} }
protected ReflectionLazyLoader(List<String> possibleClassNames) { protected ReflectionLazyLoader(List<String> possibleClassNames, boolean strict) {
this.possibleClassNames = possibleClassNames; this.possibleClassNames = possibleClassNames;
for (String classes : possibleClassNames) { this.strict = strict;
try { for (String name : possibleClassNames) try {
this.reflectionClass = Class.forName(classes); reflectionClasses.add(Class.forName(name));
break; } catch (ClassNotFoundException ignored) {}
} catch (ClassNotFoundException ignored) {
}
}
} }
public T get() { public T get() {
return get(false);
}
public T get(boolean missAllowed) {
if (this.loaded) return this.cached; if (this.loaded) return this.cached;
try { try {
if (this.reflectionClass == null) throw new ClassNotFoundException("No class found: " + possibleClassNames); if (this.reflectionClasses.size() == 0) throw new ClassNotFoundException("No class found: " + possibleClassNames);
T eval = (this.cached != null) ? this.cached : (this.cached = load()); T eval = (this.cached != null) ? this.cached : (this.cached = load());
if (eval == null) throw new NullPointerException(); if (eval == null) throw new RuntimeException("Returned value is null");
} catch (Throwable throwable) { } catch (Throwable throwable) {
if (!missAllowed) { if (strict) {
warn(getClass().getSimpleName() + " get failed!"); warn(" ----- REFLECTION FAILURE DEBUG INFORMATION, REPORT THIS ON OUR GITHUB ----- ");
warn(getClass().getSimpleName() + " failed!");
warn("Class Names: " + possibleClassNames); warn("Class Names: " + possibleClassNames);
warn("Loader Type: " + getClass().getCanonicalName()); warn("Reflection Type: " + getClass().getCanonicalName());
warn("Bukkit Version: " + Utils.BUKKIT_VERSION + " (" + Utils.getBukkitPackage() + ")"); warn("Bukkit Version: " + Utils.BUKKIT_VERSION + " (" + Utils.getBukkitPackage() + ")");
printDebugInfo(this::warn);
warn("Exception:"); warn("Exception:");
throwable.printStackTrace(); throwable.printStackTrace();
warn(" ----- REFLECTION FAILURE DEBUG INFORMATION, REPORT THIS ON OUR GITHUB ----- ");
} }
} }
this.loaded = true; this.loaded = true;
@ -58,4 +54,5 @@ public abstract class ReflectionLazyLoader<T> {
} }
protected abstract T load() throws Exception; protected abstract T load() throws Exception;
protected void printDebugInfo(Consumer<String> logger) {}
} }

@ -1,10 +1,14 @@
package io.github.znetworkw.znpcservers.reflection; package io.github.znetworkw.znpcservers.reflection;
import com.mojang.authlib.GameProfile; import com.mojang.authlib.GameProfile;
import io.github.znetworkw.znpcservers.reflection.types.*; import io.github.znetworkw.znpcservers.reflection.types.ClassReflection;
import io.github.znetworkw.znpcservers.reflection.types.ConstructorReflection;
import io.github.znetworkw.znpcservers.reflection.types.FieldReflection;
import io.github.znetworkw.znpcservers.reflection.types.MethodReflection;
import io.github.znetworkw.znpcservers.utility.Utils; import io.github.znetworkw.znpcservers.utility.Utils;
import io.netty.channel.Channel; import io.netty.channel.Channel;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.command.CommandMap;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
@ -104,7 +108,8 @@ public final class Reflections {
public static final Class<?> ENTITY_LLAMA_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) public static final Class<?> ENTITY_LLAMA_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY)
.withSubClass("animal.horse") .withSubClass("animal.horse")
.withClassName("EntityLlama")).get(!Utils.versionNewer(11)); .withClassName("EntityLlama")
.setStrict(Utils.versionNewer(11))).get();
public static final Class<?> ENTITY_MAGMA_CUBE_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) public static final Class<?> ENTITY_MAGMA_CUBE_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY)
.withSubClass("monster") .withSubClass("monster")
@ -120,20 +125,24 @@ public final class Reflections {
public static final Class<?> ENTITY_TURTLE = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) public static final Class<?> ENTITY_TURTLE = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY)
.withSubClass("animal") .withSubClass("animal")
.withClassName("EntityTurtle")).get(!Utils.versionNewer(13)); .withClassName("EntityTurtle")
.setStrict(Utils.versionNewer(13))).get();
public static final Class<?> ENTITY_WARDEN = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) public static final Class<?> ENTITY_WARDEN = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY)
.withSubClass("monster.warden") .withSubClass("monster.warden")
.withClassName("EntityWarden") .withClassName("EntityWarden")
.withClassName("Warden")).get(!Utils.versionNewer(19)); .withClassName("Warden")
.setStrict(Utils.versionNewer(19))).get();
public static final Class<?> ENTITY_BEE_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) public static final Class<?> ENTITY_BEE_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY)
.withSubClass("animal") .withSubClass("animal")
.withClassName("EntityBee")).get(!Utils.versionNewer(15)); .withClassName("EntityBee")
.setStrict(Utils.versionNewer(15))).get();
public static final Class<?> ENTITY_PARROT_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) public static final Class<?> ENTITY_PARROT_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY)
.withSubClass("animal") .withSubClass("animal")
.withClassName("EntityParrot")).get(!Utils.versionNewer(12)); .withClassName("EntityParrot")
.setStrict(Utils.versionNewer(12))).get();
public static final Class<?> ENTITY_PIG_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) public static final Class<?> ENTITY_PIG_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY)
.withSubClass("animal") .withSubClass("animal")
@ -145,11 +154,13 @@ public final class Reflections {
public static final Class<?> ENTITY_POLAR_BEAR_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) public static final Class<?> ENTITY_POLAR_BEAR_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY)
.withSubClass("animal") .withSubClass("animal")
.withClassName("EntityPolarBear")).get(!Utils.versionNewer(10)); .withClassName("EntityPolarBear")
.setStrict(Utils.versionNewer(10))).get();
public static final Class<?> ENTITY_PANDA_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) public static final Class<?> ENTITY_PANDA_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY)
.withSubClass("animal") .withSubClass("animal")
.withClassName("EntityPanda")).get(!Utils.versionNewer(14)); .withClassName("EntityPanda")
.setStrict(Utils.versionNewer(14))).get();
public static final Class<?> ENTITY_SHEEP_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) public static final Class<?> ENTITY_SHEEP_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY)
.withSubClass("animal") .withSubClass("animal")
@ -161,7 +172,8 @@ public final class Reflections {
public static final Class<?> ENTITY_SHULKER_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) public static final Class<?> ENTITY_SHULKER_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY)
.withSubClass("monster") .withSubClass("monster")
.withClassName("EntityShulker")).get(!Utils.versionNewer(9)); .withClassName("EntityShulker")
.setStrict(Utils.versionNewer(9))).get();
public static final Class<?> ENTITY_SILVERFISH_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) public static final Class<?> ENTITY_SILVERFISH_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY)
.withSubClass("monster") .withSubClass("monster")
@ -205,15 +217,18 @@ public final class Reflections {
public static final Class<?> ENTITY_AXOLOTL_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) public static final Class<?> ENTITY_AXOLOTL_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY)
.withSubClass("animal.axolotl") .withSubClass("animal.axolotl")
.withClassName("Axolotl")).get(!Utils.versionNewer(17)); .withClassName("Axolotl")
.setStrict(Utils.versionNewer(17))).get();
public static final Class<?> ENTITY_GOAT_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) public static final Class<?> ENTITY_GOAT_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY)
.withSubClass("animal.goat") .withSubClass("animal.goat")
.withClassName("Goat")).get(!Utils.versionNewer(17)); .withClassName("Goat")
.setStrict(Utils.versionNewer(17))).get();
public static final Class<?> ENTITY_FOX_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) public static final Class<?> ENTITY_FOX_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY)
.withSubClass("animal") .withSubClass("animal")
.withClassName("EntityFox")).get(!Utils.versionNewer(14)); .withClassName("EntityFox")
.setStrict(Utils.versionNewer(14))).get();
public static final Class<?> ENTITY_TYPES_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) public static final Class<?> ENTITY_TYPES_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY)
.withClassName("EntityTypes")).get(); .withClassName("EntityTypes")).get();
@ -222,7 +237,8 @@ public final class Reflections {
.withClassName("EnumChatFormat")).get(); .withClassName("EnumChatFormat")).get();
public static final Class<?> ENUM_ITEM_SLOT = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) public static final Class<?> ENUM_ITEM_SLOT = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY)
.withClassName("EnumItemSlot")).get(!Utils.versionNewer(9)); .withClassName("EnumItemSlot")
.setStrict(Utils.versionNewer(9))).get();
public static final Class<?> I_CHAT_BASE_COMPONENT = new ClassReflection(new ReflectionBuilder(ReflectionPackage.CHAT) public static final Class<?> I_CHAT_BASE_COMPONENT = new ClassReflection(new ReflectionBuilder(ReflectionPackage.CHAT)
.withClassName("IChatBaseComponent")).get(); .withClassName("IChatBaseComponent")).get();
@ -231,16 +247,20 @@ public final class Reflections {
.withClassName("ItemStack")).get(); .withClassName("ItemStack")).get();
public static final Class<?> DATA_WATCHER_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.SYNCHER) public static final Class<?> DATA_WATCHER_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.SYNCHER)
.withClassName("DataWatcher")).get(!Utils.versionNewer(9)); .withClassName("DataWatcher")
.setStrict(Utils.versionNewer(9))).get();
public static final Class<?> DATA_WATCHER_OBJECT = new ClassReflection(new ReflectionBuilder(ReflectionPackage.SYNCHER) public static final Class<?> DATA_WATCHER_OBJECT = new ClassReflection(new ReflectionBuilder(ReflectionPackage.SYNCHER)
.withClassName("DataWatcherObject")).get(!Utils.versionNewer(9)); .withClassName("DataWatcherObject")
.setStrict(Utils.versionNewer(9))).get();
public static final Class<?> DATA_WATCHER_REGISTRY = new ClassReflection(new ReflectionBuilder(ReflectionPackage.SYNCHER) public static final Class<?> DATA_WATCHER_REGISTRY = new ClassReflection(new ReflectionBuilder(ReflectionPackage.SYNCHER)
.withClassName("DataWatcherRegistry")).get(!Utils.versionNewer(9)); .withClassName("DataWatcherRegistry")
.setStrict(Utils.versionNewer(9))).get();
public static final Class<?> DATA_WATCHER_SERIALIZER = new ClassReflection(new ReflectionBuilder(ReflectionPackage.SYNCHER) public static final Class<?> DATA_WATCHER_SERIALIZER = new ClassReflection(new ReflectionBuilder(ReflectionPackage.SYNCHER)
.withClassName("DataWatcherSerializer")).get(!Utils.versionNewer(9)); .withClassName("DataWatcherSerializer")
.setStrict(Utils.versionNewer(9))).get();
public static final Class<?> WORLD_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.WORLD_LEVEL) public static final Class<?> WORLD_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.WORLD_LEVEL)
.withClassName("World")).get(); .withClassName("World")).get();
@ -265,12 +285,11 @@ public final class Reflections {
public static final Class<?> PACKET_PLAY_OUT_PLAYER_INFO_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.PACKET) public static final Class<?> PACKET_PLAY_OUT_PLAYER_INFO_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.PACKET)
.withClassName("PacketPlayOutPlayerInfo") .withClassName("PacketPlayOutPlayerInfo")
.withClassName("ClientboundPlayerInfoUpdatePacket")) .withClassName("ClientboundPlayerInfoUpdatePacket")).get();
.get();
public static final Class<?> PACKET_PLAY_OUT_PLAYER_INFO_REMOVE_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.PACKET) public static final Class<?> PACKET_PLAY_OUT_PLAYER_INFO_REMOVE_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.PACKET)
.withClassName("ClientboundPlayerInfoRemovePacket")) .withClassName("ClientboundPlayerInfoRemovePacket")
.get(true); .setStrict(false)).get();
public static final Class<?> PACKET_PLAY_OUT_SCOREBOARD_TEAM_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.PACKET) public static final Class<?> PACKET_PLAY_OUT_SCOREBOARD_TEAM_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.PACKET)
.withClassName("PacketPlayOutScoreboardTeam")).get(); .withClassName("PacketPlayOutScoreboardTeam")).get();
@ -291,7 +310,8 @@ public final class Reflections {
.withClassName("util.CraftChatMessage")).get(); .withClassName("util.CraftChatMessage")).get();
public static final Class<?> PROFILE_PUBLIC_KEY_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.WORLD_ENTITY_PLAYER) public static final Class<?> PROFILE_PUBLIC_KEY_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.WORLD_ENTITY_PLAYER)
.withClassName("ProfilePublicKey")).get(!Utils.versionNewer(19)); .withClassName("ProfilePublicKey")
.setStrict(Utils.versionNewer(19))).get();
public static final ReflectionLazyLoader<Constructor<?>> SCOREBOARD_TEAM_CONSTRUCTOR = new ConstructorReflection(new ReflectionBuilder(ReflectionPackage.PACKET) public static final ReflectionLazyLoader<Constructor<?>> SCOREBOARD_TEAM_CONSTRUCTOR = new ConstructorReflection(new ReflectionBuilder(ReflectionPackage.PACKET)
.withClassName(SCOREBOARD_TEAM_CLASS) .withClassName(SCOREBOARD_TEAM_CLASS)
@ -307,7 +327,8 @@ public final class Reflections {
public static final ReflectionLazyLoader<Constructor<?>> PLAYER_CONSTRUCTOR_NEW_1 = new ConstructorReflection(new ReflectionBuilder(ReflectionPackage.PACKET) public static final ReflectionLazyLoader<Constructor<?>> PLAYER_CONSTRUCTOR_NEW_1 = new ConstructorReflection(new ReflectionBuilder(ReflectionPackage.PACKET)
.withClassName(ENTITY_PLAYER_CLASS) .withClassName(ENTITY_PLAYER_CLASS)
.withParameterTypes(MINECRAFT_SERVER_CLASS, WORLD_SERVER_CLASS, GameProfile.class, PROFILE_PUBLIC_KEY_CLASS)); .withParameterTypes(MINECRAFT_SERVER_CLASS, WORLD_SERVER_CLASS, GameProfile.class, PROFILE_PUBLIC_KEY_CLASS)
.setStrict(false));
public static final ReflectionLazyLoader<Constructor<?>> PLAYER_CONSTRUCTOR_NEW_2 = new ConstructorReflection(new ReflectionBuilder(ReflectionPackage.PACKET) public static final ReflectionLazyLoader<Constructor<?>> PLAYER_CONSTRUCTOR_NEW_2 = new ConstructorReflection(new ReflectionBuilder(ReflectionPackage.PACKET)
.withClassName(ENTITY_PLAYER_CLASS) .withClassName(ENTITY_PLAYER_CLASS)
@ -335,7 +356,8 @@ public final class Reflections {
public static final ReflectionLazyLoader<Constructor<?>> PACKET_PLAY_OUT_ENTITY_META_DATA_CONSTRUCTOR = new ConstructorReflection(new ReflectionBuilder(ReflectionPackage.PACKET) public static final ReflectionLazyLoader<Constructor<?>> PACKET_PLAY_OUT_ENTITY_META_DATA_CONSTRUCTOR = new ConstructorReflection(new ReflectionBuilder(ReflectionPackage.PACKET)
.withClassName("PacketPlayOutEntityMetadata") .withClassName("PacketPlayOutEntityMetadata")
.withParameterTypes(int.class, DATA_WATCHER_CLASS, boolean.class)); .withParameterTypes(int.class, DATA_WATCHER_CLASS, boolean.class)
.setStrict(false));
public static final ReflectionLazyLoader<Constructor<?>> PACKET_PLAY_OUT_ENTITY_META_DATA_CONSTRUCTOR_V1 = new ConstructorReflection(new ReflectionBuilder(ReflectionPackage.PACKET) public static final ReflectionLazyLoader<Constructor<?>> PACKET_PLAY_OUT_ENTITY_META_DATA_CONSTRUCTOR_V1 = new ConstructorReflection(new ReflectionBuilder(ReflectionPackage.PACKET)
.withClassName("PacketPlayOutEntityMetadata") .withClassName("PacketPlayOutEntityMetadata")
@ -558,7 +580,7 @@ public final class Reflections {
.withClassName(ENUM_TAG_VISIBILITY) .withClassName(ENUM_TAG_VISIBILITY)
.withFieldName("b")).staticValueLoader(); .withFieldName("b")).staticValueLoader();
public static final ReflectionLazyLoader<Object> COMMAND_MAP_FIELD = new FieldReflection(new ReflectionBuilder(ReflectionPackage.BUKKIT) public static final ReflectionLazyLoader<CommandMap> COMMAND_MAP_FIELD = new FieldReflection(new ReflectionBuilder(ReflectionPackage.BUKKIT)
.withClassName("CraftServer") .withClassName("CraftServer")
.withFieldName("commandMap")).valueLoader(Bukkit.getServer()); .withFieldName("commandMap")).valueLoader(Bukkit.getServer(), CommandMap.class);
} }

@ -1,7 +1,7 @@
package io.github.znetworkw.znpcservers.reflection.types; package io.github.znetworkw.znpcservers.reflection.types;
import io.github.znetworkw.znpcservers.reflection.ReflectionLazyLoader;
import io.github.znetworkw.znpcservers.reflection.ReflectionBuilder; import io.github.znetworkw.znpcservers.reflection.ReflectionBuilder;
import io.github.znetworkw.znpcservers.reflection.ReflectionLazyLoader;
public class ClassReflection extends ReflectionLazyLoader<Class<?>> { public class ClassReflection extends ReflectionLazyLoader<Class<?>> {
public ClassReflection(ReflectionBuilder reflectionBuilder) { public ClassReflection(ReflectionBuilder reflectionBuilder) {
@ -9,6 +9,6 @@ public class ClassReflection extends ReflectionLazyLoader<Class<?>> {
} }
protected Class<?> load() { protected Class<?> load() {
return this.reflectionClass; return this.reflectionClasses.size() > 0 ? this.reflectionClasses.get(0) : null;
} }
} }

@ -1,11 +1,12 @@
package io.github.znetworkw.znpcservers.reflection.types; package io.github.znetworkw.znpcservers.reflection.types;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import io.github.znetworkw.znpcservers.reflection.ReflectionLazyLoader;
import io.github.znetworkw.znpcservers.reflection.ReflectionBuilder; import io.github.znetworkw.znpcservers.reflection.ReflectionBuilder;
import io.github.znetworkw.znpcservers.reflection.ReflectionLazyLoader;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.util.Arrays;
import java.util.function.Consumer;
public class ConstructorReflection extends ReflectionLazyLoader<Constructor<?>> { public class ConstructorReflection extends ReflectionLazyLoader<Constructor<?>> {
private final ImmutableList<Class<?>[]> parameterTypes; private final ImmutableList<Class<?>[]> parameterTypes;
@ -16,13 +17,28 @@ public class ConstructorReflection extends ReflectionLazyLoader<Constructor<?>>
} }
protected Constructor<?> load() throws NoSuchMethodException { protected Constructor<?> load() throws NoSuchMethodException {
Constructor<?> constructor = null; for (Class<?> clazz : this.reflectionClasses) {
if (Iterables.size(parameterTypes) > 1) { Constructor<?> constructor = load(clazz);
for (Class<?>[] keyParameters : parameterTypes) try { if (constructor != null) return constructor;
constructor = this.reflectionClass.getDeclaredConstructor(keyParameters); }
} catch (NoSuchMethodException ignored) {} return null;
} else constructor = (Iterables.size(parameterTypes) > 0) ? this.reflectionClass.getDeclaredConstructor(Iterables.get(parameterTypes, 0)) : this.reflectionClass.getDeclaredConstructor(); }
if (constructor != null) constructor.setAccessible(true);
private Constructor<?> load(Class<?> clazz) {
if (parameterTypes != null && parameterTypes.size() > 0) for (Class<?>[] possibleConstructor : parameterTypes) try {
Constructor<?> constructor = clazz.getDeclaredConstructor(possibleConstructor);
constructor.setAccessible(true);
return constructor; return constructor;
} catch (NoSuchMethodException ignored) {}
else try {
return clazz.getDeclaredConstructor();
} catch (NoSuchMethodException ignored) {}
return null;
}
@Override
protected void printDebugInfo(Consumer<String> logger) {
logger.accept("Possible Parameter Type Combinations:");
for (Class<?>[] possible : parameterTypes) logger.accept(Arrays.toString(possible));
} }
} }

@ -1,8 +1,8 @@
package io.github.znetworkw.znpcservers.reflection.types; package io.github.znetworkw.znpcservers.reflection.types;
import io.github.znetworkw.znpcservers.reflection.ReflectionLazyLoader;
import io.github.znetworkw.znpcservers.reflection.EnumPropertyCache; import io.github.znetworkw.znpcservers.reflection.EnumPropertyCache;
import io.github.znetworkw.znpcservers.reflection.ReflectionBuilder; import io.github.znetworkw.znpcservers.reflection.ReflectionBuilder;
import io.github.znetworkw.znpcservers.reflection.ReflectionLazyLoader;
public class EnumReflection extends ReflectionLazyLoader<Enum<?>[]> { public class EnumReflection extends ReflectionLazyLoader<Enum<?>[]> {
public EnumReflection(ReflectionBuilder reflectionBuilder) { public EnumReflection(ReflectionBuilder reflectionBuilder) {
@ -10,8 +10,9 @@ public class EnumReflection extends ReflectionLazyLoader<Enum<?>[]> {
} }
protected Enum<?>[] load() { protected Enum<?>[] load() {
Enum<?>[] enums = (Enum<?>[]) this.reflectionClass.getEnumConstants(); if (reflectionClasses.size() == 0) return null;
for (Enum<?> enumConstant : enums) EnumPropertyCache.register(enumConstant.name(), enumConstant, this.reflectionClass); Enum<?>[] enums = (Enum<?>[]) this.reflectionClasses.get(0).getEnumConstants();
for (Enum<?> enumConstant : enums) EnumPropertyCache.register(enumConstant.name(), enumConstant, this.reflectionClasses.get(0));
return enums; return enums;
} }
} }

@ -5,6 +5,7 @@ import io.github.znetworkw.znpcservers.reflection.ReflectionBuilder;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.List; import java.util.List;
import java.util.function.Consumer;
public class FieldReflection extends ReflectionLazyLoader<Field> { public class FieldReflection extends ReflectionLazyLoader<Field> {
private final String fieldName; private final String fieldName;
@ -17,39 +18,64 @@ public class FieldReflection extends ReflectionLazyLoader<Field> {
} }
protected Field load() throws NoSuchFieldException { protected Field load() throws NoSuchFieldException {
if (expectType != null) for (Class<?> clazz : this.reflectionClasses) {
for (Field field1 : this.reflectionClass.getDeclaredFields()) { Field field = load(clazz);
if (field1.getType() == expectType) { if (field != null) return field;
field1.setAccessible(true);
return field1;
} }
return null;
} }
Field field = this.reflectionClass.getDeclaredField(fieldName);
private Field load(Class<?> clazz) {
if (expectType != null) for (Field field : clazz.getDeclaredFields()) if (field.getType() == expectType) {
field.setAccessible(true); field.setAccessible(true);
return field; return field;
} }
try {
public FieldValueReflection staticValueLoader() { Field field = clazz.getDeclaredField(fieldName);
return new FieldValueReflection(this, possibleClassNames, null); field.setAccessible(true);
return field;
} catch (NoSuchFieldException ignored) {}
return null;
} }
public FieldValueReflection valueLoader(Object obj) { @Override
return new FieldValueReflection(this, possibleClassNames, obj); protected void printDebugInfo(Consumer<String> logger) {
logger.accept("Field Name: " + fieldName);
logger.accept("Field Type: " + expectType);
} }
private static class FieldValueReflection extends ReflectionLazyLoader<Object> { public FieldValueReflection<Object> staticValueLoader() {
return staticValueLoader(Object.class);
}
@SuppressWarnings("unused")
public <T> FieldValueReflection<T> staticValueLoader(Class<T> valueType) {
return new FieldValueReflection<>(this, possibleClassNames, null, strict);
}
@SuppressWarnings("unused")
public <T> FieldValueReflection<T> valueLoader(Object obj, Class<T> valueType) {
return new FieldValueReflection<>(this, possibleClassNames, obj, strict);
}
private static class FieldValueReflection<T> extends ReflectionLazyLoader<T> {
private final Object obj; private final Object obj;
private final FieldReflection fieldReflection; private final FieldReflection fieldReflection;
public FieldValueReflection(FieldReflection fieldReflection, List<String> className, Object obj) { public FieldValueReflection(FieldReflection fieldReflection, List<String> className, Object obj, boolean strict) {
super(className); super(className, strict);
this.obj = obj; this.obj = obj;
this.fieldReflection = fieldReflection; this.fieldReflection = fieldReflection;
} }
protected Object load() throws IllegalAccessException, NoSuchFieldException { @SuppressWarnings("unchecked")
Field field = this.fieldReflection.get(); protected T load() throws IllegalAccessException, NoSuchFieldException, ClassCastException {
return field.get(obj); return (T) this.fieldReflection.get().get(obj);
}
@Override
protected void printDebugInfo(Consumer<String> logger) {
fieldReflection.printDebugInfo(logger);
} }
} }
} }

@ -1,11 +1,12 @@
package io.github.znetworkw.znpcservers.reflection.types; package io.github.znetworkw.znpcservers.reflection.types;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import io.github.znetworkw.znpcservers.reflection.ReflectionLazyLoader;
import io.github.znetworkw.znpcservers.reflection.ReflectionBuilder; import io.github.znetworkw.znpcservers.reflection.ReflectionBuilder;
import io.github.znetworkw.znpcservers.reflection.ReflectionLazyLoader;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.*;
import java.util.function.Consumer;
public class MethodReflection extends ReflectionLazyLoader<Method> { public class MethodReflection extends ReflectionLazyLoader<Method> {
private final ImmutableList<String> methods; private final ImmutableList<String> methods;
@ -20,17 +21,43 @@ public class MethodReflection extends ReflectionLazyLoader<Method> {
} }
protected Method load() { protected Method load() {
Method methodThis = null; Map<Integer, List<Method>> imperfectMatches = new HashMap<>();
boolean hasExpectedType = (expectType != null); for (Class<?> clazz : this.reflectionClasses) {
if (methods.isEmpty() && hasExpectedType) for (Method method : this.reflectionClass.getDeclaredMethods()) if (method.getReturnType() == expectType) return method; Method method = load(clazz, imperfectMatches);
for (String methodName : methods) try { if (method != null) return method;
Method maybeGet; }
if (!Iterables.isEmpty(parameterTypes)) maybeGet = this.reflectionClass.getDeclaredMethod(methodName, Iterables.get(parameterTypes, 0)); for (int i = 2; i > 0; i--) if (imperfectMatches.containsKey(i)) {
else maybeGet = this.reflectionClass.getDeclaredMethod(methodName); return imperfectMatches.get(i).get(0);
if (expectType != null && expectType != maybeGet.getReturnType()) continue; }
maybeGet.setAccessible(true); return null;
methodThis = maybeGet; }
} catch (NoSuchMethodException ignored) {}
return methodThis; private Method load(Class<?> clazz, Map<Integer, List<Method>> imperfectMatches) {
for (Method method : clazz.getDeclaredMethods()) {
int matches = 0;
if (expectType != null) {
if (!method.getReturnType().equals(expectType)) continue;
matches++;
}
if (parameterTypes.size() > 0) out: for (Class<?>[] possible : parameterTypes) {
if (method.getParameterCount() != possible.length) continue;
for (int i = 0; i < possible.length; i++) if (!method.getParameterTypes()[i].equals(possible[i])) continue out;
matches++;
}
if (methods.contains(method.getName())) {
matches++;
}
if (matches == 3) return method;
else imperfectMatches.computeIfAbsent(matches, i -> new ArrayList<>()).add(method);
}
return null;
}
@Override
protected void printDebugInfo(Consumer<String> logger) {
logger.accept("Expected Return Type: " + expectType);
logger.accept("Possible method names: " + methods);
logger.accept("Possible Parameter Type Combinations:");
for (Class<?>[] possible : parameterTypes) logger.accept(Arrays.toString(possible));
} }
} }