diff --git a/src/main/java/io/github/znetworkw/znpcservers/commands/Command.java b/src/main/java/io/github/znetworkw/znpcservers/commands/Command.java index a8d150e..1a53a2c 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/commands/Command.java +++ b/src/main/java/io/github/znetworkw/znpcservers/commands/Command.java @@ -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.reflection.Reflections; import org.bukkit.ChatColor; -import org.bukkit.command.CommandMap; import org.bukkit.command.CommandSender; import org.bukkit.command.defaults.BukkitCommand; @@ -23,7 +22,7 @@ public class Command extends BukkitCommand { } 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()) { if (method.isAnnotationPresent(CommandInformation.class)) { CommandInformation cmdInfo = method.getAnnotation(CommandInformation.class); diff --git a/src/main/java/io/github/znetworkw/znpcservers/npc/packet/PacketV19.java b/src/main/java/io/github/znetworkw/znpcservers/npc/packet/PacketV19.java index db096dd..d8de7b6 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/npc/packet/PacketV19.java +++ b/src/main/java/io/github/znetworkw/znpcservers/npc/packet/PacketV19.java @@ -11,7 +11,7 @@ public class PacketV19 extends PacketV18 { public Object getPlayerPacket(Object nmsWorld, GameProfile gameProfile) throws ReflectiveOperationException { 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) { return Reflections.PLAYER_CONSTRUCTOR_NEW_2.get().newInstance(Reflections.GET_SERVER_METHOD.get().invoke(Bukkit.getServer()), nmsWorld, gameProfile); } diff --git a/src/main/java/io/github/znetworkw/znpcservers/npc/packet/PacketV8.java b/src/main/java/io/github/znetworkw/znpcservers/npc/packet/PacketV8.java index 51efbc0..08bbd65 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/npc/packet/PacketV8.java +++ b/src/main/java/io/github/znetworkw/znpcservers/npc/packet/PacketV8.java @@ -39,7 +39,7 @@ public class PacketV8 implements Packet { public Object getMetadataPacket(int entityId, Object nmsEntity) throws ReflectiveOperationException { Object dataWatcher = Reflections.GET_DATA_WATCHER_METHOD.get().invoke(nmsEntity); 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) { return Reflections.PACKET_PLAY_OUT_ENTITY_META_DATA_CONSTRUCTOR_V1.get().newInstance(entityId, Reflections.GET_DATAWATCHER_B_LIST.get().invoke(dataWatcher)); } diff --git a/src/main/java/io/github/znetworkw/znpcservers/reflection/ReflectionBuilder.java b/src/main/java/io/github/znetworkw/znpcservers/reflection/ReflectionBuilder.java index d486bba..c4e3fb3 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/reflection/ReflectionBuilder.java +++ b/src/main/java/io/github/znetworkw/znpcservers/reflection/ReflectionBuilder.java @@ -13,6 +13,7 @@ public class ReflectionBuilder { private final ArrayList methods = new ArrayList<>(); private final ArrayList[]> parameterTypes = new ArrayList<>(); private Class expectType; + private boolean strict = true; public ReflectionBuilder(String reflectionPackage) { this(reflectionPackage, "", "", null); @@ -60,6 +61,15 @@ public class ReflectionBuilder { return this; } + public ReflectionBuilder setStrict(boolean strict) { + this.strict = strict; + return this; + } + + public boolean isStrict() { + return strict; + } + public Class getExpectType() { return expectType; } diff --git a/src/main/java/io/github/znetworkw/znpcservers/reflection/ReflectionLazyLoader.java b/src/main/java/io/github/znetworkw/znpcservers/reflection/ReflectionLazyLoader.java index 26b2f07..4ef12a8 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/reflection/ReflectionLazyLoader.java +++ b/src/main/java/io/github/znetworkw/znpcservers/reflection/ReflectionLazyLoader.java @@ -3,50 +3,46 @@ package io.github.znetworkw.znpcservers.reflection; import io.github.znetworkw.znpcservers.utility.Utils; import lol.pyr.znpcsplus.ZNPCsPlus; +import java.util.ArrayList; import java.util.List; +import java.util.function.Consumer; public abstract class ReflectionLazyLoader { protected final List possibleClassNames; - - protected Class reflectionClass; - + protected List> reflectionClasses = new ArrayList<>(); + protected final boolean strict; private T cached; - private boolean loaded = false; protected ReflectionLazyLoader(ReflectionBuilder builder) { - this(builder.getClassNames()); + this(builder.getClassNames(), builder.isStrict()); } - protected ReflectionLazyLoader(List possibleClassNames) { + protected ReflectionLazyLoader(List possibleClassNames, boolean strict) { this.possibleClassNames = possibleClassNames; - for (String classes : possibleClassNames) { - try { - this.reflectionClass = Class.forName(classes); - break; - } catch (ClassNotFoundException ignored) { - } - } + this.strict = strict; + for (String name : possibleClassNames) try { + reflectionClasses.add(Class.forName(name)); + } catch (ClassNotFoundException ignored) {} } public T get() { - return get(false); - } - - public T get(boolean missAllowed) { if (this.loaded) return this.cached; 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()); - if (eval == null) throw new NullPointerException(); + if (eval == null) throw new RuntimeException("Returned value is null"); } catch (Throwable throwable) { - if (!missAllowed) { - warn(getClass().getSimpleName() + " get failed!"); + if (strict) { + warn(" ----- REFLECTION FAILURE DEBUG INFORMATION, REPORT THIS ON OUR GITHUB ----- "); + warn(getClass().getSimpleName() + " failed!"); warn("Class Names: " + possibleClassNames); - warn("Loader Type: " + getClass().getCanonicalName()); + warn("Reflection Type: " + getClass().getCanonicalName()); warn("Bukkit Version: " + Utils.BUKKIT_VERSION + " (" + Utils.getBukkitPackage() + ")"); + printDebugInfo(this::warn); warn("Exception:"); throwable.printStackTrace(); + warn(" ----- REFLECTION FAILURE DEBUG INFORMATION, REPORT THIS ON OUR GITHUB ----- "); } } this.loaded = true; @@ -58,4 +54,5 @@ public abstract class ReflectionLazyLoader { } protected abstract T load() throws Exception; + protected void printDebugInfo(Consumer logger) {} } \ No newline at end of file diff --git a/src/main/java/io/github/znetworkw/znpcservers/reflection/Reflections.java b/src/main/java/io/github/znetworkw/znpcservers/reflection/Reflections.java index c83cb8d..4fe745b 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/reflection/Reflections.java +++ b/src/main/java/io/github/znetworkw/znpcservers/reflection/Reflections.java @@ -1,10 +1,14 @@ package io.github.znetworkw.znpcservers.reflection; 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.netty.channel.Channel; import org.bukkit.Bukkit; +import org.bukkit.command.CommandMap; import org.bukkit.inventory.ItemStack; 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) .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) .withSubClass("monster") @@ -120,20 +125,24 @@ public final class Reflections { public static final Class ENTITY_TURTLE = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) .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) .withSubClass("monster.warden") .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) .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) .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) .withSubClass("animal") @@ -145,11 +154,13 @@ public final class Reflections { public static final Class ENTITY_POLAR_BEAR_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) .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) .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) .withSubClass("animal") @@ -161,7 +172,8 @@ public final class Reflections { public static final Class ENTITY_SHULKER_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) .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) .withSubClass("monster") @@ -205,15 +217,18 @@ public final class Reflections { public static final Class ENTITY_AXOLOTL_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.ENTITY) .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) .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) .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) .withClassName("EntityTypes")).get(); @@ -222,7 +237,8 @@ public final class Reflections { .withClassName("EnumChatFormat")).get(); 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) .withClassName("IChatBaseComponent")).get(); @@ -231,16 +247,20 @@ public final class Reflections { .withClassName("ItemStack")).get(); 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) - .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) - .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) - .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) .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) .withClassName("PacketPlayOutPlayerInfo") - .withClassName("ClientboundPlayerInfoUpdatePacket")) - .get(); + .withClassName("ClientboundPlayerInfoUpdatePacket")).get(); public static final Class PACKET_PLAY_OUT_PLAYER_INFO_REMOVE_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.PACKET) - .withClassName("ClientboundPlayerInfoRemovePacket")) - .get(true); + .withClassName("ClientboundPlayerInfoRemovePacket") + .setStrict(false)).get(); public static final Class PACKET_PLAY_OUT_SCOREBOARD_TEAM_CLASS = new ClassReflection(new ReflectionBuilder(ReflectionPackage.PACKET) .withClassName("PacketPlayOutScoreboardTeam")).get(); @@ -291,7 +310,8 @@ public final class Reflections { .withClassName("util.CraftChatMessage")).get(); 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> SCOREBOARD_TEAM_CONSTRUCTOR = new ConstructorReflection(new ReflectionBuilder(ReflectionPackage.PACKET) .withClassName(SCOREBOARD_TEAM_CLASS) @@ -307,7 +327,8 @@ public final class Reflections { public static final ReflectionLazyLoader> PLAYER_CONSTRUCTOR_NEW_1 = new ConstructorReflection(new ReflectionBuilder(ReflectionPackage.PACKET) .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> PLAYER_CONSTRUCTOR_NEW_2 = new ConstructorReflection(new ReflectionBuilder(ReflectionPackage.PACKET) .withClassName(ENTITY_PLAYER_CLASS) @@ -335,7 +356,8 @@ public final class Reflections { public static final ReflectionLazyLoader> PACKET_PLAY_OUT_ENTITY_META_DATA_CONSTRUCTOR = new ConstructorReflection(new ReflectionBuilder(ReflectionPackage.PACKET) .withClassName("PacketPlayOutEntityMetadata") - .withParameterTypes(int.class, DATA_WATCHER_CLASS, boolean.class)); + .withParameterTypes(int.class, DATA_WATCHER_CLASS, boolean.class) + .setStrict(false)); public static final ReflectionLazyLoader> PACKET_PLAY_OUT_ENTITY_META_DATA_CONSTRUCTOR_V1 = new ConstructorReflection(new ReflectionBuilder(ReflectionPackage.PACKET) .withClassName("PacketPlayOutEntityMetadata") @@ -558,7 +580,7 @@ public final class Reflections { .withClassName(ENUM_TAG_VISIBILITY) .withFieldName("b")).staticValueLoader(); - public static final ReflectionLazyLoader COMMAND_MAP_FIELD = new FieldReflection(new ReflectionBuilder(ReflectionPackage.BUKKIT) + public static final ReflectionLazyLoader COMMAND_MAP_FIELD = new FieldReflection(new ReflectionBuilder(ReflectionPackage.BUKKIT) .withClassName("CraftServer") - .withFieldName("commandMap")).valueLoader(Bukkit.getServer()); + .withFieldName("commandMap")).valueLoader(Bukkit.getServer(), CommandMap.class); } diff --git a/src/main/java/io/github/znetworkw/znpcservers/reflection/types/ClassReflection.java b/src/main/java/io/github/znetworkw/znpcservers/reflection/types/ClassReflection.java index 6b06b9b..29dfe41 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/reflection/types/ClassReflection.java +++ b/src/main/java/io/github/znetworkw/znpcservers/reflection/types/ClassReflection.java @@ -1,7 +1,7 @@ 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.ReflectionLazyLoader; public class ClassReflection extends ReflectionLazyLoader> { public ClassReflection(ReflectionBuilder reflectionBuilder) { @@ -9,6 +9,6 @@ public class ClassReflection extends ReflectionLazyLoader> { } protected Class load() { - return this.reflectionClass; + return this.reflectionClasses.size() > 0 ? this.reflectionClasses.get(0) : null; } } \ No newline at end of file diff --git a/src/main/java/io/github/znetworkw/znpcservers/reflection/types/ConstructorReflection.java b/src/main/java/io/github/znetworkw/znpcservers/reflection/types/ConstructorReflection.java index 250bc35..87871b0 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/reflection/types/ConstructorReflection.java +++ b/src/main/java/io/github/znetworkw/znpcservers/reflection/types/ConstructorReflection.java @@ -1,11 +1,12 @@ package io.github.znetworkw.znpcservers.reflection.types; 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.ReflectionLazyLoader; import java.lang.reflect.Constructor; +import java.util.Arrays; +import java.util.function.Consumer; public class ConstructorReflection extends ReflectionLazyLoader> { private final ImmutableList[]> parameterTypes; @@ -16,13 +17,28 @@ public class ConstructorReflection extends ReflectionLazyLoader> } protected Constructor load() throws NoSuchMethodException { - Constructor constructor = null; - if (Iterables.size(parameterTypes) > 1) { - for (Class[] keyParameters : parameterTypes) try { - constructor = this.reflectionClass.getDeclaredConstructor(keyParameters); - } catch (NoSuchMethodException ignored) {} - } else constructor = (Iterables.size(parameterTypes) > 0) ? this.reflectionClass.getDeclaredConstructor(Iterables.get(parameterTypes, 0)) : this.reflectionClass.getDeclaredConstructor(); - if (constructor != null) constructor.setAccessible(true); - return constructor; + for (Class clazz : this.reflectionClasses) { + Constructor constructor = load(clazz); + if (constructor != null) return constructor; + } + return null; + } + + 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; + } catch (NoSuchMethodException ignored) {} + else try { + return clazz.getDeclaredConstructor(); + } catch (NoSuchMethodException ignored) {} + return null; + } + + @Override + protected void printDebugInfo(Consumer logger) { + logger.accept("Possible Parameter Type Combinations:"); + for (Class[] possible : parameterTypes) logger.accept(Arrays.toString(possible)); } } \ No newline at end of file diff --git a/src/main/java/io/github/znetworkw/znpcservers/reflection/types/EnumReflection.java b/src/main/java/io/github/znetworkw/znpcservers/reflection/types/EnumReflection.java index ddf4cbf..43737ec 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/reflection/types/EnumReflection.java +++ b/src/main/java/io/github/znetworkw/znpcservers/reflection/types/EnumReflection.java @@ -1,8 +1,8 @@ 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.ReflectionBuilder; +import io.github.znetworkw.znpcservers.reflection.ReflectionLazyLoader; public class EnumReflection extends ReflectionLazyLoader[]> { public EnumReflection(ReflectionBuilder reflectionBuilder) { @@ -10,8 +10,9 @@ public class EnumReflection extends ReflectionLazyLoader[]> { } protected Enum[] load() { - Enum[] enums = (Enum[]) this.reflectionClass.getEnumConstants(); - for (Enum enumConstant : enums) EnumPropertyCache.register(enumConstant.name(), enumConstant, this.reflectionClass); + if (reflectionClasses.size() == 0) return null; + Enum[] enums = (Enum[]) this.reflectionClasses.get(0).getEnumConstants(); + for (Enum enumConstant : enums) EnumPropertyCache.register(enumConstant.name(), enumConstant, this.reflectionClasses.get(0)); return enums; } } \ No newline at end of file diff --git a/src/main/java/io/github/znetworkw/znpcservers/reflection/types/FieldReflection.java b/src/main/java/io/github/znetworkw/znpcservers/reflection/types/FieldReflection.java index 70e34c6..3262a93 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/reflection/types/FieldReflection.java +++ b/src/main/java/io/github/znetworkw/znpcservers/reflection/types/FieldReflection.java @@ -5,6 +5,7 @@ import io.github.znetworkw.znpcservers.reflection.ReflectionBuilder; import java.lang.reflect.Field; import java.util.List; +import java.util.function.Consumer; public class FieldReflection extends ReflectionLazyLoader { private final String fieldName; @@ -17,39 +18,64 @@ public class FieldReflection extends ReflectionLazyLoader { } protected Field load() throws NoSuchFieldException { - if (expectType != null) - for (Field field1 : this.reflectionClass.getDeclaredFields()) { - if (field1.getType() == expectType) { - field1.setAccessible(true); - return field1; - } - } - Field field = this.reflectionClass.getDeclaredField(fieldName); - field.setAccessible(true); - return field; + for (Class clazz : this.reflectionClasses) { + Field field = load(clazz); + if (field != null) return field; + } + return null; } - public FieldValueReflection staticValueLoader() { - return new FieldValueReflection(this, possibleClassNames, null); + private Field load(Class clazz) { + if (expectType != null) for (Field field : clazz.getDeclaredFields()) if (field.getType() == expectType) { + field.setAccessible(true); + return field; + } + try { + Field field = clazz.getDeclaredField(fieldName); + field.setAccessible(true); + return field; + } catch (NoSuchFieldException ignored) {} + return null; } - public FieldValueReflection valueLoader(Object obj) { - return new FieldValueReflection(this, possibleClassNames, obj); + @Override + protected void printDebugInfo(Consumer logger) { + logger.accept("Field Name: " + fieldName); + logger.accept("Field Type: " + expectType); } - private static class FieldValueReflection extends ReflectionLazyLoader { + public FieldValueReflection staticValueLoader() { + return staticValueLoader(Object.class); + } + + @SuppressWarnings("unused") + public FieldValueReflection staticValueLoader(Class valueType) { + return new FieldValueReflection<>(this, possibleClassNames, null, strict); + } + + @SuppressWarnings("unused") + public FieldValueReflection valueLoader(Object obj, Class valueType) { + return new FieldValueReflection<>(this, possibleClassNames, obj, strict); + } + + private static class FieldValueReflection extends ReflectionLazyLoader { private final Object obj; private final FieldReflection fieldReflection; - public FieldValueReflection(FieldReflection fieldReflection, List className, Object obj) { - super(className); + public FieldValueReflection(FieldReflection fieldReflection, List className, Object obj, boolean strict) { + super(className, strict); this.obj = obj; this.fieldReflection = fieldReflection; } - protected Object load() throws IllegalAccessException, NoSuchFieldException { - Field field = this.fieldReflection.get(); - return field.get(obj); + @SuppressWarnings("unchecked") + protected T load() throws IllegalAccessException, NoSuchFieldException, ClassCastException { + return (T) this.fieldReflection.get().get(obj); + } + + @Override + protected void printDebugInfo(Consumer logger) { + fieldReflection.printDebugInfo(logger); } } } \ No newline at end of file diff --git a/src/main/java/io/github/znetworkw/znpcservers/reflection/types/MethodReflection.java b/src/main/java/io/github/znetworkw/znpcservers/reflection/types/MethodReflection.java index 50410ef..cb912e1 100644 --- a/src/main/java/io/github/znetworkw/znpcservers/reflection/types/MethodReflection.java +++ b/src/main/java/io/github/znetworkw/znpcservers/reflection/types/MethodReflection.java @@ -1,11 +1,12 @@ package io.github.znetworkw.znpcservers.reflection.types; 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.ReflectionLazyLoader; import java.lang.reflect.Method; +import java.util.*; +import java.util.function.Consumer; public class MethodReflection extends ReflectionLazyLoader { private final ImmutableList methods; @@ -20,17 +21,43 @@ public class MethodReflection extends ReflectionLazyLoader { } protected Method load() { - Method methodThis = null; - boolean hasExpectedType = (expectType != null); - if (methods.isEmpty() && hasExpectedType) for (Method method : this.reflectionClass.getDeclaredMethods()) if (method.getReturnType() == expectType) return method; - for (String methodName : methods) try { - Method maybeGet; - if (!Iterables.isEmpty(parameterTypes)) maybeGet = this.reflectionClass.getDeclaredMethod(methodName, Iterables.get(parameterTypes, 0)); - else maybeGet = this.reflectionClass.getDeclaredMethod(methodName); - if (expectType != null && expectType != maybeGet.getReturnType()) continue; - maybeGet.setAccessible(true); - methodThis = maybeGet; - } catch (NoSuchMethodException ignored) {} - return methodThis; + Map> imperfectMatches = new HashMap<>(); + for (Class clazz : this.reflectionClasses) { + Method method = load(clazz, imperfectMatches); + if (method != null) return method; + } + for (int i = 2; i > 0; i--) if (imperfectMatches.containsKey(i)) { + return imperfectMatches.get(i).get(0); + } + return null; + } + + private Method load(Class clazz, Map> 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 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)); } } \ No newline at end of file