Code cleanup
This commit is contained in:
		| @@ -89,10 +89,10 @@ public class LibsDisguises extends JavaPlugin { | ||||
|  | ||||
|         ReflectionManager.init(); | ||||
|  | ||||
|         PacketsManager.init(this); | ||||
|         DisguiseUtilities.init(this); | ||||
|         PacketsManager.init(); | ||||
|         DisguiseUtilities.init(); | ||||
|  | ||||
|         registerValues(); | ||||
|         ReflectionManager.registerValues(); | ||||
|  | ||||
|         DisguiseConfig.loadConfig(); | ||||
|  | ||||
| @@ -171,346 +171,6 @@ public class LibsDisguises extends JavaPlugin { | ||||
|         DisguiseConfig.loadConfig(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Here we create a nms entity for each disguise. Then grab their default values in their datawatcher. Then their | ||||
|      * sound volume | ||||
|      * for mob noises. As well as setting their watcher class and entity size. | ||||
|      */ | ||||
|     private void registerValues() { | ||||
|         for (DisguiseType disguiseType : DisguiseType.values()) { | ||||
|             if (disguiseType.getEntityType() == null) { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             Class watcherClass; | ||||
|  | ||||
|             try { | ||||
|                 switch (disguiseType) { | ||||
|                     case ARROW: | ||||
|                         watcherClass = TippedArrowWatcher.class; | ||||
|                         break; | ||||
|                     case COD: | ||||
|                     case SALMON: | ||||
|                         watcherClass = FishWatcher.class; | ||||
|                         break; | ||||
|                     case SPECTRAL_ARROW: | ||||
|                         watcherClass = ArrowWatcher.class; | ||||
|                         break; | ||||
|                     case PRIMED_TNT: | ||||
|                         watcherClass = TNTWatcher.class; | ||||
|                         break; | ||||
|                     case MINECART_CHEST: | ||||
|                     case MINECART_HOPPER: | ||||
|                     case MINECART_MOB_SPAWNER: | ||||
|                     case MINECART_TNT: | ||||
|                         watcherClass = MinecartWatcher.class; | ||||
|                         break; | ||||
|                     case SPIDER: | ||||
|                     case CAVE_SPIDER: | ||||
|                         watcherClass = SpiderWatcher.class; | ||||
|                         break; | ||||
|                     case PIG_ZOMBIE: | ||||
|                     case HUSK: | ||||
|                     case DROWNED: | ||||
|                         watcherClass = ZombieWatcher.class; | ||||
|                         break; | ||||
|                     case MAGMA_CUBE: | ||||
|                         watcherClass = SlimeWatcher.class; | ||||
|                         break; | ||||
|                     case ELDER_GUARDIAN: | ||||
|                         watcherClass = GuardianWatcher.class; | ||||
|                         break; | ||||
|                     case WITHER_SKELETON: | ||||
|                     case STRAY: | ||||
|                         watcherClass = SkeletonWatcher.class; | ||||
|                         break; | ||||
|                     case ILLUSIONER: | ||||
|                     case EVOKER: | ||||
|                         watcherClass = IllagerWizardWatcher.class; | ||||
|                         break; | ||||
|                     case PUFFERFISH: | ||||
|                         watcherClass = PufferFishWatcher.class; | ||||
|                         break; | ||||
|                     default: | ||||
|                         watcherClass = Class.forName( | ||||
|                                 "me.libraryaddict.disguise.disguisetypes.watchers." + toReadable(disguiseType.name()) + | ||||
|                                         "Watcher"); | ||||
|                         break; | ||||
|                 } | ||||
|             } | ||||
|             catch (ClassNotFoundException ex) { | ||||
|                 // There is no explicit watcher for this entity. | ||||
|                 Class entityClass = disguiseType.getEntityType().getEntityClass(); | ||||
|  | ||||
|                 if (entityClass != null) { | ||||
|                     if (Tameable.class.isAssignableFrom(entityClass)) { | ||||
|                         watcherClass = TameableWatcher.class; | ||||
|                     } else if (Ageable.class.isAssignableFrom(entityClass)) { | ||||
|                         watcherClass = AgeableWatcher.class; | ||||
|                     } else if (Creature.class.isAssignableFrom(entityClass)) { | ||||
|                         watcherClass = InsentientWatcher.class; | ||||
|                     } else if (LivingEntity.class.isAssignableFrom(entityClass)) { | ||||
|                         watcherClass = LivingWatcher.class; | ||||
|                     } else if (Fish.class.isAssignableFrom(entityClass)) { | ||||
|                         watcherClass = FishWatcher.class; | ||||
|                     } else { | ||||
|                         watcherClass = FlagWatcher.class; | ||||
|                     } | ||||
|                 } else { | ||||
|                     watcherClass = FlagWatcher.class; // Disguise is unknown type | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             if (watcherClass == null) { | ||||
|                 getLogger().severe("Error loading " + disguiseType.name() + ", FlagWatcher not assigned"); | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             // Invalidate invalid distribution | ||||
|             if (LibsPremium.isPremium() && | ||||
|                     ((LibsPremium.getPaidInformation() != null && LibsPremium.getPaidInformation().isPremium() && | ||||
|                             !LibsPremium.getPaidInformation().isLegit()) || | ||||
|                             (LibsPremium.getPluginInformation() != null && | ||||
|                                     LibsPremium.getPluginInformation().isPremium() && | ||||
|                                     !LibsPremium.getPluginInformation().isLegit()))) { | ||||
|                 throw new IllegalStateException( | ||||
|                         "Error while checking pi rate on startup! Please re-download the jar from SpigotMC before " + | ||||
|                                 "reporting this error!"); | ||||
|             } | ||||
|  | ||||
|             disguiseType.setWatcherClass(watcherClass); | ||||
|  | ||||
|             if (DisguiseValues.getDisguiseValues(disguiseType) != null) { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             String nmsEntityName = toReadable(disguiseType.name()); | ||||
|             Class nmsClass = ReflectionManager.getNmsClassIgnoreErrors("Entity" + nmsEntityName); | ||||
|  | ||||
|             if (nmsClass == null || Modifier.isAbstract(nmsClass.getModifiers())) { | ||||
|                 String[] split = splitReadable(disguiseType.name()); | ||||
|                 ArrayUtils.reverse(split); | ||||
|  | ||||
|                 nmsEntityName = StringUtils.join(split); | ||||
|                 nmsClass = ReflectionManager.getNmsClassIgnoreErrors("Entity" + nmsEntityName); | ||||
|  | ||||
|                 if (nmsClass == null || Modifier.isAbstract(nmsClass.getModifiers())) { | ||||
|                     nmsEntityName = null; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             if (nmsEntityName == null) { | ||||
|                 switch (disguiseType) { | ||||
|                     case DONKEY: | ||||
|                         nmsEntityName = "HorseDonkey"; | ||||
|                         break; | ||||
|                     case ARROW: | ||||
|                         nmsEntityName = "TippedArrow"; | ||||
|                         break; | ||||
|                     case DROPPED_ITEM: | ||||
|                         nmsEntityName = "Item"; | ||||
|                         break; | ||||
|                     case FIREBALL: | ||||
|                         nmsEntityName = "LargeFireball"; | ||||
|                         break; | ||||
|                     case FIREWORK: | ||||
|                         nmsEntityName = "Fireworks"; | ||||
|                         break; | ||||
|                     case GIANT: | ||||
|                         nmsEntityName = "GiantZombie"; | ||||
|                         break; | ||||
|                     case HUSK: | ||||
|                         nmsEntityName = "ZombieHusk"; | ||||
|                         break; | ||||
|                     case ILLUSIONER: | ||||
|                         nmsEntityName = "IllagerIllusioner"; | ||||
|                         break; | ||||
|                     case LEASH_HITCH: | ||||
|                         nmsEntityName = "Leash"; | ||||
|                         break; | ||||
|                     case MINECART: | ||||
|                         nmsEntityName = "MinecartRideable"; | ||||
|                         break; | ||||
|                     case MINECART_COMMAND: | ||||
|                         nmsEntityName = "MinecartCommandBlock"; | ||||
|                         break; | ||||
|                     case MINECART_TNT: | ||||
|                         nmsEntityName = "MinecartTNT"; | ||||
|                         break; | ||||
|                     case MULE: | ||||
|                         nmsEntityName = "HorseMule"; | ||||
|                         break; | ||||
|                     case PRIMED_TNT: | ||||
|                         nmsEntityName = "TNTPrimed"; | ||||
|                         break; | ||||
|                     case PUFFERFISH: | ||||
|                         nmsEntityName = "PufferFish"; | ||||
|                         break; | ||||
|                     case SPLASH_POTION: | ||||
|                         nmsEntityName = "Potion"; | ||||
|                         break; | ||||
|                     case STRAY: | ||||
|                         nmsEntityName = "SkeletonStray"; | ||||
|                         break; | ||||
|                     case TRIDENT: | ||||
|                         nmsEntityName = "ThrownTrident"; | ||||
|                         break; | ||||
|                     case WANDERING_TRADER: | ||||
|                         nmsEntityName = "VillagerTrader"; | ||||
|                         break; | ||||
|                     case TRADER_LLAMA: | ||||
|                         nmsEntityName = "LLamaTrader"; // Interesting capitalization | ||||
|                         break; | ||||
|                     default: | ||||
|                         break; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             try { | ||||
|                 if (disguiseType == DisguiseType.UNKNOWN) { | ||||
|                     DisguiseValues disguiseValues = new DisguiseValues(disguiseType, null, 0, 0); | ||||
|  | ||||
|                     disguiseValues.setAdultBox(new FakeBoundingBox(0, 0, 0)); | ||||
|  | ||||
|                     DisguiseSound sound = DisguiseSound.getType(disguiseType.name()); | ||||
|  | ||||
|                     if (sound != null) { | ||||
|                         sound.setDamageAndIdleSoundVolume(1f); | ||||
|                     } | ||||
|  | ||||
|                     continue; | ||||
|                 } | ||||
|  | ||||
|                 if (nmsEntityName == null) { | ||||
|                     getLogger().warning("Entity name not found! (" + disguiseType.name() + ")"); | ||||
|                     continue; | ||||
|                 } | ||||
|  | ||||
|                 Object nmsEntity = ReflectionManager.createEntityInstance(disguiseType, nmsEntityName); | ||||
|  | ||||
|                 if (nmsEntity == null) { | ||||
|                     getLogger().warning("Entity not found! (" + nmsEntityName + ")"); | ||||
|                     continue; | ||||
|                 } | ||||
|  | ||||
|                 disguiseType.setTypeId(ReflectionManager.getEntityTypeId(disguiseType.getEntityType())); | ||||
|  | ||||
|                 Entity bukkitEntity = ReflectionManager.getBukkitEntity(nmsEntity); | ||||
|  | ||||
|                 int entitySize = 0; | ||||
|  | ||||
|                 for (Field field : ReflectionManager.getNmsClass("Entity").getFields()) { | ||||
|                     if (field.getType().getName().equals("EnumEntitySize")) { | ||||
|                         Enum enumEntitySize = (Enum) field.get(nmsEntity); | ||||
|  | ||||
|                         entitySize = enumEntitySize.ordinal(); | ||||
|  | ||||
|                         break; | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 DisguiseValues disguiseValues = new DisguiseValues(disguiseType, nmsEntity.getClass(), entitySize, | ||||
|                         bukkitEntity instanceof Damageable ? ((Damageable) bukkitEntity).getMaxHealth() : 0); | ||||
|  | ||||
|                 WrappedDataWatcher watcher = WrappedDataWatcher.getEntityWatcher(bukkitEntity); | ||||
|                 ArrayList<MetaIndex> indexes = MetaIndex.getMetaIndexes(disguiseType.getWatcherClass()); | ||||
|                 boolean loggedName = false; | ||||
|  | ||||
|                 for (WrappedWatchableObject watch : watcher.getWatchableObjects()) { | ||||
|                     MetaIndex flagType = MetaIndex.getMetaIndex(watcherClass, watch.getIndex()); | ||||
|  | ||||
|                     if (flagType == null) { | ||||
|                         getLogger().severe("MetaIndex not found for " + disguiseType + "! Index: " + watch.getIndex()); | ||||
|                         getLogger().severe("Value: " + watch.getRawValue() + " (" + watch.getRawValue().getClass() + | ||||
|                                 ") (" + nmsEntity.getClass() + ") & " + watcherClass.getSimpleName()); | ||||
|                         continue; | ||||
|                     } | ||||
|  | ||||
|                     indexes.remove(flagType); | ||||
|  | ||||
|                     Object ourValue = ReflectionManager.convertInvalidMeta(flagType.getDefault()); | ||||
|                     Object nmsValue = ReflectionManager.convertInvalidMeta(watch.getValue()); | ||||
|  | ||||
|                     if (ourValue.getClass() != nmsValue.getClass()) { | ||||
|                         if (!loggedName) { | ||||
|                             getLogger().severe(StringUtils.repeat("=", 20)); | ||||
|                             getLogger().severe("MetaIndex mismatch! Disguise " + disguiseType + ", Entity " + | ||||
|                                     nmsEntityName); | ||||
|                             loggedName = true; | ||||
|                         } | ||||
|  | ||||
|                         getLogger().severe(StringUtils.repeat("-", 20)); | ||||
|                         getLogger().severe("Index: " + watch.getIndex() + " | " + | ||||
|                                 flagType.getFlagWatcher().getSimpleName() + " | " + MetaIndex.getName(flagType)); | ||||
|                         Object flagDefault = flagType.getDefault(); | ||||
|  | ||||
|                         getLogger().severe("LibsDisguises: " + flagDefault + " (" + flagDefault.getClass() + ")"); | ||||
|                         getLogger().severe("LibsDisguises Converted: " + ourValue + " (" + ourValue.getClass() + ")"); | ||||
|                         getLogger().severe("Minecraft: " + watch.getRawValue() + " (" + watch.getRawValue().getClass() + | ||||
|                                 ")"); | ||||
|                         getLogger().severe("Minecraft Converted: " + nmsValue + " (" + nmsValue.getClass() + ")"); | ||||
|                         getLogger().severe(StringUtils.repeat("-", 20)); | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 for (MetaIndex index : indexes) { | ||||
|                     getLogger().warning( | ||||
|                             disguiseType + " has MetaIndex remaining! " + index.getFlagWatcher().getSimpleName() + | ||||
|                                     " at index " + index.getIndex()); | ||||
|                 } | ||||
|  | ||||
|                 DisguiseSound sound = DisguiseSound.getType(disguiseType.name()); | ||||
|  | ||||
|                 if (sound != null) { | ||||
|                     Float soundStrength = ReflectionManager.getSoundModifier(nmsEntity); | ||||
|  | ||||
|                     if (soundStrength != null) { | ||||
|                         sound.setDamageAndIdleSoundVolume(soundStrength); | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 // Get the bounding box | ||||
|                 disguiseValues.setAdultBox(ReflectionManager.getBoundingBox(bukkitEntity)); | ||||
|  | ||||
|                 if (bukkitEntity instanceof Ageable) { | ||||
|                     ((Ageable) bukkitEntity).setBaby(); | ||||
|  | ||||
|                     disguiseValues.setBabyBox(ReflectionManager.getBoundingBox(bukkitEntity)); | ||||
|                 } else if (bukkitEntity instanceof Zombie) { | ||||
|                     ((Zombie) bukkitEntity).setBaby(true); | ||||
|  | ||||
|                     disguiseValues.setBabyBox(ReflectionManager.getBoundingBox(bukkitEntity)); | ||||
|                 } | ||||
|  | ||||
|                 //disguiseValues.setEntitySize(ReflectionManager.getSize(bukkitEntity)); | ||||
|             } | ||||
|             catch (SecurityException | IllegalArgumentException | IllegalAccessException | FieldAccessException ex) { | ||||
|                 getLogger().severe("Uh oh! Trouble while making values for the disguise " + disguiseType.name() + "!"); | ||||
|                 getLogger().severe("Before reporting this error, " + | ||||
|                         "please make sure you are using the latest version of LibsDisguises and ProtocolLib."); | ||||
|                 getLogger().severe("Development builds are available at (ProtocolLib) " + | ||||
|                         "http://ci.dmulloy2.net/job/ProtocolLib/ and (LibsDisguises) https://ci.md-5" + | ||||
|                         ".net/job/LibsDisguises/"); | ||||
|  | ||||
|                 ex.printStackTrace(); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private String[] splitReadable(String string) { | ||||
|         String[] split = string.split("_"); | ||||
|  | ||||
|         for (int i = 0; i < split.length; i++) { | ||||
|             split[i] = split[i].substring(0, 1) + split[i].substring(1).toLowerCase(); | ||||
|         } | ||||
|  | ||||
|         return split; | ||||
|     } | ||||
|  | ||||
|     private String toReadable(String string) { | ||||
|         return StringUtils.join(splitReadable(string)); | ||||
|     } | ||||
|  | ||||
|     public DisguiseListener getListener() { | ||||
|         return listener; | ||||
|     } | ||||
|   | ||||
| @@ -19,7 +19,6 @@ public class PacketsManager { | ||||
|     private static PacketListener clientInteractEntityListener; | ||||
|     private static PacketListener inventoryListener; | ||||
|     private static boolean inventoryModifierEnabled; | ||||
|     private static LibsDisguises libsDisguises; | ||||
|     private static PacketListener mainListener; | ||||
|     private static PacketListener soundsListener; | ||||
|     private static boolean soundsListenerEnabled; | ||||
| @@ -32,8 +31,8 @@ public class PacketsManager { | ||||
|         // You ain't supposed to be allowed to 'interact' with a item that cannot be clicked. | ||||
|         // Because it kicks you for hacking. | ||||
|  | ||||
|         clientInteractEntityListener = new PacketListenerClientInteract(libsDisguises); | ||||
|         PacketListener tabListListener = new PacketListenerTabList(libsDisguises); | ||||
|         clientInteractEntityListener = new PacketListenerClientInteract(LibsDisguises.getInstance()); | ||||
|         PacketListener tabListListener = new PacketListenerTabList(LibsDisguises.getInstance()); | ||||
|  | ||||
|         ProtocolLibrary.getProtocolManager().addPacketListener(clientInteractEntityListener); | ||||
|         ProtocolLibrary.getProtocolManager().addPacketListener(tabListListener); | ||||
| @@ -45,14 +44,13 @@ public class PacketsManager { | ||||
|     /** | ||||
|      * Creates the packet listeners | ||||
|      */ | ||||
|     public static void init(LibsDisguises plugin) { | ||||
|         libsDisguises = plugin; | ||||
|         soundsListener = new PacketListenerSounds(libsDisguises); | ||||
|     public static void init() { | ||||
|         soundsListener = new PacketListenerSounds(LibsDisguises.getInstance()); | ||||
|  | ||||
|         // Self disguise (/vsd) listener | ||||
|         viewDisguisesListener = new PacketListenerViewSelfDisguise(libsDisguises); | ||||
|         viewDisguisesListener = new PacketListenerViewSelfDisguise(LibsDisguises.getInstance()); | ||||
|  | ||||
|         inventoryListener = new PacketListenerInventory(libsDisguises); | ||||
|         inventoryListener = new PacketListenerInventory(LibsDisguises.getInstance()); | ||||
|         packetsHandler = new PacketsHandler(); | ||||
|     } | ||||
|  | ||||
| @@ -161,7 +159,7 @@ public class PacketsManager { | ||||
|                 packetsToListen.add(Server.ENTITY_STATUS); | ||||
|             } | ||||
|  | ||||
|             mainListener = new PacketListenerMain(libsDisguises, packetsToListen); | ||||
|             mainListener = new PacketListenerMain(LibsDisguises.getInstance(), packetsToListen); | ||||
|  | ||||
|             ProtocolLibrary.getProtocolManager().addPacketListener(mainListener); | ||||
|         } | ||||
|   | ||||
| @@ -29,6 +29,9 @@ import java.util.Map.Entry; | ||||
| import java.util.concurrent.TimeUnit; | ||||
|  | ||||
| public class DisguiseParser { | ||||
|     /** | ||||
|      * <Setter, <Getter, DefaultValue>> | ||||
|      */ | ||||
|     private static HashMap<Method, Map.Entry<Method, Object>> defaultWatcherValues = new HashMap<>(); | ||||
|  | ||||
|     public static void createDefaultMethods() { | ||||
| @@ -115,6 +118,10 @@ public class DisguiseParser { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public static HashMap<Method, Entry<Method, Object>> getMethodDefaults() { | ||||
|         return defaultWatcherValues; | ||||
|     } | ||||
|  | ||||
|     public static String parseToString(Disguise disguise) { | ||||
|         return parseToString(disguise, true); | ||||
|     } | ||||
|   | ||||
| @@ -3,7 +3,9 @@ package me.libraryaddict.disguise.utilities.parser.params; | ||||
| import me.libraryaddict.disguise.disguisetypes.Disguise; | ||||
| import me.libraryaddict.disguise.disguisetypes.DisguiseType; | ||||
| import me.libraryaddict.disguise.disguisetypes.FlagWatcher; | ||||
| import me.libraryaddict.disguise.disguisetypes.PlayerDisguise; | ||||
| import me.libraryaddict.disguise.disguisetypes.watchers.LivingWatcher; | ||||
| import me.libraryaddict.disguise.disguisetypes.watchers.PlayerWatcher; | ||||
| import me.libraryaddict.disguise.utilities.parser.DisguisePerm; | ||||
| import me.libraryaddict.disguise.utilities.parser.params.ParamInfo; | ||||
| import me.libraryaddict.disguise.utilities.parser.params.ParamInfoTypes; | ||||
| @@ -130,6 +132,15 @@ public class ParamInfoManager { | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (watcherClass == PlayerWatcher.class) { | ||||
|             try { | ||||
|                 methods.add(PlayerDisguise.class.getMethod("setNameVisible", boolean.class)); | ||||
|             } | ||||
|             catch (NoSuchMethodException e) { | ||||
|                 e.printStackTrace(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return methods.toArray(new Method[0]); | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -1,19 +1,22 @@ | ||||
| package me.libraryaddict.disguise.utilities.reflection; | ||||
|  | ||||
| import com.comphenix.protocol.reflect.FieldAccessException; | ||||
| import com.comphenix.protocol.wrappers.*; | ||||
| import com.comphenix.protocol.wrappers.EnumWrappers.Direction; | ||||
| import com.comphenix.protocol.wrappers.WrappedDataWatcher.WrappedDataWatcherObject; | ||||
| import com.comphenix.protocol.wrappers.nbt.NbtWrapper; | ||||
| import me.libraryaddict.disguise.DisguiseConfig; | ||||
| import me.libraryaddict.disguise.disguisetypes.DisguiseType; | ||||
| import me.libraryaddict.disguise.disguisetypes.EntityPose; | ||||
| import me.libraryaddict.disguise.disguisetypes.MetaIndex; | ||||
| import me.libraryaddict.disguise.disguisetypes.VillagerData; | ||||
| import me.libraryaddict.disguise.LibsDisguises; | ||||
| import me.libraryaddict.disguise.disguisetypes.*; | ||||
| import me.libraryaddict.disguise.disguisetypes.watchers.*; | ||||
| import me.libraryaddict.disguise.utilities.DisguiseSound; | ||||
| import me.libraryaddict.disguise.utilities.DisguiseUtilities; | ||||
| import me.libraryaddict.disguise.utilities.LibsPremium; | ||||
| import org.apache.commons.lang.ArrayUtils; | ||||
| import org.apache.commons.lang.StringUtils; | ||||
| import org.bukkit.*; | ||||
| import org.bukkit.configuration.InvalidConfigurationException; | ||||
| import org.bukkit.configuration.file.YamlConfiguration; | ||||
| import org.bukkit.craftbukkit.libs.it.unimi.dsi.fastutil.ints.Int2ObjectMap; | ||||
| import org.bukkit.craftbukkit.libs.org.apache.commons.io.IOUtils; | ||||
| import org.bukkit.entity.*; | ||||
| import org.bukkit.inventory.EquipmentSlot; | ||||
| @@ -26,13 +29,14 @@ import java.io.IOException; | ||||
| import java.io.InputStream; | ||||
| import java.lang.reflect.*; | ||||
| import java.nio.ByteBuffer; | ||||
| import java.util.ArrayList; | ||||
| import java.util.Map; | ||||
| import java.util.Optional; | ||||
| import java.util.UUID; | ||||
| import java.util.concurrent.atomic.AtomicInteger; | ||||
|  | ||||
| public class ReflectionManager { | ||||
|     private static String bukkitVersion = Bukkit.getServer().getClass().getName().split("\\.")[3]; | ||||
|     private static String bukkitVersion; | ||||
|     private static Class<?> craftItemClass; | ||||
|     private static Method damageAndIdleSoundMethod; | ||||
|     private static Constructor<?> boundingBoxConstructor; | ||||
| @@ -45,6 +49,8 @@ public class ReflectionManager { | ||||
|     private static Field trackedEntitiesField; | ||||
|  | ||||
|     public static void init() { | ||||
|         bukkitVersion = Bukkit.getServer().getClass().getName().split("\\.")[3]; | ||||
|  | ||||
|         try { | ||||
|             Object entity = createEntityInstance(DisguiseType.COW, "Cow"); | ||||
|  | ||||
| @@ -1176,4 +1182,362 @@ public class ReflectionManager { | ||||
|  | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     private static Class<? extends FlagWatcher> getFlagWatcher(DisguiseType disguiseType) { | ||||
|         Class<? extends FlagWatcher> watcherClass; | ||||
|  | ||||
|         try { | ||||
|             switch (disguiseType) { | ||||
|                 case ARROW: | ||||
|                     watcherClass = TippedArrowWatcher.class; | ||||
|                     break; | ||||
|                 case COD: | ||||
|                 case SALMON: | ||||
|                     watcherClass = FishWatcher.class; | ||||
|                     break; | ||||
|                 case SPECTRAL_ARROW: | ||||
|                     watcherClass = ArrowWatcher.class; | ||||
|                     break; | ||||
|                 case PRIMED_TNT: | ||||
|                     watcherClass = TNTWatcher.class; | ||||
|                     break; | ||||
|                 case MINECART_CHEST: | ||||
|                 case MINECART_HOPPER: | ||||
|                 case MINECART_MOB_SPAWNER: | ||||
|                 case MINECART_TNT: | ||||
|                     watcherClass = MinecartWatcher.class; | ||||
|                     break; | ||||
|                 case SPIDER: | ||||
|                 case CAVE_SPIDER: | ||||
|                     watcherClass = SpiderWatcher.class; | ||||
|                     break; | ||||
|                 case PIG_ZOMBIE: | ||||
|                 case HUSK: | ||||
|                 case DROWNED: | ||||
|                     watcherClass = ZombieWatcher.class; | ||||
|                     break; | ||||
|                 case MAGMA_CUBE: | ||||
|                     watcherClass = SlimeWatcher.class; | ||||
|                     break; | ||||
|                 case ELDER_GUARDIAN: | ||||
|                     watcherClass = GuardianWatcher.class; | ||||
|                     break; | ||||
|                 case WITHER_SKELETON: | ||||
|                 case STRAY: | ||||
|                     watcherClass = SkeletonWatcher.class; | ||||
|                     break; | ||||
|                 case ILLUSIONER: | ||||
|                 case EVOKER: | ||||
|                     watcherClass = IllagerWizardWatcher.class; | ||||
|                     break; | ||||
|                 case PUFFERFISH: | ||||
|                     watcherClass = PufferFishWatcher.class; | ||||
|                     break; | ||||
|                 default: | ||||
|                     watcherClass = (Class<? extends FlagWatcher>) Class.forName( | ||||
|                             "me.libraryaddict.disguise.disguisetypes.watchers." + toReadable(disguiseType.name()) + | ||||
|                                     "Watcher"); | ||||
|                     break; | ||||
|             } | ||||
|         } | ||||
|         catch (ClassNotFoundException ex) { | ||||
|             // There is no explicit watcher for this entity. | ||||
|             Class entityClass = disguiseType.getEntityType().getEntityClass(); | ||||
|  | ||||
|             if (entityClass != null) { | ||||
|                 if (Tameable.class.isAssignableFrom(entityClass)) { | ||||
|                     watcherClass = TameableWatcher.class; | ||||
|                 } else if (Ageable.class.isAssignableFrom(entityClass)) { | ||||
|                     watcherClass = AgeableWatcher.class; | ||||
|                 } else if (Creature.class.isAssignableFrom(entityClass)) { | ||||
|                     watcherClass = InsentientWatcher.class; | ||||
|                 } else if (LivingEntity.class.isAssignableFrom(entityClass)) { | ||||
|                     watcherClass = LivingWatcher.class; | ||||
|                 } else if (Fish.class.isAssignableFrom(entityClass)) { | ||||
|                     watcherClass = FishWatcher.class; | ||||
|                 } else { | ||||
|                     watcherClass = FlagWatcher.class; | ||||
|                 } | ||||
|             } else { | ||||
|                 watcherClass = FlagWatcher.class; // Disguise is unknown type | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return watcherClass; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Here we create a nms entity for each disguise. Then grab their default values in their datawatcher. Then their | ||||
|      * sound volume | ||||
|      * for mob noises. As well as setting their watcher class and entity size. | ||||
|      */ | ||||
|     public static void registerValues() { | ||||
|         for (DisguiseType disguiseType : DisguiseType.values()) { | ||||
|             if (disguiseType.getEntityType() == null) { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             Class watcherClass = getFlagWatcher(disguiseType); | ||||
|  | ||||
|             if (watcherClass == null) { | ||||
|                 DisguiseUtilities.getLogger() | ||||
|                         .severe("Error loading " + disguiseType.name() + ", FlagWatcher not assigned"); | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             // Invalidate invalid distribution | ||||
|             if (LibsPremium.isPremium() && | ||||
|                     ((LibsPremium.getPaidInformation() != null && LibsPremium.getPaidInformation().isPremium() && | ||||
|                             !LibsPremium.getPaidInformation().isLegit()) || | ||||
|                             (LibsPremium.getPluginInformation() != null && | ||||
|                                     LibsPremium.getPluginInformation().isPremium() && | ||||
|                                     !LibsPremium.getPluginInformation().isLegit()))) { | ||||
|                 throw new IllegalStateException( | ||||
|                         "Error while checking pi rate on startup! Please re-download the jar from SpigotMC before " + | ||||
|                                 "reporting this error!"); | ||||
|             } | ||||
|  | ||||
|             disguiseType.setWatcherClass(watcherClass); | ||||
|  | ||||
|             if (LibsDisguises.getInstance() == null || DisguiseValues.getDisguiseValues(disguiseType) != null) { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             createNMSValues(disguiseType); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private static void createNMSValues(DisguiseType disguiseType) { | ||||
|         String nmsEntityName = toReadable(disguiseType.name()); | ||||
|         Class nmsClass = ReflectionManager.getNmsClassIgnoreErrors("Entity" + nmsEntityName); | ||||
|  | ||||
|         if (nmsClass == null || Modifier.isAbstract(nmsClass.getModifiers())) { | ||||
|             String[] split = splitReadable(disguiseType.name()); | ||||
|             ArrayUtils.reverse(split); | ||||
|  | ||||
|             nmsEntityName = StringUtils.join(split); | ||||
|             nmsClass = ReflectionManager.getNmsClassIgnoreErrors("Entity" + nmsEntityName); | ||||
|  | ||||
|             if (nmsClass == null || Modifier.isAbstract(nmsClass.getModifiers())) { | ||||
|                 nmsEntityName = null; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (nmsEntityName == null) { | ||||
|             switch (disguiseType) { | ||||
|                 case DONKEY: | ||||
|                     nmsEntityName = "HorseDonkey"; | ||||
|                     break; | ||||
|                 case ARROW: | ||||
|                     nmsEntityName = "TippedArrow"; | ||||
|                     break; | ||||
|                 case DROPPED_ITEM: | ||||
|                     nmsEntityName = "Item"; | ||||
|                     break; | ||||
|                 case FIREBALL: | ||||
|                     nmsEntityName = "LargeFireball"; | ||||
|                     break; | ||||
|                 case FIREWORK: | ||||
|                     nmsEntityName = "Fireworks"; | ||||
|                     break; | ||||
|                 case GIANT: | ||||
|                     nmsEntityName = "GiantZombie"; | ||||
|                     break; | ||||
|                 case HUSK: | ||||
|                     nmsEntityName = "ZombieHusk"; | ||||
|                     break; | ||||
|                 case ILLUSIONER: | ||||
|                     nmsEntityName = "IllagerIllusioner"; | ||||
|                     break; | ||||
|                 case LEASH_HITCH: | ||||
|                     nmsEntityName = "Leash"; | ||||
|                     break; | ||||
|                 case MINECART: | ||||
|                     nmsEntityName = "MinecartRideable"; | ||||
|                     break; | ||||
|                 case MINECART_COMMAND: | ||||
|                     nmsEntityName = "MinecartCommandBlock"; | ||||
|                     break; | ||||
|                 case MINECART_TNT: | ||||
|                     nmsEntityName = "MinecartTNT"; | ||||
|                     break; | ||||
|                 case MULE: | ||||
|                     nmsEntityName = "HorseMule"; | ||||
|                     break; | ||||
|                 case PRIMED_TNT: | ||||
|                     nmsEntityName = "TNTPrimed"; | ||||
|                     break; | ||||
|                 case PUFFERFISH: | ||||
|                     nmsEntityName = "PufferFish"; | ||||
|                     break; | ||||
|                 case SPLASH_POTION: | ||||
|                     nmsEntityName = "Potion"; | ||||
|                     break; | ||||
|                 case STRAY: | ||||
|                     nmsEntityName = "SkeletonStray"; | ||||
|                     break; | ||||
|                 case TRIDENT: | ||||
|                     nmsEntityName = "ThrownTrident"; | ||||
|                     break; | ||||
|                 case WANDERING_TRADER: | ||||
|                     nmsEntityName = "VillagerTrader"; | ||||
|                     break; | ||||
|                 case TRADER_LLAMA: | ||||
|                     nmsEntityName = "LLamaTrader"; // Interesting capitalization | ||||
|                     break; | ||||
|                 default: | ||||
|                     break; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         try { | ||||
|             if (disguiseType == DisguiseType.UNKNOWN) { | ||||
|                 DisguiseValues disguiseValues = new DisguiseValues(disguiseType, null, 0, 0); | ||||
|  | ||||
|                 disguiseValues.setAdultBox(new FakeBoundingBox(0, 0, 0)); | ||||
|  | ||||
|                 DisguiseSound sound = DisguiseSound.getType(disguiseType.name()); | ||||
|  | ||||
|                 if (sound != null) { | ||||
|                     sound.setDamageAndIdleSoundVolume(1f); | ||||
|                 } | ||||
|  | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             if (nmsEntityName == null) { | ||||
|                 DisguiseUtilities.getLogger().warning("Entity name not found! (" + disguiseType.name() + ")"); | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             Object nmsEntity = ReflectionManager.createEntityInstance(disguiseType, nmsEntityName); | ||||
|  | ||||
|             if (nmsEntity == null) { | ||||
|                 DisguiseUtilities.getLogger().warning("Entity not found! (" + nmsEntityName + ")"); | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             disguiseType.setTypeId(ReflectionManager.getEntityTypeId(disguiseType.getEntityType())); | ||||
|  | ||||
|             Entity bukkitEntity = ReflectionManager.getBukkitEntity(nmsEntity); | ||||
|  | ||||
|             int entitySize = 0; | ||||
|  | ||||
|             for (Field field : ReflectionManager.getNmsClass("Entity").getFields()) { | ||||
|                 if (field.getType().getName().equals("EnumEntitySize")) { | ||||
|                     Enum enumEntitySize = (Enum) field.get(nmsEntity); | ||||
|  | ||||
|                     entitySize = enumEntitySize.ordinal(); | ||||
|  | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             DisguiseValues disguiseValues = new DisguiseValues(disguiseType, nmsEntity.getClass(), entitySize, | ||||
|                     bukkitEntity instanceof Damageable ? ((Damageable) bukkitEntity).getMaxHealth() : 0); | ||||
|  | ||||
|             WrappedDataWatcher watcher = WrappedDataWatcher.getEntityWatcher(bukkitEntity); | ||||
|             ArrayList<MetaIndex> indexes = MetaIndex.getMetaIndexes(disguiseType.getWatcherClass()); | ||||
|             boolean loggedName = false; | ||||
|  | ||||
|             for (WrappedWatchableObject watch : watcher.getWatchableObjects()) { | ||||
|                 MetaIndex flagType = MetaIndex.getMetaIndex(disguiseType.getWatcherClass(), watch.getIndex()); | ||||
|  | ||||
|                 if (flagType == null) { | ||||
|                     DisguiseUtilities.getLogger() | ||||
|                             .severe("MetaIndex not found for " + disguiseType + "! Index: " + watch.getIndex()); | ||||
|                     DisguiseUtilities.getLogger() | ||||
|                             .severe("Value: " + watch.getRawValue() + " (" + watch.getRawValue().getClass() + ") (" + | ||||
|                                     nmsEntity.getClass() + ") & " + disguiseType.getWatcherClass().getSimpleName()); | ||||
|                     continue; | ||||
|                 } | ||||
|  | ||||
|                 indexes.remove(flagType); | ||||
|  | ||||
|                 Object ourValue = ReflectionManager.convertInvalidMeta(flagType.getDefault()); | ||||
|                 Object nmsValue = ReflectionManager.convertInvalidMeta(watch.getValue()); | ||||
|  | ||||
|                 if (ourValue.getClass() != nmsValue.getClass()) { | ||||
|                     if (!loggedName) { | ||||
|                         DisguiseUtilities.getLogger().severe(StringUtils.repeat("=", 20)); | ||||
|                         DisguiseUtilities.getLogger() | ||||
|                                 .severe("MetaIndex mismatch! Disguise " + disguiseType + ", Entity " + nmsEntityName); | ||||
|                         loggedName = true; | ||||
|                     } | ||||
|  | ||||
|                     DisguiseUtilities.getLogger().severe(StringUtils.repeat("-", 20)); | ||||
|                     DisguiseUtilities.getLogger() | ||||
|                             .severe("Index: " + watch.getIndex() + " | " + flagType.getFlagWatcher().getSimpleName() + | ||||
|                                     " | " + MetaIndex.getName(flagType)); | ||||
|                     Object flagDefault = flagType.getDefault(); | ||||
|  | ||||
|                     DisguiseUtilities.getLogger() | ||||
|                             .severe("LibsDisguises: " + flagDefault + " (" + flagDefault.getClass() + ")"); | ||||
|                     DisguiseUtilities.getLogger() | ||||
|                             .severe("LibsDisguises Converted: " + ourValue + " (" + ourValue.getClass() + ")"); | ||||
|                     DisguiseUtilities.getLogger() | ||||
|                             .severe("Minecraft: " + watch.getRawValue() + " (" + watch.getRawValue().getClass() + ")"); | ||||
|                     DisguiseUtilities.getLogger() | ||||
|                             .severe("Minecraft Converted: " + nmsValue + " (" + nmsValue.getClass() + ")"); | ||||
|                     DisguiseUtilities.getLogger().severe(StringUtils.repeat("-", 20)); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             for (MetaIndex index : indexes) { | ||||
|                 DisguiseUtilities.getLogger().warning( | ||||
|                         disguiseType + " has MetaIndex remaining! " + index.getFlagWatcher().getSimpleName() + | ||||
|                                 " at index " + index.getIndex()); | ||||
|             } | ||||
|  | ||||
|             DisguiseSound sound = DisguiseSound.getType(disguiseType.name()); | ||||
|  | ||||
|             if (sound != null) { | ||||
|                 Float soundStrength = ReflectionManager.getSoundModifier(nmsEntity); | ||||
|  | ||||
|                 if (soundStrength != null) { | ||||
|                     sound.setDamageAndIdleSoundVolume(soundStrength); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             // Get the bounding box | ||||
|             disguiseValues.setAdultBox(ReflectionManager.getBoundingBox(bukkitEntity)); | ||||
|  | ||||
|             if (bukkitEntity instanceof Ageable) { | ||||
|                 ((Ageable) bukkitEntity).setBaby(); | ||||
|  | ||||
|                 disguiseValues.setBabyBox(ReflectionManager.getBoundingBox(bukkitEntity)); | ||||
|             } else if (bukkitEntity instanceof Zombie) { | ||||
|                 ((Zombie) bukkitEntity).setBaby(true); | ||||
|  | ||||
|                 disguiseValues.setBabyBox(ReflectionManager.getBoundingBox(bukkitEntity)); | ||||
|             } | ||||
|  | ||||
|             //disguiseValues.setEntitySize(ReflectionManager.getSize(bukkitEntity)); | ||||
|         } | ||||
|         catch (SecurityException | IllegalArgumentException | IllegalAccessException | FieldAccessException ex) { | ||||
|             DisguiseUtilities.getLogger() | ||||
|                     .severe("Uh oh! Trouble while making values for the disguise " + disguiseType.name() + "!"); | ||||
|             DisguiseUtilities.getLogger().severe("Before reporting this error, " + | ||||
|                     "please make sure you are using the latest version of LibsDisguises and ProtocolLib."); | ||||
|             DisguiseUtilities.getLogger().severe("Development builds are available at (ProtocolLib) " + | ||||
|                     "http://ci.dmulloy2.net/job/ProtocolLib/ and (LibsDisguises) https://ci.md-5" + | ||||
|                     ".net/job/LibsDisguises/"); | ||||
|  | ||||
|             ex.printStackTrace(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private static String[] splitReadable(String string) { | ||||
|         String[] split = string.split("_"); | ||||
|  | ||||
|         for (int i = 0; i < split.length; i++) { | ||||
|             split[i] = split[i].substring(0, 1) + split[i].substring(1).toLowerCase(); | ||||
|         } | ||||
|  | ||||
|         return split; | ||||
|     } | ||||
|  | ||||
|     private static String toReadable(String string) { | ||||
|         return StringUtils.join(splitReadable(string)); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,121 @@ | ||||
| package me.libraryaddict.disguise.disguisetypes; | ||||
|  | ||||
| import me.libraryaddict.disguise.LibsDisguises; | ||||
| import me.libraryaddict.disguise.utilities.DisguiseUtilities; | ||||
| import me.libraryaddict.disguise.utilities.parser.DisguiseParser; | ||||
| import me.libraryaddict.disguise.utilities.reflection.ReflectionManager; | ||||
| import org.bukkit.Material; | ||||
| import org.bukkit.entity.EntityType; | ||||
| import org.bukkit.inventory.ItemStack; | ||||
| import org.junit.Assert; | ||||
| import org.junit.Test; | ||||
|  | ||||
| import java.lang.reflect.InvocationTargetException; | ||||
| import java.lang.reflect.Method; | ||||
| import java.util.Enumeration; | ||||
| import java.util.Map; | ||||
|  | ||||
| /** | ||||
|  * Created by libraryaddict on 19/01/2020. | ||||
|  */ | ||||
| public class DisguiseCloneTest { | ||||
|  | ||||
|     /** | ||||
|      * MetaIndex needs ProtocolLib to have initialized so. | ||||
|      */ | ||||
|   //  @Test | ||||
|     public void testCloneDisguise() { | ||||
|         try { | ||||
|             ReflectionManager.registerValues(); | ||||
|             DisguiseParser.createDefaultMethods(); | ||||
|             DisguiseUtilities.init(); | ||||
|  | ||||
|             for (DisguiseType type : DisguiseType.values()) { | ||||
|                 Disguise disguise; | ||||
|  | ||||
|                 if (type.isPlayer()) { | ||||
|                     disguise = new PlayerDisguise("libraryaddict"); | ||||
|                 } else if (type.isMob()) { | ||||
|                     disguise = new MobDisguise(type); | ||||
|                 } else { | ||||
|                     disguise = new MiscDisguise(type); | ||||
|                 } | ||||
|  | ||||
|                 for (Map.Entry<Method, Map.Entry<Method, Object>> entry : DisguiseParser.getMethodDefaults() | ||||
|                         .entrySet()) { | ||||
|                     Object dValue = entry.getValue().getValue(); | ||||
|  | ||||
|                     if (dValue instanceof String) { | ||||
|                         dValue = "NewString"; | ||||
|                     } else if (dValue instanceof Float) { | ||||
|                         dValue = ((float) dValue) + 1; | ||||
|                     } else if (dValue instanceof Double) { | ||||
|                         dValue = ((double) dValue) + 1; | ||||
|                     } else if (dValue instanceof Long) { | ||||
|                         dValue = ((long) dValue) + 1; | ||||
|                     } else if (dValue instanceof Integer) { | ||||
|                         dValue = ((int) dValue) + 1; | ||||
|                     } else if (dValue instanceof Byte) { | ||||
|                         dValue = ((byte) dValue) + 1; | ||||
|                     } else if (dValue instanceof Short) { | ||||
|                         dValue = ((short) dValue) + 1; | ||||
|                     } else if (dValue instanceof ItemStack) { | ||||
|                         dValue = new ItemStack(Material.DIAMOND_BLOCK); | ||||
|                     } else if (dValue instanceof Boolean) { | ||||
|                         dValue = !((Boolean) dValue); | ||||
|                     } else if (dValue instanceof Enum) { | ||||
|                         Object[] vals = dValue.getClass().getEnumConstants(); | ||||
|  | ||||
|                         for (int i = 0; i < vals.length; i++) { | ||||
|                             if (vals[i] == dValue) { | ||||
|                                 continue; | ||||
|                             } | ||||
|  | ||||
|                             dValue = vals[i]; | ||||
|                             break; | ||||
|                         } | ||||
|                     } else { | ||||
|                         continue; | ||||
|                     } | ||||
|  | ||||
|                     Method m = entry.getKey(); | ||||
|  | ||||
|                     Object invokeWith = disguise; | ||||
|  | ||||
|                     if (FlagWatcher.class.isAssignableFrom(entry.getKey().getDeclaringClass())) { | ||||
|                         invokeWith = disguise.getWatcher(); | ||||
|                     } | ||||
|  | ||||
|                     try { | ||||
|                         entry.getKey().invoke(invokeWith, dValue); | ||||
|                     } | ||||
|                     catch (IllegalAccessException e) { | ||||
|                         e.printStackTrace(); | ||||
|                     } | ||||
|                     catch (InvocationTargetException e) { | ||||
|                         e.printStackTrace(); | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 Disguise cloned = disguise.clone(); | ||||
|                 String dString = DisguiseUtilities.getGson().toJson(disguise); | ||||
|                 String cString = DisguiseUtilities.getGson().toJson(cloned); | ||||
|  | ||||
|                 if (!dString.equals(cString)) { | ||||
|                     System.err.println(dString); | ||||
|                     System.err.println(cString); | ||||
|                     Assert.fail("Cloned disguise is not the same!"); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         catch (Exception ex) { | ||||
|             ex.printStackTrace(); | ||||
|  | ||||
|             if (ex.getCause() != null) { | ||||
|                 ex.getCause().printStackTrace(); | ||||
|             } | ||||
|  | ||||
|             throw ex; | ||||
|         } | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user