diff --git a/build.gradle b/build.gradle index 3943f0ea..e9b13fe8 100644 --- a/build.gradle +++ b/build.gradle @@ -98,7 +98,7 @@ ant.get src: 'http://server.o2gaming.com/downloads/spigot-1.9.jar', dest: file(' dependencies { compile "org.spigotmc:spigot-api:$project.ext.spigotVersion" - compile 'com.comphenix.protocol:ProtocolLib:3.7.0-BETA' + compile 'com.comphenix.protocol:ProtocolLib:3.7.0-SNAPSHOT' compile name: 'spigot-1.9' testCompile group: 'junit', name: 'junit', version: '4.10' } diff --git a/src/main/java/me/libraryaddict/disguise/DisguiseAPI.java b/src/main/java/me/libraryaddict/disguise/DisguiseAPI.java index a596bbe3..e19d361d 100644 --- a/src/main/java/me/libraryaddict/disguise/DisguiseAPI.java +++ b/src/main/java/me/libraryaddict/disguise/DisguiseAPI.java @@ -24,6 +24,7 @@ import org.bukkit.inventory.EntityEquipment; import org.bukkit.inventory.HorseInventory; import org.bukkit.inventory.ItemStack; import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; import java.lang.reflect.Field; import java.lang.reflect.Method; @@ -52,8 +53,10 @@ public class DisguiseAPI { if (entity instanceof LivingEntity) { for (PotionEffect effect : ((LivingEntity) entity).getActivePotionEffects()) { ((LivingWatcher) watcher).addPotionEffect(effect.getType()); - if (effect.getType().getName().equals("INVISIBILITY")) { + if (effect.getType() == PotionEffectType.INVISIBILITY) { watcher.setInvisible(true); + } else if (effect.getType() == PotionEffectType.GLOWING) { + watcher.setGlowing(true); } } } @@ -110,9 +113,7 @@ public class DisguiseAPI { value = (float) d; } } else if (toCast == double.class) { - if (value instanceof Double) { - value = value; - } else { + if (!(value instanceof Double)) { float d = (Float) value; value = (double) d; } diff --git a/src/main/java/me/libraryaddict/disguise/LibsDisguises.java b/src/main/java/me/libraryaddict/disguise/LibsDisguises.java index 087646b8..5d99911e 100644 --- a/src/main/java/me/libraryaddict/disguise/LibsDisguises.java +++ b/src/main/java/me/libraryaddict/disguise/LibsDisguises.java @@ -25,6 +25,7 @@ import me.libraryaddict.disguise.disguisetypes.watchers.MinecartWatcher; import me.libraryaddict.disguise.disguisetypes.watchers.SkeletonWatcher; import me.libraryaddict.disguise.disguisetypes.watchers.SlimeWatcher; import me.libraryaddict.disguise.disguisetypes.watchers.TameableWatcher; +import me.libraryaddict.disguise.disguisetypes.watchers.TippedArrowWatcher; import me.libraryaddict.disguise.disguisetypes.watchers.ZombieWatcher; import me.libraryaddict.disguise.utilities.DisguiseSound; import me.libraryaddict.disguise.utilities.DisguiseUtilities; @@ -101,9 +102,11 @@ public class LibsDisguises extends JavaPlugin { if (disguiseType.getEntityType() == null) { continue; } - Class watcherClass; + Class watcherClass = null; try { switch (disguiseType) { + case ITEM_FRAME: //Not really supported... + break; case MINECART_CHEST: case MINECART_COMMAND: case MINECART_FURNACE: @@ -134,6 +137,9 @@ public class LibsDisguises extends JavaPlugin { case WITHER_SKELETON: watcherClass = SkeletonWatcher.class; break; + case ARROW: + watcherClass = TippedArrowWatcher.class; + break; default: watcherClass = Class.forName("me.libraryaddict.disguise.disguisetypes.watchers." + toReadable(disguiseType.name()) + "Watcher"); @@ -199,6 +205,8 @@ public class LibsDisguises extends JavaPlugin { case ELDER_GUARDIAN: nmsEntityName = "Guardian"; break; + case ARROW: + nmsEntityName = "TippedArrow"; default: break; } diff --git a/src/main/java/me/libraryaddict/disguise/commands/BaseDisguiseCommand.java b/src/main/java/me/libraryaddict/disguise/commands/BaseDisguiseCommand.java index b17a2502..ff883be6 100644 --- a/src/main/java/me/libraryaddict/disguise/commands/BaseDisguiseCommand.java +++ b/src/main/java/me/libraryaddict/disguise/commands/BaseDisguiseCommand.java @@ -404,7 +404,7 @@ public abstract class BaseDisguiseCommand implements CommandExecutor { int miscData = -1; String secondArg = null; if (args.length > 1) { - // They have defined more arguements! + // They have defined more arguments! // If the first arg is a number if (args[1].contains(":")) { String[] split = args[1].split(":"); @@ -432,6 +432,7 @@ public abstract class BaseDisguiseCommand implements CommandExecutor { case SPLASH_POTION: case DROPPED_ITEM: case FISHING_HOOK: + case ARROW: case TIPPED_ARROW: case SPECTRAL_ARROW: case SMALL_FIREBALL: diff --git a/src/main/java/me/libraryaddict/disguise/disguisetypes/Disguise.java b/src/main/java/me/libraryaddict/disguise/disguisetypes/Disguise.java index 2fe5083b..d6f0758b 100644 --- a/src/main/java/me/libraryaddict/disguise/disguisetypes/Disguise.java +++ b/src/main/java/me/libraryaddict/disguise/disguisetypes/Disguise.java @@ -233,7 +233,7 @@ public abstract class Disguise { if (isModifyBoundingBox()) { DisguiseUtilities.doBoundingBox(disguise); } - if (getType() == DisguiseType.BAT && !((BatWatcher) getWatcher()).isFlying()) { + if (getType() == DisguiseType.BAT && !((BatWatcher) getWatcher()).isHanging()) { return; } // If the vectorY isn't 0. Cos if it is. Then it doesn't want to send any vectors. @@ -306,8 +306,7 @@ public abstract class Disguise { PacketContainer selfPacket = packet.shallowClone(); selfPacket.getModifier().write(0, DisguiseAPI.getSelfDisguiseId()); try { - ProtocolLibrary.getProtocolManager().sendServerPacket((Player) getEntity(), selfPacket, - false); + ProtocolLibrary.getProtocolManager().sendServerPacket((Player) getEntity(), selfPacket, false); } catch (InvocationTargetException e) { e.printStackTrace(System.out); } @@ -636,13 +635,13 @@ public abstract class Disguise { // Since they both share it. With the same classes. Time to check if its from something they extend. // Better make this clear before I compare the values because some default values are different! // Entity is 0 & 1 - But we aint gonna be checking that - // EntityAgeable is 16 - // EntityInsentient is 10 & 11 - // EntityZombie is 12 & 13 & 14 - But it overrides other values and another check already does this. - // EntityLiving is 6 & 7 & 8 & 9 + // EntityAgeable is 11 + // EntityInsentient is 10 + // EntityLiving is 5 & 6 & 7 & 8 & 9 // Lets use switch Class baseClass = null; switch (dataNo) { + case 5: case 6: case 7: case 8: @@ -650,10 +649,9 @@ public abstract class Disguise { baseClass = ReflectionManager.getNmsClass("EntityLiving"); break; case 10: - case 11: baseClass = ReflectionManager.getNmsClass("EntityInsentient"); break; - case 16: + case 11: baseClass = ReflectionManager.getNmsClass("EntityAgeable"); break; default: diff --git a/src/main/java/me/libraryaddict/disguise/disguisetypes/DisguiseType.java b/src/main/java/me/libraryaddict/disguise/disguisetypes/DisguiseType.java index b3352ae1..5a654c7f 100644 --- a/src/main/java/me/libraryaddict/disguise/disguisetypes/DisguiseType.java +++ b/src/main/java/me/libraryaddict/disguise/disguisetypes/DisguiseType.java @@ -14,6 +14,7 @@ public enum DisguiseType { AREA_EFFECT_CLOUD, ARMOR_STAND, + ARROW, BAT, BLAZE, BOAT, @@ -23,35 +24,35 @@ public enum DisguiseType { CREEPER, DONKEY, DRAGON_FIREBALL, - DROPPED_ITEM(-1, 1), + DROPPED_ITEM(1), EGG, ELDER_GUARDIAN, ENDER_CRYSTAL, ENDER_DRAGON, ENDER_PEARL, - ENDER_SIGNAL(15), + ENDER_SIGNAL, ENDERMAN, ENDERMITE, EXPERIENCE_ORB, - FALLING_BLOCK(12, 1), - FIREBALL(26, 0), - FIREWORK(22), + FALLING_BLOCK(1), + FIREBALL(0), + FIREWORK, FISHING_HOOK, GHAST, GIANT, GUARDIAN, HORSE, IRON_GOLEM, - ITEM_FRAME(18), - LEASH_HITCH(8), + ITEM_FRAME, + LEASH_HITCH, MAGMA_CUBE, MINECART, - MINECART_CHEST, - MINECART_COMMAND, - MINECART_FURNACE, - MINECART_HOPPER, - MINECART_MOB_SPAWNER, - MINECART_TNT, + MINECART_CHEST(1), + MINECART_COMMAND(6), + MINECART_FURNACE(2), + MINECART_HOPPER(5), + MINECART_MOB_SPAWNER(4), + MINECART_TNT(5), MULE, MUSHROOM_COW, OCELOT, @@ -59,30 +60,30 @@ public enum DisguiseType { PIG, PIG_ZOMBIE, PLAYER, - PRIMED_TNT(20), + PRIMED_TNT, RABBIT, SHEEP, SHULKER, - SHULKER_BULLET(25), + SHULKER_BULLET, SILVERFISH, SKELETON, SKELETON_HORSE, SLIME, - SMALL_FIREBALL(13, 0), - SNOWBALL(11), + SMALL_FIREBALL(0), + SNOWBALL, SNOWMAN, - SPECTRAL_ARROW(24), + SPECTRAL_ARROW, SPIDER, SPLASH_POTION, SQUID, - TIPPED_ARROW(23), - THROWN_EXP_BOTTLE(17), + TIPPED_ARROW, + THROWN_EXP_BOTTLE, UNDEAD_HORSE, VILLAGER, WITCH, WITHER, WITHER_SKELETON, - WITHER_SKULL(19), + WITHER_SKULL, WOLF, ZOMBIE, ZOMBIE_VILLAGER, @@ -116,6 +117,8 @@ public enum DisguiseType { case ELDER_GUARDIAN: toUse = DisguiseType.GUARDIAN; break; + case ARROW: + toUse = DisguiseType.TIPPED_ARROW; default: break; } @@ -196,7 +199,7 @@ public enum DisguiseType { } } - private int defaultId, entityId; + private int defaultData = -1; private EntityType entityType; private Class watcherClass; @@ -205,10 +208,7 @@ public enum DisguiseType { int value = ints[i]; switch (i) { case 0: - entityId = value; - break; - case 1: - defaultId = value; + defaultData = value; break; default: break; @@ -216,8 +216,8 @@ public enum DisguiseType { } } - public int getDefaultId() { - return defaultId; + public int getDefaultData() { + return defaultData; } public Class getEntityClass() { @@ -227,10 +227,6 @@ public enum DisguiseType { return Entity.class; } - public int getEntityId() { - return entityId; - } - public EntityType getEntityType() { return entityType; } diff --git a/src/main/java/me/libraryaddict/disguise/disguisetypes/MiscDisguise.java b/src/main/java/me/libraryaddict/disguise/disguisetypes/MiscDisguise.java index 433bde4a..ccdbfc5a 100644 --- a/src/main/java/me/libraryaddict/disguise/disguisetypes/MiscDisguise.java +++ b/src/main/java/me/libraryaddict/disguise/disguisetypes/MiscDisguise.java @@ -6,7 +6,6 @@ import me.libraryaddict.disguise.disguisetypes.watchers.PaintingWatcher; import me.libraryaddict.disguise.disguisetypes.watchers.SplashPotionWatcher; import org.bukkit.Art; import org.bukkit.entity.Entity; -import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; @@ -17,95 +16,53 @@ public class MiscDisguise extends TargetedDisguise { private int id = -1, data = 0; public MiscDisguise(DisguiseType disguiseType) { - this(disguiseType, -1, -1); - } - - @Deprecated - public MiscDisguise(DisguiseType disguiseType, boolean replaceSounds) { - this(disguiseType, replaceSounds, -1, -1); - } - - @Deprecated - public MiscDisguise(DisguiseType disguiseType, boolean replaceSounds, int addictionalData) { - this(disguiseType, replaceSounds, (disguiseType == DisguiseType.FALLING_BLOCK - || disguiseType == DisguiseType.DROPPED_ITEM ? addictionalData : -1), (disguiseType == DisguiseType.FALLING_BLOCK - || disguiseType == DisguiseType.DROPPED_ITEM ? -1 : addictionalData)); - } - - @Deprecated - public MiscDisguise(DisguiseType disguiseType, boolean replaceSounds, int id, int data) { - this(disguiseType, id, data); - this.setReplaceSounds(replaceSounds); + this(disguiseType, -1, disguiseType.getDefaultData()); } public MiscDisguise(DisguiseType disguiseType, int id) { - this(disguiseType, id, -1); + this(disguiseType, id, disguiseType.getDefaultData()); } - public MiscDisguise(DisguiseType disguiseType, int firstParam, int secondParam) { + public MiscDisguise(DisguiseType disguiseType, int id, int data) { if (!disguiseType.isMisc()) { throw new InvalidParameterException("Expected a non-living DisguiseType while constructing MiscDisguise. Received " + disguiseType + " instead. Please use " + (disguiseType.isPlayer() ? "PlayerDisguise" : "MobDisguise") + " instead"); } createDisguise(disguiseType); - this.id = getType().getEntityId(); - this.data = getType().getDefaultId(); + this.id = getType().getTypeId(); + this.data = getType().getDefaultData(); switch (disguiseType) { // The only disguises which should use a custom data. case PAINTING: - ((PaintingWatcher) getWatcher()).setArt(Art.values()[Math.max(0, firstParam) % Art.values().length]); + ((PaintingWatcher) getWatcher()).setArt(Art.values()[Math.max(0, id) % Art.values().length]); break; case FALLING_BLOCK: - ((FallingBlockWatcher) getWatcher()).setBlock(new ItemStack(Math.max(1, firstParam), 1, (short) Math.max(0, - secondParam))); + ((FallingBlockWatcher) getWatcher()).setBlock(new ItemStack(Math.max(1, id), 1, (short) Math.max(0, + data))); break; case SPLASH_POTION: - ((SplashPotionWatcher) getWatcher()).setPotionId(Math.max(0, firstParam)); + ((SplashPotionWatcher) getWatcher()).setPotionId(Math.max(0, id)); break; case DROPPED_ITEM: - if (firstParam > 0) { - ((DroppedItemWatcher) getWatcher()).setItemStack(new ItemStack(firstParam, Math.max(0, secondParam))); + if (id > 0) { + ((DroppedItemWatcher) getWatcher()).setItemStack(new ItemStack(id, Math.max(0, data))); } break; case FISHING_HOOK: // Entity ID of whoever is holding fishing rod + case ARROW: case TIPPED_ARROW: // Entity ID of shooter. Used for "Is he on this scoreboard team and do I render it moving through his body?" case SPECTRAL_ARROW: case SMALL_FIREBALL: // Unknown. Uses entity id of shooter. 0 if no shooter case FIREBALL: // Unknown. Uses entity id of shooter. 0 if no shooter case WITHER_SKULL: // Unknown. Uses entity id of shooter. 0 if no shooter - this.data = firstParam; + this.data = id; break; default: break; } } - @Deprecated - public MiscDisguise(EntityType entityType) { - this(entityType, -1, -1); - } - - @Deprecated - public MiscDisguise(EntityType entityType, boolean replaceSounds) { - this(entityType, replaceSounds, -1, -1); - } - - @Deprecated - public MiscDisguise(EntityType entityType, boolean replaceSounds, int id, int data) { - this(DisguiseType.getType(entityType), replaceSounds, id, data); - } - - @Deprecated - public MiscDisguise(EntityType entityType, int id) { - this(entityType, id, -1); - } - - @Deprecated - public MiscDisguise(EntityType disguiseType, int id, int data) { - this(DisguiseType.getType(disguiseType), id, data); - } - @Override public MiscDisguise addPlayer(Player player) { return (MiscDisguise) super.addPlayer(player); diff --git a/src/main/java/me/libraryaddict/disguise/disguisetypes/PlayerDisguise.java b/src/main/java/me/libraryaddict/disguise/disguisetypes/PlayerDisguise.java index edbb5d59..dcf287b7 100644 --- a/src/main/java/me/libraryaddict/disguise/disguisetypes/PlayerDisguise.java +++ b/src/main/java/me/libraryaddict/disguise/disguisetypes/PlayerDisguise.java @@ -80,8 +80,7 @@ public class PlayerDisguise extends TargetedDisguise { if (getSkin() != null) { gameProfile = ReflectionManager.getGameProfile(null, getName()); } else { - gameProfile = ReflectionManager.getGameProfileWithThisSkin(null, getName(), - DisguiseUtilities.getProfileFromMojang(this)); + gameProfile = ReflectionManager.getGameProfileWithThisSkin(null, getName(), DisguiseUtilities.getProfileFromMojang(this)); } } return gameProfile; diff --git a/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/BatWatcher.java b/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/BatWatcher.java index 0a1e5dfe..d6464d9a 100644 --- a/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/BatWatcher.java +++ b/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/BatWatcher.java @@ -6,15 +6,15 @@ public class BatWatcher extends LivingWatcher { public BatWatcher(Disguise disguise) { super(disguise); - setFlying(true); + setHanging(false); } - public boolean isFlying() { - return (boolean) getValue(11, true); + public boolean isHanging() { + return ((byte)getValue(11, (byte) 1)) == 1; } - public void setFlying(boolean flying) { - setValue(11, flying); + public void setHanging(boolean hanging) { + setValue(11, hanging ? (byte) 1 : (byte) 0); sendData(11); } } diff --git a/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/PaintingWatcher.java b/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/PaintingWatcher.java index 94c0e9b4..944c66cb 100644 --- a/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/PaintingWatcher.java +++ b/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/PaintingWatcher.java @@ -9,7 +9,6 @@ public class PaintingWatcher extends FlagWatcher { private Art painting; - //TODO: Check this public PaintingWatcher(Disguise disguise) { super(disguise); } diff --git a/src/main/java/me/libraryaddict/disguise/utilities/DisguiseSound.java b/src/main/java/me/libraryaddict/disguise/utilities/DisguiseSound.java index 02199dfb..4ea1a3dd 100644 --- a/src/main/java/me/libraryaddict/disguise/utilities/DisguiseSound.java +++ b/src/main/java/me/libraryaddict/disguise/utilities/DisguiseSound.java @@ -11,67 +11,67 @@ import java.util.HashSet; public enum DisguiseSound { ARROW(null, null, null, null, "random.bowhit"), - BAT("mob.bat.hurt", null, "mob.bat.death", "mob.bat.idle", "damage.fallsmall", "mob.bat.loop", "damage.fallbig", - "mob.bat.takeoff"), - BLAZE("mob.blaze.hit", null, "mob.blaze.death", "mob.blaze.breathe", "damage.fallsmall", "damage.fallbig"), - CAVE_SPIDER("mob.spider.say", "mob.spider.step", "mob.spider.death", "mob.spider.say"), - CHICKEN("mob.chicken.hurt", "mob.chicken.step", "mob.chicken.hurt", "mob.chicken.say", "damage.fallsmall", - "mob.chicken.plop", "damage.fallbig"), - COW("mob.cow.hurt", "mob.cow.step", "mob.cow.hurt", "mob.cow.say"), - CREEPER("mob.creeper.say", "step.grass", "mob.creeper.death", null), - DONKEY("mob.horse.donkey.hit", "step.grass", "mob.horse.donkey.death", "mob.horse.donkey.idle", "mob.horse.gallop", - "mob.horse.leather", "mob.horse.donkey.angry", "mob.horse.wood", "mob.horse.armor", "mob.horse.soft", - "mob.horse.land", "mob.horse.jump", "mob.horse.angry"), - ELDER_GUARDIAN("mob.guardian.elder.hit", null, "mob.guardian.elder.death", "mob.guardian.elder.death"), - ENDER_DRAGON("mob.enderdragon.hit", null, "mob.enderdragon.end", "mob.enderdragon.growl", "damage.fallsmall", - "mob.enderdragon.wings", "damage.fallbig"), - ENDERMAN("mob.endermen.hit", "step.grass", "mob.endermen.death", "mob.endermen.idle", "mob.endermen.scream", - "mob.endermen.portal", "mob.endermen.stare"), - ENDERMITE("mob.silverfish.hit", "mob.silverfish.step", "mob.silverfish.kill", "mob.silverfish.say"), - GHAST("mob.ghast.scream", null, "mob.ghast.death", "mob.ghast.moan", "damage.fallsmall", "mob.ghast.fireball", - "damage.fallbig", "mob.ghast.affectionate_scream", "mob.ghast.charge"), + BAT("entity.bat.hurt", null, "entity.bat.death", "entity.bat.idle", "damage.fallsmall", "entity.bat.loop", "damage.fallbig", + "entity.bat.takeoff"), + BLAZE("entity.blaze.hit", null, "entity.blaze.death", "entity.blaze.breathe", "damage.fallsmall", "damage.fallbig"), + CAVE_SPIDER("entity.spider.ambient", "entity.spider.step", "entity.spider.death", "entity.spider.ambient"), + CHICKEN("entity.chicken.hurt", "entity.chicken.step", "entity.chicken.hurt", "entity.chicken.ambient", "damage.fallsmall", + "entity.chicken.plop", "damage.fallbig"), + COW("entity.cow.hurt", "entity.cow.step", "entity.cow.hurt", "entity.cow.ambient"), + CREEPER("entity.creeper.ambient", "step.grass", "entity.creeper.death", null), + DONKEY("entity.horse.donkey.hit", "step.grass", "entity.horse.donkey.death", "entity.horse.donkey.idle", "entity.horse.gallop", + "entity.horse.leather", "entity.horse.donkey.angry", "entity.horse.wood", "entity.horse.armor", "entity.horse.soft", + "entity.horse.land", "entity.horse.jump", "entity.horse.angry"), + ELDER_GUARDIAN("entity.guardian.elder.hit", null, "entity.guardian.elder.death", "entity.guardian.elder.death"), + ENDER_DRAGON("entity.enderdragon.hit", null, "entity.enderdragon.end", "entity.enderdragon.growl", "damage.fallsmall", + "entity.enderdragon.wings", "damage.fallbig"), + ENDERMAN("entity.endermen.hit", "step.grass", "entity.endermen.death", "entity.endermen.idle", "entity.endermen.scream", + "entity.endermen.portal", "entity.endermen.stare"), + ENDERMITE("entity.silverfish.hit", "entity.silverfish.step", "entity.silverfish.kill", "entity.silverfish.ambient"), + GHAST("entity.ghast.scream", null, "entity.ghast.death", "entity.ghast.moan", "damage.fallsmall", "entity.ghast.fireball", + "damage.fallbig", "entity.ghast.affectionate_scream", "entity.ghast.charge"), GIANT("damage.hit", "step.grass", null, null), - GUARDIAN("mob.guardian.hit", null, "mob.guardian.death", "mob.guardian.death"), - HORSE("mob.horse.hit", "step.grass", "mob.horse.death", "mob.horse.idle", "mob.horse.gallop", "mob.horse.leather", - "mob.horse.wood", "mob.horse.armor", "mob.horse.soft", "mob.horse.land", "mob.horse.jump", "mob.horse.angry", - "mob.horse.leather"), - IRON_GOLEM("mob.irongolem.hit", "mob.irongolem.walk", "mob.irongolem.death", "mob.irongolem.throw"), - MAGMA_CUBE("mob.slime.attack", "mob.slime.big", null, null, "mob.slime.small"), - MULE("mob.horse.donkey.hit", "step.grass", "mob.horse.donkey.death", "mob.horse.donkey.idle"), - MUSHROOM_COW("mob.cow.hurt", "mob.cow.step", "mob.cow.hurt", "mob.cow.say"), - OCELOT("mob.cat.hitt", "step.grass", "mob.cat.hitt", "mob.cat.meow", "mob.cat.purreow", "mob.cat.purr"), - PIG("mob.pig.say", "mob.pig.step", "mob.pig.death", "mob.pig.say"), - PIG_ZOMBIE("mob.zombiepig.zpighurt", null, "mob.zombiepig.zpigdeath", "mob.zombiepig.zpig", "mob.zombiepig.zpigangry"), + GUARDIAN("entity.guardian.hit", null, "entity.guardian.death", "entity.guardian.death"), + HORSE("entity.horse.hit", "step.grass", "entity.horse.death", "entity.horse.idle", "entity.horse.gallop", "entity.horse.leather", + "entity.horse.wood", "entity.horse.armor", "entity.horse.soft", "entity.horse.land", "entity.horse.jump", "entity.horse.angry", + "entity.horse.leather"), + IRON_GOLEM("entity.irongolem.hit", "entity.irongolem.walk", "entity.irongolem.death", "entity.irongolem.throw"), + MAGMA_CUBE("entity.slime.attack", "entity.slime.big", null, null, "entity.slime.small"), + MULE("entity.horse.donkey.hit", "step.grass", "entity.horse.donkey.death", "entity.horse.donkey.idle"), + MUSHROOM_COW("entity.cow.hurt", "entity.cow.step", "entity.cow.hurt", "entity.cow.ambient"), + OCELOT("entity.cat.hitt", "step.grass", "entity.cat.hitt", "entity.cat.meow", "entity.cat.purreow", "entity.cat.purr"), + PIG("entity.pig.ambient", "entity.pig.step", "entity.pig.death", "entity.pig.ambient"), + PIG_ZOMBIE("entity.zombiepig.zpighurt", null, "entity.zombiepig.zpigdeath", "entity.zombiepig.zpig", "entity.zombiepig.zpigangry"), PLAYER("game.player.hurt", "step.grass", "game.player.hurt", null), - RABBIT("mob.rabbit.hurt", "mob.rabbit.hop", "mob.rabbit.death", "mob.rabbit.idle"), - SHEEP("mob.sheep.say", "mob.sheep.step", null, "mob.sheep.say", "mob.sheep.shear"), + RABBIT("entity.rabbit.hurt", "entity.rabbit.hop", "entity.rabbit.death", "entity.rabbit.idle"), + SHEEP("entity.sheep.ambient", "entity.sheep.step", null, "entity.sheep.ambient", "entity.sheep.shear"), SHULKER("entity.shulker.hurt", null, "entity.shulker.death", "entity.shulker.ambient", "entity.shulker.open", "entity.shulker.hurt_closed", "entity.shulker.close", "entity.shulker.teleport", "entity.shulker_bullet.hit", "entity.shulker_bullet.hurt"), - SILVERFISH("mob.silverfish.hit", "mob.silverfish.step", "mob.silverfish.kill", "mob.silverfish.say"), - SKELETON("mob.skeleton.hurt", "mob.skeleton.step", "mob.skeleton.death", "mob.skeleton.say"), - SKELETON_HORSE("mob.horse.skeleton.hit", "step.grass", "mob.horse.skeleton.death", "mob.horse.skeleton.idle", - "mob.horse.gallop", "mob.horse.leather", "mob.horse.wood", "mob.horse.armor", "mob.horse.soft", "mob.horse.land", - "mob.horse.jump", "mob.horse.angry"), - SLIME("mob.slime.attack", "mob.slime.big", null, null, "mob.slime.small"), + SILVERFISH("entity.silverfish.hit", "entity.silverfish.step", "entity.silverfish.kill", "entity.silverfish.ambient"), + SKELETON("entity.skeleton.hurt", "entity.skeleton.step", "entity.skeleton.death", "entity.skeleton.ambient"), + SKELETON_HORSE("entity.horse.skeleton.hit", "step.grass", "entity.horse.skeleton.death", "entity.horse.skeleton.idle", + "entity.horse.gallop", "entity.horse.leather", "entity.horse.wood", "entity.horse.armor", "entity.horse.soft", "entity.horse.land", + "entity.horse.jump", "entity.horse.angry"), + SLIME("entity.slime.attack", "entity.slime.big", null, null, "entity.slime.small"), SNOWMAN(), - SPIDER("mob.spider.say", "mob.spider.step", "mob.spider.death", "mob.spider.say"), + SPIDER("entity.spider.ambient", "entity.spider.step", "entity.spider.death", "entity.spider.ambient"), SQUID(), - UNDEAD_HORSE("mob.horse.zombie.hit", "step.grass", "mob.horse.zombie.death", "mob.horse.zombie.idle", "mob.horse.gallop", - "mob.horse.leather", "mob.horse.wood", "mob.horse.armor", "mob.horse.soft", "mob.horse.land", "mob.horse.jump", - "mob.horse.angry"), - VILLAGER("mob.villager.hit", null, "mob.villager.death", "mob.villager.idle", "mob.villager.haggle", "mob.villager.no", - "mob.villager.yes"), - WITCH("mob.witch.hurt", null, "mob.witch.death", "mob.witch.idle"), - WITHER("mob.wither.hurt", null, "mob.wither.death", "mob.wither.idle", "damage.fallsmall", "mob.wither.spawn", - "damage.fallbig", "mob.wither.shoot"), - WITHER_SKELETON("mob.skeleton.hurt", "mob.skeleton.step", "mob.skeleton.death", "mob.skeleton.say"), - WOLF("mob.wolf.hurt", "mob.wolf.step", "mob.wolf.death", "mob.wolf.bark", "mob.wolf.panting", "mob.wolf.whine", - "mob.wolf.howl", "mob.wolf.growl", "mob.wolf.shake"), - ZOMBIE("mob.zombie.hurt", "mob.zombie.step", "mob.zombie.death", "mob.zombie.say", "mob.zombie.infect", - "mob.zombie.woodbreak", "mob.zombie.metal", "mob.zombie.wood"), - ZOMBIE_VILLAGER("mob.zombie.hurt", "mob.zombie.step", "mob.zombie.death", "mob.zombie.say", "mob.zombie.infect", - "mob.zombie.woodbreak", "mob.zombie.metal", "mob.zombie.wood"); + UNDEAD_HORSE("entity.horse.zombie.hit", "step.grass", "entity.horse.zombie.death", "entity.horse.zombie.idle", "entity.horse.gallop", + "entity.horse.leather", "entity.horse.wood", "entity.horse.armor", "entity.horse.soft", "entity.horse.land", "entity.horse.jump", + "entity.horse.angry"), + VILLAGER("entity.villager.hit", null, "entity.villager.death", "entity.villager.idle", "entity.villager.haggle", "entity.villager.no", + "entity.villager.yes"), + WITCH("entity.witch.hurt", null, "entity.witch.death", "entity.witch.idle"), + WITHER("entity.wither.hurt", null, "entity.wither.death", "entity.wither.idle", "damage.fallsmall", "entity.wither.spawn", + "damage.fallbig", "entity.wither.shoot"), + WITHER_SKELETON("entity.skeleton.hurt", "entity.skeleton.step", "entity.skeleton.death", "entity.skeleton.ambient"), + WOLF("entity.wolf.hurt", "entity.wolf.step", "entity.wolf.death", "entity.wolf.bark", "entity.wolf.panting", "entity.wolf.whine", + "entity.wolf.howl", "entity.wolf.growl", "entity.wolf.shake"), + ZOMBIE("entity.zombie.hurt", "entity.zombie.step", "entity.zombie.death", "entity.zombie.ambient", "entity.zombie.infect", + "entity.zombie.break_wood_door", "entity.zombie.attack_wood_door", "entity.zombie.break_wood_door"), + ZOMBIE_VILLAGER("entity.zombie.hurt", "entity.zombie.step", "entity.zombie.death", "entity.zombie.ambient", "entity.zombie.infect", + "entity.zombie.break_wood_door", "entity.zombie.attack_wood_door", "entity.zombie.break_wood_door"); public enum SoundType { CANCEL, DEATH, HURT, IDLE, STEP diff --git a/src/main/java/me/libraryaddict/disguise/utilities/DisguiseUtilities.java b/src/main/java/me/libraryaddict/disguise/utilities/DisguiseUtilities.java index 42217160..df952a3f 100644 --- a/src/main/java/me/libraryaddict/disguise/utilities/DisguiseUtilities.java +++ b/src/main/java/me/libraryaddict/disguise/utilities/DisguiseUtilities.java @@ -270,7 +270,6 @@ public class DisguiseUtilities { } public static void doBoundingBox(TargetedDisguise disguise) { - //TODO: Slimes Entity entity = disguise.getEntity(); if (entity != null) { if (isDisguiseInUse(disguise)) { @@ -722,10 +721,8 @@ public class DisguiseUtilities { final Object entityTrackerEntry = ReflectionManager.getEntityTrackerEntry(disguise.getEntity()); if (entityTrackerEntry != null) { Set trackedPlayers = (Set) ReflectionManager.getNmsField("EntityTrackerEntry", "trackedPlayers").get(entityTrackerEntry); - Method clear = ReflectionManager.getNmsMethod("EntityTrackerEntry", "clear", - ReflectionManager.getNmsClass("EntityPlayer")); - final Method updatePlayer = ReflectionManager.getNmsMethod("EntityTrackerEntry", "updatePlayer", - ReflectionManager.getNmsClass("EntityPlayer")); + final Method clear = ReflectionManager.getNmsMethod("EntityTrackerEntry", "clear", ReflectionManager.getNmsClass("EntityPlayer")); + final Method updatePlayer = ReflectionManager.getNmsMethod("EntityTrackerEntry", "updatePlayer", ReflectionManager.getNmsClass("EntityPlayer")); trackedPlayers = new HashSet(trackedPlayers); //Copy before iterating to prevent ConcurrentModificationException for (final Object p : trackedPlayers) { Player player = (Player) ReflectionManager.getBukkitEntity(p); @@ -779,7 +776,6 @@ public class DisguiseUtilities { ex.printStackTrace(System.out); } //Code to stop player pushing in 1.9 - //TODO: Check validity Scoreboard scoreboard = player.getScoreboard(); Team t; if ((t = scoreboard.getTeam("LDPushing")) != null) { @@ -1023,7 +1019,6 @@ public class DisguiseUtilities { return; } //Code to stop player pushing in 1.9 - //TODO: Check validity Scoreboard scoreboard = player.getScoreboard(); Team t; if ((t = scoreboard.getTeam("LDPushing")) != null) { @@ -1042,5 +1037,4 @@ public class DisguiseUtilities { } } } - } diff --git a/src/main/java/me/libraryaddict/disguise/utilities/DisguiseValues.java b/src/main/java/me/libraryaddict/disguise/utilities/DisguiseValues.java index bb428de0..06cb36a8 100644 --- a/src/main/java/me/libraryaddict/disguise/utilities/DisguiseValues.java +++ b/src/main/java/me/libraryaddict/disguise/utilities/DisguiseValues.java @@ -30,6 +30,8 @@ public class DisguiseValues { case ZOMBIE_VILLAGER: type = DisguiseType.ZOMBIE; break; + case ARROW: + type = DisguiseType.TIPPED_ARROW; default: break; } diff --git a/src/main/java/me/libraryaddict/disguise/utilities/PacketsManager.java b/src/main/java/me/libraryaddict/disguise/utilities/PacketsManager.java index 28aed4ba..4b3939f7 100644 --- a/src/main/java/me/libraryaddict/disguise/utilities/PacketsManager.java +++ b/src/main/java/me/libraryaddict/disguise/utilities/PacketsManager.java @@ -24,16 +24,19 @@ import me.libraryaddict.disguise.disguisetypes.Disguise; import me.libraryaddict.disguise.disguisetypes.DisguiseType; import me.libraryaddict.disguise.disguisetypes.FlagWatcher; import me.libraryaddict.disguise.disguisetypes.MiscDisguise; +import me.libraryaddict.disguise.disguisetypes.MobDisguise; import me.libraryaddict.disguise.disguisetypes.PlayerDisguise; import me.libraryaddict.disguise.disguisetypes.watchers.LivingWatcher; import me.libraryaddict.disguise.disguisetypes.watchers.PlayerWatcher; import me.libraryaddict.disguise.disguisetypes.watchers.SheepWatcher; import me.libraryaddict.disguise.disguisetypes.watchers.SlimeWatcher; import me.libraryaddict.disguise.disguisetypes.watchers.WolfWatcher; +import me.libraryaddict.disguise.utilities.DisguiseSound.SoundType; import org.bukkit.Art; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; +import org.bukkit.entity.Ageable; import org.bukkit.entity.Arrow; import org.bukkit.entity.Damageable; import org.bukkit.entity.Entity; @@ -43,14 +46,18 @@ import org.bukkit.entity.Item; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.entity.Slime; +import org.bukkit.entity.Zombie; import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemStack; import org.bukkit.metadata.FixedMetadataValue; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Random; import java.util.UUID; public class PacketsManager { @@ -173,7 +180,6 @@ public class PacketsManager { } if (disguise.getType() == DisguiseType.EXPERIENCE_ORB) { - //TODO: Fix experience orb spawnPackets[0] = new PacketContainer(Server.SPAWN_ENTITY_EXPERIENCE_ORB); StructureModifier mods = spawnPackets[0].getModifier(); mods.write(0, disguisedEntity.getEntityId()); @@ -182,7 +188,6 @@ public class PacketsManager { mods.write(3, Math.floor(loc.getZ() * 32)); mods.write(4, 1); } else if (disguise.getType() == DisguiseType.PAINTING) { - //TODO: Fix painting spawnPackets[0] = new PacketContainer(Server.SPAWN_ENTITY_PAINTING); StructureModifier mods = spawnPackets[0].getModifier(); mods.write(0, disguisedEntity.getEntityId()); @@ -206,34 +211,27 @@ public class PacketsManager { spawnPackets[0] = new PacketContainer(Server.NAMED_ENTITY_SPAWN); PlayerDisguise playerDisguise = (PlayerDisguise) disguise; String name = playerDisguise.getSkin() != null ? playerDisguise.getSkin() : playerDisguise.getName(); + int entityId = disguisedEntity.getEntityId(); boolean removeName = false; if (!DisguiseUtilities.hasGameProfile(name)) { removeName = !DisguiseUtilities.getAddedByPlugins().contains(name); } + WrappedGameProfile gameProfile = playerDisguise.getGameProfile(); if (removeName) { DisguiseUtilities.getAddedByPlugins().remove(name); } - //Write spawn packet in order - //Id - //UUID - //x - //y - //z - //pitch - //yaw - spawnPackets[0].getIntegers().write(0, disguisedEntity.getEntityId()); - spawnPackets[0].getSpecificModifier(UUID.class).write(0, gameProfile.getUUID()); + spawnPackets[0].getIntegers().write(0, entityId); //Id + spawnPackets[0].getSpecificModifier(UUID.class).write(0, gameProfile.getUUID()); //UUID StructureModifier doubleMods = spawnPackets[0].getDoubles(); - doubleMods.write(0, Math.floor(loc.getX() * 32)); - doubleMods.write(1, Math.floor(loc.getY() * 32)); - doubleMods.write(2, Math.floor(loc.getZ() * 32)); + doubleMods.write(0, Math.floor(loc.getX() * 32)); //x + doubleMods.write(1, Math.floor(loc.getY() * 32)); //y + doubleMods.write(2, Math.floor(loc.getZ() * 32)); //z StructureModifier byteMods = spawnPackets[0].getBytes(); - byteMods.write(0, pitch); - byteMods.write(1, yaw); - - spawnPackets[0].getDataWatcherModifier().write(0, createDataWatcher(WrappedDataWatcher.getEntityWatcher(disguisedEntity), disguise.getWatcher())); + byteMods.write(0, yaw); //yaw + byteMods.write(1, pitch); //pitch + spawnPackets[0].getDataWatcherModifier().write(0, createDataWatcher(WrappedDataWatcher.getEntityWatcher(disguisedEntity), disguise.getWatcher())); //watcher, duh if (DisguiseConfig.isBedPacketsEnabled() && ((PlayerWatcher) disguise.getWatcher()).isSleeping()) { PacketContainer[] newPackets = new PacketContainer[spawnPackets.length + 1]; @@ -268,42 +266,40 @@ public class PacketsManager { PacketContainer delayedPacket = spawnPackets[0].shallowClone(); delayedPacket.getModifier().write(0, ReflectionManager.getEnumPlayerInfoAction(4)); delayedPackets = new PacketContainer[]{delayedPacket}; - } else if (disguise.getType().isMob() || disguise.getType() == DisguiseType.ARMOR_STAND) { - Class entityClass = disguise.getType().getEntityClass(); - int entityId = disguise.getType().getEntityId(); - Entity entity = Bukkit.getWorlds().get(0).spawn(disguise.getEntity().getLocation(), entityClass); + int entityId = disguisedEntity.getEntityId(); + LivingEntity entity = (LivingEntity) disguisedEntity.getWorld().spawnEntity(loc, disguise.getType().getEntityType()); entity.setVelocity(disguisedEntity.getVelocity()); if (disguise.getType() == DisguiseType.SLIME || disguise.getType() == DisguiseType.MAGMA_CUBE) { - ((Slime)entity).setSize(((SlimeWatcher)disguise.getWatcher()).getSize()); + ((Slime) entity).setSize(((SlimeWatcher) disguise.getWatcher()).getSize()); } Object nms = ReflectionManager.getNmsEntity(entity); - PacketContainer packet = ProtocolLibrary.getProtocolManager().createPacketConstructor(Server.SPAWN_ENTITY_LIVING, nms).createPacket(nms); + PacketContainer packet = ProtocolLibrary.getProtocolManager().createPacketConstructor(Server.SPAWN_ENTITY_LIVING, nms).createPacket(nms).deepClone(); spawnPackets[0] = packet; spawnPackets[0].getIntegers().write(0, entityId); spawnPackets[0].getDataWatcherModifier().write(0, createDataWatcher(WrappedDataWatcher.getEntityWatcher(disguisedEntity), disguise.getWatcher())); + entity.addPotionEffect(new PotionEffect(PotionEffectType.INVISIBILITY, 1, Integer.MAX_VALUE, true, false)); entity.remove(); //You know, as cheap as this may seem, this is pretty damn effective } else if (disguise.getType().isMisc()) { //TODO: Fix miscs - Class entityClass = disguise.getType().getEntityClass(); - Entity entity = Bukkit.getWorlds().get(0).spawn(disguise.getEntity().getLocation().add(0, 0.5, 0), entityClass); - entity.setVelocity(disguisedEntity.getVelocity()); - int entityId = disguise.getType().getEntityId(); - int typeId = disguise.getType().getTypeId(); + int id = disguise.getType().getTypeId(); int data = ((MiscDisguise) disguise).getData(); if (disguise.getType() == DisguiseType.FALLING_BLOCK) { - data = (((MiscDisguise) disguise).getId() | data << 16); + data = (((MiscDisguise) disguise).getId() + data << 12); } else if (disguise.getType() == DisguiseType.FISHING_HOOK && data == 0) { // If the MiscDisguise data isn't set. Then no entity id was provided, so default to the owners entity id data = disguisedEntity.getEntityId(); } else if (disguise.getType() == DisguiseType.ITEM_FRAME) { data = ((((int) loc.getYaw() % 360) + 720 + 45) / 90) % 4; } - Object nms = ReflectionManager.getNmsEntity(entity); - spawnPackets[0] = ProtocolLibrary.getProtocolManager().createPacketConstructor(Server.SPAWN_ENTITY, nms, typeId, data) - .createPacket(nms, typeId, data); - spawnPackets[0].getIntegers().write(0, entityId); + Object nmsEntity = ReflectionManager.getNmsEntity(disguisedEntity); + spawnPackets[0] = ProtocolLibrary.getProtocolManager() + .createPacketConstructor(PacketType.Play.Server.SPAWN_ENTITY, nmsEntity, id, data) + .createPacket(nmsEntity, id, data); + spawnPackets[0].getModifier().write(2, (int) Math.floor(loc.getY() * 32D)); + spawnPackets[0].getModifier().write(7, pitch); + spawnPackets[0].getModifier().write(8, yaw); if (disguise.getType() == DisguiseType.ITEM_FRAME) { if (data % 2 == 0) { spawnPackets[0].getModifier().write(3, (int) Math.floor((loc.getZ() + (data == 0 ? -1 : 1)) * 32D)); @@ -311,7 +307,6 @@ public class PacketsManager { spawnPackets[0].getModifier().write(1, (int) Math.floor((loc.getX() + (data == 3 ? -1 : 1)) * 32D)); } } - entity.remove(); } if (spawnPackets[1] == null || disguise.isPlayerDisguise()) { int entry = spawnPackets[1] == null ? 1 : 0; @@ -501,233 +496,234 @@ public class PacketsManager { */ public static void init(LibsDisguises plugin) { libsDisguises = plugin; - soundsListener = new PacketAdapter(libsDisguises, ListenerPriority.NORMAL, Server.NAMED_SOUND_EFFECT, - Server.ENTITY_STATUS) { + soundsListener = new PacketAdapter(libsDisguises, ListenerPriority.NORMAL, Server.NAMED_SOUND_EFFECT, Server.ENTITY_STATUS) { @Override public void onPacketSending(PacketEvent event) { - //TODO: Fix this later once ProtocolLib's deepClone for NamedSoundEffect and EntityStatus is fixed -// if (event.isCancelled()) { -// return; -// } -// event.setPacket(event.getPacket().deepClone()); -// StructureModifier mods = event.getPacket().getModifier(); -// Player observer = event.getPlayer(); -// if (event.getPacketType() == Server.NAMED_SOUND_EFFECT) { -//// if (event.isAsync()) { -//// return; -//// } -//// Object soundEffect = mods.read(0); -//// SoundType soundType = null; -//// Location soundLoc = new Location(observer.getWorld(), ((Integer) mods.read(2)) / 8D, -//// ((Integer) mods.read(3)) / 8D, ((Integer) mods.read(4)) / 8D); -//// Entity disguisedEntity = null; -//// DisguiseSound entitySound = null; -//// Disguise disguise = null; -//// Entity[] entities = soundLoc.getChunk().getEntities(); -//// for (Entity entity : entities) { -//// Disguise entityDisguise = DisguiseAPI.getDisguise(observer, entity); -//// if (entityDisguise != null) { -//// Location loc = entity.getLocation(); -//// loc = new Location(observer.getWorld(), ((int) (loc.getX() * 8)) / 8D, ((int) (loc.getY() * 8)) / 8D, -//// ((int) (loc.getZ() * 8)) / 8D); -//// if (loc.equals(soundLoc)) { -//// entitySound = DisguiseSound.getType(entity.getType().name()); -//// if (entitySound != null) { -//// Object obj = null; -//// if (entity instanceof LivingEntity) { -//// try { -//// // Use reflection so that this works for either int or double methods -//// obj = LivingEntity.class.getMethod("getHealth").invoke(entity); -//// if (obj instanceof Double ? (Double) obj == 0 : (Integer) obj == 0) { -//// soundType = SoundType.DEATH; -//// } else { -//// obj = null; -//// } -//// } catch (Exception e) { -//// e.printStackTrace(); -//// } -//// } -//// if (obj == null) { -//// boolean hasInvun = false; -//// Object nmsEntity = ReflectionManager.getNmsEntity(entity); -//// try { -//// if (entity instanceof LivingEntity) { -//// hasInvun = ReflectionManager.getNmsField("Entity", "noDamageTicks").getInt( -//// nmsEntity) == ReflectionManager.getNmsField("EntityLiving", -//// "maxNoDamageTicks").getInt(nmsEntity); -//// } else { -//// Class clazz = ReflectionManager.getNmsClass("DamageSource"); -//// hasInvun = (Boolean) ReflectionManager.getNmsMethod("Entity", "isInvulnerable", clazz) -//// .invoke(nmsEntity, ReflectionManager.getNmsField(clazz, "GENERIC")); -//// } -//// } catch (Exception ex) { -//// ex.printStackTrace(); -//// } -//// soundType = entitySound.getType(ReflectionManager.convertSoundEffectToString(soundEffect), !hasInvun); -//// } -//// if (soundType != null) { -//// disguise = entityDisguise; -//// disguisedEntity = entity; -//// break; -//// } -//// } -//// } -//// } -//// } -//// if (disguise != null) { -//// if (disguise.isSelfDisguiseSoundsReplaced() || disguisedEntity != event.getPlayer()) { -//// if (disguise.isSoundsReplaced()) { -//// String sound = null; -//// DisguiseSound dSound = DisguiseSound.getType(disguise.getType().name()); -//// if (dSound != null) -//// sound = dSound.getSound(soundType); -//// -//// if (sound == null) { -//// event.setCancelled(true); -//// } else { -//// if (sound.equals("step.grass")) { -//// try { -//// int typeId = soundLoc.getWorld().getBlockTypeIdAt(soundLoc.getBlockX(), -//// soundLoc.getBlockY() - 1, soundLoc.getBlockZ()); -//// Object block = ReflectionManager.getNmsMethod("RegistryMaterials", "a", int.class) -//// .invoke(ReflectionManager.getNmsField("Block", "REGISTRY").get(null), -//// typeId); -//// if (block != null) { -//// Object step = ReflectionManager.getNmsField("Block", "stepSound").get(block); -//// mods.write(0, ReflectionManager.getNmsMethod(step.getClass(), "getStepSound").invoke(step)); -//// } -//// } catch (Exception ex) { -//// ex.printStackTrace(); -//// } -//// // There is no else statement. Because seriously. This should never be null. Unless -//// // someone is -//// // sending fake sounds. In which case. Why cancel it. -//// } else { -//// mods.write(0, ReflectionManager.getCraftSoundEffect(sound)); -//// // Time to change the pitch and volume -//// if (soundType == SoundType.HURT || soundType == SoundType.DEATH -//// || soundType == SoundType.IDLE) { -//// // If the volume is the default -//// if (mods.read(5).equals(entitySound.getDamageAndIdleSoundVolume())) { -//// mods.write(5, dSound.getDamageAndIdleSoundVolume()); -//// } -//// // Here I assume its the default pitch as I can't calculate if its real. -//// if (disguise instanceof MobDisguise && disguisedEntity instanceof LivingEntity -//// && ((MobDisguise) disguise).doesDisguiseAge()) { -//// boolean baby = false; -//// if (disguisedEntity instanceof Zombie) { -//// baby = ((Zombie) disguisedEntity).isBaby(); -//// } else if (disguisedEntity instanceof Ageable) { -//// baby = !((Ageable) disguisedEntity).isAdult(); -//// } -//// if (((MobDisguise) disguise).isAdult() == baby) { -//// -//// float pitch = (Integer) mods.read(5); -//// if (baby) { -//// // If the pitch is not the expected -//// if (pitch > 97 || pitch < 111) -//// return; -//// pitch = (new Random().nextFloat() - new Random().nextFloat()) * 0.2F + 1.5F; -//// // Min = 1.5 -//// // Cap = 97.5 -//// // Max = 1.7 -//// // Cap = 110.5 -//// } else { -//// // If the pitch is not the expected -//// if (pitch >= 63 || pitch <= 76) -//// return; -//// pitch = (new Random().nextFloat() - new Random().nextFloat()) * 0.2F + 1.0F; -//// // Min = 1 -//// // Cap = 63 -//// // Max = 1.2 -//// // Cap = 75.6 -//// } -//// pitch *= 63; -//// if (pitch < 0) -//// pitch = 0; -//// if (pitch > 255) -//// pitch = 255; -//// mods.write(6, (int) pitch); -//// } -//// } -//// } -//// } -//// } -//// } -//// } -//// } -// } else if (event.getPacketType() == Server.ENTITY_STATUS) { -// if ((byte) mods.read(1) == 2) { -// // It made a damage animation -// Entity entity = event.getPacket().getEntityModifier(observer.getWorld()).read(0); -// Disguise disguise = DisguiseAPI.getDisguise(observer, entity); -// if (disguise != null && !disguise.getType().isPlayer() -// && (disguise.isSelfDisguiseSoundsReplaced() || entity != event.getPlayer())) { -// DisguiseSound disSound = DisguiseSound.getType(entity.getType().name()); -// if (disSound == null) -// return; -// SoundType soundType = null; -// Object obj = null; -// if (entity instanceof LivingEntity) { -// try { -// obj = LivingEntity.class.getMethod("getHealth").invoke(entity); -// if (obj instanceof Double ? (Double) obj == 0 : (Integer) obj == 0) { -// soundType = SoundType.DEATH; -// } else { -// obj = null; -// } -// } catch (Exception e) { -// e.printStackTrace(); -// } -// } -// if (obj == null) { -// soundType = SoundType.HURT; -// } -// if (disSound.getSound(soundType) == null -// || (disguise.isSelfDisguiseSoundsReplaced() && entity == event.getPlayer())) { -// if (disguise.isSelfDisguiseSoundsReplaced() && entity == event.getPlayer()) { -// cancelSound = !cancelSound; -// if (cancelSound) -// return; -// } -// disSound = DisguiseSound.getType(disguise.getType().name()); -// if (disSound != null) { -// String sound = disSound.getSound(soundType); -// if (sound != null) { -// Location loc = entity.getLocation(); -// PacketContainer packet = new PacketContainer(Server.NAMED_SOUND_EFFECT); -// mods = packet.getModifier(); -// mods.write(0, sound); -// mods.write(1, (int) (loc.getX() * 8D)); -// mods.write(2, (int) (loc.getY() * 8D)); -// mods.write(3, (int) (loc.getZ() * 8D)); -// mods.write(4, disSound.getDamageAndIdleSoundVolume()); -// float pitch; -// if (disguise instanceof MobDisguise && !((MobDisguise) disguise).isAdult()) { -// pitch = (new Random().nextFloat() - new Random().nextFloat()) * 0.2F + 1.5F; -// } else -// pitch = (new Random().nextFloat() - new Random().nextFloat()) * 0.2F + 1.0F; -// if (disguise.getType() == DisguiseType.BAT) -// pitch *= 95F; -// pitch *= 63; -// if (pitch < 0) -// pitch = 0; -// if (pitch > 255) -// pitch = 255; -// mods.write(5, (int) pitch); -// try { -// ProtocolLibrary.getProtocolManager().sendServerPacket(observer, packet); -// } catch (InvocationTargetException e) { -// e.printStackTrace(); -// } -// } -// } -// } -// } -// } -// } + if (event.isCancelled()) { + return; + } + event.setPacket(event.getPacket().deepClone()); + StructureModifier mods = event.getPacket().getModifier(); + Player observer = event.getPlayer(); + if (event.getPacketType() == Server.NAMED_SOUND_EFFECT) { + if (event.isAsync()) { + return; + } + Object soundEffect = mods.read(0); + SoundType soundType = null; + Location soundLoc = new Location(observer.getWorld(), ((Integer) mods.read(2)) / 8D, + ((Integer) mods.read(3)) / 8D, ((Integer) mods.read(4)) / 8D); + Entity disguisedEntity = null; + DisguiseSound entitySound = null; + Disguise disguise = null; + Entity[] entities = soundLoc.getChunk().getEntities(); + for (Entity entity : entities) { + Disguise entityDisguise = DisguiseAPI.getDisguise(observer, entity); + if (entityDisguise != null) { + Location loc = entity.getLocation(); + loc = new Location(observer.getWorld(), ((int) (loc.getX() * 8)) / 8D, ((int) (loc.getY() * 8)) / 8D, + ((int) (loc.getZ() * 8)) / 8D); + if (loc.equals(soundLoc)) { + entitySound = DisguiseSound.getType(entity.getType().name()); + if (entitySound != null) { + Object obj = null; + if (entity instanceof LivingEntity) { + try { + // Use reflection so that this works for either int or double methods + obj = LivingEntity.class.getMethod("getHealth").invoke(entity); + if (obj instanceof Double ? (Double) obj == 0 : (Integer) obj == 0) { + soundType = SoundType.DEATH; + } else { + obj = null; + } + } catch (Exception e) { + e.printStackTrace(); + } + } + if (obj == null) { + boolean hasInvun = false; + Object nmsEntity = ReflectionManager.getNmsEntity(entity); + try { + if (entity instanceof LivingEntity) { + hasInvun = ReflectionManager.getNmsField("Entity", "noDamageTicks").getInt( + nmsEntity) == ReflectionManager.getNmsField("EntityLiving", + "maxNoDamageTicks").getInt(nmsEntity); + } else { + Class clazz = ReflectionManager.getNmsClass("DamageSource"); + hasInvun = (Boolean) ReflectionManager.getNmsMethod("Entity", "isInvulnerable", clazz) + .invoke(nmsEntity, ReflectionManager.getNmsField(clazz, "GENERIC")); + } + } catch (Exception ex) { + ex.printStackTrace(); + } + soundType = entitySound.getType(ReflectionManager.convertSoundEffectToString(soundEffect), !hasInvun); + } + if (soundType != null) { + disguise = entityDisguise; + disguisedEntity = entity; + break; + } + } + } + } + } + if (disguise != null) { + if (disguise.isSelfDisguiseSoundsReplaced() || disguisedEntity != event.getPlayer()) { + if (disguise.isSoundsReplaced()) { + String sound = null; + DisguiseSound dSound = DisguiseSound.getType(disguise.getType().name()); + if (dSound != null) + sound = dSound.getSound(soundType); + + if (sound == null) { + event.setCancelled(true); + } else { + if (sound.equals("step.grass")) { + try { + int typeId = soundLoc.getWorld().getBlockTypeIdAt(soundLoc.getBlockX(), + soundLoc.getBlockY() - 1, soundLoc.getBlockZ()); + Object block = ReflectionManager.getNmsMethod("RegistryMaterials", "a", int.class) + .invoke(ReflectionManager.getNmsField("Block", "REGISTRY").get(null), + typeId); + if (block != null) { + Object step = ReflectionManager.getNmsField("Block", "stepSound").get(block); + mods.write(0, ReflectionManager.getNmsMethod(step.getClass(), "getStepSound").invoke(step)); + } + } catch (Exception ex) { + ex.printStackTrace(); + } + // There is no else statement. Because seriously. This should never be null. Unless + // someone is + // sending fake sounds. In which case. Why cancel it. + } else { + mods.write(0, ReflectionManager.getCraftSoundEffect(sound)); + // Time to change the pitch and volume + if (soundType == SoundType.HURT || soundType == SoundType.DEATH + || soundType == SoundType.IDLE) { + // If the volume is the default + if (mods.read(5).equals(entitySound.getDamageAndIdleSoundVolume())) { + mods.write(5, dSound.getDamageAndIdleSoundVolume()); + } + // Here I assume its the default pitch as I can't calculate if its real. + if (disguise instanceof MobDisguise && disguisedEntity instanceof LivingEntity + && ((MobDisguise) disguise).doesDisguiseAge()) { + boolean baby = false; + if (disguisedEntity instanceof Zombie) { + baby = ((Zombie) disguisedEntity).isBaby(); + } else if (disguisedEntity instanceof Ageable) { + baby = !((Ageable) disguisedEntity).isAdult(); + } + if (((MobDisguise) disguise).isAdult() == baby) { + + float pitch = (Integer) mods.read(5); + if (baby) { + // If the pitch is not the expected + if (pitch > 97 || pitch < 111) + return; + pitch = (new Random().nextFloat() - new Random().nextFloat()) * 0.2F + 1.5F; + // Min = 1.5 + // Cap = 97.5 + // Max = 1.7 + // Cap = 110.5 + } else { + // If the pitch is not the expected + if (pitch >= 63 || pitch <= 76) + return; + pitch = (new Random().nextFloat() - new Random().nextFloat()) * 0.2F + 1.0F; + // Min = 1 + // Cap = 63 + // Max = 1.2 + // Cap = 75.6 + } + pitch *= 63; + if (pitch < 0) + pitch = 0; + if (pitch > 255) + pitch = 255; + mods.write(6, (int) pitch); + } + } + } + } + } + } + } + } + } else if (event.getPacketType() == Server.ENTITY_STATUS) { + if ((byte) mods.read(1) == 2) { + // It made a damage animation + Entity entity = event.getPacket().getEntityModifier(observer.getWorld()).read(0); + Disguise disguise = DisguiseAPI.getDisguise(observer, entity); + if (disguise != null && !disguise.getType().isPlayer() + && (disguise.isSelfDisguiseSoundsReplaced() || entity != event.getPlayer())) { + DisguiseSound disSound = DisguiseSound.getType(entity.getType().name()); + if (disSound == null) + return; + SoundType soundType = null; + Object obj = null; + if (entity instanceof LivingEntity) { + try { + obj = LivingEntity.class.getMethod("getHealth").invoke(entity); + if (obj instanceof Double ? (Double) obj == 0 : (Integer) obj == 0) { + soundType = SoundType.DEATH; + } else { + obj = null; + } + } catch (Exception e) { + e.printStackTrace(); + } + } + if (obj == null) { + soundType = SoundType.HURT; + } + if (disSound.getSound(soundType) == null + || (disguise.isSelfDisguiseSoundsReplaced() && entity == event.getPlayer())) { + if (disguise.isSelfDisguiseSoundsReplaced() && entity == event.getPlayer()) { + cancelSound = !cancelSound; + if (cancelSound) + return; + } + disSound = DisguiseSound.getType(disguise.getType().name()); + if (disSound != null) { + String sound = disSound.getSound(soundType); + if (sound != null) { + Location loc = entity.getLocation(); + PacketContainer packet = new PacketContainer(Server.NAMED_SOUND_EFFECT); + mods = packet.getModifier(); + Object craftSoundEffect = ReflectionManager.getCraftSoundEffect(sound); + mods.write(0, craftSoundEffect); + mods.write(1, ReflectionManager.getSoundCategory("master")); //Meh + mods.write(2, (int) (loc.getX() * 8D)); + mods.write(3, (int) (loc.getY() * 8D)); + mods.write(4, (int) (loc.getZ() * 8D)); + mods.write(5, disSound.getDamageAndIdleSoundVolume()); + float pitch; + if (disguise instanceof MobDisguise && !((MobDisguise) disguise).isAdult()) { + pitch = (new Random().nextFloat() - new Random().nextFloat()) * 0.2F + 1.5F; + } else + pitch = (new Random().nextFloat() - new Random().nextFloat()) * 0.2F + 1.0F; + if (disguise.getType() == DisguiseType.BAT) + pitch *= 95F; + pitch *= 63; + if (pitch < 0) + pitch = 0; + if (pitch > 255) + pitch = 255; + mods.write(6, (int) pitch); + try { + ProtocolLibrary.getProtocolManager().sendServerPacket(observer, packet); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } + } + } + } + } + } + } } }; + //Self disguise (/vsd) listener viewDisguisesListener = new PacketAdapter(libsDisguises, ListenerPriority.HIGH, Server.NAMED_ENTITY_SPAWN, Server.ATTACH_ENTITY, Server.REL_ENTITY_MOVE, Server.ENTITY_MOVE_LOOK, @@ -841,8 +837,7 @@ public class PacketsManager { && event.getPlayer().getVehicle() == null) { Disguise disguise = DisguiseAPI.getDisguise(event.getPlayer(), event.getPlayer()); // If player is disguised, views self disguises and has a inventory modifier - if (disguise != null && disguise.isSelfDisguiseVisible() - && (disguise.isHidingArmorFromSelf() || disguise.isHidingHeldItemFromSelf())) { + if (disguise != null && disguise.isSelfDisguiseVisible() && (disguise.isHidingArmorFromSelf() || disguise.isHidingHeldItemFromSelf())) { // If they are in creative and clicked on a slot if (event.getPacketType() == PacketType.Play.Client.SET_CREATIVE_SLOT) { int slot = event.getPacket().getIntegers().read(0); @@ -926,7 +921,8 @@ public class PacketsManager { } else if (event.getPacketType() == PacketType.Play.Client.WINDOW_CLICK) { int slot = event.getPacket().getIntegers().read(1); org.bukkit.inventory.ItemStack clickedItem; - if (event.getPacket().getShorts().read(3) == 1) { + //TODO: Check this to make sure it is accurate + if (event.getPacket().getShorts().read(0) == 1) { // Its a shift click clickedItem = event.getPacket().getItemModifier().read(0); if (clickedItem != null && clickedItem.getType() != Material.AIR) { @@ -1163,6 +1159,7 @@ public class PacketsManager { if (DisguiseConfig.isEntityStatusPacketsEnabled()) { packetsToListen.add(Server.ENTITY_STATUS); } + mainListener = new PacketAdapter(libsDisguises, ListenerPriority.HIGH, packetsToListen) { @Override public void onPacketSending(PacketEvent event) { @@ -1171,8 +1168,7 @@ public class PacketsManager { final Player observer = event.getPlayer(); // First get the entity, the one sending this packet StructureModifier entityModifer = event.getPacket().getEntityModifier(observer.getWorld()); - org.bukkit.entity.Entity entity = entityModifer - .read((Server.COLLECT == event.getPacketType() ? 1 : 0)); + org.bukkit.entity.Entity entity = entityModifer.read((Server.COLLECT == event.getPacketType() ? 1 : 0)); // If the entity is the same as the sender. Don't disguise! // Prevents problems and there is no advantage to be gained. if (entity == observer) @@ -1315,7 +1311,10 @@ public class PacketsManager { .getWatcher()).isSleeping())))) { packets = new PacketContainer[0]; } - } else if (sentPacket.getType() == Server.COLLECT) { + } + + //Else if the disguise is collecting stuff + else if (sentPacket.getType() == Server.COLLECT) { if (disguise.getType().isMisc()) { packets = new PacketContainer[0]; } else if (DisguiseConfig.isBedPacketsEnabled() && disguise.getType().isPlayer() @@ -1334,6 +1333,7 @@ public class PacketsManager { || sentPacket.getType() == Server.ENTITY_TELEPORT || sentPacket.getType() == Server.REL_ENTITY_MOVE) { if (disguise.getType() == DisguiseType.RABBIT && (sentPacket.getType() == Server.REL_ENTITY_MOVE || sentPacket.getType() == Server.ENTITY_MOVE_LOOK)) { + //Rabbit robbing... if (entity.getMetadata("LibsRabbitHop").isEmpty() || System.currentTimeMillis() - entity.getMetadata("LibsRabbitHop").get(0).asLong() < 100 || System.currentTimeMillis() - entity.getMetadata("LibsRabbitHop").get(0).asLong() > 500) { @@ -1349,17 +1349,16 @@ public class PacketsManager { } } + //Stop wither skulls from looking if (sentPacket.getType() == Server.ENTITY_LOOK && disguise.getType() == DisguiseType.WITHER_SKULL) { packets = new PacketContainer[0]; } else if (sentPacket.getType() != Server.REL_ENTITY_MOVE) { - packets[0] = sentPacket.shallowClone(); StructureModifier bytes = packets[0].getBytes(); byte yawValue = bytes.read(1); bytes.write(1, getYaw(disguise.getType(), entity.getType(), yawValue)); byte pitchValue = bytes.read(0); bytes.write(0, getPitch(disguise.getType(), DisguiseType.getType(entity.getType()), pitchValue)); - if (sentPacket.getType() == Server.ENTITY_TELEPORT && disguise.getType() == DisguiseType.ITEM_FRAME) { StructureModifier doubles = packets[0].getDoubles(); Location loc = entity.getLocation(); @@ -1378,7 +1377,10 @@ public class PacketsManager { } } } - } else if (sentPacket.getType() == Server.ENTITY_EQUIPMENT) { + } + + //Else if the disguise is updating equipment + else if (sentPacket.getType() == Server.ENTITY_EQUIPMENT) { EquipmentSlot slot = ReflectionManager.createEquipmentSlot(packets[0].getModifier().read(1)); org.bukkit.inventory.ItemStack itemStack = disguise.getWatcher().getItemStack(slot); if (itemStack != null) { @@ -1420,15 +1422,24 @@ public class PacketsManager { // it. } } - } else if (sentPacket.getType() == Server.BED) { + } + + //If the entity is going into a bed, stop everything but players from doing this + else if (sentPacket.getType() == Server.BED) { if (!disguise.getType().isPlayer()) { packets = new PacketContainer[0]; } - } else if (sentPacket.getType() == Server.ENTITY_STATUS) { + } + + //If the entity is updating their Facebook status, stop them from showing death + else if (sentPacket.getType() == Server.ENTITY_STATUS) { if (packets[0].getBytes().read(0) == (byte) 3) { packets = new PacketContainer[0]; } - } else if (sentPacket.getType() == Server.ENTITY_HEAD_ROTATION) { + } + + //If the entity is rotating his head + else if (sentPacket.getType() == Server.ENTITY_HEAD_ROTATION) { if (disguise.getType().isPlayer() && entity.getType() != EntityType.PLAYER) { Location loc = entity.getLocation(); byte pitch = getPitch(disguise.getType(), DisguiseType.getType(entity.getType()), @@ -1444,7 +1455,10 @@ public class PacketsManager { look.getBytes().write(4, pitch); packets = new PacketContainer[]{look, rotation}; } - } else { + } + + //Whatever + else { packets = null; } diff --git a/src/main/java/me/libraryaddict/disguise/utilities/ReflectionManager.java b/src/main/java/me/libraryaddict/disguise/utilities/ReflectionManager.java index b8abf416..0258fe54 100644 --- a/src/main/java/me/libraryaddict/disguise/utilities/ReflectionManager.java +++ b/src/main/java/me/libraryaddict/disguise/utilities/ReflectionManager.java @@ -39,6 +39,7 @@ public class ReflectionManager { private static final Field pingField; private static Map, String> primitiveTypes; private static final Field trackerField; + public static final Field entityCountField; /* * This portion of code is originally Copyright (C) 2014-2014 Kane York. @@ -79,6 +80,8 @@ public class ReflectionManager { boundingBoxConstructor = getNmsConstructor("AxisAlignedBB", double.class, double.class, double.class, double.class, double.class, double.class); setBoundingBoxMethod = getNmsMethod("Entity", "a", getNmsClass("AxisAlignedBB")); + entityCountField = getNmsField("Entity", "entityCount"); + entityCountField.setAccessible(true); } public static Object createEntityInstance(String entityName) { @@ -109,20 +112,30 @@ public class ReflectionManager { return null; } - public static Object createMobEffect(int id, int duration, int amplification, boolean ambient, boolean particles) { + public static Object getMobEffectList(int id) { + Method nmsMethod = getNmsMethod("MobEffectList", "fromId", Integer.class); try { - return getNmsClass("MobEffect").getDeclaredConstructor(int.class, int.class, int.class, boolean.class, boolean.class) - .newInstance(id, duration, amplification, ambient, particles); - } catch (Exception e) { - e.printStackTrace(System.out); + return nmsMethod.invoke(null, id); + } catch (IllegalAccessException | InvocationTargetException e) { + e.printStackTrace(); + return null; } - return null; } public static Object createMobEffect(PotionEffect effect) { return createMobEffect(effect.getType().getId(), effect.getDuration(), effect.getAmplifier(), effect.isAmbient(), effect.hasParticles()); } + public static Object createMobEffect(int id, int duration, int amplification, boolean ambient, boolean particles) { + try { + return getNmsClass("MobEffect").getDeclaredConstructor(getNmsClass("MobEffectList"), Integer.TYPE, Integer.TYPE, Boolean.TYPE, Boolean.TYPE) + .newInstance(getMobEffectList(id), duration, amplification, ambient, particles); + } catch (Exception e) { + e.printStackTrace(System.out); + } + return null; + } + private static String dir2fqn(String s) { return s.replaceAll("/", "."); } @@ -283,7 +296,6 @@ public class ReflectionManager { } public static WrappedGameProfile getGameProfileWithThisSkin(UUID uuid, String playerName, WrappedGameProfile profileWithSkin) { - try { WrappedGameProfile gameProfile = new WrappedGameProfile(uuid != null ? uuid : UUID.randomUUID(), playerName); gameProfile.getProperties().putAll(profileWithSkin.getProperties()); @@ -491,6 +503,24 @@ public class ReflectionManager { } } + public static Enum getSoundCategory(String category) { + Method method = getNmsMethod("SoundCategory", "a", String.class); + try { + Enum invoke = (Enum) method.invoke(null, category.toLowerCase()); + if (invoke == null) { + Class clazz = getNmsClass("SoundCategory"); + Enum[] enums = clazz != null ? (Enum[]) clazz.getEnumConstants() : null; + for (Enum anEnum : enums != null ? enums : new Enum[0]) { + if (anEnum.name().equals("MASTER")) return anEnum; + } + } + return null; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + /** * Creates the NMS object EnumItemSlot from an EquipmentSlot. * @param slot @@ -587,9 +617,8 @@ public class ReflectionManager { } public static Object getCraftSoundEffect(String sound) { - Method nmsMethod = getNmsMethod("CraftSound", "getSoundEffect"); try { - return nmsMethod.invoke(null, sound); + return getCraftMethod("CraftSound", "getSoundEffect", String.class).invoke(null, sound); } catch (IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); } @@ -625,4 +654,5 @@ public class ReflectionManager { } return null; } + }