From 986dfe6246359037aeb04f0f99804e1df3e19b61 Mon Sep 17 00:00:00 2001 From: libraryaddict Date: Thu, 12 May 2016 23:30:22 +1200 Subject: [PATCH] Cleanup code, fix locations in packets being assumed pre-1.9 --- .../libraryaddict/disguise/DisguiseAPI.java | 22 +- .../disguise/DisguiseConfig.java | 1067 +++--- .../disguise/disguisetypes/Disguise.java | 2 +- .../disguise/disguisetypes/DisguiseType.java | 776 ++-- .../disguise/disguisetypes/FlagWatcher.java | 1272 +++---- .../disguise/disguisetypes/MobDisguise.java | 117 +- .../disguisetypes/PlayerDisguise.java | 182 +- .../watchers/AgeableWatcher.java | 75 +- .../watchers/MinecartWatcher.java | 103 +- .../disguise/utilities/ClassGetter.java | 184 +- .../disguise/utilities/DisguiseUtilities.java | 9 +- .../disguise/utilities/DisguiseValues.java | 261 +- .../disguise/utilities/PacketsManager.java | 3376 ++++++----------- .../disguise/utilities/ReflectionManager.java | 2065 +++++----- .../PacketListenerClientInteract.java | 86 + .../PacketListenerInventory.java | 390 ++ .../packetlisteners/PacketListenerMain.java | 97 + .../packetlisteners/PacketListenerSounds.java | 406 ++ .../PacketListenerViewDisguises.java | 188 + 19 files changed, 5410 insertions(+), 5268 deletions(-) create mode 100644 src/me/libraryaddict/disguise/utilities/packetlisteners/PacketListenerClientInteract.java create mode 100644 src/me/libraryaddict/disguise/utilities/packetlisteners/PacketListenerInventory.java create mode 100644 src/me/libraryaddict/disguise/utilities/packetlisteners/PacketListenerMain.java create mode 100644 src/me/libraryaddict/disguise/utilities/packetlisteners/PacketListenerSounds.java create mode 100644 src/me/libraryaddict/disguise/utilities/packetlisteners/PacketListenerViewDisguises.java diff --git a/src/me/libraryaddict/disguise/DisguiseAPI.java b/src/me/libraryaddict/disguise/DisguiseAPI.java index 2d73871c..2f10863e 100644 --- a/src/me/libraryaddict/disguise/DisguiseAPI.java +++ b/src/me/libraryaddict/disguise/DisguiseAPI.java @@ -4,7 +4,6 @@ import java.lang.reflect.Method; import java.util.Arrays; import java.util.Collection; import java.util.List; -import java.util.UUID; import org.bukkit.DyeColor; import org.bukkit.Material; @@ -151,11 +150,7 @@ public class DisguiseAPI { if (toCast == float.class) { - if (value instanceof Float) - { - value = value; - } - else + if (!(value instanceof Float)) { double d = (Double) value; value = (float) d; @@ -267,7 +262,7 @@ public class DisguiseAPI } /** - * Disguise the next entity to spawn with this disguise. This may not work however if the entity doesn't actually spawn. + * Disguise the next entity to spawn, this means you need to spawn an entity immediately after calling this. * * @param disguise * @return @@ -288,6 +283,7 @@ public class DisguiseAPI { int id = ReflectionManager.getNmsField("Entity", "entityCount").getInt(null); DisguiseUtilities.addFutureDisguise(id, (TargetedDisguise) disguise); + return id; } catch (IllegalAccessException e) @@ -423,18 +419,6 @@ public class DisguiseAPI return DisguiseUtilities.getDisguises(disguised.getUniqueId()); } - /** - * Get the ID of a fake disguise for a entityplayer - * - * @param entityId - * @return - */ - @Deprecated - public static int getFakeDisguise(UUID entityId) - { - return -10; - } - public static int getSelfDisguiseId() { return -10; diff --git a/src/me/libraryaddict/disguise/DisguiseConfig.java b/src/me/libraryaddict/disguise/DisguiseConfig.java index 47f733a3..70b3a2bd 100644 --- a/src/me/libraryaddict/disguise/DisguiseConfig.java +++ b/src/me/libraryaddict/disguise/DisguiseConfig.java @@ -1,541 +1,526 @@ -package me.libraryaddict.disguise; - -import org.bukkit.ChatColor; -import org.bukkit.configuration.ConfigurationSection; - -import me.libraryaddict.disguise.utilities.PacketsManager; - -public class DisguiseConfig -{ - - private static boolean animationEnabled; - private static boolean bedEnabled; - private static boolean blowDisguisesOnAttack; - private static boolean collectEnabled; - private static boolean colorizeSheep; - private static boolean colorizeWolf; - private static String disguiseBlownMessage; - private static int disguiseCloneExpire; - private static int disguiseEntityExpire; - private static boolean entityAnimationsAdded; - private static boolean entityStatusEnabled; - private static boolean equipmentEnabled; - private static boolean hearSelfDisguise; - private static boolean viewSelfDisguise; - private static boolean hidingArmor; - private static boolean hidingHeldItem; - private static boolean keepDisguiseEntityDespawn; - private static boolean keepDisguisePlayerDeath; - private static boolean keepDisguisePlayerLogout; - private static int maxClonedDisguises; - private static boolean maxHealthIsDisguisedEntity; - private static boolean miscDisguisesForLivingEnabled; - private static boolean modifyBoundingBox; - private static boolean movementEnabled; - private static boolean sendsEntityMetadata; - private static boolean sendVelocity; - private static boolean showNameAboveHead; - private static boolean showNameAboveHeadAlwaysVisible; - private static boolean targetDisguises; - private static boolean undisguiseSwitchWorlds; - private static boolean stopShulkerDisguisesFromMoving; - private static String updateMessage = ChatColor.RED + "[LibsDisguises] " + ChatColor.DARK_RED - + "There is a update ready to be downloaded! You are using " + ChatColor.RED + "v%s" + ChatColor.DARK_RED - + ", the new version is " + ChatColor.RED + "%s" + ChatColor.DARK_RED + "!"; - private static String updateNotificationPermission; - private static boolean witherSkullEnabled; - - public static String getDisguiseBlownMessage() - { - return disguiseBlownMessage; - } - - public static int getDisguiseCloneExpire() - { - return disguiseCloneExpire; - } - - public static int getDisguiseEntityExpire() - { - return disguiseEntityExpire; - } - - public static int getMaxClonedDisguises() - { - return maxClonedDisguises; - } - - public static String getUpdateMessage() - { - return updateMessage; - } - - public static String getUpdateNotificationPermission() - { - return updateNotificationPermission; - } - - public static void initConfig(ConfigurationSection config) - { - - setSoundsEnabled(config.getBoolean("DisguiseSounds")); - setVelocitySent(config.getBoolean("SendVelocity")); - setViewDisguises(config.getBoolean("ViewSelfDisguises")); // Since we can now toggle, the view disguises listener must - // always be on - PacketsManager.setViewDisguisesListener(true); - setHearSelfDisguise(config.getBoolean("HearSelfDisguise")); - setHideArmorFromSelf(config.getBoolean("RemoveArmor")); - setHideHeldItemFromSelf(config.getBoolean("RemoveHeldItem")); - setAddEntityAnimations(config.getBoolean("AddEntityAnimations")); - setNameOfPlayerShownAboveDisguise(config.getBoolean("ShowNamesAboveDisguises")); - setNameAboveHeadAlwaysVisible(config.getBoolean("NameAboveHeadAlwaysVisible")); - setModifyBoundingBox(config.getBoolean("ModifyBoundingBox")); - setMonstersIgnoreDisguises(config.getBoolean("MonstersIgnoreDisguises")); - setDisguiseBlownOnAttack(config.getBoolean("BlowDisguises")); - setDisguiseBlownMessage(ChatColor.translateAlternateColorCodes('&', config.getString("BlownDisguiseMessage"))); - setKeepDisguiseOnPlayerDeath(config.getBoolean("KeepDisguises.PlayerDeath")); - setKeepDisguiseOnPlayerLogout(config.getBoolean("KeepDisguises.PlayerLogout")); - setKeepDisguiseOnEntityDespawn(config.getBoolean("KeepDisguises.EntityDespawn")); - setMiscDisguisesForLivingEnabled(config.getBoolean("MiscDisguisesForLiving")); - setMovementPacketsEnabled(config.getBoolean("PacketsEnabled.Movement")); - setWitherSkullPacketsEnabled(config.getBoolean("PacketsEnabled.WitherSkull")); - setEquipmentPacketsEnabled(config.getBoolean("PacketsEnabled.Equipment")); - setAnimationPacketsEnabled(config.getBoolean("PacketsEnabled.Animation")); - setBedPacketsEnabled(config.getBoolean("PacketsEnabled.Bed")); - setEntityStatusPacketsEnabled(config.getBoolean("PacketsEnabled.EntityStatus")); - setCollectPacketsEnabled(config.getBoolean("PacketsEnabled.Collect")); - setMetadataPacketsEnabled(config.getBoolean("PacketsEnabled.Metadata")); - setMaxHealthDeterminedByDisguisedEntity(config.getBoolean("MaxHealthDeterminedByEntity")); - setDisguiseEntityExpire(config.getInt("DisguiseEntityExpire")); - setDisguiseCloneExpire(config.getInt("DisguiseCloneExpire")); - setMaxClonedDisguises(config.getInt("DisguiseCloneSize")); - setSheepDyeable(config.getBoolean("DyeableSheep")); - setWolfDyeable(config.getBoolean("DyeableWolf")); - setUndisguiseOnWorldChange(config.getBoolean("UndisguiseOnWorldChange")); - setUpdateNotificationPermission(config.getString("Permission")); - setStopShulkerDisguisesFromMoving(config.getBoolean("StopShulkerDisguisesFromMoving", true)); - } - - public static boolean isAnimationPacketsEnabled() - { - return animationEnabled; - } - - public static boolean isBedPacketsEnabled() - { - return bedEnabled; - } - - public static boolean isCollectPacketsEnabled() - { - return collectEnabled; - } - - public static boolean isDisguiseBlownOnAttack() - { - return blowDisguisesOnAttack; - } - - /** - * @deprecated Spelling mistake. - */ - @Deprecated - public static boolean isEnquipmentPacketsEnabled() - { - return equipmentEnabled; - } - - public static boolean isEntityAnimationsAdded() - { - return entityAnimationsAdded; - } - - public static boolean isEntityStatusPacketsEnabled() - { - return entityStatusEnabled; - } - - public static boolean isEquipmentPacketsEnabled() - { - return equipmentEnabled; - } - - /** - * Is the plugin modifying the inventory packets so that players when self disguised, do not see their armor floating around - */ - public static boolean isHidingArmorFromSelf() - { - return hidingArmor; - } - - /** - * Does the plugin appear to remove the item they are holding, to prevent a floating sword when they are viewing self disguise - */ - public static boolean isHidingHeldItemFromSelf() - { - return hidingHeldItem; - } - - public static boolean isKeepDisguiseOnEntityDespawn() - { - return keepDisguiseEntityDespawn; - } - - public static boolean isKeepDisguiseOnPlayerDeath() - { - return keepDisguisePlayerDeath; - } - - public static boolean isKeepDisguiseOnPlayerLogout() - { - return keepDisguisePlayerLogout; - } - - public static boolean isMaxHealthDeterminedByDisguisedEntity() - { - return maxHealthIsDisguisedEntity; - } - - public static boolean isMetadataPacketsEnabled() - { - return sendsEntityMetadata; - } - - public static boolean isMiscDisguisesForLivingEnabled() - { - return miscDisguisesForLivingEnabled; - } - - public static boolean isModifyBoundingBox() - { - return modifyBoundingBox; - } - - public static boolean isMonstersIgnoreDisguises() - { - return targetDisguises; - } - - public static boolean isMovementPacketsEnabled() - { - return movementEnabled; - } - - public static boolean isNameAboveHeadAlwaysVisible() - { - return showNameAboveHeadAlwaysVisible; - } - - public static boolean isNameOfPlayerShownAboveDisguise() - { - return showNameAboveHead; - } - - public static boolean isSelfDisguisesSoundsReplaced() - { - return hearSelfDisguise; - } - - public static boolean isSheepDyeable() - { - return colorizeSheep; - } - - /** - * Is the sound packets caught and modified - */ - public static boolean isSoundEnabled() - { - return PacketsManager.isHearDisguisesEnabled(); - } - - public static boolean isUndisguiseOnWorldChange() - { - return undisguiseSwitchWorlds; - } - - /** - * Is the velocity packets sent - * - * @return - */ - public static boolean isVelocitySent() - { - return sendVelocity; - } - - /** - * The default value if a player views his own disguise - * - * @return - */ - public static boolean isViewDisguises() - { - return viewSelfDisguise; - } - - public static boolean isWitherSkullPacketsEnabled() - { - return witherSkullEnabled; - } - - public static boolean isWolfDyeable() - { - return colorizeWolf; - } - - public static void setAddEntityAnimations(boolean isEntityAnimationsAdded) - { - entityAnimationsAdded = isEntityAnimationsAdded; - } - - public static void setAnimationPacketsEnabled(boolean enabled) - { - if (enabled != isAnimationPacketsEnabled()) - { - animationEnabled = enabled; - - PacketsManager.setupMainPacketsListener(); - } - } - - public static void setBedPacketsEnabled(boolean enabled) - { - if (enabled != isBedPacketsEnabled()) - { - bedEnabled = enabled; - - PacketsManager.setupMainPacketsListener(); - } - } - - public static void setCollectPacketsEnabled(boolean enabled) - { - if (enabled != isCollectPacketsEnabled()) - { - collectEnabled = enabled; - - PacketsManager.setupMainPacketsListener(); - } - } - - public static void setDisguiseBlownMessage(String newMessage) - { - disguiseBlownMessage = newMessage; - } - - public static void setDisguiseBlownOnAttack(boolean blowDisguise) - { - blowDisguisesOnAttack = blowDisguise; - } - - public static void setDisguiseCloneExpire(int newExpires) - { - disguiseCloneExpire = newExpires; - } - - public static void setDisguiseEntityExpire(int newExpires) - { - disguiseEntityExpire = newExpires; - } - - @Deprecated - public static void setEnquipmentPacketsEnabled(boolean enabled) - { - setEquipmentPacketsEnabled(enabled); - } - - public static void setEntityStatusPacketsEnabled(boolean enabled) - { - if (enabled != isEntityStatusPacketsEnabled()) - { - entityStatusEnabled = enabled; - - PacketsManager.setupMainPacketsListener(); - } - } - - public static void setEquipmentPacketsEnabled(boolean enabled) - { - if (enabled != isEquipmentPacketsEnabled()) - { - equipmentEnabled = enabled; - - PacketsManager.setupMainPacketsListener(); - } - } - - /** - * Can players hear their own disguises - */ - public static void setHearSelfDisguise(boolean replaceSound) - { - if (hearSelfDisguise != replaceSound) - { - hearSelfDisguise = replaceSound; - } - } - - /** - * Set the plugin to hide self disguises armor from theirselves - */ - public static void setHideArmorFromSelf(boolean hideArmor) - { - if (hidingArmor != hideArmor) - { - hidingArmor = hideArmor; - - PacketsManager.setInventoryListenerEnabled(isHidingHeldItemFromSelf() || isHidingArmorFromSelf()); - } - } - - /** - * Does the plugin appear to remove the item they are holding, to prevent a floating sword when they are viewing self disguise - */ - public static void setHideHeldItemFromSelf(boolean hideHelditem) - { - if (hidingHeldItem != hideHelditem) - { - hidingHeldItem = hideHelditem; - - PacketsManager.setInventoryListenerEnabled(isHidingHeldItemFromSelf() || isHidingArmorFromSelf()); - } - } - - public static void setKeepDisguiseOnEntityDespawn(boolean keepDisguise) - { - keepDisguiseEntityDespawn = keepDisguise; - } - - public static void setKeepDisguiseOnPlayerDeath(boolean keepDisguise) - { - keepDisguisePlayerDeath = keepDisguise; - } - - public static void setKeepDisguiseOnPlayerLogout(boolean keepDisguise) - { - keepDisguisePlayerLogout = keepDisguise; - } - - public static void setMaxClonedDisguises(int newMax) - { - maxClonedDisguises = newMax; - } - - public static void setMaxHealthDeterminedByDisguisedEntity(boolean isDetermined) - { - maxHealthIsDisguisedEntity = isDetermined; - } - - public static void setMetadataPacketsEnabled(boolean enabled) - { - sendsEntityMetadata = enabled; - } - - public static void setMiscDisguisesForLivingEnabled(boolean enabled) - { - if (enabled != isMiscDisguisesForLivingEnabled()) - { - miscDisguisesForLivingEnabled = enabled; - - PacketsManager.setupMainPacketsListener(); - } - } - - public static void setModifyBoundingBox(boolean modifyBounding) - { - modifyBoundingBox = modifyBounding; - } - - public static void setMonstersIgnoreDisguises(boolean ignore) - { - targetDisguises = ignore; - } - - public static void setMovementPacketsEnabled(boolean enabled) - { - if (enabled != isMovementPacketsEnabled()) - { - movementEnabled = enabled; - - PacketsManager.setupMainPacketsListener(); - } - } - - public static void setNameAboveHeadAlwaysVisible(boolean alwaysVisible) - { - showNameAboveHeadAlwaysVisible = alwaysVisible; - } - - public static void setNameOfPlayerShownAboveDisguise(boolean showNames) - { - showNameAboveHead = showNames; - } - - public static void setSheepDyeable(boolean color) - { - colorizeSheep = color; - } - - /** - * Set if the disguises play sounds when hurt - */ - public static void setSoundsEnabled(boolean isSoundsEnabled) - { - PacketsManager.setHearDisguisesListener(isSoundsEnabled); - } - - public static void setUndisguiseOnWorldChange(boolean isUndisguise) - { - undisguiseSwitchWorlds = isUndisguise; - } - - public static void setUpdateMessage(String newMessage) - { - updateMessage = newMessage; - } - - public static void setUpdateNotificationPermission(String newPermission) - { - updateNotificationPermission = newPermission; - } - - public static void setStopShulkerDisguisesFromMoving(boolean stopShulkerDisguisesFromMoving) - { - DisguiseConfig.stopShulkerDisguisesFromMoving = stopShulkerDisguisesFromMoving; - } - - public static boolean isStopShulkerDisguisesFromMoving() - { - return stopShulkerDisguisesFromMoving; - } - - /** - * Disable velocity packets being sent for w/e reason. Maybe you want every ounce of performance you can get? - * - * @param sendVelocityPackets - */ - public static void setVelocitySent(boolean sendVelocityPackets) - { - sendVelocity = sendVelocityPackets; - } - - public static void setViewDisguises(boolean seeOwnDisguise) - { - viewSelfDisguise = seeOwnDisguise; - } - - public static void setWitherSkullPacketsEnabled(boolean enabled) - { - witherSkullEnabled = enabled; - } - - public static void setWolfDyeable(boolean color) - { - colorizeWolf = color; - } - - private DisguiseConfig() - { - } -} +package me.libraryaddict.disguise; + +import org.bukkit.ChatColor; +import org.bukkit.configuration.ConfigurationSection; + +import me.libraryaddict.disguise.utilities.PacketsManager; + +public class DisguiseConfig +{ + + private static boolean animationEnabled; + private static boolean bedEnabled; + private static boolean blowDisguisesOnAttack; + private static boolean collectEnabled; + private static boolean colorizeSheep; + private static boolean colorizeWolf; + private static String disguiseBlownMessage; + private static int disguiseCloneExpire; + private static int disguiseEntityExpire; + private static boolean entityAnimationsAdded; + private static boolean entityStatusEnabled; + private static boolean equipmentEnabled; + private static boolean hearSelfDisguise; + private static boolean viewSelfDisguise; + private static boolean hidingArmor; + private static boolean hidingHeldItem; + private static boolean keepDisguiseEntityDespawn; + private static boolean keepDisguisePlayerDeath; + private static boolean keepDisguisePlayerLogout; + private static int maxClonedDisguises; + private static boolean maxHealthIsDisguisedEntity; + private static boolean miscDisguisesForLivingEnabled; + private static boolean modifyBoundingBox; + private static boolean movementEnabled; + private static boolean sendsEntityMetadata; + private static boolean sendVelocity; + private static boolean showNameAboveHead; + private static boolean showNameAboveHeadAlwaysVisible; + private static boolean targetDisguises; + private static boolean undisguiseSwitchWorlds; + private static boolean stopShulkerDisguisesFromMoving; + private static String updateMessage = ChatColor.RED + "[LibsDisguises] " + ChatColor.DARK_RED + + "There is a update ready to be downloaded! You are using " + ChatColor.RED + "v%s" + ChatColor.DARK_RED + + ", the new version is " + ChatColor.RED + "%s" + ChatColor.DARK_RED + "!"; + private static String updateNotificationPermission; + private static boolean witherSkullEnabled; + + public static String getDisguiseBlownMessage() + { + return disguiseBlownMessage; + } + + public static int getDisguiseCloneExpire() + { + return disguiseCloneExpire; + } + + public static int getDisguiseEntityExpire() + { + return disguiseEntityExpire; + } + + public static int getMaxClonedDisguises() + { + return maxClonedDisguises; + } + + public static String getUpdateMessage() + { + return updateMessage; + } + + public static String getUpdateNotificationPermission() + { + return updateNotificationPermission; + } + + public static void initConfig(ConfigurationSection config) + { + + setSoundsEnabled(config.getBoolean("DisguiseSounds")); + setVelocitySent(config.getBoolean("SendVelocity")); + setViewDisguises(config.getBoolean("ViewSelfDisguises")); // Since we can now toggle, the view disguises listener must + // always be on + PacketsManager.setViewDisguisesListener(true); + setHearSelfDisguise(config.getBoolean("HearSelfDisguise")); + setHideArmorFromSelf(config.getBoolean("RemoveArmor")); + setHideHeldItemFromSelf(config.getBoolean("RemoveHeldItem")); + setAddEntityAnimations(config.getBoolean("AddEntityAnimations")); + setNameOfPlayerShownAboveDisguise(config.getBoolean("ShowNamesAboveDisguises")); + setNameAboveHeadAlwaysVisible(config.getBoolean("NameAboveHeadAlwaysVisible")); + setModifyBoundingBox(config.getBoolean("ModifyBoundingBox")); + setMonstersIgnoreDisguises(config.getBoolean("MonstersIgnoreDisguises")); + setDisguiseBlownOnAttack(config.getBoolean("BlowDisguises")); + setDisguiseBlownMessage(ChatColor.translateAlternateColorCodes('&', config.getString("BlownDisguiseMessage"))); + setKeepDisguiseOnPlayerDeath(config.getBoolean("KeepDisguises.PlayerDeath")); + setKeepDisguiseOnPlayerLogout(config.getBoolean("KeepDisguises.PlayerLogout")); + setKeepDisguiseOnEntityDespawn(config.getBoolean("KeepDisguises.EntityDespawn")); + setMiscDisguisesForLivingEnabled(config.getBoolean("MiscDisguisesForLiving")); + setMovementPacketsEnabled(config.getBoolean("PacketsEnabled.Movement")); + setWitherSkullPacketsEnabled(config.getBoolean("PacketsEnabled.WitherSkull")); + setEquipmentPacketsEnabled(config.getBoolean("PacketsEnabled.Equipment")); + setAnimationPacketsEnabled(config.getBoolean("PacketsEnabled.Animation")); + setBedPacketsEnabled(config.getBoolean("PacketsEnabled.Bed")); + setEntityStatusPacketsEnabled(config.getBoolean("PacketsEnabled.EntityStatus")); + setCollectPacketsEnabled(config.getBoolean("PacketsEnabled.Collect")); + setMetadataPacketsEnabled(config.getBoolean("PacketsEnabled.Metadata")); + setMaxHealthDeterminedByDisguisedEntity(config.getBoolean("MaxHealthDeterminedByEntity")); + setDisguiseEntityExpire(config.getInt("DisguiseEntityExpire")); + setDisguiseCloneExpire(config.getInt("DisguiseCloneExpire")); + setMaxClonedDisguises(config.getInt("DisguiseCloneSize")); + setSheepDyeable(config.getBoolean("DyeableSheep")); + setWolfDyeable(config.getBoolean("DyeableWolf")); + setUndisguiseOnWorldChange(config.getBoolean("UndisguiseOnWorldChange")); + setUpdateNotificationPermission(config.getString("Permission")); + setStopShulkerDisguisesFromMoving(config.getBoolean("StopShulkerDisguisesFromMoving", true)); + } + + public static boolean isAnimationPacketsEnabled() + { + return animationEnabled; + } + + public static boolean isBedPacketsEnabled() + { + return bedEnabled; + } + + public static boolean isCollectPacketsEnabled() + { + return collectEnabled; + } + + public static boolean isDisguiseBlownOnAttack() + { + return blowDisguisesOnAttack; + } + + public static boolean isEntityAnimationsAdded() + { + return entityAnimationsAdded; + } + + public static boolean isEntityStatusPacketsEnabled() + { + return entityStatusEnabled; + } + + public static boolean isEquipmentPacketsEnabled() + { + return equipmentEnabled; + } + + /** + * Is the plugin modifying the inventory packets so that players when self disguised, do not see their armor floating around + */ + public static boolean isHidingArmorFromSelf() + { + return hidingArmor; + } + + /** + * Does the plugin appear to remove the item they are holding, to prevent a floating sword when they are viewing self disguise + */ + public static boolean isHidingHeldItemFromSelf() + { + return hidingHeldItem; + } + + public static boolean isKeepDisguiseOnEntityDespawn() + { + return keepDisguiseEntityDespawn; + } + + public static boolean isKeepDisguiseOnPlayerDeath() + { + return keepDisguisePlayerDeath; + } + + public static boolean isKeepDisguiseOnPlayerLogout() + { + return keepDisguisePlayerLogout; + } + + public static boolean isMaxHealthDeterminedByDisguisedEntity() + { + return maxHealthIsDisguisedEntity; + } + + public static boolean isMetadataPacketsEnabled() + { + return sendsEntityMetadata; + } + + public static boolean isMiscDisguisesForLivingEnabled() + { + return miscDisguisesForLivingEnabled; + } + + public static boolean isModifyBoundingBox() + { + return modifyBoundingBox; + } + + public static boolean isMonstersIgnoreDisguises() + { + return targetDisguises; + } + + public static boolean isMovementPacketsEnabled() + { + return movementEnabled; + } + + public static boolean isNameAboveHeadAlwaysVisible() + { + return showNameAboveHeadAlwaysVisible; + } + + public static boolean isNameOfPlayerShownAboveDisguise() + { + return showNameAboveHead; + } + + public static boolean isSelfDisguisesSoundsReplaced() + { + return hearSelfDisguise; + } + + public static boolean isSheepDyeable() + { + return colorizeSheep; + } + + /** + * Is the sound packets caught and modified + */ + public static boolean isSoundEnabled() + { + return PacketsManager.isHearDisguisesEnabled(); + } + + public static boolean isUndisguiseOnWorldChange() + { + return undisguiseSwitchWorlds; + } + + /** + * Is the velocity packets sent + * + * @return + */ + public static boolean isVelocitySent() + { + return sendVelocity; + } + + /** + * The default value if a player views his own disguise + * + * @return + */ + public static boolean isViewDisguises() + { + return viewSelfDisguise; + } + + public static boolean isWitherSkullPacketsEnabled() + { + return witherSkullEnabled; + } + + public static boolean isWolfDyeable() + { + return colorizeWolf; + } + + public static void setAddEntityAnimations(boolean isEntityAnimationsAdded) + { + entityAnimationsAdded = isEntityAnimationsAdded; + } + + public static void setAnimationPacketsEnabled(boolean enabled) + { + if (enabled != isAnimationPacketsEnabled()) + { + animationEnabled = enabled; + + PacketsManager.setupMainPacketsListener(); + } + } + + public static void setBedPacketsEnabled(boolean enabled) + { + if (enabled != isBedPacketsEnabled()) + { + bedEnabled = enabled; + + PacketsManager.setupMainPacketsListener(); + } + } + + public static void setCollectPacketsEnabled(boolean enabled) + { + if (enabled != isCollectPacketsEnabled()) + { + collectEnabled = enabled; + + PacketsManager.setupMainPacketsListener(); + } + } + + public static void setDisguiseBlownMessage(String newMessage) + { + disguiseBlownMessage = newMessage; + } + + public static void setDisguiseBlownOnAttack(boolean blowDisguise) + { + blowDisguisesOnAttack = blowDisguise; + } + + public static void setDisguiseCloneExpire(int newExpires) + { + disguiseCloneExpire = newExpires; + } + + public static void setDisguiseEntityExpire(int newExpires) + { + disguiseEntityExpire = newExpires; + } + + public static void setEntityStatusPacketsEnabled(boolean enabled) + { + if (enabled != isEntityStatusPacketsEnabled()) + { + entityStatusEnabled = enabled; + + PacketsManager.setupMainPacketsListener(); + } + } + + public static void setEquipmentPacketsEnabled(boolean enabled) + { + if (enabled != isEquipmentPacketsEnabled()) + { + equipmentEnabled = enabled; + + PacketsManager.setupMainPacketsListener(); + } + } + + /** + * Can players hear their own disguises + */ + public static void setHearSelfDisguise(boolean replaceSound) + { + if (hearSelfDisguise != replaceSound) + { + hearSelfDisguise = replaceSound; + } + } + + /** + * Set the plugin to hide self disguises armor from theirselves + */ + public static void setHideArmorFromSelf(boolean hideArmor) + { + if (hidingArmor != hideArmor) + { + hidingArmor = hideArmor; + + PacketsManager.setInventoryListenerEnabled(isHidingHeldItemFromSelf() || isHidingArmorFromSelf()); + } + } + + /** + * Does the plugin appear to remove the item they are holding, to prevent a floating sword when they are viewing self disguise + */ + public static void setHideHeldItemFromSelf(boolean hideHelditem) + { + if (hidingHeldItem != hideHelditem) + { + hidingHeldItem = hideHelditem; + + PacketsManager.setInventoryListenerEnabled(isHidingHeldItemFromSelf() || isHidingArmorFromSelf()); + } + } + + public static void setKeepDisguiseOnEntityDespawn(boolean keepDisguise) + { + keepDisguiseEntityDespawn = keepDisguise; + } + + public static void setKeepDisguiseOnPlayerDeath(boolean keepDisguise) + { + keepDisguisePlayerDeath = keepDisguise; + } + + public static void setKeepDisguiseOnPlayerLogout(boolean keepDisguise) + { + keepDisguisePlayerLogout = keepDisguise; + } + + public static void setMaxClonedDisguises(int newMax) + { + maxClonedDisguises = newMax; + } + + public static void setMaxHealthDeterminedByDisguisedEntity(boolean isDetermined) + { + maxHealthIsDisguisedEntity = isDetermined; + } + + public static void setMetadataPacketsEnabled(boolean enabled) + { + sendsEntityMetadata = enabled; + } + + public static void setMiscDisguisesForLivingEnabled(boolean enabled) + { + if (enabled != isMiscDisguisesForLivingEnabled()) + { + miscDisguisesForLivingEnabled = enabled; + + PacketsManager.setupMainPacketsListener(); + } + } + + public static void setModifyBoundingBox(boolean modifyBounding) + { + modifyBoundingBox = modifyBounding; + } + + public static void setMonstersIgnoreDisguises(boolean ignore) + { + targetDisguises = ignore; + } + + public static void setMovementPacketsEnabled(boolean enabled) + { + if (enabled != isMovementPacketsEnabled()) + { + movementEnabled = enabled; + + PacketsManager.setupMainPacketsListener(); + } + } + + public static void setNameAboveHeadAlwaysVisible(boolean alwaysVisible) + { + showNameAboveHeadAlwaysVisible = alwaysVisible; + } + + public static void setNameOfPlayerShownAboveDisguise(boolean showNames) + { + showNameAboveHead = showNames; + } + + public static void setSheepDyeable(boolean color) + { + colorizeSheep = color; + } + + /** + * Set if the disguises play sounds when hurt + */ + public static void setSoundsEnabled(boolean isSoundsEnabled) + { + PacketsManager.setHearDisguisesListener(isSoundsEnabled); + } + + public static void setUndisguiseOnWorldChange(boolean isUndisguise) + { + undisguiseSwitchWorlds = isUndisguise; + } + + public static void setUpdateMessage(String newMessage) + { + updateMessage = newMessage; + } + + public static void setUpdateNotificationPermission(String newPermission) + { + updateNotificationPermission = newPermission; + } + + public static void setStopShulkerDisguisesFromMoving(boolean stopShulkerDisguisesFromMoving) + { + DisguiseConfig.stopShulkerDisguisesFromMoving = stopShulkerDisguisesFromMoving; + } + + public static boolean isStopShulkerDisguisesFromMoving() + { + return stopShulkerDisguisesFromMoving; + } + + /** + * Disable velocity packets being sent for w/e reason. Maybe you want every ounce of performance you can get? + * + * @param sendVelocityPackets + */ + public static void setVelocitySent(boolean sendVelocityPackets) + { + sendVelocity = sendVelocityPackets; + } + + public static void setViewDisguises(boolean seeOwnDisguise) + { + viewSelfDisguise = seeOwnDisguise; + } + + public static void setWitherSkullPacketsEnabled(boolean enabled) + { + witherSkullEnabled = enabled; + } + + public static void setWolfDyeable(boolean color) + { + colorizeWolf = color; + } + + private DisguiseConfig() + { + } +} diff --git a/src/me/libraryaddict/disguise/disguisetypes/Disguise.java b/src/me/libraryaddict/disguise/disguisetypes/Disguise.java index 0cfb3003..253a0350 100644 --- a/src/me/libraryaddict/disguise/disguisetypes/Disguise.java +++ b/src/me/libraryaddict/disguise/disguisetypes/Disguise.java @@ -82,7 +82,7 @@ public abstract class Disguise if (newType.getEntityType() == null) { throw new RuntimeException("DisguiseType " + newType - + " was used in a futile attempt to construct a disguise, but this version of Spigot does not have that entity"); + + " was used in a futile attempt to construct a disguise, but this Minecraft version does not have that entity"); } // Set the disguise type diff --git a/src/me/libraryaddict/disguise/disguisetypes/DisguiseType.java b/src/me/libraryaddict/disguise/disguisetypes/DisguiseType.java index d37e5337..d1de2545 100644 --- a/src/me/libraryaddict/disguise/disguisetypes/DisguiseType.java +++ b/src/me/libraryaddict/disguise/disguisetypes/DisguiseType.java @@ -1,389 +1,387 @@ -package me.libraryaddict.disguise.disguisetypes; - -import java.lang.reflect.Method; - -import org.apache.commons.lang.StringUtils; -import org.bukkit.entity.Entity; -import org.bukkit.entity.EntityType; -import org.bukkit.entity.Guardian; -import org.bukkit.entity.Horse; -import org.bukkit.entity.Skeleton; -import org.bukkit.entity.Skeleton.SkeletonType; -import org.bukkit.entity.Zombie; - -public enum DisguiseType -{ - - AREA_EFFECT_CLOUD(3, 0), - - ARMOR_STAND(78), - - ARROW(60, 0), - - BAT, - - BLAZE, - - BOAT(1), - - CAVE_SPIDER, - - CHICKEN, - - COW, - - CREEPER, - - DONKEY, - - DRAGON_FIREBALL(93), - - DROPPED_ITEM(2, 1), - - EGG(62), - - ELDER_GUARDIAN, - - ENDER_CRYSTAL(51), - - ENDER_DRAGON, - - ENDER_PEARL(65), - - ENDER_SIGNAL(72), - - ENDERMAN, - - ENDERMITE, - - EXPERIENCE_ORB, - - FALLING_BLOCK(70, 1), - - FIREBALL(63), - - FIREWORK(76), - - FISHING_HOOK(90), - - GHAST, - - GIANT, - - GUARDIAN, - - HORSE, - - IRON_GOLEM, - - ITEM_FRAME(71), - - LEASH_HITCH(77), - - MAGMA_CUBE, - - MINECART(10), - - MINECART_CHEST(10, 1), - - MINECART_COMMAND(10, 6), - - MINECART_FURNACE(10, 2), - - MINECART_HOPPER(10, 5), - - MINECART_MOB_SPAWNER(10, 4), - - MINECART_TNT(10, 3), - - MULE, - - MUSHROOM_COW, - - OCELOT, - - PAINTING, - - PIG, - - PIG_ZOMBIE, - - PLAYER, - - PRIMED_TNT(50), - - RABBIT, - - SHEEP, - - SHULKER, - - SHULKER_BULLET(67), - - SILVERFISH, - - SKELETON, - - SKELETON_HORSE, - - SLIME, - - SMALL_FIREBALL(63), - - SNOWBALL(61), - - SNOWMAN, - - SPECTRAL_ARROW(91), - - SPIDER, - - SPLASH_POTION(73, 0), - - SQUID, - - TIPPED_ARROW(92), - - THROWN_EXP_BOTTLE(75), - - UNDEAD_HORSE, - - VILLAGER, - - WITCH, - - WITHER, - - WITHER_SKELETON, - - WITHER_SKULL(66), - - WOLF, - - ZOMBIE, - - ZOMBIE_VILLAGER, - - UNKNOWN; - - static - { - // We set the entity type in this so that we can safely ignore disguisetypes which don't exist in older versions of MC. - // Without erroring up everything. - - for (DisguiseType type : values()) - { - - try - { - DisguiseType toUse = type; - String name; - - switch (type) - { - // Disguise item frame isn't supported. So we don't give it a entity type which should prevent it from being.. - // Usable. - case ITEM_FRAME: - break; - case DONKEY: - case MULE: - case UNDEAD_HORSE: - case SKELETON_HORSE: - toUse = DisguiseType.HORSE; - break; - case ZOMBIE_VILLAGER: - toUse = DisguiseType.ZOMBIE; - break; - case WITHER_SKELETON: - toUse = DisguiseType.SKELETON; - break; - case ELDER_GUARDIAN: - toUse = DisguiseType.GUARDIAN; - break; - default: - break; - } - - name = toUse.name(); - - type.setEntityType(EntityType.valueOf(name)); - } - catch (Throwable ex) - { - // This version of Spigot doesn't have the disguise. - } - } - } - - public static DisguiseType getType(Entity entity) - { - DisguiseType disguiseType = getType(entity.getType()); - - switch (disguiseType) - { - case ZOMBIE: - - if (((Zombie) entity).isVillager()) - { - disguiseType = DisguiseType.ZOMBIE_VILLAGER; - } - - break; - - case HORSE: - - disguiseType = DisguiseType.valueOf(((Horse) entity).getVariant().name()); - - break; - - case SKELETON: - - if (((Skeleton) entity).getSkeletonType() == SkeletonType.WITHER) - { - disguiseType = DisguiseType.WITHER_SKELETON; - } - - break; - case GUARDIAN: - - if (((Guardian) entity).isElder()) - { - disguiseType = DisguiseType.ELDER_GUARDIAN; - } - - break; - default: - break; - } - - return disguiseType; - - } - - public static DisguiseType getType(EntityType entityType) - { - try - { - return valueOf(entityType.name().toUpperCase()); - } - catch (Throwable ex) - { - return DisguiseType.UNKNOWN; - } - } - - private int objectId = -1, defaultData = 0; - - private EntityType entityType; - - private Class watcherClass; - - DisguiseType(int... ints) - { - for (int i = 0; i < ints.length; i++) - { - int value = ints[i]; - - switch (i) - { - case 0: - objectId = value; - - break; - case 1: - defaultData = value; - - break; - default: - break; - } - } - } - - public int getDefaultData() - { - return defaultData; - } - - public Class getEntityClass() - { - if (entityType != null) - { - return getEntityType().getEntityClass(); - } - - return Entity.class; - } - - public EntityType getEntityType() - { - return entityType; - } - - /** - * The TYPE id of this entity. Different from the Object Id send in spawn packets when spawning miscs. - * - * @return - */ - public int getTypeId() - { - return (int) getEntityType().getTypeId(); - } - - /** - * The object type send in packets when spawning a misc entity. Otherwise, -1. - * - * @return - */ - public int getObjectId() - { - return objectId; - } - - public Class getWatcherClass() - { - return watcherClass; - } - - public boolean isMisc() - { - return getEntityType() != null && !getEntityType().isAlive(); - } - - public boolean isMob() - { - return getEntityType() != null && getEntityType().isAlive() && !isPlayer(); - } - - public boolean isPlayer() - { - return this == DisguiseType.PLAYER; - } - - public boolean isUnknown() - { - return this == DisguiseType.UNKNOWN; - } - - private void setEntityType(EntityType entityType) - { - this.entityType = entityType; - } - - public void setWatcherClass(Class c) - { - watcherClass = c; - } - - public String toReadable() - { - String[] split = name().split("_"); - - for (int i = 0; i < split.length; i++) - { - split[i] = split[i].substring(0, 1) + split[i].substring(1).toLowerCase(); - } - - return StringUtils.join(split, " "); - } -} +package me.libraryaddict.disguise.disguisetypes; + +import org.apache.commons.lang.StringUtils; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Guardian; +import org.bukkit.entity.Horse; +import org.bukkit.entity.Skeleton; +import org.bukkit.entity.Skeleton.SkeletonType; +import org.bukkit.entity.Zombie; + +public enum DisguiseType +{ + + AREA_EFFECT_CLOUD(3, 0), + + ARMOR_STAND(78), + + ARROW(60, 0), + + BAT, + + BLAZE, + + BOAT(1), + + CAVE_SPIDER, + + CHICKEN, + + COW, + + CREEPER, + + DONKEY, + + DRAGON_FIREBALL(93), + + DROPPED_ITEM(2, 1), + + EGG(62), + + ELDER_GUARDIAN, + + ENDER_CRYSTAL(51), + + ENDER_DRAGON, + + ENDER_PEARL(65), + + ENDER_SIGNAL(72), + + ENDERMAN, + + ENDERMITE, + + EXPERIENCE_ORB, + + FALLING_BLOCK(70, 1), + + FIREBALL(63), + + FIREWORK(76), + + FISHING_HOOK(90), + + GHAST, + + GIANT, + + GUARDIAN, + + HORSE, + + IRON_GOLEM, + + ITEM_FRAME(71), + + LEASH_HITCH(77), + + MAGMA_CUBE, + + MINECART(10), + + MINECART_CHEST(10, 1), + + MINECART_COMMAND(10, 6), + + MINECART_FURNACE(10, 2), + + MINECART_HOPPER(10, 5), + + MINECART_MOB_SPAWNER(10, 4), + + MINECART_TNT(10, 3), + + MULE, + + MUSHROOM_COW, + + OCELOT, + + PAINTING, + + PIG, + + PIG_ZOMBIE, + + PLAYER, + + PRIMED_TNT(50), + + RABBIT, + + SHEEP, + + SHULKER, + + SHULKER_BULLET(67), + + SILVERFISH, + + SKELETON, + + SKELETON_HORSE, + + SLIME, + + SMALL_FIREBALL(63), + + SNOWBALL(61), + + SNOWMAN, + + SPECTRAL_ARROW(91), + + SPIDER, + + SPLASH_POTION(73, 0), + + SQUID, + + TIPPED_ARROW(92), + + THROWN_EXP_BOTTLE(75), + + UNDEAD_HORSE, + + VILLAGER, + + WITCH, + + WITHER, + + WITHER_SKELETON, + + WITHER_SKULL(66), + + WOLF, + + ZOMBIE, + + ZOMBIE_VILLAGER, + + UNKNOWN; + + static + { + // We set the entity type in this so that we can safely ignore disguisetypes which don't exist in older versions of MC. + // Without erroring up everything. + + for (DisguiseType type : values()) + { + + try + { + DisguiseType toUse = type; + String name; + + switch (type) + { + // Disguise item frame isn't supported. So we don't give it a entity type which should prevent it from being.. + // Usable. + case ITEM_FRAME: + break; + case DONKEY: + case MULE: + case UNDEAD_HORSE: + case SKELETON_HORSE: + toUse = DisguiseType.HORSE; + break; + case ZOMBIE_VILLAGER: + toUse = DisguiseType.ZOMBIE; + break; + case WITHER_SKELETON: + toUse = DisguiseType.SKELETON; + break; + case ELDER_GUARDIAN: + toUse = DisguiseType.GUARDIAN; + break; + default: + break; + } + + name = toUse.name(); + + type.setEntityType(EntityType.valueOf(name)); + } + catch (Throwable ex) + { + // This version of Spigot doesn't have the disguise. + } + } + } + + public static DisguiseType getType(Entity entity) + { + DisguiseType disguiseType = getType(entity.getType()); + + switch (disguiseType) + { + case ZOMBIE: + + if (((Zombie) entity).isVillager()) + { + disguiseType = DisguiseType.ZOMBIE_VILLAGER; + } + + break; + + case HORSE: + + disguiseType = DisguiseType.valueOf(((Horse) entity).getVariant().name()); + + break; + + case SKELETON: + + if (((Skeleton) entity).getSkeletonType() == SkeletonType.WITHER) + { + disguiseType = DisguiseType.WITHER_SKELETON; + } + + break; + case GUARDIAN: + + if (((Guardian) entity).isElder()) + { + disguiseType = DisguiseType.ELDER_GUARDIAN; + } + + break; + default: + break; + } + + return disguiseType; + + } + + public static DisguiseType getType(EntityType entityType) + { + try + { + return valueOf(entityType.name().toUpperCase()); + } + catch (Throwable ex) + { + return DisguiseType.UNKNOWN; + } + } + + private int objectId = -1, defaultData = 0; + + private EntityType entityType; + + private Class watcherClass; + + DisguiseType(int... ints) + { + for (int i = 0; i < ints.length; i++) + { + int value = ints[i]; + + switch (i) + { + case 0: + objectId = value; + + break; + case 1: + defaultData = value; + + break; + default: + break; + } + } + } + + public int getDefaultData() + { + return defaultData; + } + + public Class getEntityClass() + { + if (entityType != null) + { + return getEntityType().getEntityClass(); + } + + return Entity.class; + } + + public EntityType getEntityType() + { + return entityType; + } + + /** + * The TYPE id of this entity. Different from the Object Id send in spawn packets when spawning miscs. + * + * @return + */ + public int getTypeId() + { + return (int) getEntityType().getTypeId(); + } + + /** + * The object type send in packets when spawning a misc entity. Otherwise, -1. + * + * @return + */ + public int getObjectId() + { + return objectId; + } + + public Class getWatcherClass() + { + return watcherClass; + } + + public boolean isMisc() + { + return getEntityType() != null && !getEntityType().isAlive(); + } + + public boolean isMob() + { + return getEntityType() != null && getEntityType().isAlive() && !isPlayer(); + } + + public boolean isPlayer() + { + return this == DisguiseType.PLAYER; + } + + public boolean isUnknown() + { + return this == DisguiseType.UNKNOWN; + } + + private void setEntityType(EntityType entityType) + { + this.entityType = entityType; + } + + public void setWatcherClass(Class c) + { + watcherClass = c; + } + + public String toReadable() + { + String[] split = name().split("_"); + + for (int i = 0; i < split.length; i++) + { + split[i] = split[i].substring(0, 1) + split[i].substring(1).toLowerCase(); + } + + return StringUtils.join(split, " "); + } +} diff --git a/src/me/libraryaddict/disguise/disguisetypes/FlagWatcher.java b/src/me/libraryaddict/disguise/disguisetypes/FlagWatcher.java index 359f186d..51580fe5 100644 --- a/src/me/libraryaddict/disguise/disguisetypes/FlagWatcher.java +++ b/src/me/libraryaddict/disguise/disguisetypes/FlagWatcher.java @@ -1,636 +1,636 @@ -package me.libraryaddict.disguise.disguisetypes; - -import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; - -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.inventory.EntityEquipment; -import org.bukkit.inventory.EquipmentSlot; -import org.bukkit.inventory.ItemStack; - -import com.comphenix.protocol.PacketType.Play.Server; -import com.comphenix.protocol.ProtocolLibrary; -import com.comphenix.protocol.events.PacketContainer; -import com.comphenix.protocol.reflect.StructureModifier; -import com.comphenix.protocol.wrappers.WrappedDataWatcher; -import com.comphenix.protocol.wrappers.WrappedWatchableObject; - -import me.libraryaddict.disguise.DisguiseAPI; -import me.libraryaddict.disguise.DisguiseConfig; -import me.libraryaddict.disguise.utilities.DisguiseUtilities; -import me.libraryaddict.disguise.utilities.PacketsManager; -import me.libraryaddict.disguise.utilities.ReflectionManager; - -public class FlagWatcher -{ - - private boolean addEntityAnimations = DisguiseConfig.isEntityAnimationsAdded(); - /** - * These are the entity values I need to add else it could crash them.. - */ - private HashMap backupEntityValues = new HashMap<>(); - private TargetedDisguise disguise; - private HashMap entityValues = new HashMap<>(); - private boolean hasDied; - public EntityEquipment equipment; - private HashSet modifiedEntityAnimations = new HashSet<>(); - private List watchableObjects; - - public FlagWatcher(Disguise disguise) - { - this.disguise = (TargetedDisguise) disguise; - equipment = ReflectionManager.createEntityEquipment(disguise.getEntity()); - } - - private byte addEntityAnimations(byte originalValue, byte entityValue) - { - byte valueByte = originalValue; - - for (int i = 0; i < 6; i++) - { - if ((entityValue & 1 << i) != 0 && !modifiedEntityAnimations.contains(i)) - { - valueByte = (byte) (valueByte | 1 << i); - } - } - - originalValue = valueByte; - - return originalValue; - } - - public FlagWatcher clone(Disguise owningDisguise) - { - FlagWatcher cloned; - - try - { - cloned = getClass().getConstructor(Disguise.class).newInstance(getDisguise()); - } - catch (Exception e) - { - e.printStackTrace(System.out); - cloned = new FlagWatcher(getDisguise()); - } - - cloned.entityValues = (HashMap) entityValues.clone(); - cloned.equipment = ReflectionManager.createEntityEquipment(cloned.getDisguise().getEntity()); - cloned.modifiedEntityAnimations = (HashSet) modifiedEntityAnimations.clone(); - cloned.addEntityAnimations = addEntityAnimations; - - return cloned; - } - - public List convert(List list) - { - List newList = new ArrayList<>(); - HashSet sentValues = new HashSet<>(); - boolean sendAllCustom = false; - - for (WrappedWatchableObject watch : list) - { - int id = watch.getIndex(); - sentValues.add(id); - - // Its sending the air metadata. This is the least commonly sent metadata which all entitys still share. - // I send my custom values if I see this! - if (id == 1) - { - sendAllCustom = true; - } - - Object value = null; - - if (entityValues.containsKey(id)) - { - if (entityValues.get(id) == null) - { - continue; - } - - value = entityValues.get(id); - } - else if (backupEntityValues.containsKey(id)) - { - if (backupEntityValues.get(id) == null) - { - continue; - } - - value = backupEntityValues.get(id); - } - - if (value != null) - { - if (isEntityAnimationsAdded() && id == 0) - { - value = this.addEntityAnimations((byte) value, (byte) watch.getValue()); - } - - boolean isDirty = watch.getDirtyState(); - - watch = new WrappedWatchableObject(ReflectionManager.createDataWatcherItem(id, value)); - - if (!isDirty) - { - watch.setDirtyState(false); - } - } - else - { - boolean isDirty = watch.getDirtyState(); - - watch = new WrappedWatchableObject(ReflectionManager.createDataWatcherItem(id, watch.getValue())); - - if (!isDirty) - { - watch.setDirtyState(false); - } - } - - newList.add(watch); - } - - if (sendAllCustom) - { - // Its sending the entire meta data. Better add the custom meta - for (int id : entityValues.keySet()) - { - if (sentValues.contains(id)) - { - continue; - } - - Object value = entityValues.get(id); - - if (value == null) - { - continue; - } - - WrappedWatchableObject watch = new WrappedWatchableObject(ReflectionManager.createDataWatcherItem(id, value)); - - newList.add(watch); - } - } - // Here we check for if there is a health packet that says they died. - if (getDisguise().isSelfDisguiseVisible() && getDisguise().getEntity() != null - && getDisguise().getEntity() instanceof Player) - { - for (WrappedWatchableObject watch : newList) - { - // Its a health packet - if (watch.getIndex() == 6) - { - Object value = watch.getValue(); - - if (value != null && value instanceof Float) - { - float newHealth = (Float) value; - - if (newHealth > 0 && hasDied) - { - hasDied = false; - DisguiseUtilities.sendSelfDisguise((Player) getDisguise().getEntity(), disguise); - } - else if (newHealth <= 0 && !hasDied) - { - hasDied = true; - } - } - } - } - } - - return newList; - } - - public ItemStack[] getArmor() - { - ItemStack[] armor = new ItemStack[4]; - System.arraycopy(armor, 0, armor, 0, 4); - - return armor; - } - - public String getCustomName() - { - return (String) getValue(2, null); - } - - protected TargetedDisguise getDisguise() - { - return disguise; - } - - private boolean getEntityFlag(int byteValue) - { - return ((byte) getValue(0, (byte) 0) & 1 << byteValue) != 0; - } - - public ItemStack getItemInMainHand() - { - if (equipment == null) - return null; - - return equipment.getItemInMainHand(); - } - - public ItemStack getItemInOffHand() - { - if (equipment == null) - return null; - - return equipment.getItemInOffHand(); - } - - public EntityEquipment getEquipment() - { - return equipment; - } - - protected Y getValue(int no, Y backup) - { - if (entityValues.containsKey(no)) - { - return (Y) entityValues.get(no); - } - - return backup; - } - - public List getWatchableObjects() - { - if (watchableObjects == null) - { - rebuildWatchableObjects(); - } - - return watchableObjects; - } - - public boolean hasCustomName() - { - return getCustomName() != null; - } - - protected boolean hasValue(int no) - { - return entityValues.containsKey(no); - } - - public boolean isCustomNameVisible() - { - return (boolean) getValue(3, false); - } - - public boolean isEntityAnimationsAdded() - { - return addEntityAnimations; - } - - public boolean isBurning() - { - return getEntityFlag(0); - } - - public boolean isSneaking() - { - return getEntityFlag(1); - } - - public boolean isSprinting() - { - return getEntityFlag(3); - } - - public boolean isRightClicking() - { - return getEntityFlag(4); - } - - public boolean isInvisible() - { - return getEntityFlag(5); - } - - public boolean isGlowing() - { - return getEntityFlag(6); - } - - public boolean isFlyingWithElytra() - { - return getEntityFlag(7); - } - - public void rebuildWatchableObjects() - { - watchableObjects = new ArrayList<>(); - - for (int i = 0; i <= 31; i++) - { - WrappedWatchableObject watchable = null; - - if (this.entityValues.containsKey(i) && this.entityValues.get(i) != null) - { - watchable = new WrappedWatchableObject(ReflectionManager.createDataWatcherItem(i, entityValues.get(i))); - } - else if (this.backupEntityValues.containsKey(i) && this.backupEntityValues.get(i) != null) - { - watchable = new WrappedWatchableObject(ReflectionManager.createDataWatcherItem(i, entityValues.get(i))); - } - - if (watchable != null) - { - watchableObjects.add(watchable); - } - } - } - - protected void sendData(int... dataValues) - { - if (!DisguiseAPI.isDisguiseInUse(getDisguise()) || getDisguise().getWatcher() != this) - { - return; - } - - List list = new ArrayList<>(); - - for (int data : dataValues) - { - if (!entityValues.containsKey(data) || entityValues.get(data) == null) - { - continue; - } - - Object value = entityValues.get(data); - - if (isEntityAnimationsAdded() && DisguiseConfig.isMetadataPacketsEnabled() && data == 0) - { - if (!PacketsManager.isStaticMetadataDisguiseType(disguise)) - { - value = addEntityAnimations((byte) value, - WrappedDataWatcher.getEntityWatcher(disguise.getEntity()).getByte(0)); - } - } - - WrappedWatchableObject watch = new WrappedWatchableObject(ReflectionManager.createDataWatcherItem(data, value)); - - list.add(watch); - } - - if (!list.isEmpty()) - { - PacketContainer packet = new PacketContainer(Server.ENTITY_METADATA); - - StructureModifier mods = packet.getModifier(); - mods.write(0, getDisguise().getEntity().getEntityId()); - - packet.getWatchableCollectionModifier().write(0, list); - - for (Player player : DisguiseUtilities.getPerverts(getDisguise())) - { - try - { - ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet); - } - catch (InvocationTargetException e) - { - e.printStackTrace(System.out); - } - } - } - } - - public void setAddEntityAnimations(boolean isEntityAnimationsAdded) - { - this.addEntityAnimations = isEntityAnimationsAdded; - } - - public void setArmor(ItemStack[] itemstack) - { - setItemStack(EquipmentSlot.HEAD, itemstack[0]); - setItemStack(EquipmentSlot.CHEST, itemstack[1]); - setItemStack(EquipmentSlot.LEGS, itemstack[2]); - setItemStack(EquipmentSlot.FEET, itemstack[3]); - } - - protected void setBackupValue(int no, Object value) - { - backupEntityValues.put(no, value); - } - - public void setBurning(boolean setBurning) - { - setEntityFlag(0, setBurning); - - sendData(0); - } - - public void setCustomName(String name) - { - if (name != null && name.length() > 64) - { - name = name.substring(0, 64); - } - - setValue(2, name); - sendData(2); - } - - public void setCustomNameVisible(boolean display) - { - setValue(3, display); - sendData(3); - } - - private void setEntityFlag(int byteValue, boolean flag) - { - modifiedEntityAnimations.add(byteValue); - - byte b0 = (byte) getValue(0, (byte) 0); - - if (flag) - { - setValue(0, (byte) (b0 | 1 << byteValue)); - } - else - { - setValue(0, (byte) (b0 & ~(1 << byteValue))); - } - } - - public void setInvisible(boolean setInvis) - { - setEntityFlag(5, setInvis); - sendData(0); - } - - public void setGlowing(boolean glowing) - { - setEntityFlag(6, glowing); - sendData(0); - } - - public void setFlyingWithElytra(boolean flying) - { - setEntityFlag(7, flying); - sendData(0); - } - - /** - * Don't use this, use setItemInMainHand instead - * - * @param itemstack - */ - @Deprecated - public void setItemInHand(ItemStack itemstack) - { - setItemInMainHand(itemstack); - } - - public void setItemInMainHand(ItemStack itemstack) - { - setItemStack(EquipmentSlot.HAND, itemstack); - } - - public void setItemInOffHand(ItemStack itemstack) - { - setItemStack(EquipmentSlot.OFF_HAND, itemstack); - } - - public void setItemStack(EquipmentSlot slot, ItemStack itemStack) - { - if (equipment == null) - return; - - // Itemstack which is null means that its not replacing the disguises itemstack. - if (itemStack == null) - { - // Find the item to replace it with - if (getDisguise().getEntity() instanceof LivingEntity) - { - EntityEquipment equipment = ((LivingEntity) getDisguise().getEntity()).getEquipment(); - setItemStack(equipment, slot, itemStack); - } - } - - Object itemToSend = null; - - if (itemStack != null && itemStack.getTypeId() != 0) - { - itemToSend = ReflectionManager.getNmsItem(itemStack); - } - - setItemStack(equipment, slot, itemStack); - - if (DisguiseAPI.isDisguiseInUse(getDisguise()) && getDisguise().getWatcher() == this) - { - PacketContainer packet = new PacketContainer(Server.ENTITY_EQUIPMENT); - - StructureModifier mods = packet.getModifier(); - - mods.write(0, getDisguise().getEntity().getEntityId()); - mods.write(1, ReflectionManager.createEnumItemSlot(slot)); - mods.write(2, itemToSend); - - for (Player player : DisguiseUtilities.getPerverts(getDisguise())) - { - try - { - ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet); - } - catch (InvocationTargetException e) - { - e.printStackTrace(System.out); - } - } - } - } - - private void setItemStack(EntityEquipment equipment, EquipmentSlot slot, ItemStack itemStack) - { - if (equipment == null) - return; - - switch (slot) - { - case CHEST: - equipment.setChestplate(itemStack); - break; - case FEET: - equipment.setBoots(itemStack); - break; - case HAND: - equipment.setItemInMainHand(itemStack); - break; - case HEAD: - equipment.setHelmet(itemStack); - break; - case LEGS: - equipment.setLeggings(itemStack); - break; - case OFF_HAND: - equipment.setItemInOffHand(itemStack); - break; - } - } - - public ItemStack getItemStack(EquipmentSlot slot) - { - if (equipment == null) - return null; - - switch (slot) - { - case CHEST: - return equipment.getChestplate(); - case FEET: - return equipment.getBoots(); - case HAND: - return equipment.getItemInMainHand(); - case HEAD: - return equipment.getHelmet(); - case LEGS: - return equipment.getLeggings(); - case OFF_HAND: - return equipment.getItemInOffHand(); - } - - return null; - } - - public void setRightClicking(boolean setRightClicking) - { - setEntityFlag(4, setRightClicking); - sendData(0); - } - - public void setSneaking(boolean setSneaking) - { - setEntityFlag(1, setSneaking); - sendData(0); - } - - public void setSprinting(boolean setSprinting) - { - setEntityFlag(3, setSprinting); - sendData(0); - } - - protected void setValue(int id, Object value) - { - entityValues.put(id, value); - - if (!DisguiseConfig.isMetadataPacketsEnabled()) - { - this.rebuildWatchableObjects(); - } - } - -} +package me.libraryaddict.disguise.disguisetypes; + +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; + +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.inventory.EntityEquipment; +import org.bukkit.inventory.EquipmentSlot; +import org.bukkit.inventory.ItemStack; + +import com.comphenix.protocol.PacketType.Play.Server; +import com.comphenix.protocol.ProtocolLibrary; +import com.comphenix.protocol.events.PacketContainer; +import com.comphenix.protocol.reflect.StructureModifier; +import com.comphenix.protocol.wrappers.WrappedDataWatcher; +import com.comphenix.protocol.wrappers.WrappedWatchableObject; + +import me.libraryaddict.disguise.DisguiseAPI; +import me.libraryaddict.disguise.DisguiseConfig; +import me.libraryaddict.disguise.utilities.DisguiseUtilities; +import me.libraryaddict.disguise.utilities.PacketsManager; +import me.libraryaddict.disguise.utilities.ReflectionManager; + +public class FlagWatcher +{ + + private boolean addEntityAnimations = DisguiseConfig.isEntityAnimationsAdded(); + /** + * These are the entity values I need to add else it could crash them.. + */ + private HashMap backupEntityValues = new HashMap<>(); + private TargetedDisguise disguise; + private HashMap entityValues = new HashMap<>(); + private boolean hasDied; + private EntityEquipment equipment; + private HashSet modifiedEntityAnimations = new HashSet<>(); + private List watchableObjects; + + public FlagWatcher(Disguise disguise) + { + this.disguise = (TargetedDisguise) disguise; + equipment = ReflectionManager.createEntityEquipment(disguise.getEntity()); + } + + private byte addEntityAnimations(byte originalValue, byte entityValue) + { + byte valueByte = originalValue; + + for (int i = 0; i < 6; i++) + { + if ((entityValue & 1 << i) != 0 && !modifiedEntityAnimations.contains(i)) + { + valueByte = (byte) (valueByte | 1 << i); + } + } + + originalValue = valueByte; + + return originalValue; + } + + public FlagWatcher clone(Disguise owningDisguise) + { + FlagWatcher cloned; + + try + { + cloned = getClass().getConstructor(Disguise.class).newInstance(getDisguise()); + } + catch (Exception e) + { + e.printStackTrace(System.out); + cloned = new FlagWatcher(getDisguise()); + } + + cloned.entityValues = (HashMap) entityValues.clone(); + cloned.equipment = ReflectionManager.createEntityEquipment(cloned.getDisguise().getEntity()); + cloned.modifiedEntityAnimations = (HashSet) modifiedEntityAnimations.clone(); + cloned.addEntityAnimations = addEntityAnimations; + + return cloned; + } + + public List convert(List list) + { + List newList = new ArrayList<>(); + HashSet sentValues = new HashSet<>(); + boolean sendAllCustom = false; + + for (WrappedWatchableObject watch : list) + { + int id = watch.getIndex(); + sentValues.add(id); + + // Its sending the air metadata. This is the least commonly sent metadata which all entitys still share. + // I send my custom values if I see this! + if (id == 1) + { + sendAllCustom = true; + } + + Object value = null; + + if (entityValues.containsKey(id)) + { + if (entityValues.get(id) == null) + { + continue; + } + + value = entityValues.get(id); + } + else if (backupEntityValues.containsKey(id)) + { + if (backupEntityValues.get(id) == null) + { + continue; + } + + value = backupEntityValues.get(id); + } + + if (value != null) + { + if (isEntityAnimationsAdded() && id == 0) + { + value = this.addEntityAnimations((byte) value, (byte) watch.getValue()); + } + + boolean isDirty = watch.getDirtyState(); + + watch = new WrappedWatchableObject(ReflectionManager.createDataWatcherItem(id, value)); + + if (!isDirty) + { + watch.setDirtyState(false); + } + } + else + { + boolean isDirty = watch.getDirtyState(); + + watch = new WrappedWatchableObject(ReflectionManager.createDataWatcherItem(id, watch.getValue())); + + if (!isDirty) + { + watch.setDirtyState(false); + } + } + + newList.add(watch); + } + + if (sendAllCustom) + { + // Its sending the entire meta data. Better add the custom meta + for (int id : entityValues.keySet()) + { + if (sentValues.contains(id)) + { + continue; + } + + Object value = entityValues.get(id); + + if (value == null) + { + continue; + } + + WrappedWatchableObject watch = new WrappedWatchableObject(ReflectionManager.createDataWatcherItem(id, value)); + + newList.add(watch); + } + } + // Here we check for if there is a health packet that says they died. + if (getDisguise().isSelfDisguiseVisible() && getDisguise().getEntity() != null + && getDisguise().getEntity() instanceof Player) + { + for (WrappedWatchableObject watch : newList) + { + // Its a health packet + if (watch.getIndex() == 6) + { + Object value = watch.getValue(); + + if (value != null && value instanceof Float) + { + float newHealth = (Float) value; + + if (newHealth > 0 && hasDied) + { + hasDied = false; + DisguiseUtilities.sendSelfDisguise((Player) getDisguise().getEntity(), disguise); + } + else if (newHealth <= 0 && !hasDied) + { + hasDied = true; + } + } + } + } + } + + return newList; + } + + public ItemStack[] getArmor() + { + ItemStack[] armor = new ItemStack[4]; + System.arraycopy(armor, 0, armor, 0, 4); + + return armor; + } + + public String getCustomName() + { + return (String) getValue(2, null); + } + + protected TargetedDisguise getDisguise() + { + return disguise; + } + + private boolean getEntityFlag(int byteValue) + { + return ((byte) getValue(0, (byte) 0) & 1 << byteValue) != 0; + } + + public ItemStack getItemInMainHand() + { + if (equipment == null) + return null; + + return equipment.getItemInMainHand(); + } + + public ItemStack getItemInOffHand() + { + if (equipment == null) + return null; + + return equipment.getItemInOffHand(); + } + + public EntityEquipment getEquipment() + { + return equipment; + } + + protected Y getValue(int no, Y backup) + { + if (entityValues.containsKey(no)) + { + return (Y) entityValues.get(no); + } + + return backup; + } + + public List getWatchableObjects() + { + if (watchableObjects == null) + { + rebuildWatchableObjects(); + } + + return watchableObjects; + } + + public boolean hasCustomName() + { + return getCustomName() != null; + } + + protected boolean hasValue(int no) + { + return entityValues.containsKey(no); + } + + public boolean isCustomNameVisible() + { + return (boolean) getValue(3, false); + } + + public boolean isEntityAnimationsAdded() + { + return addEntityAnimations; + } + + public boolean isBurning() + { + return getEntityFlag(0); + } + + public boolean isSneaking() + { + return getEntityFlag(1); + } + + public boolean isSprinting() + { + return getEntityFlag(3); + } + + public boolean isRightClicking() + { + return getEntityFlag(4); + } + + public boolean isInvisible() + { + return getEntityFlag(5); + } + + public boolean isGlowing() + { + return getEntityFlag(6); + } + + public boolean isFlyingWithElytra() + { + return getEntityFlag(7); + } + + public void rebuildWatchableObjects() + { + watchableObjects = new ArrayList<>(); + + for (int i = 0; i <= 31; i++) + { + WrappedWatchableObject watchable = null; + + if (this.entityValues.containsKey(i) && this.entityValues.get(i) != null) + { + watchable = new WrappedWatchableObject(ReflectionManager.createDataWatcherItem(i, entityValues.get(i))); + } + else if (this.backupEntityValues.containsKey(i) && this.backupEntityValues.get(i) != null) + { + watchable = new WrappedWatchableObject(ReflectionManager.createDataWatcherItem(i, entityValues.get(i))); + } + + if (watchable != null) + { + watchableObjects.add(watchable); + } + } + } + + protected void sendData(int... dataValues) + { + if (!DisguiseAPI.isDisguiseInUse(getDisguise()) || getDisguise().getWatcher() != this) + { + return; + } + + List list = new ArrayList<>(); + + for (int data : dataValues) + { + if (!entityValues.containsKey(data) || entityValues.get(data) == null) + { + continue; + } + + Object value = entityValues.get(data); + + if (isEntityAnimationsAdded() && DisguiseConfig.isMetadataPacketsEnabled() && data == 0) + { + if (!PacketsManager.isStaticMetadataDisguiseType(disguise)) + { + value = addEntityAnimations((byte) value, + WrappedDataWatcher.getEntityWatcher(disguise.getEntity()).getByte(0)); + } + } + + WrappedWatchableObject watch = new WrappedWatchableObject(ReflectionManager.createDataWatcherItem(data, value)); + + list.add(watch); + } + + if (!list.isEmpty()) + { + PacketContainer packet = new PacketContainer(Server.ENTITY_METADATA); + + StructureModifier mods = packet.getModifier(); + mods.write(0, getDisguise().getEntity().getEntityId()); + + packet.getWatchableCollectionModifier().write(0, list); + + for (Player player : DisguiseUtilities.getPerverts(getDisguise())) + { + try + { + ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet); + } + catch (InvocationTargetException e) + { + e.printStackTrace(System.out); + } + } + } + } + + public void setAddEntityAnimations(boolean isEntityAnimationsAdded) + { + this.addEntityAnimations = isEntityAnimationsAdded; + } + + public void setArmor(ItemStack[] itemstack) + { + setItemStack(EquipmentSlot.HEAD, itemstack[0]); + setItemStack(EquipmentSlot.CHEST, itemstack[1]); + setItemStack(EquipmentSlot.LEGS, itemstack[2]); + setItemStack(EquipmentSlot.FEET, itemstack[3]); + } + + protected void setBackupValue(int no, Object value) + { + backupEntityValues.put(no, value); + } + + public void setBurning(boolean setBurning) + { + setEntityFlag(0, setBurning); + + sendData(0); + } + + public void setCustomName(String name) + { + if (name != null && name.length() > 64) + { + name = name.substring(0, 64); + } + + setValue(2, name); + sendData(2); + } + + public void setCustomNameVisible(boolean display) + { + setValue(3, display); + sendData(3); + } + + private void setEntityFlag(int byteValue, boolean flag) + { + modifiedEntityAnimations.add(byteValue); + + byte b0 = (byte) getValue(0, (byte) 0); + + if (flag) + { + setValue(0, (byte) (b0 | 1 << byteValue)); + } + else + { + setValue(0, (byte) (b0 & ~(1 << byteValue))); + } + } + + public void setInvisible(boolean setInvis) + { + setEntityFlag(5, setInvis); + sendData(0); + } + + public void setGlowing(boolean glowing) + { + setEntityFlag(6, glowing); + sendData(0); + } + + public void setFlyingWithElytra(boolean flying) + { + setEntityFlag(7, flying); + sendData(0); + } + + /** + * Don't use this, use setItemInMainHand instead + * + * @param itemstack + */ + @Deprecated + public void setItemInHand(ItemStack itemstack) + { + setItemInMainHand(itemstack); + } + + public void setItemInMainHand(ItemStack itemstack) + { + setItemStack(EquipmentSlot.HAND, itemstack); + } + + public void setItemInOffHand(ItemStack itemstack) + { + setItemStack(EquipmentSlot.OFF_HAND, itemstack); + } + + public void setItemStack(EquipmentSlot slot, ItemStack itemStack) + { + if (equipment == null) + return; + + // Itemstack which is null means that its not replacing the disguises itemstack. + if (itemStack == null) + { + // Find the item to replace it with + if (getDisguise().getEntity() instanceof LivingEntity) + { + EntityEquipment equipment = ((LivingEntity) getDisguise().getEntity()).getEquipment(); + setItemStack(equipment, slot, itemStack); + } + } + + Object itemToSend = null; + + if (itemStack != null && itemStack.getTypeId() != 0) + { + itemToSend = ReflectionManager.getNmsItem(itemStack); + } + + setItemStack(equipment, slot, itemStack); + + if (DisguiseAPI.isDisguiseInUse(getDisguise()) && getDisguise().getWatcher() == this) + { + PacketContainer packet = new PacketContainer(Server.ENTITY_EQUIPMENT); + + StructureModifier mods = packet.getModifier(); + + mods.write(0, getDisguise().getEntity().getEntityId()); + mods.write(1, ReflectionManager.createEnumItemSlot(slot)); + mods.write(2, itemToSend); + + for (Player player : DisguiseUtilities.getPerverts(getDisguise())) + { + try + { + ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet); + } + catch (InvocationTargetException e) + { + e.printStackTrace(System.out); + } + } + } + } + + private void setItemStack(EntityEquipment equipment, EquipmentSlot slot, ItemStack itemStack) + { + if (equipment == null) + return; + + switch (slot) + { + case CHEST: + equipment.setChestplate(itemStack); + break; + case FEET: + equipment.setBoots(itemStack); + break; + case HAND: + equipment.setItemInMainHand(itemStack); + break; + case HEAD: + equipment.setHelmet(itemStack); + break; + case LEGS: + equipment.setLeggings(itemStack); + break; + case OFF_HAND: + equipment.setItemInOffHand(itemStack); + break; + } + } + + public ItemStack getItemStack(EquipmentSlot slot) + { + if (equipment == null) + return null; + + switch (slot) + { + case CHEST: + return equipment.getChestplate(); + case FEET: + return equipment.getBoots(); + case HAND: + return equipment.getItemInMainHand(); + case HEAD: + return equipment.getHelmet(); + case LEGS: + return equipment.getLeggings(); + case OFF_HAND: + return equipment.getItemInOffHand(); + } + + return null; + } + + public void setRightClicking(boolean setRightClicking) + { + setEntityFlag(4, setRightClicking); + sendData(0); + } + + public void setSneaking(boolean setSneaking) + { + setEntityFlag(1, setSneaking); + sendData(0); + } + + public void setSprinting(boolean setSprinting) + { + setEntityFlag(3, setSprinting); + sendData(0); + } + + protected void setValue(int id, Object value) + { + entityValues.put(id, value); + + if (!DisguiseConfig.isMetadataPacketsEnabled()) + { + this.rebuildWatchableObjects(); + } + } + +} diff --git a/src/me/libraryaddict/disguise/disguisetypes/MobDisguise.java b/src/me/libraryaddict/disguise/disguisetypes/MobDisguise.java index 63b1f8e7..73fdc9b9 100644 --- a/src/me/libraryaddict/disguise/disguisetypes/MobDisguise.java +++ b/src/me/libraryaddict/disguise/disguisetypes/MobDisguise.java @@ -3,23 +3,26 @@ package me.libraryaddict.disguise.disguisetypes; import java.security.InvalidParameterException; import org.bukkit.entity.Entity; -import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; import me.libraryaddict.disguise.disguisetypes.watchers.AgeableWatcher; import me.libraryaddict.disguise.disguisetypes.watchers.LivingWatcher; import me.libraryaddict.disguise.disguisetypes.watchers.ZombieWatcher; -public class MobDisguise extends TargetedDisguise { +public class MobDisguise extends TargetedDisguise +{ private boolean isAdult; - public MobDisguise(DisguiseType disguiseType) { + public MobDisguise(DisguiseType disguiseType) + { this(disguiseType, true); } - public MobDisguise(DisguiseType disguiseType, boolean isAdult) { - if (!disguiseType.isMob()) { + public MobDisguise(DisguiseType disguiseType, boolean isAdult) + { + if (!disguiseType.isMob()) + { throw new InvalidParameterException("Expected a living DisguiseType while constructing MobDisguise. Received " + disguiseType + " instead. Please use " + (disguiseType.isPlayer() ? "PlayerDisguise" : "MiscDisguise") + " instead"); @@ -28,40 +31,21 @@ public class MobDisguise extends TargetedDisguise { createDisguise(disguiseType); } - @Deprecated - public MobDisguise(DisguiseType disguiseType, boolean isAdult, boolean replaceSounds) { - this(disguiseType, isAdult); - this.setReplaceSounds(replaceSounds); - } - - @Deprecated - public MobDisguise(EntityType entityType) { - this(entityType, true); - } - - @Deprecated - public MobDisguise(EntityType entityType, boolean isAdult) { - this(DisguiseType.getType(entityType), isAdult); - } - - @Deprecated - public MobDisguise(EntityType entityType, boolean isAdult, boolean replaceSounds) { - this(entityType, isAdult); - this.setReplaceSounds(replaceSounds); - } - @Override - public MobDisguise addPlayer(Player player) { + public MobDisguise addPlayer(Player player) + { return (MobDisguise) super.addPlayer(player); } @Override - public MobDisguise addPlayer(String playername) { + public MobDisguise addPlayer(String playername) + { return (MobDisguise) super.addPlayer(playername); } @Override - public MobDisguise clone() { + public MobDisguise clone() + { MobDisguise disguise = new MobDisguise(getType(), isAdult()); disguise.setReplaceSounds(isSoundsReplaced()); disguise.setViewSelfDisguise(isSelfDisguiseVisible()); @@ -74,20 +58,27 @@ public class MobDisguise extends TargetedDisguise { return disguise; } - public boolean doesDisguiseAge() { + public boolean doesDisguiseAge() + { return getWatcher() != null && (getWatcher() instanceof AgeableWatcher || getWatcher() instanceof ZombieWatcher); } @Override - public LivingWatcher getWatcher() { + public LivingWatcher getWatcher() + { return (LivingWatcher) super.getWatcher(); } - public boolean isAdult() { - if (getWatcher() != null) { - if (getWatcher() instanceof AgeableWatcher) { + public boolean isAdult() + { + if (getWatcher() != null) + { + if (getWatcher() instanceof AgeableWatcher) + { return ((AgeableWatcher) getWatcher()).isAdult(); - } else if (getWatcher() instanceof ZombieWatcher) { + } + else if (getWatcher() instanceof ZombieWatcher) + { return ((ZombieWatcher) getWatcher()).isAdult(); } return true; @@ -96,92 +87,110 @@ public class MobDisguise extends TargetedDisguise { } @Override - public boolean isMobDisguise() { + public boolean isMobDisguise() + { return true; } @Override - public MobDisguise removePlayer(Player player) { + public MobDisguise removePlayer(Player player) + { return (MobDisguise) super.removePlayer(player); } @Override - public MobDisguise removePlayer(String playername) { + public MobDisguise removePlayer(String playername) + { return (MobDisguise) super.removePlayer(playername); } @Override - public MobDisguise setDisguiseTarget(TargetType newTargetType) { + public MobDisguise setDisguiseTarget(TargetType newTargetType) + { return (MobDisguise) super.setDisguiseTarget(newTargetType); } @Override - public MobDisguise setEntity(Entity entity) { + public MobDisguise setEntity(Entity entity) + { return (MobDisguise) super.setEntity(entity); } @Override - public MobDisguise setHearSelfDisguise(boolean hearSelfDisguise) { + public MobDisguise setHearSelfDisguise(boolean hearSelfDisguise) + { return (MobDisguise) super.setHearSelfDisguise(hearSelfDisguise); } @Override - public MobDisguise setHideArmorFromSelf(boolean hideArmor) { + public MobDisguise setHideArmorFromSelf(boolean hideArmor) + { return (MobDisguise) super.setHideArmorFromSelf(hideArmor); } @Override - public MobDisguise setHideHeldItemFromSelf(boolean hideHeldItem) { + public MobDisguise setHideHeldItemFromSelf(boolean hideHeldItem) + { return (MobDisguise) super.setHideHeldItemFromSelf(hideHeldItem); } @Override - public MobDisguise setKeepDisguiseOnEntityDespawn(boolean keepDisguise) { + public MobDisguise setKeepDisguiseOnEntityDespawn(boolean keepDisguise) + { return (MobDisguise) super.setKeepDisguiseOnEntityDespawn(keepDisguise); } @Override - public MobDisguise setKeepDisguiseOnPlayerDeath(boolean keepDisguise) { + public MobDisguise setKeepDisguiseOnPlayerDeath(boolean keepDisguise) + { return (MobDisguise) super.setKeepDisguiseOnPlayerDeath(keepDisguise); } @Override - public MobDisguise setKeepDisguiseOnPlayerLogout(boolean keepDisguise) { + public MobDisguise setKeepDisguiseOnPlayerLogout(boolean keepDisguise) + { return (MobDisguise) super.setKeepDisguiseOnPlayerLogout(keepDisguise); } @Override - public MobDisguise setModifyBoundingBox(boolean modifyBox) { + public MobDisguise setModifyBoundingBox(boolean modifyBox) + { return (MobDisguise) super.setModifyBoundingBox(modifyBox); } @Override - public MobDisguise setReplaceSounds(boolean areSoundsReplaced) { + public MobDisguise setReplaceSounds(boolean areSoundsReplaced) + { return (MobDisguise) super.setReplaceSounds(areSoundsReplaced); } @Override - public MobDisguise setVelocitySent(boolean sendVelocity) { + public MobDisguise setVelocitySent(boolean sendVelocity) + { return (MobDisguise) super.setVelocitySent(sendVelocity); } @Override - public MobDisguise setViewSelfDisguise(boolean viewSelfDisguise) { + public MobDisguise setViewSelfDisguise(boolean viewSelfDisguise) + { return (MobDisguise) super.setViewSelfDisguise(viewSelfDisguise); } @Override - public MobDisguise setWatcher(FlagWatcher newWatcher) { + public MobDisguise setWatcher(FlagWatcher newWatcher) + { return (MobDisguise) super.setWatcher(newWatcher); } @Override - public MobDisguise silentlyAddPlayer(String playername) { + public MobDisguise silentlyAddPlayer(String playername) + { return (MobDisguise) super.silentlyAddPlayer(playername); } @Override - public MobDisguise silentlyRemovePlayer(String playername) { + public MobDisguise silentlyRemovePlayer(String playername) + { return (MobDisguise) super.silentlyRemovePlayer(playername); } } diff --git a/src/me/libraryaddict/disguise/disguisetypes/PlayerDisguise.java b/src/me/libraryaddict/disguise/disguisetypes/PlayerDisguise.java index 6cb6a812..255e00b3 100644 --- a/src/me/libraryaddict/disguise/disguisetypes/PlayerDisguise.java +++ b/src/me/libraryaddict/disguise/disguisetypes/PlayerDisguise.java @@ -12,56 +12,70 @@ import me.libraryaddict.disguise.utilities.DisguiseUtilities; import me.libraryaddict.disguise.utilities.LibsProfileLookup; import me.libraryaddict.disguise.utilities.ReflectionManager; -public class PlayerDisguise extends TargetedDisguise { +public class PlayerDisguise extends TargetedDisguise +{ private LibsProfileLookup currentLookup; private WrappedGameProfile gameProfile; private String playerName; private String skinToUse; - public PlayerDisguise(String name) { - if (name.length() > 16) { + public PlayerDisguise(String name) + { + if (name.length() > 16) + { name = name.substring(0, 16); } + playerName = name; createDisguise(DisguiseType.PLAYER); } - @Deprecated - public PlayerDisguise(String name, boolean replaceSounds) { - this(name); - this.setReplaceSounds(replaceSounds); - } - - public PlayerDisguise(String name, String skinToUse) { + public PlayerDisguise(String name, String skinToUse) + { this(name); setSkin(skinToUse); } - public PlayerDisguise(WrappedGameProfile gameProfile) { + public PlayerDisguise(Player player) + { + this(ReflectionManager.getGameProfile(player)); + } + + public PlayerDisguise(WrappedGameProfile gameProfile) + { this(gameProfile.getName()); + this.gameProfile = gameProfile; } @Override - public PlayerDisguise addPlayer(Player player) { + public PlayerDisguise addPlayer(Player player) + { return (PlayerDisguise) super.addPlayer(player); } @Override - public PlayerDisguise addPlayer(String playername) { + public PlayerDisguise addPlayer(String playername) + { return (PlayerDisguise) super.addPlayer(playername); } @Override - public PlayerDisguise clone() { + public PlayerDisguise clone() + { PlayerDisguise disguise = new PlayerDisguise(getName()); - if (disguise.currentLookup == null && disguise.gameProfile != null) { + + if (disguise.currentLookup == null && disguise.gameProfile != null) + { disguise.skinToUse = getSkin(); disguise.gameProfile = gameProfile; - } else { + } + else + { disguise.setSkin(getSkin()); } + disguise.setReplaceSounds(isSoundsReplaced()); disguise.setViewSelfDisguise(isSelfDisguiseVisible()); disguise.setHearSelfDisguise(isSelfDisguiseSoundsReplaced()); @@ -70,175 +84,229 @@ public class PlayerDisguise extends TargetedDisguise { disguise.setVelocitySent(isVelocitySent()); disguise.setModifyBoundingBox(isModifyBoundingBox()); disguise.setWatcher(getWatcher().clone(disguise)); + return disguise; } - public void setGameProfile(WrappedGameProfile gameProfile) { + public void setGameProfile(WrappedGameProfile gameProfile) + { this.gameProfile = ReflectionManager.getGameProfileWithThisSkin(null, gameProfile.getName(), gameProfile); } - public WrappedGameProfile getGameProfile() { - if (gameProfile == null) { - if (getSkin() != null) { + public WrappedGameProfile getGameProfile() + { + if (gameProfile == null) + { + if (getSkin() != null) + { gameProfile = ReflectionManager.getGameProfile(null, getName()); - } else { - gameProfile = ReflectionManager.getGameProfileWithThisSkin(null, getName(), DisguiseUtilities.getProfileFromMojang(this)); + } + else + { + gameProfile = ReflectionManager.getGameProfileWithThisSkin(null, getName(), + DisguiseUtilities.getProfileFromMojang(this)); } } + return gameProfile; } - public String getName() { + public String getName() + { return playerName; } - public String getSkin() { + public String getSkin() + { return skinToUse; } @Override - public PlayerWatcher getWatcher() { + public PlayerWatcher getWatcher() + { return (PlayerWatcher) super.getWatcher(); } @Override - public boolean isPlayerDisguise() { + public boolean isPlayerDisguise() + { return true; } @Override - public PlayerDisguise removePlayer(Player player) { + public PlayerDisguise removePlayer(Player player) + { return (PlayerDisguise) super.removePlayer(player); } @Override - public PlayerDisguise removePlayer(String playername) { + public PlayerDisguise removePlayer(String playername) + { return (PlayerDisguise) super.removePlayer(playername); } @Override - public PlayerDisguise setDisguiseTarget(TargetType newTargetType) { + public PlayerDisguise setDisguiseTarget(TargetType newTargetType) + { return (PlayerDisguise) super.setDisguiseTarget(newTargetType); } @Override - public PlayerDisguise setEntity(Entity entity) { + public PlayerDisguise setEntity(Entity entity) + { return (PlayerDisguise) super.setEntity(entity); } @Override - public PlayerDisguise setHearSelfDisguise(boolean hearSelfDisguise) { + public PlayerDisguise setHearSelfDisguise(boolean hearSelfDisguise) + { return (PlayerDisguise) super.setHearSelfDisguise(hearSelfDisguise); } @Override - public PlayerDisguise setHideArmorFromSelf(boolean hideArmor) { + public PlayerDisguise setHideArmorFromSelf(boolean hideArmor) + { return (PlayerDisguise) super.setHideArmorFromSelf(hideArmor); } @Override - public PlayerDisguise setHideHeldItemFromSelf(boolean hideHeldItem) { + public PlayerDisguise setHideHeldItemFromSelf(boolean hideHeldItem) + { return (PlayerDisguise) super.setHideHeldItemFromSelf(hideHeldItem); } @Override - public PlayerDisguise setKeepDisguiseOnEntityDespawn(boolean keepDisguise) { + public PlayerDisguise setKeepDisguiseOnEntityDespawn(boolean keepDisguise) + { return (PlayerDisguise) super.setKeepDisguiseOnEntityDespawn(keepDisguise); } @Override - public PlayerDisguise setKeepDisguiseOnPlayerDeath(boolean keepDisguise) { + public PlayerDisguise setKeepDisguiseOnPlayerDeath(boolean keepDisguise) + { return (PlayerDisguise) super.setKeepDisguiseOnPlayerDeath(keepDisguise); } @Override - public PlayerDisguise setKeepDisguiseOnPlayerLogout(boolean keepDisguise) { + public PlayerDisguise setKeepDisguiseOnPlayerLogout(boolean keepDisguise) + { return (PlayerDisguise) super.setKeepDisguiseOnPlayerLogout(keepDisguise); } @Override - public PlayerDisguise setModifyBoundingBox(boolean modifyBox) { + public PlayerDisguise setModifyBoundingBox(boolean modifyBox) + { return (PlayerDisguise) super.setModifyBoundingBox(modifyBox); } @Override - public PlayerDisguise setReplaceSounds(boolean areSoundsReplaced) { + public PlayerDisguise setReplaceSounds(boolean areSoundsReplaced) + { return (PlayerDisguise) super.setReplaceSounds(areSoundsReplaced); } - public PlayerDisguise setSkin(String skinToUse) { + public PlayerDisguise setSkin(String skinToUse) + { this.skinToUse = skinToUse; - if (skinToUse == null) { + + if (skinToUse == null) + { this.currentLookup = null; this.gameProfile = null; - } else { - if (skinToUse.length() > 16) { + } + else + { + if (skinToUse.length() > 16) + { this.skinToUse = skinToUse.substring(0, 16); } - if (LibsDisguises.getInstance().getConfig().getBoolean("ContactMojangServers", true)) { - currentLookup = new LibsProfileLookup() { + + if (LibsDisguises.getInstance().getConfig().getBoolean("ContactMojangServers", true)) + { + currentLookup = new LibsProfileLookup() + { @Override - public void onLookup(WrappedGameProfile gameProfile) { - if (currentLookup == this && gameProfile != null) { + public void onLookup(WrappedGameProfile gameProfile) + { + if (currentLookup == this && gameProfile != null) + { setSkin(gameProfile); - if (!gameProfile.getProperties().isEmpty() && DisguiseUtilities.isDisguiseInUse(PlayerDisguise.this)) { + + if (!gameProfile.getProperties().isEmpty() && DisguiseUtilities.isDisguiseInUse(PlayerDisguise.this)) + { DisguiseUtilities.refreshTrackers(PlayerDisguise.this); } + currentLookup = null; } } }; + WrappedGameProfile gameProfile = DisguiseUtilities.getProfileFromMojang(this.skinToUse, currentLookup); - if (gameProfile != null) { + + if (gameProfile != null) + { setSkin(gameProfile); } } } + return this; } /** * Set the GameProfile, without tampering. * - * @param gameProfile GameProfile + * @param gameProfile + * GameProfile * @return */ - public PlayerDisguise setSkin(WrappedGameProfile gameProfile) { - if (gameProfile == null) { + public PlayerDisguise setSkin(WrappedGameProfile gameProfile) + { + if (gameProfile == null) + { this.gameProfile = null; this.skinToUse = null; return this; } - if (LibsDisguises.getInstance().getConfig().getBoolean("ContactMojangServers", true)) { + + if (LibsDisguises.getInstance().getConfig().getBoolean("ContactMojangServers", true)) + { Validate.notEmpty(gameProfile.getName(), "Name must be set"); this.skinToUse = gameProfile.getName(); this.gameProfile = ReflectionManager.getGameProfileWithThisSkin(null, getName(), gameProfile); } + return this; } @Override - public PlayerDisguise setVelocitySent(boolean sendVelocity) { + public PlayerDisguise setVelocitySent(boolean sendVelocity) + { return (PlayerDisguise) super.setVelocitySent(sendVelocity); } @Override - public PlayerDisguise setViewSelfDisguise(boolean viewSelfDisguise) { + public PlayerDisguise setViewSelfDisguise(boolean viewSelfDisguise) + { return (PlayerDisguise) super.setViewSelfDisguise(viewSelfDisguise); } @Override - public PlayerDisguise setWatcher(FlagWatcher newWatcher) { + public PlayerDisguise setWatcher(FlagWatcher newWatcher) + { return (PlayerDisguise) super.setWatcher(newWatcher); } @Override - public PlayerDisguise silentlyAddPlayer(String playername) { + public PlayerDisguise silentlyAddPlayer(String playername) + { return (PlayerDisguise) super.silentlyAddPlayer(playername); } @Override - public PlayerDisguise silentlyRemovePlayer(String playername) { + public PlayerDisguise silentlyRemovePlayer(String playername) + { return (PlayerDisguise) super.silentlyRemovePlayer(playername); } } diff --git a/src/me/libraryaddict/disguise/disguisetypes/watchers/AgeableWatcher.java b/src/me/libraryaddict/disguise/disguisetypes/watchers/AgeableWatcher.java index bca9192e..97289e2a 100644 --- a/src/me/libraryaddict/disguise/disguisetypes/watchers/AgeableWatcher.java +++ b/src/me/libraryaddict/disguise/disguisetypes/watchers/AgeableWatcher.java @@ -1,36 +1,39 @@ -package me.libraryaddict.disguise.disguisetypes.watchers; - -import org.bukkit.entity.Entity; - -import me.libraryaddict.disguise.disguisetypes.Disguise; - -public class AgeableWatcher extends LivingWatcher { - - public AgeableWatcher(Disguise disguise) { - super(disguise); - Entity e; - - } - - public boolean isAdult() { - return !isBaby(); - } - - public boolean isBaby() { - return (boolean) getValue(11, false); - } - - public void setAdult() { - setBaby(false); - } - - public void setBaby() { - setBaby(true); - } - - public void setBaby(boolean isBaby) { - setValue(11, isBaby); - sendData(11); - } - -} +package me.libraryaddict.disguise.disguisetypes.watchers; + +import me.libraryaddict.disguise.disguisetypes.Disguise; + +public class AgeableWatcher extends LivingWatcher +{ + + public AgeableWatcher(Disguise disguise) + { + super(disguise); + } + + public boolean isAdult() + { + return !isBaby(); + } + + public boolean isBaby() + { + return (boolean) getValue(11, false); + } + + public void setAdult() + { + setBaby(false); + } + + public void setBaby() + { + setBaby(true); + } + + public void setBaby(boolean isBaby) + { + setValue(11, isBaby); + sendData(11); + } + +} diff --git a/src/me/libraryaddict/disguise/disguisetypes/watchers/MinecartWatcher.java b/src/me/libraryaddict/disguise/disguisetypes/watchers/MinecartWatcher.java index 58a13562..c73b911c 100644 --- a/src/me/libraryaddict/disguise/disguisetypes/watchers/MinecartWatcher.java +++ b/src/me/libraryaddict/disguise/disguisetypes/watchers/MinecartWatcher.java @@ -1,50 +1,53 @@ -package me.libraryaddict.disguise.disguisetypes.watchers; - -import org.bukkit.inventory.ItemStack; - -import me.libraryaddict.disguise.disguisetypes.Disguise; -import me.libraryaddict.disguise.disguisetypes.FlagWatcher; - -public class MinecartWatcher extends FlagWatcher { - - public MinecartWatcher(Disguise disguise) { - super(disguise); - } - - public ItemStack getBlockInCart() { - int id = (int) getValue(8, 0) & 0xffff; - int data = (int) getValue(8, 0) >> 16; - return new ItemStack(id, 1, (short) data); - } - - public int getBlockYOffset() { - return (int) getValue(9, 0); - } - - public boolean isViewBlockInCart() { - return (boolean) getValue(10, false); - } - - public void setBlockInCart(ItemStack item) { - int id = item.getTypeId(); - int data = item.getDurability(); - setValue(8, id & 0xffff | data << 16); - setValue(10, true); //Show block - sendData(8, 10); - } - - public void setBlockOffset(int i) { - setValue(9, i); - sendData(9); - } - - @Deprecated - public void setBlockOffSet(int i) { - setBlockOffset(i); - } - - public void setViewBlockInCart(boolean viewBlock) { - setValue(10, viewBlock); - sendData(10); - } -} +package me.libraryaddict.disguise.disguisetypes.watchers; + +import org.bukkit.inventory.ItemStack; + +import me.libraryaddict.disguise.disguisetypes.Disguise; +import me.libraryaddict.disguise.disguisetypes.FlagWatcher; + +public class MinecartWatcher extends FlagWatcher +{ + + public MinecartWatcher(Disguise disguise) + { + super(disguise); + } + + public ItemStack getBlockInCart() + { + int id = (int) getValue(8, 0) & 0xffff; + int data = (int) getValue(8, 0) >> 16; + return new ItemStack(id, 1, (short) data); + } + + public int getBlockYOffset() + { + return (int) getValue(9, 0); + } + + public boolean isViewBlockInCart() + { + return (boolean) getValue(10, false); + } + + public void setBlockInCart(ItemStack item) + { + int id = item.getTypeId(); + int data = item.getDurability(); + setValue(8, id & 0xffff | data << 16); + setValue(10, true); // Show block + sendData(8, 10); + } + + public void setBlockOffset(int i) + { + setValue(9, i); + sendData(9); + } + + public void setViewBlockInCart(boolean viewBlock) + { + setValue(10, viewBlock); + sendData(10); + } +} diff --git a/src/me/libraryaddict/disguise/utilities/ClassGetter.java b/src/me/libraryaddict/disguise/utilities/ClassGetter.java index f1018a63..ef9885bf 100644 --- a/src/me/libraryaddict/disguise/utilities/ClassGetter.java +++ b/src/me/libraryaddict/disguise/utilities/ClassGetter.java @@ -1,89 +1,95 @@ -package me.libraryaddict.disguise.utilities; - -import java.net.URL; -import java.net.URLDecoder; -import java.security.CodeSource; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; - -import org.bukkit.entity.Entity; - -/** - * User: Austin Date: 4/22/13 Time: 11:47 PM (c) lazertester - */ -// Code for this taken and slightly modified from -// https://github.com/ddopson/java-class-enumerator -public class ClassGetter -{ - - public static ArrayList> getClassesForPackage(String pkgname) - { - ArrayList> classes = new ArrayList<>(); - // String relPath = pkgname.replace('.', '/'); - - // Get a File object for the package - CodeSource src = Entity.class.getProtectionDomain().getCodeSource(); - - if (src != null) - { - URL resource = src.getLocation(); - resource.getPath(); - processJarfile(resource, pkgname, classes); - } - - return classes; - } - - private static Class loadClass(String className) - { - try - { - return Class.forName(className); - } - catch (ClassNotFoundException e) - { - throw new RuntimeException("Unexpected ClassNotFoundException loading class '" + className + "'"); - } - catch (NoClassDefFoundError e) - { - return null; - } - } - - private static void processJarfile(URL resource, String pkgname, ArrayList> classes) - { - try - { - String relPath = pkgname.replace('.', '/'); - String resPath = URLDecoder.decode(resource.getPath(), "UTF-8"); - String jarPath = resPath.replaceFirst("[.]jar[!].*", ".jar").replaceFirst("file:", ""); - JarFile jarFile = new JarFile(jarPath); - Enumeration entries = jarFile.entries(); - while (entries.hasMoreElements()) - { - JarEntry entry = entries.nextElement(); - String entryName = entry.getName(); - String className = null; - if (entryName.endsWith(".class") && entryName.startsWith(relPath) - && entryName.length() > (relPath.length() + "/".length())) - { - className = entryName.replace('/', '.').replace('\\', '.').replace(".class", ""); - } - if (className != null) - { - Class c = loadClass(className); - if (c != null) - { - classes.add(c); - } - } - } - } - catch (Exception ex) - { - ex.printStackTrace(System.out); - } - } -} +package me.libraryaddict.disguise.utilities; + +import java.net.URL; +import java.net.URLDecoder; +import java.security.CodeSource; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; + +import org.bukkit.entity.Entity; + +/** + * User: Austin Date: 4/22/13 Time: 11:47 PM (c) lazertester + */ +// Code for this taken and slightly modified from +// https://github.com/ddopson/java-class-enumerator +public class ClassGetter +{ + + public static ArrayList> getClassesForPackage(String pkgname) + { + ArrayList> classes = new ArrayList<>(); + // String relPath = pkgname.replace('.', '/'); + + // Get a File object for the package + CodeSource src = Entity.class.getProtectionDomain().getCodeSource(); + + if (src != null) + { + URL resource = src.getLocation(); + resource.getPath(); + processJarfile(resource, pkgname, classes); + } + + return classes; + } + + private static Class loadClass(String className) + { + try + { + return Class.forName(className); + } + catch (ClassNotFoundException e) + { + throw new RuntimeException("Unexpected ClassNotFoundException loading class '" + className + "'"); + } + catch (NoClassDefFoundError e) + { + return null; + } + } + + private static void processJarfile(URL resource, String pkgname, ArrayList> classes) + { + try + { + String relPath = pkgname.replace('.', '/'); + String resPath = URLDecoder.decode(resource.getPath(), "UTF-8"); + String jarPath = resPath.replaceFirst("[.]jar[!].*", ".jar").replaceFirst("file:", ""); + + JarFile jarFile = new JarFile(jarPath); + + Enumeration entries = jarFile.entries(); + + while (entries.hasMoreElements()) + { + JarEntry entry = entries.nextElement(); + String entryName = entry.getName(); + String className = null; + if (entryName.endsWith(".class") && entryName.startsWith(relPath) + && entryName.length() > (relPath.length() + "/".length())) + { + className = entryName.replace('/', '.').replace('\\', '.').replace(".class", ""); + } + if (className != null) + { + Class c = loadClass(className); + + if (c != null) + { + classes.add(c); + } + } + } + + jarFile.close(); + } + catch (Exception ex) + { + ex.printStackTrace(System.out); + } + } +} diff --git a/src/me/libraryaddict/disguise/utilities/DisguiseUtilities.java b/src/me/libraryaddict/disguise/utilities/DisguiseUtilities.java index 5bf7c33e..789629e0 100644 --- a/src/me/libraryaddict/disguise/utilities/DisguiseUtilities.java +++ b/src/me/libraryaddict/disguise/utilities/DisguiseUtilities.java @@ -521,9 +521,12 @@ public class DisguiseUtilities StructureModifier ints = teleport.getIntegers(); ints.write(0, entity.getEntityId()); - ints.write(1, (int) Math.floor(loc.getX() * 32)); - ints.write(2, (int) Math.floor((PacketsManager.getYModifier(disguise.getEntity(), disguise) + loc.getY()) * 32)); - ints.write(3, (int) Math.floor(loc.getZ() * 32)); + + StructureModifier doubles = teleport.getDoubles(); + + doubles.write(0, loc.getX()); + doubles.write(1, PacketsManager.getYModifier(disguise.getEntity(), disguise) + loc.getY()); + doubles.write(2, loc.getZ()); return new PacketContainer[] { diff --git a/src/me/libraryaddict/disguise/utilities/DisguiseValues.java b/src/me/libraryaddict/disguise/utilities/DisguiseValues.java index 70296a5e..338cae2e 100644 --- a/src/me/libraryaddict/disguise/utilities/DisguiseValues.java +++ b/src/me/libraryaddict/disguise/utilities/DisguiseValues.java @@ -1,146 +1,115 @@ -package me.libraryaddict.disguise.utilities; - -import java.util.HashMap; - -import me.libraryaddict.disguise.disguisetypes.DisguiseType; - -public class DisguiseValues { - - private static HashMap values = new HashMap<>(); - - public static DisguiseValues getDisguiseValues(DisguiseType type) { - switch (type) { - case DONKEY: - case MULE: - case UNDEAD_HORSE: - case SKELETON_HORSE: - type = DisguiseType.HORSE; - break; - case MINECART_CHEST: - case MINECART_COMMAND: - case MINECART_FURNACE: - case MINECART_HOPPER: - case MINECART_TNT: - case MINECART_MOB_SPAWNER: - type = DisguiseType.MINECART; - break; - case WITHER_SKELETON: - type = DisguiseType.SKELETON; - break; - case ZOMBIE_VILLAGER: - type = DisguiseType.ZOMBIE; - break; - default: - break; - } - return values.get(type); - } - - public static HashMap getMetaValues(DisguiseType type) { - return getDisguiseValues(type).getMetaValues(); - } - - public static Class getNmsEntityClass(DisguiseType type) { - return getDisguiseValues(type).getNmsEntityClass(); - } - - private FakeBoundingBox adultBox; - private FakeBoundingBox babyBox; - private float[] entitySize; - private int enumEntitySize; - private double maxHealth; - private HashMap metaValues = new HashMap<>(); - private Class nmsEntityClass; - - @SuppressWarnings("LeakingThisInConstructor") - public DisguiseValues(DisguiseType type, Class classType, int entitySize, double maxHealth) { - values.put(type, this); - enumEntitySize = entitySize; - nmsEntityClass = classType; - this.maxHealth = maxHealth; - } - - public FakeBoundingBox getAdultBox() { - return adultBox; - } - - public FakeBoundingBox getBabyBox() { - return babyBox; - } - - public float[] getEntitySize() { - return entitySize; - } - - public int getEntitySize(double paramDouble) { - double d = paramDouble - (((int) Math.floor(paramDouble)) + 0.5D); - - switch (enumEntitySize) { - case 1: - if (d < 0.0D ? d < -0.3125D : d < 0.3125D) { - return (int) Math.ceil(paramDouble * 32.0D); - } - - return (int) Math.floor(paramDouble * 32.0D); - case 2: - if (d < 0.0D ? d < -0.3125D : d < 0.3125D) { - return (int) Math.floor(paramDouble * 32.0D); - } - - return (int) Math.ceil(paramDouble * 32.0D); - case 3: - if (d > 0.0D) { - return (int) Math.floor(paramDouble * 32.0D); - } - - return (int) Math.ceil(paramDouble * 32.0D); - case 4: - if (d < 0.0D ? d < -0.1875D : d < 0.1875D) { - return (int) Math.ceil(paramDouble * 32.0D); - } - - return (int) Math.floor(paramDouble * 32.0D); - case 5: - if (d < 0.0D ? d < -0.1875D : d < 0.1875D) { - return (int) Math.floor(paramDouble * 32.0D); - } - - return (int) Math.ceil(paramDouble * 32.0D); - default: - break; - } - if (d > 0.0D) { - return (int) Math.ceil(paramDouble * 32.0D); - } - - return (int) Math.floor(paramDouble * 32.0D); - } - - public double getMaxHealth() { - return maxHealth; - } - - public HashMap getMetaValues() { - return metaValues; - } - - public Class getNmsEntityClass() { - return nmsEntityClass; - } - - public void setAdultBox(FakeBoundingBox newBox) { - adultBox = newBox; - } - - public void setBabyBox(FakeBoundingBox newBox) { - babyBox = newBox; - } - - public void setEntitySize(float[] size) { - this.entitySize = size; - } - - public void setMetaValue(int id, Object value) { - metaValues.put(id, value); - } -} +package me.libraryaddict.disguise.utilities; + +import java.util.HashMap; + +import me.libraryaddict.disguise.disguisetypes.DisguiseType; + +public class DisguiseValues +{ + + private static HashMap values = new HashMap<>(); + + public static DisguiseValues getDisguiseValues(DisguiseType type) + { + switch (type) + { + case DONKEY: + case MULE: + case UNDEAD_HORSE: + case SKELETON_HORSE: + type = DisguiseType.HORSE; + break; + case MINECART_CHEST: + case MINECART_COMMAND: + case MINECART_FURNACE: + case MINECART_HOPPER: + case MINECART_TNT: + case MINECART_MOB_SPAWNER: + type = DisguiseType.MINECART; + break; + case WITHER_SKELETON: + type = DisguiseType.SKELETON; + break; + case ZOMBIE_VILLAGER: + type = DisguiseType.ZOMBIE; + break; + default: + break; + } + return values.get(type); + } + + public static HashMap getMetaValues(DisguiseType type) + { + return getDisguiseValues(type).getMetaValues(); + } + + public static Class getNmsEntityClass(DisguiseType type) + { + return getDisguiseValues(type).getNmsEntityClass(); + } + + private FakeBoundingBox adultBox; + private FakeBoundingBox babyBox; + private float[] entitySize; + private double maxHealth; + private HashMap metaValues = new HashMap<>(); + private Class nmsEntityClass; + + public DisguiseValues(DisguiseType type, Class classType, int entitySize, double maxHealth) + { + values.put(type, this); + nmsEntityClass = classType; + this.maxHealth = maxHealth; + } + + public FakeBoundingBox getAdultBox() + { + return adultBox; + } + + public FakeBoundingBox getBabyBox() + { + return babyBox; + } + + public float[] getEntitySize() + { + return entitySize; + } + + public double getMaxHealth() + { + return maxHealth; + } + + public HashMap getMetaValues() + { + return metaValues; + } + + public Class getNmsEntityClass() + { + return nmsEntityClass; + } + + public void setAdultBox(FakeBoundingBox newBox) + { + adultBox = newBox; + } + + public void setBabyBox(FakeBoundingBox newBox) + { + babyBox = newBox; + } + + public void setEntitySize(float[] size) + { + this.entitySize = size; + } + + public void setMetaValue(int id, Object value) + { + metaValues.put(id, value); + } +} diff --git a/src/me/libraryaddict/disguise/utilities/PacketsManager.java b/src/me/libraryaddict/disguise/utilities/PacketsManager.java index e62b8acb..daab8b72 100644 --- a/src/me/libraryaddict/disguise/utilities/PacketsManager.java +++ b/src/me/libraryaddict/disguise/utilities/PacketsManager.java @@ -1,2196 +1,1180 @@ -package me.libraryaddict.disguise.utilities; - -import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.UUID; - -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; -import org.bukkit.entity.EntityType; -import org.bukkit.entity.ExperienceOrb; -import org.bukkit.entity.Item; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.entity.Zombie; -import org.bukkit.inventory.EquipmentSlot; -import org.bukkit.inventory.ItemStack; -import org.bukkit.metadata.FixedMetadataValue; -import org.bukkit.util.Vector; - -import com.comphenix.protocol.PacketType; -import com.comphenix.protocol.PacketType.Play.Server; -import com.comphenix.protocol.ProtocolLibrary; -import com.comphenix.protocol.events.ListenerPriority; -import com.comphenix.protocol.events.PacketAdapter; -import com.comphenix.protocol.events.PacketContainer; -import com.comphenix.protocol.events.PacketEvent; -import com.comphenix.protocol.events.PacketListener; -import com.comphenix.protocol.reflect.StructureModifier; -import com.comphenix.protocol.wrappers.WrappedAttribute; -import com.comphenix.protocol.wrappers.WrappedAttribute.Builder; -import com.comphenix.protocol.wrappers.WrappedDataWatcher; -import com.comphenix.protocol.wrappers.WrappedDataWatcher.Registry; -import com.comphenix.protocol.wrappers.WrappedDataWatcher.WrappedDataWatcherObject; -import com.comphenix.protocol.wrappers.WrappedGameProfile; -import com.comphenix.protocol.wrappers.WrappedWatchableObject; - -import me.libraryaddict.disguise.DisguiseAPI; -import me.libraryaddict.disguise.DisguiseConfig; -import me.libraryaddict.disguise.LibsDisguises; -import me.libraryaddict.disguise.disguisetypes.AnimalColor; -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.WolfWatcher; -import me.libraryaddict.disguise.utilities.DisguiseSound.SoundType; - -public class PacketsManager -{ - /** - * This is a fix for the stupidity that is - * "I can't separate the sounds from the sounds the player heard, and the sounds of the entity tracker heard" - */ - private static boolean cancelSound; - 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; - private static PacketListener viewDisguisesListener; - private static boolean viewDisguisesListenerEnabled; - - public static void addPacketListeners() - { - // Add a client listener to cancel them interacting with uninteractable disguised entitys. - // You ain't supposed to be allowed to 'interact' with a item that cannot be clicked. - // Because it kicks you for hacking. - - clientInteractEntityListener = new PacketAdapter(libsDisguises, ListenerPriority.NORMAL, - PacketType.Play.Client.USE_ENTITY) - { - @Override - public void onPacketReceiving(PacketEvent event) - { - - if (event.isCancelled()) - return; - - try - { - if (event.getPlayer().getName().contains("UNKNOWN[")) // If the player is temporary - return; - - Player observer = event.getPlayer(); - - StructureModifier entityModifer = event.getPacket().getEntityModifier(observer.getWorld()); - - Entity entity = entityModifer.read(0); - - if (entity instanceof ExperienceOrb || entity instanceof Item || entity instanceof Arrow - || entity == observer) - { - event.setCancelled(true); - } - - ItemStack item = observer.getItemInHand(); - - if (item != null && item.getType() == Material.INK_SACK) - { - Disguise disguise = DisguiseAPI.getDisguise(observer, entity); - - if (disguise != null - && (disguise.getType() == DisguiseType.SHEEP || disguise.getType() == DisguiseType.WOLF)) - { - AnimalColor color = AnimalColor.getColor(item.getDurability()); - - if (disguise.getType() == DisguiseType.SHEEP) - { - SheepWatcher watcher = (SheepWatcher) disguise.getWatcher(); - - watcher.setColor(DisguiseConfig.isSheepDyeable() ? color : watcher.getColor()); - } - else - { - WolfWatcher watcher = (WolfWatcher) disguise.getWatcher(); - - watcher.setCollarColor(DisguiseConfig.isWolfDyeable() ? color : watcher.getCollarColor()); - } - } - } - } - catch (Exception e) - { - e.printStackTrace(); - } - } - }; - - ProtocolLibrary.getProtocolManager().addPacketListener(clientInteractEntityListener); - - // Now I call this and the main listener is registered! - setupMainPacketsListener(); - } - - /** - * Construct the packets I need to spawn in the disguise - */ - public static PacketContainer[][] constructSpawnPackets(final Player player, Disguise disguise, Entity disguisedEntity) - { - if (disguise.getEntity() == null) - disguise.setEntity(disguisedEntity); - - ArrayList packets = new ArrayList<>(); - // This sends the armor packets so that the player isn't naked. - // Please note it only sends the packets that wouldn't be sent normally - if (DisguiseConfig.isEquipmentPacketsEnabled()) - { - for (EquipmentSlot slot : EquipmentSlot.values()) - { - ItemStack itemstack = disguise.getWatcher().getItemStack(slot); - - if (itemstack != null && itemstack.getTypeId() != 0) - { - ItemStack item = null; - - if (disguisedEntity instanceof LivingEntity) - { - item = ReflectionManager.getEquipment(slot, disguisedEntity); - } - - if (item == null || item.getType() == Material.AIR) - { - PacketContainer packet = new PacketContainer(Server.ENTITY_EQUIPMENT); - - StructureModifier mods = packet.getModifier(); - - mods.write(0, disguisedEntity.getEntityId()); - mods.write(1, ReflectionManager.createEnumItemSlot(slot)); - mods.write(2, ReflectionManager.getNmsItem(itemstack)); - - packets.add(packet); - } - } - } - } - - if (DisguiseConfig.isMiscDisguisesForLivingEnabled()) - { - if (disguise.getWatcher() instanceof LivingWatcher) - { - PacketContainer packet = new PacketContainer(Server.UPDATE_ATTRIBUTES); - - List attributes = new ArrayList(); - - Builder builder = WrappedAttribute.newBuilder().attributeKey("generic.maxHealth"); - - if (((LivingWatcher) disguise.getWatcher()).isMaxHealthSet()) - { - builder.baseValue(((LivingWatcher) disguise.getWatcher()).getMaxHealth()); - } - else if (DisguiseConfig.isMaxHealthDeterminedByDisguisedEntity() && disguisedEntity instanceof Damageable) - { - builder.baseValue(((Damageable) disguisedEntity).getMaxHealth()); - } - else - { - builder.baseValue(DisguiseValues.getDisguiseValues(disguise.getType()).getMaxHealth()); - } - - builder.packet(packet); - - attributes.add(builder.build()); - - packet.getIntegers().write(0, disguisedEntity.getEntityId()); - packet.getAttributeCollectionModifier().write(0, attributes); - - packets.add(packet); - } - } - - PacketContainer[] spawnPackets = new PacketContainer[2 + packets.size()]; - PacketContainer[] delayedPackets = new PacketContainer[0]; - - for (int i = 0; i < packets.size(); i++) - { - spawnPackets[i + 2] = packets.get(i); - } - - Location loc = disguisedEntity.getLocation().clone().add(0, getYModifier(disguisedEntity, disguise), 0); - - byte yaw = (byte) (int) (loc.getYaw() * 256.0F / 360.0F); - byte pitch = (byte) (int) (loc.getPitch() * 256.0F / 360.0F); - - if (DisguiseConfig.isMovementPacketsEnabled()) - { - yaw = getYaw(disguise.getType(), disguisedEntity.getType(), yaw); - pitch = getPitch(disguise.getType(), DisguiseType.getType(disguisedEntity.getType()), pitch); - } - - if (disguise.getType() == DisguiseType.EXPERIENCE_ORB) - { - spawnPackets[0] = new PacketContainer(Server.SPAWN_ENTITY_EXPERIENCE_ORB); - - StructureModifier mods = spawnPackets[0].getModifier(); - - mods.write(0, disguisedEntity.getEntityId()); - mods.write(1, Math.floor(loc.getX() * 32)); - mods.write(2, Math.floor(loc.getY() * 32) + 2); - mods.write(3, Math.floor(loc.getZ() * 32)); - mods.write(4, 1); - } - else if (disguise.getType() == DisguiseType.PAINTING) - { - spawnPackets[0] = new PacketContainer(Server.SPAWN_ENTITY_PAINTING); - - StructureModifier mods = spawnPackets[0].getModifier(); - - mods.write(0, disguisedEntity.getEntityId()); - mods.write(1, disguisedEntity.getUniqueId()); - mods.write(2, ReflectionManager.getBlockPosition(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())); - mods.write(3, ReflectionManager.getEnumDirection(((int) loc.getYaw()) % 4)); - - int id = ((MiscDisguise) disguise).getData(); - - mods.write(4, ReflectionManager.getEnumArt(Art.values()[id])); - - // Make the teleport packet to make it visible.. - spawnPackets[1] = new PacketContainer(Server.ENTITY_TELEPORT); - - mods = spawnPackets[1].getModifier(); - - mods.write(0, disguisedEntity.getEntityId()); - mods.write(1, Math.floor(loc.getX() * 32D)); - mods.write(2, Math.floor(loc.getY() * 32D)); - mods.write(3, Math.floor(loc.getZ() * 32D)); - mods.write(4, yaw); - mods.write(5, pitch); - } - else if (disguise.getType().isPlayer()) - { - 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); - } - - Object entityPlayer = ReflectionManager.createEntityPlayer(player.getWorld(), gameProfile); - spawnPackets[0] = ProtocolLibrary.getProtocolManager() - .createPacketConstructor(Server.NAMED_ENTITY_SPAWN, entityPlayer).createPacket(entityPlayer); - - // Write spawn packet in order - spawnPackets[0].getIntegers().write(0, entityId); // Id - spawnPackets[0].getDoubles().write(0, loc.getX()); - spawnPackets[0].getDoubles().write(1, loc.getY()); - spawnPackets[0].getDoubles().write(2, loc.getZ()); - - 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]; - - System.arraycopy(spawnPackets, 1, newPackets, 2, spawnPackets.length - 1); - - newPackets[0] = spawnPackets[0]; - spawnPackets = newPackets; - - PacketContainer[] bedPackets = DisguiseUtilities.getBedPackets(player, - loc.clone().subtract(0, PacketsManager.getYModifier(disguisedEntity, disguise), 0), player.getLocation(), - ((PlayerDisguise) disguise)); - - System.arraycopy(bedPackets, 0, spawnPackets, 1, 2); - } - - ArrayList newPackets = new ArrayList(); - newPackets.add(null); - - for (PacketContainer spawnPacket : spawnPackets) - { - if (spawnPacket != null) - { // Get rid of empty packet '1' if it exists. - newPackets.add(spawnPacket); - } - } - - // Send player info along with the disguise - spawnPackets = newPackets.toArray(new PacketContainer[newPackets.size()]); - spawnPackets[0] = new PacketContainer(Server.PLAYER_INFO); - - // Add player to the list, necessary to spawn them - spawnPackets[0].getModifier().write(0, ReflectionManager.getEnumPlayerInfoAction(0)); - - List playerList = new ArrayList(); - - playerList.add(ReflectionManager.getPlayerInfoData(spawnPackets[0].getHandle(), playerDisguise.getGameProfile())); - spawnPackets[0].getModifier().write(1, playerList); - - // Remove player from the list - 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) - { - Vector vec = disguisedEntity.getVelocity(); - - spawnPackets[0] = new PacketContainer(PacketType.Play.Server.SPAWN_ENTITY_LIVING); - - StructureModifier mods = spawnPackets[0].getModifier(); - - mods.write(0, disguisedEntity.getEntityId()); - mods.write(1, UUID.randomUUID()); - mods.write(2, disguise.getType().getTypeId()); - - // region Vector calculations - double d1 = 3.9D; - double d2 = vec.getX(); - double d3 = vec.getY(); - double d4 = vec.getZ(); - if (d2 < -d1) - d2 = -d1; - if (d3 < -d1) - d3 = -d1; - if (d4 < -d1) - d4 = -d1; - if (d2 > d1) - d2 = d1; - if (d3 > d1) - d3 = d1; - if (d4 > d1) - d4 = d1; - // endregion - - mods.write(3, loc.getX()); - mods.write(4, loc.getY()); - mods.write(5, loc.getZ()); - mods.write(6, (int) (d2 * 8000.0D)); - mods.write(7, (int) (d3 * 8000.0D)); - mods.write(8, (int) (d4 * 8000.0D)); - mods.write(9, yaw); - mods.write(10, pitch); - - spawnPackets[0].getDataWatcherModifier().write(0, - createDataWatcher(WrappedDataWatcher.getEntityWatcher(disguisedEntity), disguise.getWatcher())); - } - else if (disguise.getType().isMisc()) - { - int objectId = disguise.getType().getObjectId(); - int data = ((MiscDisguise) disguise).getData(); - - if (disguise.getType() == DisguiseType.FALLING_BLOCK) - { - data = ReflectionManager.getCombinedId(((MiscDisguise) disguise).getId(), data); - } - 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 nmsEntity = ReflectionManager.getNmsEntity(disguisedEntity); - - spawnPackets[0] = ProtocolLibrary.getProtocolManager() - .createPacketConstructor(PacketType.Play.Server.SPAWN_ENTITY, nmsEntity, objectId, data) - .createPacket(nmsEntity, objectId, data); - spawnPackets[0].getModifier().write(8, pitch); - spawnPackets[0].getModifier().write(9, yaw); - - if (disguise.getType() == DisguiseType.ITEM_FRAME) - { - if (data % 2 == 0) - { - spawnPackets[0].getModifier().write(4, (int) Math.floor((loc.getZ() + (data == 0 ? -1 : 1)) * 32D)); - } - else - { - spawnPackets[0].getModifier().write(2, (int) Math.floor((loc.getX() + (data == 3 ? -1 : 1)) * 32D)); - } - } - } - if (spawnPackets[1] == null || disguise.isPlayerDisguise()) - { - int entry = spawnPackets[1] == null ? 1 : 0; - - if (entry == 0) - { - entry = spawnPackets.length; - spawnPackets = Arrays.copyOf(spawnPackets, spawnPackets.length + 1); - } - // Make a packet to turn his head! - - spawnPackets[entry] = new PacketContainer(Server.ENTITY_HEAD_ROTATION); - - StructureModifier mods = spawnPackets[entry].getModifier(); - - mods.write(0, disguisedEntity.getEntityId()); - mods.write(1, yaw); - } - return new PacketContainer[][] - { - spawnPackets, delayedPackets - }; - } - - /** - * Create a new datawatcher but with the 'correct' values - */ - private static WrappedDataWatcher createDataWatcher(WrappedDataWatcher watcher, FlagWatcher flagWatcher) - { - WrappedDataWatcher newWatcher = new WrappedDataWatcher(); - - try - { - List list = DisguiseConfig.isMetadataPacketsEnabled() - ? flagWatcher.convert(watcher.getWatchableObjects()) : flagWatcher.getWatchableObjects(); - - for (WrappedWatchableObject watchableObject : list) - { - if (watchableObject == null) - continue; - - if (watchableObject.getValue() == null) - continue; - - if (Registry.get(watchableObject.getValue().getClass()) == null) - continue; - - WrappedDataWatcherObject obj = new WrappedDataWatcherObject(watchableObject.getIndex(), - Registry.get(watchableObject.getValue().getClass())); - - newWatcher.setObject(obj, watchableObject.getValue()); - } - } - catch (Exception ex) - { - ex.printStackTrace(); - } - - return newWatcher; - } - - public static byte getPitch(DisguiseType disguiseType, DisguiseType entityType, byte value) - { - switch (disguiseType) - { - case MINECART: - case MINECART_CHEST: - case MINECART_COMMAND: - case MINECART_FURNACE: - case MINECART_HOPPER: - case MINECART_MOB_SPAWNER: - case MINECART_TNT: - value = (byte) -value; - break; - default: - break; - } - switch (entityType) - { - case MINECART: - case MINECART_CHEST: - case MINECART_FURNACE: - case MINECART_HOPPER: - case MINECART_MOB_SPAWNER: - case MINECART_TNT: - value = (byte) -value; - break; - default: - break; - } - - return value; - } - - /** - * Add the yaw for the disguises - */ - public static byte getYaw(DisguiseType disguiseType, EntityType entityType, byte value) - { - switch (disguiseType) - { - case MINECART: - case MINECART_CHEST: - case MINECART_COMMAND: - case MINECART_FURNACE: - case MINECART_HOPPER: - case MINECART_MOB_SPAWNER: - case MINECART_TNT: - value += 64; - break; - case ENDER_DRAGON: - value -= 128; - break; - case WITHER_SKULL: - value -= 128; - break; - case ARROW: - case TIPPED_ARROW: - case SPECTRAL_ARROW: - value = (byte) -value; - break; - case PAINTING: - case ITEM_FRAME: - value = (byte) -(value + 128); - break; - default: - if (disguiseType.isMisc() && disguiseType != DisguiseType.ARMOR_STAND) - { - value -= 64; - } - - break; - } - switch (entityType) - { - case MINECART: - case MINECART_CHEST: - case MINECART_FURNACE: - case MINECART_HOPPER: - case MINECART_MOB_SPAWNER: - case MINECART_TNT: - value -= 64; - break; - case ENDER_DRAGON: - case WITHER_SKULL: - value += 128; - break; - case ARROW: - value = (byte) -value; - break; - case PAINTING: - case ITEM_FRAME: - value = (byte) -(value - 128); - break; - default: - if (!entityType.isAlive()) - { - value += 64; - } - - break; - } - - return value; - } - - /** - * Get the Y level to add to the disguise for realism. - */ - public static double getYModifier(Entity entity, Disguise disguise) - { - double yMod = 0; - - if ((disguise.getType() != DisguiseType.PLAYER || !((PlayerWatcher) disguise.getWatcher()).isSleeping()) - && entity.getType() == EntityType.DROPPED_ITEM) - { - yMod -= 0.13; - } - - switch (disguise.getType()) - { - case BAT: - if (entity instanceof LivingEntity) - return yMod + ((LivingEntity) entity).getEyeHeight(); - case MINECART: - case MINECART_COMMAND: - case MINECART_CHEST: - case MINECART_FURNACE: - case MINECART_HOPPER: - case MINECART_MOB_SPAWNER: - case MINECART_TNT: - switch (entity.getType()) - { - case MINECART: - case MINECART_CHEST: - case MINECART_FURNACE: - case MINECART_HOPPER: - case MINECART_MOB_SPAWNER: - case MINECART_TNT: - return yMod; - default: - return yMod + 0.4; - } - case TIPPED_ARROW: - case SPECTRAL_ARROW: - case BOAT: - case EGG: - case ENDER_PEARL: - case ENDER_SIGNAL: - case FIREWORK: - case PAINTING: - case SMALL_FIREBALL: - case SNOWBALL: - case SPLASH_POTION: - case THROWN_EXP_BOTTLE: - case WITHER_SKULL: - return yMod + 0.7; - case PLAYER: - if (DisguiseConfig.isBedPacketsEnabled() && ((PlayerWatcher) disguise.getWatcher()).isSleeping()) - { - return yMod + 0.35; - } - - break; - case DROPPED_ITEM: - return yMod + 0.13; - default: - break; - } - return yMod; - } - - /** - * Creates the packet listeners - */ - public static void init(LibsDisguises plugin) - { - libsDisguises = plugin; - soundsListener = new PacketAdapter(libsDisguises, ListenerPriority.NORMAL, Server.NAMED_SOUND_EFFECT, - Server.ENTITY_STATUS) - { - @Override - public void onPacketSending(PacketEvent event) - { - if (event.isCancelled()) - { - return; - } - if (event.isAsync()) - { - return; - } - - if (event.getPlayer().getName().contains("UNKNOWN[")) // If the player is temporary - return; - - event.setPacket(event.getPacket().deepClone()); - - StructureModifier mods = event.getPacket().getModifier(); - - Player observer = event.getPlayer(); - - if (event.getPacketType() == Server.NAMED_SOUND_EFFECT) - { - 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)); - mods.write(1, ReflectionManager.getSoundCategory(disguise.getType())); - } - } - 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)); - mods.write(1, ReflectionManager.getSoundCategory(disguise.getType())); - - // 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 = (DisguiseUtilities.random.nextFloat() - - DisguiseUtilities.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 = (DisguiseUtilities.random.nextFloat() - - DisguiseUtilities.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(disguise.getType())); // 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 = (DisguiseUtilities.random.nextFloat() - DisguiseUtilities.random.nextFloat()) - * 0.2F + 1.5F; - } - else - pitch = (DisguiseUtilities.random.nextFloat() - DisguiseUtilities.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, false); - } - 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, Server.ENTITY_LOOK, Server.ENTITY_TELEPORT, - Server.ENTITY_HEAD_ROTATION, Server.ENTITY_METADATA, Server.ENTITY_EQUIPMENT, Server.ANIMATION, Server.BED, - Server.ENTITY_EFFECT, Server.ENTITY_VELOCITY, Server.UPDATE_ATTRIBUTES, Server.ENTITY_STATUS) - { - @Override - public void onPacketSending(PacketEvent event) - { - if (event.isCancelled()) - return; - - if (event.getPlayer().getName().contains("UNKNOWN[")) // If the player is temporary - return; - - final Player observer = event.getPlayer(); - - if (event.getPacket().getIntegers().read(0) == observer.getEntityId()) - { - if (DisguiseAPI.isSelfDisguised(observer)) - { - // Here I grab the packets to convert them to, So I can display them as if the disguise sent them. - PacketContainer[][] transformed = transformPacket(event.getPacket(), observer, observer); - - PacketContainer[] packets = transformed == null ? null : transformed[0]; - - final PacketContainer[] delayedPackets = transformed == null ? null : transformed[1]; - - if (packets == null) - { - packets = new PacketContainer[] - { - event.getPacket() - }; - } - - for (PacketContainer packet : packets) - { - if (packet.getType() != Server.PLAYER_INFO) - { - if (packet.equals(event.getPacket())) - { - packet = packet.shallowClone(); - } - - packet.getIntegers().write(0, DisguiseAPI.getSelfDisguiseId()); - } - - try - { - ProtocolLibrary.getProtocolManager().sendServerPacket(observer, packet, false); - } - catch (InvocationTargetException e) - { - e.printStackTrace(); - } - } - - if (delayedPackets != null && delayedPackets.length > 0) - { - Bukkit.getScheduler().scheduleSyncDelayedTask(libsDisguises, new Runnable() - { - public void run() - { - try - { - for (PacketContainer packet : delayedPackets) - { - ProtocolLibrary.getProtocolManager().sendServerPacket(observer, packet, false); - } - } - catch (InvocationTargetException e) - { - e.printStackTrace(); - } - } - }, 2); - } - - if (event.getPacketType() == Server.ENTITY_METADATA) - { - event.setPacket(event.getPacket().deepClone()); - - for (WrappedWatchableObject watch : event.getPacket().getWatchableCollectionModifier().read(0)) - { - if (watch.getIndex() == 0) - { - byte b = (byte) watch.getValue(); - - byte a = (byte) (b | 1 << 5); - - if ((b & 1 << 3) != 0) - a = (byte) (a | 1 << 3); - - watch.setValue(a); - } - } - } - else if (event.getPacketType() == Server.NAMED_ENTITY_SPAWN) - { - event.setCancelled(true); - - PacketContainer packet = new PacketContainer(Server.ENTITY_METADATA); - - StructureModifier mods = packet.getModifier(); - - mods.write(0, observer.getEntityId()); - - List watchableList = new ArrayList<>(); - Byte b = 1 << 5; - - if (observer.isSprinting()) - b = (byte) (b | 1 << 3); - - WrappedWatchableObject watch = new WrappedWatchableObject( - ReflectionManager.createDataWatcherItem(0, b)); - - watchableList.add(watch); - packet.getWatchableCollectionModifier().write(0, watchableList); - - try - { - ProtocolLibrary.getProtocolManager().sendServerPacket(observer, packet); - } - catch (InvocationTargetException e) - { - e.printStackTrace(); - } - } - else if (event.getPacketType() == Server.ANIMATION) - { - if (event.getPacket().getIntegers().read(1) != 2) - { - event.setCancelled(true); - } - } - else if (event.getPacketType() == Server.ATTACH_ENTITY || event.getPacketType() == Server.REL_ENTITY_MOVE - || event.getPacketType() == Server.ENTITY_MOVE_LOOK || event.getPacketType() == Server.ENTITY_LOOK - || event.getPacketType() == Server.ENTITY_TELEPORT - || event.getPacketType() == Server.ENTITY_HEAD_ROTATION - || event.getPacketType() == Server.ENTITY_EFFECT - || event.getPacketType() == Server.ENTITY_EQUIPMENT) - { - event.setCancelled(true); - } - else if (event.getPacketType() == Server.ENTITY_STATUS) - { - Disguise disguise = DisguiseAPI.getDisguise(event.getPlayer(), event.getPlayer()); - - if (disguise.isSelfDisguiseSoundsReplaced() && !disguise.getType().isPlayer() - && event.getPacket().getBytes().read(0) == 2) - { - event.setCancelled(true); - } - } - } - } - } - }; - - inventoryListener = new PacketAdapter(libsDisguises, ListenerPriority.HIGHEST, Server.SET_SLOT, Server.WINDOW_ITEMS, - PacketType.Play.Client.HELD_ITEM_SLOT, PacketType.Play.Client.SET_CREATIVE_SLOT, - PacketType.Play.Client.WINDOW_CLICK) - { - @Override - public void onPacketReceiving(final PacketEvent event) - { - if (event.isCancelled()) - return; - - if (event.getPlayer().getName().contains("UNKNOWN[")) // If the player is temporary - return; - - if (!(event.getPlayer() instanceof com.comphenix.net.sf.cglib.proxy.Factory) - && 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 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); - - if (slot >= 5 && slot <= 8) - { - if (disguise.isHidingArmorFromSelf()) - { - int armorSlot = Math.abs((slot - 5) - 3); - - org.bukkit.inventory.ItemStack item = event.getPlayer().getInventory() - .getArmorContents()[armorSlot]; - - if (item != null && item.getType() != Material.AIR) - { - PacketContainer packet = new PacketContainer(Server.SET_SLOT); - - StructureModifier mods = packet.getModifier(); - - mods.write(0, 0); - mods.write(1, slot); - mods.write(2, ReflectionManager.getNmsItem(new org.bukkit.inventory.ItemStack(0))); - - try - { - ProtocolLibrary.getProtocolManager().sendServerPacket(event.getPlayer(), packet, - false); - } - catch (InvocationTargetException e) - { - e.printStackTrace(); - } - } - } - } - else if (slot >= 36 && slot <= 44) - { - if (disguise.isHidingHeldItemFromSelf()) - { - int currentSlot = event.getPlayer().getInventory().getHeldItemSlot(); - - if (slot + 36 == currentSlot) - { - org.bukkit.inventory.ItemStack item = event.getPlayer().getItemInHand(); - - if (item != null && item.getType() != Material.AIR) - { - PacketContainer packet = new PacketContainer(Server.SET_SLOT); - - StructureModifier mods = packet.getModifier(); - mods.write(0, 0); - mods.write(1, slot); - mods.write(2, ReflectionManager.getNmsItem(new org.bukkit.inventory.ItemStack(0))); - - try - { - ProtocolLibrary.getProtocolManager().sendServerPacket(event.getPlayer(), packet, - false); - } - catch (InvocationTargetException e) - { - e.printStackTrace(); - } - } - } - } - } - } - // If the player switched item, aka he moved from slot 1 to slot 2 - else if (event.getPacketType() == PacketType.Play.Client.HELD_ITEM_SLOT) - { - if (disguise.isHidingHeldItemFromSelf()) - { - // From logging, it seems that both bukkit and nms uses the same thing for the slot switching. - // 0 1 2 3 - 8 - // If the packet is coming, then I need to replace the item they are switching to - // As for the old item, I need to restore it. - org.bukkit.inventory.ItemStack currentlyHeld = event.getPlayer().getItemInHand(); - // If his old weapon isn't air - if (currentlyHeld != null && currentlyHeld.getType() != Material.AIR) - { - PacketContainer packet = new PacketContainer(Server.SET_SLOT); - - StructureModifier mods = packet.getModifier(); - - mods.write(0, 0); - mods.write(1, event.getPlayer().getInventory().getHeldItemSlot() + 36); - mods.write(2, ReflectionManager.getNmsItem(currentlyHeld)); - - try - { - ProtocolLibrary.getProtocolManager().sendServerPacket(event.getPlayer(), packet, false); - } - catch (InvocationTargetException e) - { - e.printStackTrace(); - } - } - - org.bukkit.inventory.ItemStack newHeld = event.getPlayer().getInventory() - .getItem(event.getPacket().getIntegers().read(0)); - - // If his new weapon isn't air either! - if (newHeld != null && newHeld.getType() != Material.AIR) - { - PacketContainer packet = new PacketContainer(Server.SET_SLOT); - - StructureModifier mods = packet.getModifier(); - - mods.write(0, 0); - mods.write(1, event.getPacket().getIntegers().read(0) + 36); - mods.write(2, ReflectionManager.getNmsItem(new org.bukkit.inventory.ItemStack(0))); - - try - { - ProtocolLibrary.getProtocolManager().sendServerPacket(event.getPlayer(), packet, false); - } - catch (InvocationTargetException e) - { - e.printStackTrace(); - } - } - } - } - 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(0) == 1) - { - // Its a shift click - clickedItem = event.getPacket().getItemModifier().read(0); - - if (clickedItem != null && clickedItem.getType() != Material.AIR) - { - // Rather than predict the clients actions - // Lets just update the entire inventory.. - Bukkit.getScheduler().runTask(libsDisguises, new Runnable() - { - public void run() - { - event.getPlayer().updateInventory(); - } - }); - } - - return; - } - else - { - // If its not a player inventory click - // Shift clicking is exempted for the item in hand.. - if (event.getPacket().getIntegers().read(0) != 0) - { - return; - } - - clickedItem = event.getPlayer().getItemOnCursor(); - } - - if (clickedItem != null && clickedItem.getType() != Material.AIR) - { - // If the slot is a armor slot - if (slot >= 5 && slot <= 8) - { - if (disguise.isHidingArmorFromSelf()) - { - PacketContainer packet = new PacketContainer(Server.SET_SLOT); - - StructureModifier mods = packet.getModifier(); - - mods.write(0, 0); - mods.write(1, slot); - mods.write(2, ReflectionManager.getNmsItem(new org.bukkit.inventory.ItemStack(0))); - - try - { - ProtocolLibrary.getProtocolManager().sendServerPacket(event.getPlayer(), packet, - false); - } - catch (InvocationTargetException e) - { - e.printStackTrace(); - } - } - // Else if its a hotbar slot - } - else if (slot >= 36 && slot <= 44) - { - if (disguise.isHidingHeldItemFromSelf()) - { - int currentSlot = event.getPlayer().getInventory().getHeldItemSlot(); - - // Check if the player is on the same slot as the slot that its setting - if (slot == currentSlot + 36) - { - PacketContainer packet = new PacketContainer(Server.SET_SLOT); - - StructureModifier mods = packet.getModifier(); - mods.write(0, 0); - mods.write(1, slot); - mods.write(2, ReflectionManager.getNmsItem(new org.bukkit.inventory.ItemStack(0))); - - try - { - ProtocolLibrary.getProtocolManager().sendServerPacket(event.getPlayer(), packet, - false); - } - catch (InvocationTargetException e) - { - e.printStackTrace(); - } - } - } - } - } - } - } - } - } - - @Override - public void onPacketSending(PacketEvent event) - { - // If the inventory is the players inventory - if (!(event.getPlayer() instanceof com.comphenix.net.sf.cglib.proxy.Factory) - && event.getPlayer().getVehicle() == null && event.getPacket().getIntegers().read(0) == 0) - { - - Disguise disguise = DisguiseAPI.getDisguise(event.getPlayer(), event.getPlayer()); - - // If the player is disguised, views self disguises and is hiding a item. - if (disguise != null && disguise.isSelfDisguiseVisible() - && (disguise.isHidingArmorFromSelf() || disguise.isHidingHeldItemFromSelf())) - { - // If the server is setting the slot - // Need to set it to air if its in a place it shouldn't be. - // Things such as picking up a item, spawned in item. Plugin sets the item. etc. Will fire this - /** - * Done - */ - if (event.getPacketType() == Server.SET_SLOT) - { - // The raw slot - // nms code has the start of the hotbar being 36. - int slot = event.getPacket().getIntegers().read(1); - - // If the slot is a armor slot - if (slot >= 5 && slot <= 8) - { - if (disguise.isHidingArmorFromSelf()) - { - // Get the bukkit armor slot! - int armorSlot = Math.abs((slot - 5) - 3); - - org.bukkit.inventory.ItemStack item = event.getPlayer().getInventory() - .getArmorContents()[armorSlot]; - - if (item != null && item.getType() != Material.AIR) - { - event.setPacket(event.getPacket().shallowClone()); - - event.getPacket().getModifier().write(2, - ReflectionManager.getNmsItem(new org.bukkit.inventory.ItemStack(0))); - } - } - // Else if its a hotbar slot - } - else if (slot >= 36 && slot <= 44) - { - if (disguise.isHidingHeldItemFromSelf()) - { - int currentSlot = event.getPlayer().getInventory().getHeldItemSlot(); - - // Check if the player is on the same slot as the slot that its setting - if (slot == currentSlot + 36) - { - org.bukkit.inventory.ItemStack item = event.getPlayer().getItemInHand(); - - if (item != null && item.getType() != Material.AIR) - { - event.setPacket(event.getPacket().shallowClone()); - event.getPacket().getModifier().write(2, - ReflectionManager.getNmsItem(new org.bukkit.inventory.ItemStack(0))); - } - } - } - } - } - else if (event.getPacketType() == Server.WINDOW_ITEMS) - { - event.setPacket(event.getPacket().deepClone()); - - StructureModifier mods = event.getPacket().getItemArrayModifier(); - ItemStack[] items = mods.read(0); - - for (int slot = 0; slot < items.length; slot++) - { - if (slot >= 5 && slot <= 8) - { - if (disguise.isHidingArmorFromSelf()) - { - // Get the bukkit armor slot! - int armorSlot = Math.abs((slot - 5) - 3); - - org.bukkit.inventory.ItemStack item = event.getPlayer().getInventory() - .getArmorContents()[armorSlot]; - - if (item != null && item.getType() != Material.AIR) - { - items[slot] = new org.bukkit.inventory.ItemStack(0); - } - } - // Else if its a hotbar slot - } - else if (slot >= 36 && slot <= 44) - { - if (disguise.isHidingHeldItemFromSelf()) - { - int currentSlot = event.getPlayer().getInventory().getHeldItemSlot(); - - // Check if the player is on the same slot as the slot that its setting - if (slot == currentSlot + 36) - { - org.bukkit.inventory.ItemStack item = event.getPlayer().getItemInHand(); - - if (item != null && item.getType() != Material.AIR) - { - items[slot] = new org.bukkit.inventory.ItemStack(0); - } - } - } - } - } - - mods.write(0, items); - } - } - } - } - }; - } - - public static boolean isHearDisguisesEnabled() - { - return soundsListenerEnabled; - } - - public static boolean isInventoryListenerEnabled() - { - return inventoryModifierEnabled; - } - - public static boolean isViewDisguisesListenerEnabled() - { - return viewDisguisesListenerEnabled; - } - - public static void setHearDisguisesListener(boolean enabled) - { - if (soundsListenerEnabled != enabled) { - soundsListenerEnabled = enabled; - - if (soundsListenerEnabled){ - ProtocolLibrary.getProtocolManager().addPacketListener(soundsListener); - } else { - ProtocolLibrary.getProtocolManager().removePacketListener(soundsListener); - } - } - } - - public static void setInventoryListenerEnabled(boolean enabled) - { - if (inventoryModifierEnabled != enabled) - { - inventoryModifierEnabled = enabled; - - if (inventoryModifierEnabled) - { - ProtocolLibrary.getProtocolManager().addPacketListener(inventoryListener); - } - else - { - ProtocolLibrary.getProtocolManager().removePacketListener(inventoryListener); - } - - for (Player player : Bukkit.getOnlinePlayers()) - { - Disguise disguise = DisguiseAPI.getDisguise(player, player); - - if (disguise != null) - { - if (viewDisguisesListenerEnabled && disguise.isSelfDisguiseVisible() - && (disguise.isHidingArmorFromSelf() || disguise.isHidingHeldItemFromSelf())) - { - player.updateInventory(); - } - } - } - } - } - - public static void setupMainPacketsListener() - { - if (clientInteractEntityListener != null) - { - if (mainListener != null) - { - ProtocolLibrary.getProtocolManager().removePacketListener(mainListener); - } - - List packetsToListen = new ArrayList<>(); - // Add spawn packets - { - packetsToListen.add(Server.NAMED_ENTITY_SPAWN); - packetsToListen.add(Server.SPAWN_ENTITY_EXPERIENCE_ORB); - packetsToListen.add(Server.SPAWN_ENTITY); - packetsToListen.add(Server.SPAWN_ENTITY_LIVING); - packetsToListen.add(Server.SPAWN_ENTITY_PAINTING); - } - - // Add packets that always need to be enabled to ensure safety - { - packetsToListen.add(Server.ENTITY_METADATA); - } - - if (DisguiseConfig.isCollectPacketsEnabled()) - { - packetsToListen.add(Server.COLLECT); - } - - if (DisguiseConfig.isMiscDisguisesForLivingEnabled()) - { - packetsToListen.add(Server.UPDATE_ATTRIBUTES); - } - - // The bed packet. - if (DisguiseConfig.isBedPacketsEnabled()) - { - packetsToListen.add(Server.BED); - } - - // Add movement packets - if (DisguiseConfig.isMovementPacketsEnabled()) - { - packetsToListen.add(Server.ENTITY_LOOK); - packetsToListen.add(Server.ENTITY_MOVE_LOOK); - packetsToListen.add(Server.ENTITY_HEAD_ROTATION); - packetsToListen.add(Server.ENTITY_TELEPORT); - packetsToListen.add(Server.REL_ENTITY_MOVE); - } - - // Add equipment packet - if (DisguiseConfig.isEquipmentPacketsEnabled()) - { - packetsToListen.add(Server.ENTITY_EQUIPMENT); - } - - // Add the packet that ensures if they are sleeping or not - if (DisguiseConfig.isAnimationPacketsEnabled()) - { - packetsToListen.add(Server.ANIMATION); - } - - // Add the packet that makes sure that entities with armor do not send unpickupable armor on death - if (DisguiseConfig.isEntityStatusPacketsEnabled()) - { - packetsToListen.add(Server.ENTITY_STATUS); - } - - mainListener = new PacketAdapter(libsDisguises, ListenerPriority.HIGH, packetsToListen) - { - @Override - public void onPacketSending(PacketEvent event) - { - if (event.isCancelled()) - return; - - if (event.getPlayer().getName().contains("UNKNOWN[")) // If the player is temporary - return; - - 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)); - - // 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) - return; - - PacketContainer[][] packets = transformPacket(event.getPacket(), event.getPlayer(), entity); - - if (packets != null) - { - event.setCancelled(true); - - try - { - for (PacketContainer packet : packets[0]) - { - ProtocolLibrary.getProtocolManager().sendServerPacket(observer, packet, false); - } - - final PacketContainer[] delayed = packets[1]; - - if (delayed.length > 0) - { - Bukkit.getScheduler().scheduleSyncDelayedTask(libsDisguises, new Runnable() - { - public void run() - { - try - { - for (PacketContainer packet : delayed) - { - ProtocolLibrary.getProtocolManager().sendServerPacket(observer, packet, false); - } - } - catch (InvocationTargetException e) - { - e.printStackTrace(); - } - } - }, 2); - } - } - catch (InvocationTargetException ex) - { - ex.printStackTrace(); - } - } - } - }; - - ProtocolLibrary.getProtocolManager().addPacketListener(mainListener); - } - } - - public static void setViewDisguisesListener(boolean enabled) - { - if (viewDisguisesListenerEnabled != enabled) - { - viewDisguisesListenerEnabled = enabled; - - if (viewDisguisesListenerEnabled) - { - ProtocolLibrary.getProtocolManager().addPacketListener(viewDisguisesListener); - } - else - { - ProtocolLibrary.getProtocolManager().removePacketListener(viewDisguisesListener); - } - - for (Player player : Bukkit.getOnlinePlayers()) - { - Disguise disguise = DisguiseAPI.getDisguise(player, player); - - if (disguise != null) - { - if (disguise.isSelfDisguiseVisible()) - { - if (enabled) - { - DisguiseUtilities.setupFakeDisguise(disguise); - } - else - { - DisguiseUtilities.removeSelfDisguise(player); - } - - if (inventoryModifierEnabled && (disguise.isHidingArmorFromSelf() || disguise.isHidingHeldItemFromSelf())) - { - player.updateInventory(); - } - } - } - } - } - } - - /** - * Transform the packet magically into the one I have always dreamed off. My true luv!!! This will return null if its not - * transformed - */ - public static PacketContainer[][] transformPacket(PacketContainer sentPacket, Player observer, Entity entity) - { - PacketContainer[] packets = null; - - PacketContainer[] delayedPackets = new PacketContainer[0]; - - try - { - Disguise disguise = DisguiseAPI.getDisguise(observer, entity); - - // If disguised. - if (disguise != null) - { - packets = new PacketContainer[] - { - sentPacket - }; - - // This packet sends attributes - if (sentPacket.getType() == Server.UPDATE_ATTRIBUTES) - { - if (disguise.isMiscDisguise()) - { - packets = new PacketContainer[0]; - } - else - { - List attributes = new ArrayList<>(); - - for (WrappedAttribute attribute : sentPacket.getAttributeCollectionModifier().read(0)) - { - if (attribute.getAttributeKey().equals("generic.maxHealth")) - { - packets[0] = new PacketContainer(Server.UPDATE_ATTRIBUTES); - - Builder builder; - - if (((LivingWatcher) disguise.getWatcher()).isMaxHealthSet()) - { - builder = WrappedAttribute.newBuilder(); - builder.attributeKey("generic.maxHealth"); - builder.baseValue(((LivingWatcher) disguise.getWatcher()).getMaxHealth()); - } - else if (DisguiseConfig.isMaxHealthDeterminedByDisguisedEntity()) - { - builder = WrappedAttribute.newBuilder(attribute); - } - else - { - builder = WrappedAttribute.newBuilder(); - builder.attributeKey("generic.maxHealth"); - builder.baseValue(DisguiseValues.getDisguiseValues(disguise.getType()).getMaxHealth()); - } - - builder.packet(packets[0]); - - attributes.add(builder.build()); - break; - } - } - - if (!attributes.isEmpty()) - { - packets[0].getIntegers().write(0, entity.getEntityId()); - packets[0].getAttributeCollectionModifier().write(0, attributes); - } - else - { - packets = new PacketContainer[0]; - } - } - } - - // Else if the packet is sending entity metadata - else if (sentPacket.getType() == Server.ENTITY_METADATA) - { - if (DisguiseConfig.isMetadataPacketsEnabled() && !isStaticMetadataDisguiseType(disguise)) - { - List watchableObjects = disguise.getWatcher() - .convert(packets[0].getWatchableCollectionModifier().read(0)); - - packets[0] = new PacketContainer(sentPacket.getType()); - - StructureModifier newMods = packets[0].getModifier(); - - newMods.write(0, entity.getEntityId()); - - packets[0].getWatchableCollectionModifier().write(0, watchableObjects); - } - else - { - packets = new PacketContainer[0]; - } - } - - // Else if the packet is spawning.. - else if (sentPacket.getType() == Server.NAMED_ENTITY_SPAWN || sentPacket.getType() == Server.SPAWN_ENTITY_LIVING - || sentPacket.getType() == Server.SPAWN_ENTITY_EXPERIENCE_ORB - || sentPacket.getType() == Server.SPAWN_ENTITY || sentPacket.getType() == Server.SPAWN_ENTITY_PAINTING) - { - PacketContainer[][] spawnPackets = constructSpawnPackets(observer, disguise, entity); - - packets = spawnPackets[0]; - delayedPackets = spawnPackets[1]; - } - - // Else if the disguise is attempting to send players a forbidden packet - else if (sentPacket.getType() == Server.ANIMATION) - { - if (disguise.getType().isMisc() || (packets[0].getIntegers().read(1) == 2 && (!disguise.getType().isPlayer() - || (DisguiseConfig.isBedPacketsEnabled() && ((PlayerWatcher) disguise.getWatcher()).isSleeping())))) - { - packets = new PacketContainer[0]; - } - } - - // 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() - && ((PlayerWatcher) disguise.getWatcher()).isSleeping()) - { - PacketContainer newPacket = new PacketContainer(Server.ANIMATION); - - StructureModifier mods = newPacket.getIntegers(); - mods.write(0, disguise.getEntity().getEntityId()); - mods.write(1, 3); - - packets = new PacketContainer[] - { - newPacket, sentPacket - }; - } - } - - // Else if the disguise is moving. - else if (sentPacket.getType() == Server.ENTITY_MOVE_LOOK || sentPacket.getType() == Server.ENTITY_LOOK - || 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) - { - if (entity.getMetadata("LibsRabbitHop").isEmpty() - || System.currentTimeMillis() - entity.getMetadata("LibsRabbitHop").get(0).asLong() > 500) - { - entity.removeMetadata("LibsRabbitHop", libsDisguises); - entity.setMetadata("LibsRabbitHop", - new FixedMetadataValue(libsDisguises, System.currentTimeMillis())); - } - - packets = Arrays.copyOf(packets, packets.length + 1); - - packets[1] = new PacketContainer(Server.ENTITY_STATUS); - - packets[1].getIntegers().write(0, entity.getEntityId()); - packets[1].getBytes().write(0, (byte) 1); - } - } - - // 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(0); - byte pitchValue = bytes.read(1); - - bytes.write(0, getYaw(disguise.getType(), entity.getType(), yawValue)); - bytes.write(1, 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(); - - double data = (((loc.getYaw() % 360) + 720 + 45) / 90) % 4; - - if (data % 2 == 0) - { - if (data % 2 == 0) - { - doubles.write(3, loc.getZ()); - } - else - { - doubles.write(1, loc.getZ()); - } - } - - double y = getYModifier(entity, disguise); - - if (y != 0) - { - y *= 32; - doubles.write(2, doubles.read(2) + y); - } - } - } - } - - // 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) - { - packets[0] = packets[0].shallowClone(); - - packets[0].getModifier().write(2, - (itemStack.getTypeId() == 0 ? null : ReflectionManager.getNmsItem(itemStack))); - } - if (disguise.getWatcher().isRightClicking() && slot == EquipmentSlot.HAND) - { - ItemStack heldItem = packets[0].getItemModifier().read(0); - - if (heldItem != null && heldItem.getType() != Material.AIR) - { - // Convert the datawatcher - List list = new ArrayList<>(); - - if (DisguiseConfig.isMetadataPacketsEnabled() && !isStaticMetadataDisguiseType(disguise)) - { - WrappedWatchableObject watch = new WrappedWatchableObject(ReflectionManager - .createDataWatcherItem(0, WrappedDataWatcher.getEntityWatcher(entity).getByte(0))); - - list.add(watch); - - list = disguise.getWatcher().convert(list); - } - else - { - for (WrappedWatchableObject obj : disguise.getWatcher().getWatchableObjects()) - { - if (obj.getIndex() == 0) - { - list.add(obj); - break; - } - } - } - - // Construct the packets to return - PacketContainer packetBlock = new PacketContainer(Server.ENTITY_METADATA); - - packetBlock.getModifier().write(0, entity.getEntityId()); - packetBlock.getWatchableCollectionModifier().write(0, list); - - PacketContainer packetUnblock = packetBlock.deepClone(); - // Make a packet to send the 'unblock' - for (WrappedWatchableObject watcher : packetUnblock.getWatchableCollectionModifier().read(0)) - { - watcher.setValue((byte) ((byte) watcher.getValue() & ~(1 << 4))); - } - - // Send the unblock before the itemstack change so that the 2nd metadata packet works. Why? Scheduler - // delay. - packets = new PacketContainer[] - { - packetUnblock, packets[0], packetBlock - }; - // Silly mojang made the right clicking datawatcher value only valid for one use. So I have to reset - // it. - } - } - } - - // 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]; - } - } - - // 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]; - } - } - - // 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()), - (byte) (int) (loc.getPitch() * 256.0F / 360.0F)); - byte yaw = getYaw(disguise.getType(), entity.getType(), sentPacket.getBytes().read(0)); - - PacketContainer rotation = new PacketContainer(Server.ENTITY_HEAD_ROTATION); - - StructureModifier mods = rotation.getModifier(); - - mods.write(0, entity.getEntityId()); - mods.write(1, yaw); - - PacketContainer look = new PacketContainer(Server.ENTITY_LOOK); - - look.getIntegers().write(0, entity.getEntityId()); - look.getBytes().write(0, yaw); - look.getBytes().write(1, pitch); - - packets = new PacketContainer[] - { - look, rotation - }; - } - } - - // Whatever - else - { - packets = null; - } - - } - } - catch (Exception e) - { - e.printStackTrace(); - } - return packets == null ? null : new PacketContainer[][] - { - packets, delayedPackets - }; - } - - /** - * Returns true if this disguise type doesn't have changing metadata. - * - * @param disguise - * @return - */ - public static boolean isStaticMetadataDisguiseType(Disguise disguise) - { - return (disguise.getType() == DisguiseType.WOLF || disguise.getType() == DisguiseType.OCELOT - || disguise.getType() == DisguiseType.ENDERMAN || disguise.getType() == DisguiseType.SHULKER - || disguise.getType() == DisguiseType.SPLASH_POTION || disguise.getType() == DisguiseType.FIREWORK - || disguise.getType() == DisguiseType.DROPPED_ITEM || disguise.getType() == DisguiseType.ENDER_CRYSTAL); - } -} +package me.libraryaddict.disguise.utilities; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; + +import org.bukkit.Art; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.entity.Damageable; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.inventory.EquipmentSlot; +import org.bukkit.inventory.ItemStack; +import org.bukkit.metadata.FixedMetadataValue; +import org.bukkit.util.Vector; + +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.PacketType.Play.Server; +import com.comphenix.protocol.ProtocolLibrary; +import com.comphenix.protocol.events.PacketContainer; +import com.comphenix.protocol.events.PacketListener; +import com.comphenix.protocol.reflect.StructureModifier; +import com.comphenix.protocol.wrappers.WrappedAttribute; +import com.comphenix.protocol.wrappers.WrappedAttribute.Builder; +import com.comphenix.protocol.wrappers.WrappedDataWatcher; +import com.comphenix.protocol.wrappers.WrappedDataWatcher.Registry; +import com.comphenix.protocol.wrappers.WrappedDataWatcher.WrappedDataWatcherObject; +import com.comphenix.protocol.wrappers.WrappedGameProfile; +import com.comphenix.protocol.wrappers.WrappedWatchableObject; + +import me.libraryaddict.disguise.DisguiseAPI; +import me.libraryaddict.disguise.DisguiseConfig; +import me.libraryaddict.disguise.LibsDisguises; +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.PlayerDisguise; +import me.libraryaddict.disguise.disguisetypes.watchers.LivingWatcher; +import me.libraryaddict.disguise.disguisetypes.watchers.PlayerWatcher; +import me.libraryaddict.disguise.utilities.packetlisteners.PacketListenerClientInteract; +import me.libraryaddict.disguise.utilities.packetlisteners.PacketListenerInventory; +import me.libraryaddict.disguise.utilities.packetlisteners.PacketListenerMain; +import me.libraryaddict.disguise.utilities.packetlisteners.PacketListenerSounds; +import me.libraryaddict.disguise.utilities.packetlisteners.PacketListenerViewDisguises; + +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; + private static PacketListener viewDisguisesListener; + private static boolean viewDisguisesListenerEnabled; + + public static void addPacketListeners() + { + // Add a client listener to cancel them interacting with uninteractable disguised entitys. + // 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); + + ProtocolLibrary.getProtocolManager().addPacketListener(clientInteractEntityListener); + + // Now I call this and the main listener is registered! + setupMainPacketsListener(); + } + + /** + * Construct the packets I need to spawn in the disguise + */ + public static PacketContainer[][] constructSpawnPackets(final Player observer, Disguise disguise, Entity disguisedEntity) + { + if (disguise.getEntity() == null) + { + disguise.setEntity(disguisedEntity); + } + + ArrayList packets = new ArrayList<>(); + + // This sends the armor packets so that the player isn't naked. + // Please note it only sends the packets that wouldn't be sent normally + if (DisguiseConfig.isEquipmentPacketsEnabled()) + { + for (EquipmentSlot slot : EquipmentSlot.values()) + { + ItemStack itemstack = disguise.getWatcher().getItemStack(slot); + + if (itemstack == null || itemstack.getType() == Material.AIR) + { + continue; + } + + ItemStack item = null; + + if (disguisedEntity instanceof LivingEntity) + { + item = ReflectionManager.getEquipment(slot, disguisedEntity); + } + + if (item != null && item.getType() != Material.AIR) + { + continue; + } + + PacketContainer packet = new PacketContainer(Server.ENTITY_EQUIPMENT); + + StructureModifier mods = packet.getModifier(); + + mods.write(0, disguisedEntity.getEntityId()); + mods.write(1, ReflectionManager.createEnumItemSlot(slot)); + mods.write(2, ReflectionManager.getNmsItem(itemstack)); + + packets.add(packet); + } + } + + if (DisguiseConfig.isMiscDisguisesForLivingEnabled()) + { + if (disguise.getWatcher() instanceof LivingWatcher) + { + + ArrayList attributes = new ArrayList(); + + Builder builder = WrappedAttribute.newBuilder().attributeKey("generic.maxHealth"); + + if (((LivingWatcher) disguise.getWatcher()).isMaxHealthSet()) + { + builder.baseValue(((LivingWatcher) disguise.getWatcher()).getMaxHealth()); + } + else if (DisguiseConfig.isMaxHealthDeterminedByDisguisedEntity() && disguisedEntity instanceof Damageable) + { + builder.baseValue(((Damageable) disguisedEntity).getMaxHealth()); + } + else + { + builder.baseValue(DisguiseValues.getDisguiseValues(disguise.getType()).getMaxHealth()); + } + + PacketContainer packet = new PacketContainer(Server.UPDATE_ATTRIBUTES); + + builder.packet(packet); + + attributes.add(builder.build()); + + packet.getIntegers().write(0, disguisedEntity.getEntityId()); + packet.getAttributeCollectionModifier().write(0, attributes); + + packets.add(packet); + } + } + + PacketContainer[] spawnPackets = new PacketContainer[2 + packets.size()]; + PacketContainer[] delayedPackets = new PacketContainer[0]; + + for (int i = 0; i < packets.size(); i++) + { + spawnPackets[i + 2] = packets.get(i); + } + + Location loc = disguisedEntity.getLocation().clone().add(0, getYModifier(disguisedEntity, disguise), 0); + + byte yaw = (byte) (int) (loc.getYaw() * 256.0F / 360.0F); + byte pitch = (byte) (int) (loc.getPitch() * 256.0F / 360.0F); + + if (DisguiseConfig.isMovementPacketsEnabled()) + { + yaw = getYaw(disguise.getType(), disguisedEntity.getType(), yaw); + pitch = getPitch(disguise.getType(), DisguiseType.getType(disguisedEntity.getType()), pitch); + } + + if (disguise.getType() == DisguiseType.EXPERIENCE_ORB) + { + spawnPackets[0] = new PacketContainer(Server.SPAWN_ENTITY_EXPERIENCE_ORB); + + StructureModifier mods = spawnPackets[0].getModifier(); + + mods.write(0, disguisedEntity.getEntityId()); + mods.write(1, loc.getX()); + mods.write(2, loc.getY() + 0.06); + mods.write(3, loc.getZ()); + mods.write(4, 1); + } + else if (disguise.getType() == DisguiseType.PAINTING) + { + spawnPackets[0] = new PacketContainer(Server.SPAWN_ENTITY_PAINTING); + + StructureModifier mods = spawnPackets[0].getModifier(); + + mods.write(0, disguisedEntity.getEntityId()); + mods.write(1, disguisedEntity.getUniqueId()); + mods.write(2, ReflectionManager.getBlockPosition(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())); + mods.write(3, ReflectionManager.getEnumDirection(((int) loc.getYaw()) % 4)); + + int id = ((MiscDisguise) disguise).getData(); + + mods.write(4, ReflectionManager.getEnumArt(Art.values()[id])); + + // Make the teleport packet to make it visible.. + spawnPackets[1] = new PacketContainer(Server.ENTITY_TELEPORT); + + mods = spawnPackets[1].getModifier(); + + mods.write(0, disguisedEntity.getEntityId()); + mods.write(1, loc.getX()); + mods.write(2, loc.getY()); + mods.write(3, loc.getZ()); + mods.write(4, yaw); + mods.write(5, pitch); + } + else if (disguise.getType().isPlayer()) + { + 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); + } + + Object entityPlayer = ReflectionManager.createEntityPlayer(observer.getWorld(), gameProfile); + spawnPackets[0] = ProtocolLibrary.getProtocolManager() + .createPacketConstructor(Server.NAMED_ENTITY_SPAWN, entityPlayer).createPacket(entityPlayer); + + // Write spawn packet in order + spawnPackets[0].getIntegers().write(0, entityId); // Id + spawnPackets[0].getDoubles().write(0, loc.getX()); + spawnPackets[0].getDoubles().write(1, loc.getY()); + spawnPackets[0].getDoubles().write(2, loc.getZ()); + + 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]; + + System.arraycopy(spawnPackets, 1, newPackets, 2, spawnPackets.length - 1); + + newPackets[0] = spawnPackets[0]; + spawnPackets = newPackets; + + PacketContainer[] bedPackets = DisguiseUtilities.getBedPackets(observer, + loc.clone().subtract(0, PacketsManager.getYModifier(disguisedEntity, disguise), 0), + observer.getLocation(), ((PlayerDisguise) disguise)); + + System.arraycopy(bedPackets, 0, spawnPackets, 1, 2); + } + + ArrayList newPackets = new ArrayList(); + newPackets.add(null); + + for (PacketContainer spawnPacket : spawnPackets) + { + if (spawnPacket != null) + { // Get rid of empty packet '1' if it exists. + newPackets.add(spawnPacket); + } + } + + // Send player info along with the disguise + spawnPackets = newPackets.toArray(new PacketContainer[newPackets.size()]); + spawnPackets[0] = new PacketContainer(Server.PLAYER_INFO); + + // Add player to the list, necessary to spawn them + spawnPackets[0].getModifier().write(0, ReflectionManager.getEnumPlayerInfoAction(0)); + + List playerList = new ArrayList(); + + playerList.add(ReflectionManager.getPlayerInfoData(spawnPackets[0].getHandle(), playerDisguise.getGameProfile())); + spawnPackets[0].getModifier().write(1, playerList); + + // Remove player from the list + 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) + { + Vector vec = disguisedEntity.getVelocity(); + + spawnPackets[0] = new PacketContainer(PacketType.Play.Server.SPAWN_ENTITY_LIVING); + + StructureModifier mods = spawnPackets[0].getModifier(); + + mods.write(0, disguisedEntity.getEntityId()); + mods.write(1, UUID.randomUUID()); + mods.write(2, disguise.getType().getTypeId()); + + // region Vector calculations + double d1 = 3.9D; + double d2 = vec.getX(); + double d3 = vec.getY(); + double d4 = vec.getZ(); + if (d2 < -d1) + d2 = -d1; + if (d3 < -d1) + d3 = -d1; + if (d4 < -d1) + d4 = -d1; + if (d2 > d1) + d2 = d1; + if (d3 > d1) + d3 = d1; + if (d4 > d1) + d4 = d1; + // endregion + + mods.write(3, loc.getX()); + mods.write(4, loc.getY()); + mods.write(5, loc.getZ()); + mods.write(6, (int) (d2 * 8000.0D)); + mods.write(7, (int) (d3 * 8000.0D)); + mods.write(8, (int) (d4 * 8000.0D)); + mods.write(9, yaw); + mods.write(10, pitch); + + spawnPackets[0].getDataWatcherModifier().write(0, + createDataWatcher(WrappedDataWatcher.getEntityWatcher(disguisedEntity), disguise.getWatcher())); + } + else if (disguise.getType().isMisc()) + { + int objectId = disguise.getType().getObjectId(); + int data = ((MiscDisguise) disguise).getData(); + + if (disguise.getType() == DisguiseType.FALLING_BLOCK) + { + data = ReflectionManager.getCombinedId(((MiscDisguise) disguise).getId(), data); + } + 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 nmsEntity = ReflectionManager.getNmsEntity(disguisedEntity); + + spawnPackets[0] = ProtocolLibrary.getProtocolManager() + .createPacketConstructor(PacketType.Play.Server.SPAWN_ENTITY, nmsEntity, objectId, data) + .createPacket(nmsEntity, objectId, data); + spawnPackets[0].getModifier().write(8, pitch); + spawnPackets[0].getModifier().write(9, yaw); + + if (disguise.getType() == DisguiseType.ITEM_FRAME) + { + if (data % 2 == 0) + { + spawnPackets[0].getModifier().write(4, loc.getZ() + (data == 0 ? -1 : 1)); + } + else + { + spawnPackets[0].getModifier().write(2, loc.getX() + (data == 3 ? -1 : 1)); + } + } + } + if (spawnPackets[1] == null || disguise.isPlayerDisguise()) + { + int entry = spawnPackets[1] == null ? 1 : 0; + + if (entry == 0) + { + entry = spawnPackets.length; + spawnPackets = Arrays.copyOf(spawnPackets, spawnPackets.length + 1); + } + // Make a packet to turn his head! + + spawnPackets[entry] = new PacketContainer(Server.ENTITY_HEAD_ROTATION); + + StructureModifier mods = spawnPackets[entry].getModifier(); + + mods.write(0, disguisedEntity.getEntityId()); + mods.write(1, yaw); + } + return new PacketContainer[][] + { + spawnPackets, delayedPackets + }; + } + + /** + * Create a new datawatcher but with the 'correct' values + */ + private static WrappedDataWatcher createDataWatcher(WrappedDataWatcher watcher, FlagWatcher flagWatcher) + { + WrappedDataWatcher newWatcher = new WrappedDataWatcher(); + + try + { + List list = DisguiseConfig.isMetadataPacketsEnabled() + ? flagWatcher.convert(watcher.getWatchableObjects()) : flagWatcher.getWatchableObjects(); + + for (WrappedWatchableObject watchableObject : list) + { + if (watchableObject == null) + continue; + + if (watchableObject.getValue() == null) + continue; + + if (Registry.get(watchableObject.getValue().getClass()) == null) + continue; + + WrappedDataWatcherObject obj = new WrappedDataWatcherObject(watchableObject.getIndex(), + Registry.get(watchableObject.getValue().getClass())); + + newWatcher.setObject(obj, watchableObject.getValue()); + } + } + catch (Exception ex) + { + ex.printStackTrace(); + } + + return newWatcher; + } + + public static byte getPitch(DisguiseType disguiseType, DisguiseType entityType, byte value) + { + switch (disguiseType) + { + case MINECART: + case MINECART_CHEST: + case MINECART_COMMAND: + case MINECART_FURNACE: + case MINECART_HOPPER: + case MINECART_MOB_SPAWNER: + case MINECART_TNT: + value = (byte) -value; + break; + default: + break; + } + switch (entityType) + { + case MINECART: + case MINECART_CHEST: + case MINECART_FURNACE: + case MINECART_HOPPER: + case MINECART_MOB_SPAWNER: + case MINECART_TNT: + value = (byte) -value; + break; + default: + break; + } + + return value; + } + + /** + * Add the yaw for the disguises + */ + public static byte getYaw(DisguiseType disguiseType, EntityType entityType, byte value) + { + switch (disguiseType) + { + case MINECART: + case MINECART_CHEST: + case MINECART_COMMAND: + case MINECART_FURNACE: + case MINECART_HOPPER: + case MINECART_MOB_SPAWNER: + case MINECART_TNT: + value += 64; + break; + case ENDER_DRAGON: + value -= 128; + break; + case WITHER_SKULL: + value -= 128; + break; + case ARROW: + case TIPPED_ARROW: + case SPECTRAL_ARROW: + value = (byte) -value; + break; + case PAINTING: + case ITEM_FRAME: + value = (byte) -(value + 128); + break; + default: + if (disguiseType.isMisc() && disguiseType != DisguiseType.ARMOR_STAND) + { + value -= 64; + } + + break; + } + switch (entityType) + { + case MINECART: + case MINECART_CHEST: + case MINECART_FURNACE: + case MINECART_HOPPER: + case MINECART_MOB_SPAWNER: + case MINECART_TNT: + value -= 64; + break; + case ENDER_DRAGON: + case WITHER_SKULL: + value += 128; + break; + case ARROW: + value = (byte) -value; + break; + case PAINTING: + case ITEM_FRAME: + value = (byte) -(value - 128); + break; + default: + if (!entityType.isAlive()) + { + value += 64; + } + + break; + } + + return value; + } + + /** + * Get the Y level to add to the disguise for realism. + */ + public static double getYModifier(Entity entity, Disguise disguise) + { + double yMod = 0; + + if ((disguise.getType() != DisguiseType.PLAYER || !((PlayerWatcher) disguise.getWatcher()).isSleeping()) + && entity.getType() == EntityType.DROPPED_ITEM) + { + yMod -= 0.13; + } + + switch (disguise.getType()) + { + case BAT: + if (entity instanceof LivingEntity) + return yMod + ((LivingEntity) entity).getEyeHeight(); + case MINECART: + case MINECART_COMMAND: + case MINECART_CHEST: + case MINECART_FURNACE: + case MINECART_HOPPER: + case MINECART_MOB_SPAWNER: + case MINECART_TNT: + switch (entity.getType()) + { + case MINECART: + case MINECART_CHEST: + case MINECART_FURNACE: + case MINECART_HOPPER: + case MINECART_MOB_SPAWNER: + case MINECART_TNT: + return yMod; + default: + return yMod + 0.4; + } + case TIPPED_ARROW: + case SPECTRAL_ARROW: + case BOAT: + case EGG: + case ENDER_PEARL: + case ENDER_SIGNAL: + case FIREWORK: + case PAINTING: + case SMALL_FIREBALL: + case SNOWBALL: + case SPLASH_POTION: + case THROWN_EXP_BOTTLE: + case WITHER_SKULL: + return yMod + 0.7; + case PLAYER: + if (DisguiseConfig.isBedPacketsEnabled() && ((PlayerWatcher) disguise.getWatcher()).isSleeping()) + { + return yMod + 0.35; + } + + break; + case DROPPED_ITEM: + return yMod + 0.13; + default: + break; + } + return yMod; + } + + /** + * Creates the packet listeners + */ + public static void init(LibsDisguises plugin) + { + libsDisguises = plugin; + soundsListener = new PacketListenerSounds(libsDisguises); + + // Self disguise (/vsd) listener + viewDisguisesListener = new PacketListenerViewDisguises(libsDisguises); + + inventoryListener = new PacketListenerInventory(libsDisguises); + } + + public static boolean isHearDisguisesEnabled() + { + return soundsListenerEnabled; + } + + public static boolean isInventoryListenerEnabled() + { + return inventoryModifierEnabled; + } + + public static boolean isViewDisguisesListenerEnabled() + { + return viewDisguisesListenerEnabled; + } + + public static void setHearDisguisesListener(boolean enabled) + { + if (soundsListenerEnabled != enabled) + { + soundsListenerEnabled = enabled; + + if (soundsListenerEnabled) + { + ProtocolLibrary.getProtocolManager().addPacketListener(soundsListener); + } + else + { + ProtocolLibrary.getProtocolManager().removePacketListener(soundsListener); + } + } + } + + public static void setInventoryListenerEnabled(boolean enabled) + { + if (inventoryModifierEnabled != enabled) + { + inventoryModifierEnabled = enabled; + + if (inventoryModifierEnabled) + { + ProtocolLibrary.getProtocolManager().addPacketListener(inventoryListener); + } + else + { + ProtocolLibrary.getProtocolManager().removePacketListener(inventoryListener); + } + + for (Player player : Bukkit.getOnlinePlayers()) + { + Disguise disguise = DisguiseAPI.getDisguise(player, player); + + if (disguise != null) + { + if (viewDisguisesListenerEnabled && disguise.isSelfDisguiseVisible() + && (disguise.isHidingArmorFromSelf() || disguise.isHidingHeldItemFromSelf())) + { + player.updateInventory(); + } + } + } + } + } + + public static void setupMainPacketsListener() + { + if (clientInteractEntityListener != null) + { + if (mainListener != null) + { + ProtocolLibrary.getProtocolManager().removePacketListener(mainListener); + } + + ArrayList packetsToListen = new ArrayList(); + // Add spawn packets + { + packetsToListen.add(Server.NAMED_ENTITY_SPAWN); + packetsToListen.add(Server.SPAWN_ENTITY_EXPERIENCE_ORB); + packetsToListen.add(Server.SPAWN_ENTITY); + packetsToListen.add(Server.SPAWN_ENTITY_LIVING); + packetsToListen.add(Server.SPAWN_ENTITY_PAINTING); + } + + // Add packets that always need to be enabled to ensure safety + { + packetsToListen.add(Server.ENTITY_METADATA); + } + + if (DisguiseConfig.isCollectPacketsEnabled()) + { + packetsToListen.add(Server.COLLECT); + } + + if (DisguiseConfig.isMiscDisguisesForLivingEnabled()) + { + packetsToListen.add(Server.UPDATE_ATTRIBUTES); + } + + // The bed packet. + if (DisguiseConfig.isBedPacketsEnabled()) + { + packetsToListen.add(Server.BED); + } + + // Add movement packets + if (DisguiseConfig.isMovementPacketsEnabled()) + { + packetsToListen.add(Server.ENTITY_LOOK); + packetsToListen.add(Server.REL_ENTITY_MOVE_LOOK); + packetsToListen.add(Server.REL_ENTITY_MOVE_LOOK); + packetsToListen.add(Server.ENTITY_HEAD_ROTATION); + packetsToListen.add(Server.ENTITY_TELEPORT); + packetsToListen.add(Server.REL_ENTITY_MOVE); + } + + // Add equipment packet + if (DisguiseConfig.isEquipmentPacketsEnabled()) + { + packetsToListen.add(Server.ENTITY_EQUIPMENT); + } + + // Add the packet that ensures if they are sleeping or not + if (DisguiseConfig.isAnimationPacketsEnabled()) + { + packetsToListen.add(Server.ANIMATION); + } + + // Add the packet that makes sure that entities with armor do not send unpickupable armor on death + if (DisguiseConfig.isEntityStatusPacketsEnabled()) + { + packetsToListen.add(Server.ENTITY_STATUS); + } + + mainListener = new PacketListenerMain(libsDisguises, packetsToListen); + + ProtocolLibrary.getProtocolManager().addPacketListener(mainListener); + } + } + + public static void setViewDisguisesListener(boolean enabled) + { + if (viewDisguisesListenerEnabled != enabled) + { + viewDisguisesListenerEnabled = enabled; + + if (viewDisguisesListenerEnabled) + { + ProtocolLibrary.getProtocolManager().addPacketListener(viewDisguisesListener); + } + else + { + ProtocolLibrary.getProtocolManager().removePacketListener(viewDisguisesListener); + } + + for (Player player : Bukkit.getOnlinePlayers()) + { + Disguise disguise = DisguiseAPI.getDisguise(player, player); + + if (disguise != null) + { + if (disguise.isSelfDisguiseVisible()) + { + if (enabled) + { + DisguiseUtilities.setupFakeDisguise(disguise); + } + else + { + DisguiseUtilities.removeSelfDisguise(player); + } + + if (inventoryModifierEnabled && (disguise.isHidingArmorFromSelf() || disguise.isHidingHeldItemFromSelf())) + { + player.updateInventory(); + } + } + } + } + } + } + + /** + * Transform the packet magically into the one I have always dreamed off. My true luv!!! This will return null if its not + * transformed + */ + public static PacketContainer[][] transformPacket(PacketContainer sentPacket, Player observer, Entity entity) + { + PacketContainer[] packets = null; + + PacketContainer[] delayedPackets = new PacketContainer[0]; + + try + { + Disguise disguise = DisguiseAPI.getDisguise(observer, entity); + + // If disguised. + if (disguise != null) + { + packets = new PacketContainer[] + { + sentPacket + }; + + // This packet sends attributes + if (sentPacket.getType() == Server.UPDATE_ATTRIBUTES) + { + if (disguise.isMiscDisguise()) + { + packets = new PacketContainer[0]; + } + else + { + List attributes = new ArrayList<>(); + + for (WrappedAttribute attribute : sentPacket.getAttributeCollectionModifier().read(0)) + { + if (attribute.getAttributeKey().equals("generic.maxHealth")) + { + packets[0] = new PacketContainer(Server.UPDATE_ATTRIBUTES); + + Builder builder; + + if (((LivingWatcher) disguise.getWatcher()).isMaxHealthSet()) + { + builder = WrappedAttribute.newBuilder(); + builder.attributeKey("generic.maxHealth"); + builder.baseValue(((LivingWatcher) disguise.getWatcher()).getMaxHealth()); + } + else if (DisguiseConfig.isMaxHealthDeterminedByDisguisedEntity()) + { + builder = WrappedAttribute.newBuilder(attribute); + } + else + { + builder = WrappedAttribute.newBuilder(); + builder.attributeKey("generic.maxHealth"); + builder.baseValue(DisguiseValues.getDisguiseValues(disguise.getType()).getMaxHealth()); + } + + builder.packet(packets[0]); + + attributes.add(builder.build()); + break; + } + } + + if (!attributes.isEmpty()) + { + packets[0].getIntegers().write(0, entity.getEntityId()); + packets[0].getAttributeCollectionModifier().write(0, attributes); + } + else + { + packets = new PacketContainer[0]; + } + } + } + + // Else if the packet is sending entity metadata + else if (sentPacket.getType() == Server.ENTITY_METADATA) + { + if (DisguiseConfig.isMetadataPacketsEnabled() && !isStaticMetadataDisguiseType(disguise)) + { + List watchableObjects = disguise.getWatcher() + .convert(packets[0].getWatchableCollectionModifier().read(0)); + + packets[0] = new PacketContainer(sentPacket.getType()); + + StructureModifier newMods = packets[0].getModifier(); + + newMods.write(0, entity.getEntityId()); + + packets[0].getWatchableCollectionModifier().write(0, watchableObjects); + } + else + { + packets = new PacketContainer[0]; + } + } + + // Else if the packet is spawning.. + else if (sentPacket.getType() == Server.NAMED_ENTITY_SPAWN || sentPacket.getType() == Server.SPAWN_ENTITY_LIVING + || sentPacket.getType() == Server.SPAWN_ENTITY_EXPERIENCE_ORB + || sentPacket.getType() == Server.SPAWN_ENTITY || sentPacket.getType() == Server.SPAWN_ENTITY_PAINTING) + { + PacketContainer[][] spawnPackets = constructSpawnPackets(observer, disguise, entity); + + packets = spawnPackets[0]; + delayedPackets = spawnPackets[1]; + } + + // Else if the disguise is attempting to send players a forbidden packet + else if (sentPacket.getType() == Server.ANIMATION) + { + if (disguise.getType().isMisc() || (packets[0].getIntegers().read(1) == 2 && (!disguise.getType().isPlayer() + || (DisguiseConfig.isBedPacketsEnabled() && ((PlayerWatcher) disguise.getWatcher()).isSleeping())))) + { + packets = new PacketContainer[0]; + } + } + + // 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() + && ((PlayerWatcher) disguise.getWatcher()).isSleeping()) + { + PacketContainer newPacket = new PacketContainer(Server.ANIMATION); + + StructureModifier mods = newPacket.getIntegers(); + mods.write(0, disguise.getEntity().getEntityId()); + mods.write(1, 3); + + packets = new PacketContainer[] + { + newPacket, sentPacket + }; + } + } + + // Else if the disguise is moving. + else if (sentPacket.getType() == Server.REL_ENTITY_MOVE_LOOK || sentPacket.getType() == Server.ENTITY_LOOK + || 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.REL_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) + { + if (entity.getMetadata("LibsRabbitHop").isEmpty() + || System.currentTimeMillis() - entity.getMetadata("LibsRabbitHop").get(0).asLong() > 500) + { + entity.removeMetadata("LibsRabbitHop", libsDisguises); + entity.setMetadata("LibsRabbitHop", + new FixedMetadataValue(libsDisguises, System.currentTimeMillis())); + } + + packets = Arrays.copyOf(packets, packets.length + 1); + + packets[1] = new PacketContainer(Server.ENTITY_STATUS); + + packets[1].getIntegers().write(0, entity.getEntityId()); + packets[1].getBytes().write(0, (byte) 1); + } + } + + // 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(0); + byte pitchValue = bytes.read(1); + + bytes.write(0, getYaw(disguise.getType(), entity.getType(), yawValue)); + bytes.write(1, 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(); + + double data = (((loc.getYaw() % 360) + 720 + 45) / 90) % 4; + + if (data % 2 == 0) + { + if (data % 2 == 0) + { + doubles.write(3, loc.getZ()); + } + else + { + doubles.write(1, loc.getZ()); + } + } + + double y = getYModifier(entity, disguise); + + if (y != 0) + { + doubles.write(2, doubles.read(2) + y); + } + } + } + } + + // 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) + { + packets[0] = packets[0].shallowClone(); + + packets[0].getModifier().write(2, + (itemStack.getTypeId() == 0 ? null : ReflectionManager.getNmsItem(itemStack))); + } + if (disguise.getWatcher().isRightClicking() && slot == EquipmentSlot.HAND) + { + ItemStack heldItem = packets[0].getItemModifier().read(0); + + if (heldItem != null && heldItem.getType() != Material.AIR) + { + // Convert the datawatcher + List list = new ArrayList<>(); + + if (DisguiseConfig.isMetadataPacketsEnabled() && !isStaticMetadataDisguiseType(disguise)) + { + WrappedWatchableObject watch = new WrappedWatchableObject(ReflectionManager + .createDataWatcherItem(0, WrappedDataWatcher.getEntityWatcher(entity).getByte(0))); + + list.add(watch); + + list = disguise.getWatcher().convert(list); + } + else + { + for (WrappedWatchableObject obj : disguise.getWatcher().getWatchableObjects()) + { + if (obj.getIndex() == 0) + { + list.add(obj); + break; + } + } + } + + // Construct the packets to return + PacketContainer packetBlock = new PacketContainer(Server.ENTITY_METADATA); + + packetBlock.getModifier().write(0, entity.getEntityId()); + packetBlock.getWatchableCollectionModifier().write(0, list); + + PacketContainer packetUnblock = packetBlock.deepClone(); + // Make a packet to send the 'unblock' + for (WrappedWatchableObject watcher : packetUnblock.getWatchableCollectionModifier().read(0)) + { + watcher.setValue((byte) ((byte) watcher.getValue() & ~(1 << 4))); + } + + // Send the unblock before the itemstack change so that the 2nd metadata packet works. Why? Scheduler + // delay. + packets = new PacketContainer[] + { + packetUnblock, packets[0], packetBlock + }; + // Silly mojang made the right clicking datawatcher value only valid for one use. So I have to reset + // it. + } + } + } + + // 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]; + } + } + + // 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]; + } + } + + // 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()), + (byte) (int) (loc.getPitch() * 256.0F / 360.0F)); + byte yaw = getYaw(disguise.getType(), entity.getType(), sentPacket.getBytes().read(0)); + + PacketContainer rotation = new PacketContainer(Server.ENTITY_HEAD_ROTATION); + + StructureModifier mods = rotation.getModifier(); + + mods.write(0, entity.getEntityId()); + mods.write(1, yaw); + + PacketContainer look = new PacketContainer(Server.ENTITY_LOOK); + + look.getIntegers().write(0, entity.getEntityId()); + look.getBytes().write(0, yaw); + look.getBytes().write(1, pitch); + + packets = new PacketContainer[] + { + look, rotation + }; + } + } + + // Whatever + else + { + packets = null; + } + + } + } + catch (Exception e) + { + e.printStackTrace(); + } + return packets == null ? null : new PacketContainer[][] + { + packets, delayedPackets + }; + } + + /** + * Returns true if this disguise type doesn't have changing metadata. + * + * @param disguise + * @return + */ + public static boolean isStaticMetadataDisguiseType(Disguise disguise) + { + return (disguise.getType() == DisguiseType.WOLF || disguise.getType() == DisguiseType.OCELOT + || disguise.getType() == DisguiseType.ENDERMAN || disguise.getType() == DisguiseType.SHULKER + || disguise.getType() == DisguiseType.SPLASH_POTION || disguise.getType() == DisguiseType.FIREWORK + || disguise.getType() == DisguiseType.DROPPED_ITEM || disguise.getType() == DisguiseType.ENDER_CRYSTAL); + } +} diff --git a/src/me/libraryaddict/disguise/utilities/ReflectionManager.java b/src/me/libraryaddict/disguise/utilities/ReflectionManager.java index a09de30e..bb736322 100644 --- a/src/me/libraryaddict/disguise/utilities/ReflectionManager.java +++ b/src/me/libraryaddict/disguise/utilities/ReflectionManager.java @@ -1,1051 +1,1014 @@ -package me.libraryaddict.disguise.utilities; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.Map; -import java.util.UUID; - -import org.apache.commons.lang3.tuple.ImmutablePair; -import org.apache.commons.lang3.tuple.Pair; -import org.bukkit.Art; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.Sound; -import org.bukkit.World; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.inventory.EntityEquipment; -import org.bukkit.inventory.EquipmentSlot; -import org.bukkit.inventory.ItemStack; -import org.bukkit.potion.PotionEffect; - -import com.comphenix.protocol.wrappers.MinecraftKey; -import com.comphenix.protocol.wrappers.WrappedDataWatcher.Registry; -import com.comphenix.protocol.wrappers.WrappedDataWatcher.Serializer; -import com.comphenix.protocol.wrappers.WrappedDataWatcher.WrappedDataWatcherObject; -import com.comphenix.protocol.wrappers.WrappedGameProfile; -import com.google.common.collect.ImmutableMap; -import com.mojang.authlib.GameProfile; -import me.libraryaddict.disguise.disguisetypes.DisguiseType; -import org.bukkit.entity.*; - -public class ReflectionManager -{ - - private static final String bukkitVersion = Bukkit.getServer().getClass().getName().split("\\.")[3]; - private static final Class craftItemClass; - private static Method damageAndIdleSoundMethod; - private static final Field entitiesField; - private static final Constructor boundingBoxConstructor; - private static final Method setBoundingBoxMethod; - private static final Method ihmGet; - 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. - * - * In addition to the implicit license granted to libraryaddict to redistribuite the code, the - * code is also licensed to the public under the BSD 2-clause license. - * - * The publicly licensed version may be viewed here: https://gist.github.com/riking/2f330f831c30e2276df7 - */ - static - { - primitiveTypes = ImmutableMap., String> builder().put(boolean.class, "Z").put(byte.class, "B") - .put(char.class, "C").put(short.class, "S").put(int.class, "I").put(long.class, "J").put(float.class, "F") - .put(double.class, "D").put(void.class, "V").build(); - } - - static - { - for (Method method : getNmsClass("EntityLiving").getDeclaredMethods()) - { - try - { - if (method.getReturnType() == float.class && Modifier.isProtected(method.getModifiers()) - && method.getParameterTypes().length == 0) - { - Object entity = createEntityInstance("Cow"); - - method.setAccessible(true); - float value = (Float) method.invoke(entity); - - if (value == 0.4F) - { - damageAndIdleSoundMethod = method; - break; - } - } - } - catch (Exception ex) - { - ex.printStackTrace(System.out); - } - } - - craftItemClass = getCraftClass("inventory.CraftItemStack"); - - pingField = getNmsField("EntityPlayer", "ping"); - - trackerField = getNmsField("WorldServer", "tracker"); - - entitiesField = getNmsField("EntityTracker", "trackedEntities"); - - ihmGet = getNmsMethod("IntHashMap", "get", int.class); - - 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) - { - try - { - Class entityClass = getNmsClass("Entity" + entityName); - Object entityObject; - Object world = getWorldServer(Bukkit.getWorlds().get(0)); - - switch (entityName) - { - case "Player": - Object minecraftServer = getNmsMethod("MinecraftServer", "getServer").invoke(null); - - Object playerinteractmanager = getNmsClass("PlayerInteractManager").getDeclaredConstructor(getNmsClass("World")) - .newInstance(world); - - WrappedGameProfile gameProfile = getGameProfile(null, "Steve"); - - entityObject = entityClass - .getDeclaredConstructor(getNmsClass("MinecraftServer"), getNmsClass("WorldServer"), - gameProfile.getHandleType(), playerinteractmanager.getClass()) - .newInstance(minecraftServer, world, gameProfile.getHandle(), playerinteractmanager); - break; - case "EnderPearl": - entityObject = entityClass.getDeclaredConstructor(getNmsClass("World"), getNmsClass("EntityLiving")) - .newInstance(world, createEntityInstance("Cow")); - break; - case "Potion": - entityObject = entityClass - .getDeclaredConstructor(getNmsClass("World"), Double.TYPE, Double.TYPE, Double.TYPE, - getNmsClass("ItemStack")) - .newInstance(world, 0d, 0d, 0d, getNmsItem(new ItemStack(Material.SPLASH_POTION))); - break; - default: - entityObject = entityClass.getDeclaredConstructor(getNmsClass("World")).newInstance(world); - break; - } - - return entityObject; - } - catch (Exception e) - { - e.printStackTrace(System.out); - } - - return null; - } - - public static Object getMobEffectList(int id) - { - Method nmsMethod = getNmsMethod("MobEffectList", "fromId", Integer.TYPE); - - try - { - return nmsMethod.invoke(null, id); - } - catch (IllegalAccessException | InvocationTargetException e) - { - e.printStackTrace(); - } - - 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("/", "."); - } - - public static FakeBoundingBox getBoundingBox(Entity entity) - { - try - { - Object boundingBox = getNmsMethod("Entity", "getBoundingBox").invoke(getNmsEntity(entity)); - - double x = 0, y = 0, z = 0; - int stage = 0; - - for (Field field : boundingBox.getClass().getDeclaredFields()) - { - if (field.getType().getSimpleName().equals("double")) - { - stage++; - - switch (stage) - { - case 1: - x -= field.getDouble(boundingBox); - break; - case 2: - y -= field.getDouble(boundingBox); - break; - case 3: - z -= field.getDouble(boundingBox); - break; - case 4: - x += field.getDouble(boundingBox); - break; - case 5: - y += field.getDouble(boundingBox); - break; - case 6: - z += field.getDouble(boundingBox); - break; - default: - throw new Exception("Error while setting the bounding box, more doubles than I thought??"); - } - } - } - - return new FakeBoundingBox(x, y, z); - } - catch (Exception ex) - { - ex.printStackTrace(System.out); - } - - return null; - } - - public static Entity getBukkitEntity(Object nmsEntity) - { - try - { - return (Entity) getNmsMethod("Entity", "getBukkitEntity").invoke(nmsEntity); - } - catch (Exception ex) - { - ex.printStackTrace(System.out); - } - - return null; - } - - public static ItemStack getBukkitItem(Object nmsItem) - { - try - { - return (ItemStack) craftItemClass.getMethod("asBukkitCopy", getNmsClass("ItemStack")).invoke(null, nmsItem); - } - catch (Exception e) - { - e.printStackTrace(System.out); - } - - return null; - } - - public static String getBukkitVersion() - { - return bukkitVersion; - } - - public static Class getCraftClass(String className) - { - try - { - return Class.forName("org.bukkit.craftbukkit." + getBukkitVersion() + "." + className); - } - catch (Exception e) - { - e.printStackTrace(System.out); - } - - return null; - } - - public static Constructor getCraftConstructor(Class clazz, Class... parameters) - { - try - { - Constructor declaredConstructor = clazz.getDeclaredConstructor(parameters); - declaredConstructor.setAccessible(true); - return declaredConstructor; - } - catch (NoSuchMethodException e) - { - e.printStackTrace(System.out); - } - - return null; - } - - public static Constructor getCraftConstructor(String className, Class... parameters) - { - return getCraftConstructor(getCraftClass(className), parameters); - } - - public static String getCraftSound(Sound sound) - { - try - { - return (String) getCraftClass("CraftSound").getMethod("getSound", Sound.class).invoke(null, sound); - } - catch (Exception ex) - { - ex.printStackTrace(System.out); - } - - return null; - } - - public static Object getEntityTrackerEntry(Entity target) throws Exception - { - Object world = getWorldServer(target.getWorld()); - Object tracker = trackerField.get(world); - Object trackedEntities = entitiesField.get(tracker); - - return ihmGet.invoke(trackedEntities, target.getEntityId()); - } - - public static Object getMinecraftServer() - { - try - { - return getCraftMethod("CraftServer", "getServer").invoke(Bukkit.getServer()); - } - catch (IllegalAccessException | InvocationTargetException e) - { - e.printStackTrace(); - } - return null; - } - - public static String getEnumArt(Art art) - { - try - { - Object enumArt = getCraftClass("CraftArt").getMethod("BukkitToNotch", Art.class).invoke(null, art); - for (Field field : enumArt.getClass().getDeclaredFields()) - { - if (field.getType() == String.class) - { - return (String) field.get(enumArt); - } - } - } - catch (Exception ex) - { - ex.printStackTrace(System.out); - } - - return null; - } - - public static Object getBlockPosition(int x, int y, int z) - { - try - { - return getNmsClass("BlockPosition").getDeclaredConstructor(int.class, int.class, int.class).newInstance(x, y, z); - } - catch (Exception ex) - { - ex.printStackTrace(System.out); - } - - return null; - } - - public static Enum getEnumDirection(int direction) - { - try - { - return (Enum) getNmsMethod("EnumDirection", "fromType2", int.class).invoke(null, direction); - } - catch (Exception ex) - { - ex.printStackTrace(System.out); - } - - return null; - } - - public static Enum getEnumPlayerInfoAction(int action) - { - try - { - return (Enum) getNmsClass("PacketPlayOutPlayerInfo$EnumPlayerInfoAction").getEnumConstants()[action]; - } - catch (Exception ex) - { - ex.printStackTrace(System.out); - } - - return null; - } - - public static Object getPlayerInfoData(Object playerInfoPacket, WrappedGameProfile gameProfile) - { - try - { - Object playerListName = getNmsClass("ChatComponentText").getDeclaredConstructor(String.class) - .newInstance(gameProfile.getName()); - - return getNmsClass("PacketPlayOutPlayerInfo$PlayerInfoData") - .getDeclaredConstructor(getNmsClass("PacketPlayOutPlayerInfo"), gameProfile.getHandleType(), int.class, - getNmsClass("WorldSettings$EnumGamemode"), getNmsClass("IChatBaseComponent")) - .newInstance(playerInfoPacket, gameProfile.getHandle(), 0, - getNmsClass("WorldSettings$EnumGamemode").getEnumConstants()[1], playerListName); - } - catch (Exception ex) - { - ex.printStackTrace(System.out); - } - - return null; - } - - public static WrappedGameProfile getGameProfile(Player player) - { - return WrappedGameProfile.fromPlayer(player); - } - - public static WrappedGameProfile getGameProfile(UUID uuid, String playerName) - { - try - { - return new WrappedGameProfile(uuid != null ? uuid : UUID.randomUUID(), playerName); - } - catch (Exception ex) - { - ex.printStackTrace(System.out); - } - return null; - } - - 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()); - return gameProfile; - } - catch (Exception ex) - { - ex.printStackTrace(System.out); - } - - return null; - } - - public static Class getNmsClass(String className) - { - try - { - return Class.forName("net.minecraft.server." + getBukkitVersion() + "." + className); - } - catch (Exception e) - { - e.printStackTrace(System.out); - } - - return null; - } - - public static Constructor getNmsConstructor(Class clazz, Class... parameters) - { - try - { - Constructor declaredConstructor = clazz.getDeclaredConstructor(parameters); - declaredConstructor.setAccessible(true); - return declaredConstructor; - } - catch (NoSuchMethodException e) - { - e.printStackTrace(System.out); - } - - return null; - } - - public static Constructor getNmsConstructor(String className, Class... parameters) - { - return getNmsConstructor(getNmsClass(className), parameters); - } - - public static Object getNmsEntity(Entity entity) - { - try - { - return getCraftClass("entity.CraftEntity").getMethod("getHandle").invoke(entity); - } - catch (Exception ex) - { - ex.printStackTrace(System.out); - } - - return null; - } - - public static Field getNmsField(Class clazz, String fieldName) - { - try - { - Field declaredField = clazz.getDeclaredField(fieldName); - declaredField.setAccessible(true); - - return declaredField; - } - catch (NoSuchFieldException e) - { - e.printStackTrace(System.out); - } - - return null; - } - - public static Field getNmsField(String className, String fieldName) - { - return getNmsField(getNmsClass(className), fieldName); - } - - public static Object getNmsItem(ItemStack itemstack) - { - try - { - return craftItemClass.getDeclaredMethod("asNMSCopy", ItemStack.class).invoke(null, itemstack); - } - catch (Exception e) - { - e.printStackTrace(System.out); - } - - return null; - } - - public static Method getCraftMethod(String className, String methodName, Class... parameters) - { - return getCraftMethod(getCraftClass(className), methodName, parameters); - } - - public static Method getCraftMethod(Class clazz, String methodName, Class... parameters) - { - try - { - Method declaredMethod = clazz.getDeclaredMethod(methodName, parameters); - declaredMethod.setAccessible(true); - - return declaredMethod; - } - catch (NoSuchMethodException e) - { - e.printStackTrace(System.out); - } - - return null; - } - - public static Method getNmsMethod(Class clazz, String methodName, Class... parameters) - { - try - { - Method declaredMethod = clazz.getDeclaredMethod(methodName, parameters); - declaredMethod.setAccessible(true); - - return declaredMethod; - } - catch (NoSuchMethodException e) - { - e.printStackTrace(System.out); - } - - return null; - } - - public static Method getNmsMethod(String className, String methodName, Class... parameters) - { - return getNmsMethod(getNmsClass(className), methodName, parameters); - } - - public static double getPing(Player player) - { - try - { - return (double) pingField.getInt(ReflectionManager.getNmsEntity(player)); - } - catch (Exception ex) - { - ex.printStackTrace(System.out); - } - - return 0; - } - - public static float[] getSize(Entity entity) - { - try - { - float length = getNmsField("Entity", "length").getFloat(getNmsEntity(entity)); - float width = getNmsField("Entity", "width").getFloat(getNmsEntity(entity)); - - float height = (Float) getNmsMethod("Entity", "getHeadHeight").invoke(getNmsEntity(entity)); - return new float[] - { - length, width, height - }; - } - catch (Exception ex) - { - ex.printStackTrace(System.out); - } - - return null; - } - - public static WrappedGameProfile getSkullBlob(WrappedGameProfile gameProfile) - { - try - { - Object minecraftServer = getNmsMethod("MinecraftServer", "getServer").invoke(null); - - for (Method method : getNmsClass("MinecraftServer").getDeclaredMethods()) - { - if (method.getReturnType().getSimpleName().equals("MinecraftSessionService")) - { - Object session = method.invoke(minecraftServer); - - return WrappedGameProfile.fromHandle(session.getClass() - .getDeclaredMethod("fillProfileProperties", gameProfile.getHandleType(), boolean.class) - .invoke(session, gameProfile.getHandle(), true)); - } - } - } - catch (Exception ex) - { - ex.printStackTrace(System.out); - } - - return null; - } - - public static Float getSoundModifier(Object entity) - { - try - { - damageAndIdleSoundMethod.setAccessible(true); - - return (Float) damageAndIdleSoundMethod.invoke(entity); - } - catch (Exception ignored) - { - } - return null; - } - - public static WrappedGameProfile grabProfileAddUUID(String playername) - { - try - { - Object minecraftServer = getNmsMethod("MinecraftServer", "getServer").invoke(null); - - for (Method method : getNmsClass("MinecraftServer").getDeclaredMethods()) - { - if (method.getReturnType().getSimpleName().equals("GameProfileRepository")) - { - Object profileRepo = method.invoke(minecraftServer); - - Object agent = Class.forName("com.mojang.authlib.Agent").getDeclaredField("MINECRAFT").get(null); - - LibsProfileLookupCaller callback = new LibsProfileLookupCaller(); - - profileRepo.getClass().getDeclaredMethod("findProfilesByNames", String[].class, agent.getClass(), - Class.forName("com.mojang.authlib.ProfileLookupCallback")).invoke(profileRepo, new String[] - { - playername - }, agent, callback); - - if (callback.getGameProfile() != null) - { - return callback.getGameProfile(); - } - - return getGameProfile(null, playername); - } - } - } - catch (Exception ex) - { - ex.printStackTrace(System.out); - } - - return null; - } - - private static String methodSignaturePart(Class param) - { - if (param.isArray()) - { - return "[" + methodSignaturePart(param.getComponentType()); - } - else if (param.isPrimitive()) - { - return primitiveTypes.get(param); - } - else - { - return "L" + param.getName().replaceAll("\\.", "/") + ";"; - } - } - - public static void removePlayer(Player player) - { - // Some future remove code if needed - } - - public static void setBoundingBox(Entity entity, FakeBoundingBox newBox) - { - try - { - Location loc = entity.getLocation(); - - Object boundingBox = boundingBoxConstructor.newInstance(loc.getX() - newBox.getX(), loc.getY() - newBox.getY(), - loc.getZ() - newBox.getZ(), loc.getX() + newBox.getX(), loc.getY() + newBox.getY(), - loc.getZ() + newBox.getZ()); - - setBoundingBoxMethod.invoke(getNmsEntity(entity), boundingBox); - } - catch (Exception ex) - { - ex.printStackTrace(System.out); - } - } - - 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(category.toUpperCase())) - return anEnum; - } - } - - return invoke; - } - catch (Exception e) - { - e.printStackTrace(); - } - - return null; - } - - public static Enum getSoundCategory(DisguiseType disguiseType) - { - if (disguiseType == DisguiseType.PLAYER) - return getSoundCategory("player"); - - Class entityClass = disguiseType.getEntityType().getEntityClass(); - - if (Monster.class.isAssignableFrom(entityClass)) - return getSoundCategory("hostile"); - - if (Ambient.class.isAssignableFrom(entityClass)) - return getSoundCategory("ambient"); - - return getSoundCategory("neutral"); - } - - /** - * Creates the NMS object EnumItemSlot from an EquipmentSlot. - * - * @param slot - * @return null if the equipment slot is null - */ - public static Enum createEnumItemSlot(EquipmentSlot slot) - { - Class clazz = getNmsClass("EnumItemSlot"); - - Object[] enums = clazz != null ? clazz.getEnumConstants() : null; - - if (enums == null) - return null; - - switch (slot) - { - case HAND: - return (Enum) enums[0]; - case OFF_HAND: - return (Enum) enums[1]; - case FEET: - return (Enum) enums[2]; - case LEGS: - return (Enum) enums[3]; - case CHEST: - return (Enum) enums[4]; - case HEAD: - return (Enum) enums[5]; - default: - return null; - } - } - - /** - * Creates the Bukkit object EquipmentSlot from an EnumItemSlot object. - * - * @return null if the object isn't an nms EnumItemSlot - */ - public static EquipmentSlot createEquipmentSlot(Object enumItemSlot) - { - try - { - Enum nmsSlot = (Enum) enumItemSlot; - - switch (nmsSlot.name()) - { - case "MAINHAND": - return EquipmentSlot.HAND; - case "OFFHAND": - return EquipmentSlot.OFF_HAND; - case "FEET": - return EquipmentSlot.FEET; - case "LEGS": - return EquipmentSlot.LEGS; - case "CHEST": - return EquipmentSlot.CHEST; - case "HEAD": - return EquipmentSlot.HAND; - } - } - catch (Exception e) - { - } - - return null; - } - - /** - * Gets equipment from this entity based on the slot given. - * - * @param slot - * @return null if the disguisedEntity is not an instance of a living entity - */ - public static ItemStack getEquipment(EquipmentSlot slot, Entity disguisedEntity) - { - if (!(disguisedEntity instanceof LivingEntity)) - return null; - - switch (slot) - { - case HAND: - return ((LivingEntity) disguisedEntity).getEquipment().getItemInMainHand(); - case OFF_HAND: - return ((LivingEntity) disguisedEntity).getEquipment().getItemInOffHand(); - case FEET: - return ((LivingEntity) disguisedEntity).getEquipment().getBoots(); - case LEGS: - return ((LivingEntity) disguisedEntity).getEquipment().getLeggings(); - case CHEST: - return ((LivingEntity) disguisedEntity).getEquipment().getChestplate(); - case HEAD: - return ((LivingEntity) disguisedEntity).getEquipment().getHelmet(); - default: - return null; - } - } - - /** - * Necessary for 1.9 - * - * @return - */ - public static String convertSoundEffectToString(Object soundEffect) - { - try - { - Field f_getMinecraftKey = getNmsField("SoundEffect", "b"); - f_getMinecraftKey.setAccessible(true); - MinecraftKey key = MinecraftKey.fromHandle(f_getMinecraftKey.get(soundEffect)); - - return key.getKey(); - } - catch (IllegalAccessException e) - { - e.printStackTrace(); - } - - return null; - } - - public static Object getCraftSoundEffect(String sound) - { - try - { - return getCraftMethod("CraftSound", "getSoundEffect", String.class).invoke(null, sound); - } - catch (IllegalAccessException | InvocationTargetException e) - { - e.printStackTrace(); - } - - return null; - } - - /** - * This creates a DataWatcherItem usable with WrappedWatchableObject - * - * @param id - * @param value - * @return - */ - public static Object createDataWatcherItem(int id, Object value) - { - if (value == null) - return null; - - Serializer serializer = Registry.get(value.getClass()); - - WrappedDataWatcherObject watcherObject = new WrappedDataWatcherObject(id, serializer); - - Constructor construct = getNmsConstructor("DataWatcher$Item", getNmsClass("DataWatcherObject"), Object.class); - - try - { - return construct.newInstance(watcherObject.getHandle(), value); - } - catch (InstantiationException | IllegalAccessException | InvocationTargetException e) - { - e.printStackTrace(); - } - - return null; - } - - public static EntityEquipment createEntityEquipment(Entity entity) - { - if (!(entity instanceof LivingEntity)) - return null; - - Constructor construct = getCraftConstructor("inventory.CraftEntityEquipment", getCraftClass("entity.CraftLivingEntity")); - - try - { - return (EntityEquipment) construct.newInstance((LivingEntity) entity); - } - catch (InstantiationException | IllegalAccessException | InvocationTargetException | ClassCastException e) - { - e.printStackTrace(); - } - - return null; - } - - public static int getCombinedId(int id, int data) - { - return id + (data << 12); - } - - public static Pair getFromCombinedId(int combinedId) - { - int j = combinedId & 4095; - int k = combinedId >> 12 & 15; - - return new ImmutablePair<>(j, k); - } - - public static Object getWorldServer(World w) - { - try - { - return getCraftMethod("CraftWorld", "getHandle").invoke(w); - } - catch (IllegalAccessException | InvocationTargetException e) - { - e.printStackTrace(); - } - - return null; - } - - public static Object getPlayerInteractManager(World w) - { - Object worldServer = getWorldServer(w); - - try - { - return getNmsConstructor("PlayerInteractManager", getNmsClass("World")).newInstance(worldServer); - } - catch (InstantiationException | InvocationTargetException | IllegalAccessException e) - { - e.printStackTrace(); - } - - return null; - } - - public static Object createEntityPlayer(World w, WrappedGameProfile profile) - { - Object entityPlayer = null; - - try - { - entityPlayer = getNmsConstructor("EntityPlayer", getNmsClass("MinecraftServer"), getNmsClass("WorldServer"), - GameProfile.class, getNmsClass("PlayerInteractManager")).newInstance(getMinecraftServer(), getWorldServer(w), - profile.getHandle(), getPlayerInteractManager(w)); - } - catch (InstantiationException | IllegalAccessException | InvocationTargetException e) - { - e.printStackTrace(); - } - - return entityPlayer; - } - -} +package me.libraryaddict.disguise.utilities; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.UUID; + +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; +import org.bukkit.Art; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.World; +import org.bukkit.entity.Ambient; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Monster; +import org.bukkit.entity.Player; +import org.bukkit.inventory.EntityEquipment; +import org.bukkit.inventory.EquipmentSlot; +import org.bukkit.inventory.ItemStack; +import org.bukkit.potion.PotionEffect; + +import com.comphenix.protocol.wrappers.MinecraftKey; +import com.comphenix.protocol.wrappers.WrappedDataWatcher.Registry; +import com.comphenix.protocol.wrappers.WrappedDataWatcher.Serializer; +import com.comphenix.protocol.wrappers.WrappedDataWatcher.WrappedDataWatcherObject; +import com.comphenix.protocol.wrappers.WrappedGameProfile; +import com.mojang.authlib.GameProfile; + +import me.libraryaddict.disguise.disguisetypes.DisguiseType; + +public class ReflectionManager +{ + + private static final String bukkitVersion = Bukkit.getServer().getClass().getName().split("\\.")[3]; + private static final Class craftItemClass; + private static Method damageAndIdleSoundMethod; + private static final Field entitiesField; + private static final Constructor boundingBoxConstructor; + private static final Method setBoundingBoxMethod; + private static final Method ihmGet; + private static final Field pingField; + private static final Field trackerField; + public static final Field entityCountField; + + static + { + for (Method method : getNmsClass("EntityLiving").getDeclaredMethods()) + { + try + { + if (method.getReturnType() == float.class && Modifier.isProtected(method.getModifiers()) + && method.getParameterTypes().length == 0) + { + Object entity = createEntityInstance("Cow"); + + method.setAccessible(true); + float value = (Float) method.invoke(entity); + + if (value == 0.4F) + { + damageAndIdleSoundMethod = method; + break; + } + } + } + catch (Exception ex) + { + ex.printStackTrace(System.out); + } + } + + craftItemClass = getCraftClass("inventory.CraftItemStack"); + + pingField = getNmsField("EntityPlayer", "ping"); + + trackerField = getNmsField("WorldServer", "tracker"); + + entitiesField = getNmsField("EntityTracker", "trackedEntities"); + + ihmGet = getNmsMethod("IntHashMap", "get", int.class); + + 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) + { + try + { + Class entityClass = getNmsClass("Entity" + entityName); + Object entityObject; + Object world = getWorldServer(Bukkit.getWorlds().get(0)); + + switch (entityName) + { + case "Player": + Object minecraftServer = getNmsMethod("MinecraftServer", "getServer").invoke(null); + + Object playerinteractmanager = getNmsClass("PlayerInteractManager").getDeclaredConstructor(getNmsClass("World")) + .newInstance(world); + + WrappedGameProfile gameProfile = getGameProfile(null, "Steve"); + + entityObject = entityClass + .getDeclaredConstructor(getNmsClass("MinecraftServer"), getNmsClass("WorldServer"), + gameProfile.getHandleType(), playerinteractmanager.getClass()) + .newInstance(minecraftServer, world, gameProfile.getHandle(), playerinteractmanager); + break; + case "EnderPearl": + entityObject = entityClass.getDeclaredConstructor(getNmsClass("World"), getNmsClass("EntityLiving")) + .newInstance(world, createEntityInstance("Cow")); + break; + case "Potion": + entityObject = entityClass + .getDeclaredConstructor(getNmsClass("World"), Double.TYPE, Double.TYPE, Double.TYPE, + getNmsClass("ItemStack")) + .newInstance(world, 0d, 0d, 0d, getNmsItem(new ItemStack(Material.SPLASH_POTION))); + break; + default: + entityObject = entityClass.getDeclaredConstructor(getNmsClass("World")).newInstance(world); + break; + } + + return entityObject; + } + catch (Exception e) + { + e.printStackTrace(System.out); + } + + return null; + } + + public static Object getMobEffectList(int id) + { + Method nmsMethod = getNmsMethod("MobEffectList", "fromId", Integer.TYPE); + + try + { + return nmsMethod.invoke(null, id); + } + catch (IllegalAccessException | InvocationTargetException e) + { + e.printStackTrace(); + } + + 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; + } + + public static FakeBoundingBox getBoundingBox(Entity entity) + { + try + { + Object boundingBox = getNmsMethod("Entity", "getBoundingBox").invoke(getNmsEntity(entity)); + + double x = 0, y = 0, z = 0; + int stage = 0; + + for (Field field : boundingBox.getClass().getDeclaredFields()) + { + if (field.getType().getSimpleName().equals("double")) + { + stage++; + + switch (stage) + { + case 1: + x -= field.getDouble(boundingBox); + break; + case 2: + y -= field.getDouble(boundingBox); + break; + case 3: + z -= field.getDouble(boundingBox); + break; + case 4: + x += field.getDouble(boundingBox); + break; + case 5: + y += field.getDouble(boundingBox); + break; + case 6: + z += field.getDouble(boundingBox); + break; + default: + throw new Exception("Error while setting the bounding box, more doubles than I thought??"); + } + } + } + + return new FakeBoundingBox(x, y, z); + } + catch (Exception ex) + { + ex.printStackTrace(System.out); + } + + return null; + } + + public static Entity getBukkitEntity(Object nmsEntity) + { + try + { + return (Entity) getNmsMethod("Entity", "getBukkitEntity").invoke(nmsEntity); + } + catch (Exception ex) + { + ex.printStackTrace(System.out); + } + + return null; + } + + public static ItemStack getBukkitItem(Object nmsItem) + { + try + { + return (ItemStack) craftItemClass.getMethod("asBukkitCopy", getNmsClass("ItemStack")).invoke(null, nmsItem); + } + catch (Exception e) + { + e.printStackTrace(System.out); + } + + return null; + } + + public static String getBukkitVersion() + { + return bukkitVersion; + } + + public static Class getCraftClass(String className) + { + try + { + return Class.forName("org.bukkit.craftbukkit." + getBukkitVersion() + "." + className); + } + catch (Exception e) + { + e.printStackTrace(System.out); + } + + return null; + } + + public static Constructor getCraftConstructor(Class clazz, Class... parameters) + { + try + { + Constructor declaredConstructor = clazz.getDeclaredConstructor(parameters); + declaredConstructor.setAccessible(true); + return declaredConstructor; + } + catch (NoSuchMethodException e) + { + e.printStackTrace(System.out); + } + + return null; + } + + public static Constructor getCraftConstructor(String className, Class... parameters) + { + return getCraftConstructor(getCraftClass(className), parameters); + } + + public static String getCraftSound(Sound sound) + { + try + { + return (String) getCraftClass("CraftSound").getMethod("getSound", Sound.class).invoke(null, sound); + } + catch (Exception ex) + { + ex.printStackTrace(System.out); + } + + return null; + } + + public static Object getEntityTrackerEntry(Entity target) throws Exception + { + Object world = getWorldServer(target.getWorld()); + Object tracker = trackerField.get(world); + Object trackedEntities = entitiesField.get(tracker); + + return ihmGet.invoke(trackedEntities, target.getEntityId()); + } + + public static Object getMinecraftServer() + { + try + { + return getCraftMethod("CraftServer", "getServer").invoke(Bukkit.getServer()); + } + catch (IllegalAccessException | InvocationTargetException e) + { + e.printStackTrace(); + } + return null; + } + + public static String getEnumArt(Art art) + { + try + { + Object enumArt = getCraftClass("CraftArt").getMethod("BukkitToNotch", Art.class).invoke(null, art); + for (Field field : enumArt.getClass().getDeclaredFields()) + { + if (field.getType() == String.class) + { + return (String) field.get(enumArt); + } + } + } + catch (Exception ex) + { + ex.printStackTrace(System.out); + } + + return null; + } + + public static Object getBlockPosition(int x, int y, int z) + { + try + { + return getNmsClass("BlockPosition").getDeclaredConstructor(int.class, int.class, int.class).newInstance(x, y, z); + } + catch (Exception ex) + { + ex.printStackTrace(System.out); + } + + return null; + } + + public static Enum getEnumDirection(int direction) + { + try + { + return (Enum) getNmsMethod("EnumDirection", "fromType2", int.class).invoke(null, direction); + } + catch (Exception ex) + { + ex.printStackTrace(System.out); + } + + return null; + } + + public static Enum getEnumPlayerInfoAction(int action) + { + try + { + return (Enum) getNmsClass("PacketPlayOutPlayerInfo$EnumPlayerInfoAction").getEnumConstants()[action]; + } + catch (Exception ex) + { + ex.printStackTrace(System.out); + } + + return null; + } + + public static Object getPlayerInfoData(Object playerInfoPacket, WrappedGameProfile gameProfile) + { + try + { + Object playerListName = getNmsClass("ChatComponentText").getDeclaredConstructor(String.class) + .newInstance(gameProfile.getName()); + + return getNmsClass("PacketPlayOutPlayerInfo$PlayerInfoData") + .getDeclaredConstructor(getNmsClass("PacketPlayOutPlayerInfo"), gameProfile.getHandleType(), int.class, + getNmsClass("WorldSettings$EnumGamemode"), getNmsClass("IChatBaseComponent")) + .newInstance(playerInfoPacket, gameProfile.getHandle(), 0, + getNmsClass("WorldSettings$EnumGamemode").getEnumConstants()[1], playerListName); + } + catch (Exception ex) + { + ex.printStackTrace(System.out); + } + + return null; + } + + public static WrappedGameProfile getGameProfile(Player player) + { + return WrappedGameProfile.fromPlayer(player); + } + + public static WrappedGameProfile getGameProfile(UUID uuid, String playerName) + { + try + { + return new WrappedGameProfile(uuid != null ? uuid : UUID.randomUUID(), playerName); + } + catch (Exception ex) + { + ex.printStackTrace(System.out); + } + return null; + } + + 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()); + return gameProfile; + } + catch (Exception ex) + { + ex.printStackTrace(System.out); + } + + return null; + } + + public static Class getNmsClass(String className) + { + try + { + return Class.forName("net.minecraft.server." + getBukkitVersion() + "." + className); + } + catch (Exception e) + { + e.printStackTrace(System.out); + } + + return null; + } + + public static Constructor getNmsConstructor(Class clazz, Class... parameters) + { + try + { + Constructor declaredConstructor = clazz.getDeclaredConstructor(parameters); + declaredConstructor.setAccessible(true); + return declaredConstructor; + } + catch (NoSuchMethodException e) + { + e.printStackTrace(System.out); + } + + return null; + } + + public static Constructor getNmsConstructor(String className, Class... parameters) + { + return getNmsConstructor(getNmsClass(className), parameters); + } + + public static Object getNmsEntity(Entity entity) + { + try + { + return getCraftClass("entity.CraftEntity").getMethod("getHandle").invoke(entity); + } + catch (Exception ex) + { + ex.printStackTrace(System.out); + } + + return null; + } + + public static Field getNmsField(Class clazz, String fieldName) + { + try + { + Field declaredField = clazz.getDeclaredField(fieldName); + declaredField.setAccessible(true); + + return declaredField; + } + catch (NoSuchFieldException e) + { + e.printStackTrace(System.out); + } + + return null; + } + + public static Field getNmsField(String className, String fieldName) + { + return getNmsField(getNmsClass(className), fieldName); + } + + public static Object getNmsItem(ItemStack itemstack) + { + try + { + return craftItemClass.getDeclaredMethod("asNMSCopy", ItemStack.class).invoke(null, itemstack); + } + catch (Exception e) + { + e.printStackTrace(System.out); + } + + return null; + } + + public static Method getCraftMethod(String className, String methodName, Class... parameters) + { + return getCraftMethod(getCraftClass(className), methodName, parameters); + } + + public static Method getCraftMethod(Class clazz, String methodName, Class... parameters) + { + try + { + Method declaredMethod = clazz.getDeclaredMethod(methodName, parameters); + declaredMethod.setAccessible(true); + + return declaredMethod; + } + catch (NoSuchMethodException e) + { + e.printStackTrace(System.out); + } + + return null; + } + + public static Method getNmsMethod(Class clazz, String methodName, Class... parameters) + { + try + { + Method declaredMethod = clazz.getDeclaredMethod(methodName, parameters); + declaredMethod.setAccessible(true); + + return declaredMethod; + } + catch (NoSuchMethodException e) + { + e.printStackTrace(System.out); + } + + return null; + } + + public static Method getNmsMethod(String className, String methodName, Class... parameters) + { + return getNmsMethod(getNmsClass(className), methodName, parameters); + } + + public static double getPing(Player player) + { + try + { + return (double) pingField.getInt(ReflectionManager.getNmsEntity(player)); + } + catch (Exception ex) + { + ex.printStackTrace(System.out); + } + + return 0; + } + + public static float[] getSize(Entity entity) + { + try + { + float length = getNmsField("Entity", "length").getFloat(getNmsEntity(entity)); + float width = getNmsField("Entity", "width").getFloat(getNmsEntity(entity)); + + float height = (Float) getNmsMethod("Entity", "getHeadHeight").invoke(getNmsEntity(entity)); + return new float[] + { + length, width, height + }; + } + catch (Exception ex) + { + ex.printStackTrace(System.out); + } + + return null; + } + + public static WrappedGameProfile getSkullBlob(WrappedGameProfile gameProfile) + { + try + { + Object minecraftServer = getNmsMethod("MinecraftServer", "getServer").invoke(null); + + for (Method method : getNmsClass("MinecraftServer").getDeclaredMethods()) + { + if (method.getReturnType().getSimpleName().equals("MinecraftSessionService")) + { + Object session = method.invoke(minecraftServer); + + return WrappedGameProfile.fromHandle(session.getClass() + .getDeclaredMethod("fillProfileProperties", gameProfile.getHandleType(), boolean.class) + .invoke(session, gameProfile.getHandle(), true)); + } + } + } + catch (Exception ex) + { + ex.printStackTrace(System.out); + } + + return null; + } + + public static Float getSoundModifier(Object entity) + { + try + { + damageAndIdleSoundMethod.setAccessible(true); + + return (Float) damageAndIdleSoundMethod.invoke(entity); + } + catch (Exception ignored) + { + } + return null; + } + + public static WrappedGameProfile grabProfileAddUUID(String playername) + { + try + { + Object minecraftServer = getNmsMethod("MinecraftServer", "getServer").invoke(null); + + for (Method method : getNmsClass("MinecraftServer").getDeclaredMethods()) + { + if (method.getReturnType().getSimpleName().equals("GameProfileRepository")) + { + Object profileRepo = method.invoke(minecraftServer); + + Object agent = Class.forName("com.mojang.authlib.Agent").getDeclaredField("MINECRAFT").get(null); + + LibsProfileLookupCaller callback = new LibsProfileLookupCaller(); + + profileRepo.getClass().getDeclaredMethod("findProfilesByNames", String[].class, agent.getClass(), + Class.forName("com.mojang.authlib.ProfileLookupCallback")).invoke(profileRepo, new String[] + { + playername + }, agent, callback); + + if (callback.getGameProfile() != null) + { + return callback.getGameProfile(); + } + + return getGameProfile(null, playername); + } + } + } + catch (Exception ex) + { + ex.printStackTrace(System.out); + } + + return null; + } + + public static void removePlayer(Player player) + { + // Some future remove code if needed + } + + public static void setBoundingBox(Entity entity, FakeBoundingBox newBox) + { + try + { + Location loc = entity.getLocation(); + + Object boundingBox = boundingBoxConstructor.newInstance(loc.getX() - newBox.getX(), loc.getY() - newBox.getY(), + loc.getZ() - newBox.getZ(), loc.getX() + newBox.getX(), loc.getY() + newBox.getY(), + loc.getZ() + newBox.getZ()); + + setBoundingBoxMethod.invoke(getNmsEntity(entity), boundingBox); + } + catch (Exception ex) + { + ex.printStackTrace(System.out); + } + } + + 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(category.toUpperCase())) + return anEnum; + } + } + + return invoke; + } + catch (Exception e) + { + e.printStackTrace(); + } + + return null; + } + + public static Enum getSoundCategory(DisguiseType disguiseType) + { + if (disguiseType == DisguiseType.PLAYER) + return getSoundCategory("player"); + + Class entityClass = disguiseType.getEntityType().getEntityClass(); + + if (Monster.class.isAssignableFrom(entityClass)) + return getSoundCategory("hostile"); + + if (Ambient.class.isAssignableFrom(entityClass)) + return getSoundCategory("ambient"); + + return getSoundCategory("neutral"); + } + + /** + * Creates the NMS object EnumItemSlot from an EquipmentSlot. + * + * @param slot + * @return null if the equipment slot is null + */ + public static Enum createEnumItemSlot(EquipmentSlot slot) + { + Class clazz = getNmsClass("EnumItemSlot"); + + Object[] enums = clazz != null ? clazz.getEnumConstants() : null; + + if (enums == null) + return null; + + switch (slot) + { + case HAND: + return (Enum) enums[0]; + case OFF_HAND: + return (Enum) enums[1]; + case FEET: + return (Enum) enums[2]; + case LEGS: + return (Enum) enums[3]; + case CHEST: + return (Enum) enums[4]; + case HEAD: + return (Enum) enums[5]; + default: + return null; + } + } + + /** + * Creates the Bukkit object EquipmentSlot from an EnumItemSlot object. + * + * @return null if the object isn't an nms EnumItemSlot + */ + public static EquipmentSlot createEquipmentSlot(Object enumItemSlot) + { + try + { + Enum nmsSlot = (Enum) enumItemSlot; + + switch (nmsSlot.name()) + { + case "MAINHAND": + return EquipmentSlot.HAND; + case "OFFHAND": + return EquipmentSlot.OFF_HAND; + case "FEET": + return EquipmentSlot.FEET; + case "LEGS": + return EquipmentSlot.LEGS; + case "CHEST": + return EquipmentSlot.CHEST; + case "HEAD": + return EquipmentSlot.HAND; + } + } + catch (Exception e) + { + } + + return null; + } + + /** + * Gets equipment from this entity based on the slot given. + * + * @param slot + * @return null if the disguisedEntity is not an instance of a living entity + */ + public static ItemStack getEquipment(EquipmentSlot slot, Entity disguisedEntity) + { + if (!(disguisedEntity instanceof LivingEntity)) + return null; + + switch (slot) + { + case HAND: + return ((LivingEntity) disguisedEntity).getEquipment().getItemInMainHand(); + case OFF_HAND: + return ((LivingEntity) disguisedEntity).getEquipment().getItemInOffHand(); + case FEET: + return ((LivingEntity) disguisedEntity).getEquipment().getBoots(); + case LEGS: + return ((LivingEntity) disguisedEntity).getEquipment().getLeggings(); + case CHEST: + return ((LivingEntity) disguisedEntity).getEquipment().getChestplate(); + case HEAD: + return ((LivingEntity) disguisedEntity).getEquipment().getHelmet(); + default: + return null; + } + } + + /** + * Necessary for 1.9 + * + * @return + */ + public static String convertSoundEffectToString(Object soundEffect) + { + try + { + Field f_getMinecraftKey = getNmsField("SoundEffect", "b"); + f_getMinecraftKey.setAccessible(true); + MinecraftKey key = MinecraftKey.fromHandle(f_getMinecraftKey.get(soundEffect)); + + return key.getKey(); + } + catch (IllegalAccessException e) + { + e.printStackTrace(); + } + + return null; + } + + public static Object getCraftSoundEffect(String sound) + { + try + { + return getCraftMethod("CraftSound", "getSoundEffect", String.class).invoke(null, sound); + } + catch (IllegalAccessException | InvocationTargetException e) + { + e.printStackTrace(); + } + + return null; + } + + /** + * This creates a DataWatcherItem usable with WrappedWatchableObject + * + * @param id + * @param value + * @return + */ + public static Object createDataWatcherItem(int id, Object value) + { + if (value == null) + return null; + + Serializer serializer = Registry.get(value.getClass()); + + WrappedDataWatcherObject watcherObject = new WrappedDataWatcherObject(id, serializer); + + Constructor construct = getNmsConstructor("DataWatcher$Item", getNmsClass("DataWatcherObject"), Object.class); + + try + { + return construct.newInstance(watcherObject.getHandle(), value); + } + catch (InstantiationException | IllegalAccessException | InvocationTargetException e) + { + e.printStackTrace(); + } + + return null; + } + + public static EntityEquipment createEntityEquipment(Entity entity) + { + if (!(entity instanceof LivingEntity)) + return null; + + Constructor construct = getCraftConstructor("inventory.CraftEntityEquipment", getCraftClass("entity.CraftLivingEntity")); + + try + { + return (EntityEquipment) construct.newInstance((LivingEntity) entity); + } + catch (InstantiationException | IllegalAccessException | InvocationTargetException | ClassCastException e) + { + e.printStackTrace(); + } + + return null; + } + + public static int getCombinedId(int id, int data) + { + return id + (data << 12); + } + + public static Pair getFromCombinedId(int combinedId) + { + int j = combinedId & 4095; + int k = combinedId >> 12 & 15; + + return new ImmutablePair<>(j, k); + } + + public static Object getWorldServer(World w) + { + try + { + return getCraftMethod("CraftWorld", "getHandle").invoke(w); + } + catch (IllegalAccessException | InvocationTargetException e) + { + e.printStackTrace(); + } + + return null; + } + + public static Object getPlayerInteractManager(World w) + { + Object worldServer = getWorldServer(w); + + try + { + return getNmsConstructor("PlayerInteractManager", getNmsClass("World")).newInstance(worldServer); + } + catch (InstantiationException | InvocationTargetException | IllegalAccessException e) + { + e.printStackTrace(); + } + + return null; + } + + public static Object createEntityPlayer(World w, WrappedGameProfile profile) + { + Object entityPlayer = null; + + try + { + entityPlayer = getNmsConstructor("EntityPlayer", getNmsClass("MinecraftServer"), getNmsClass("WorldServer"), + GameProfile.class, getNmsClass("PlayerInteractManager")).newInstance(getMinecraftServer(), getWorldServer(w), + profile.getHandle(), getPlayerInteractManager(w)); + } + catch (InstantiationException | IllegalAccessException | InvocationTargetException e) + { + e.printStackTrace(); + } + + return entityPlayer; + } + +} diff --git a/src/me/libraryaddict/disguise/utilities/packetlisteners/PacketListenerClientInteract.java b/src/me/libraryaddict/disguise/utilities/packetlisteners/PacketListenerClientInteract.java new file mode 100644 index 00000000..b65118fc --- /dev/null +++ b/src/me/libraryaddict/disguise/utilities/packetlisteners/PacketListenerClientInteract.java @@ -0,0 +1,86 @@ +package me.libraryaddict.disguise.utilities.packetlisteners; + +import org.bukkit.Material; +import org.bukkit.entity.Arrow; +import org.bukkit.entity.Entity; +import org.bukkit.entity.ExperienceOrb; +import org.bukkit.entity.Item; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.events.ListenerPriority; +import com.comphenix.protocol.events.PacketAdapter; +import com.comphenix.protocol.events.PacketEvent; +import com.comphenix.protocol.reflect.StructureModifier; + +import me.libraryaddict.disguise.DisguiseAPI; +import me.libraryaddict.disguise.DisguiseConfig; +import me.libraryaddict.disguise.LibsDisguises; +import me.libraryaddict.disguise.disguisetypes.AnimalColor; +import me.libraryaddict.disguise.disguisetypes.Disguise; +import me.libraryaddict.disguise.disguisetypes.DisguiseType; +import me.libraryaddict.disguise.disguisetypes.watchers.SheepWatcher; +import me.libraryaddict.disguise.disguisetypes.watchers.WolfWatcher; + +public class PacketListenerClientInteract extends PacketAdapter +{ + public PacketListenerClientInteract(LibsDisguises plugin) + { + super(plugin, ListenerPriority.NORMAL, PacketType.Play.Client.USE_ENTITY); + } + + @Override + public void onPacketReceiving(PacketEvent event) + { + + if (event.isCancelled()) + return; + + try + { + Player observer = event.getPlayer(); + + if (observer.getName().contains("UNKNOWN[")) // If the player is temporary + return; + + StructureModifier entityModifer = event.getPacket().getEntityModifier(observer.getWorld()); + + Entity entity = entityModifer.read(0); + + if (entity instanceof ExperienceOrb || entity instanceof Item || entity instanceof Arrow || entity == observer) + { + event.setCancelled(true); + } + + ItemStack item = observer.getItemInHand(); + + if (item != null && item.getType() == Material.INK_SACK) + { + Disguise disguise = DisguiseAPI.getDisguise(observer, entity); + + if (disguise != null && (disguise.getType() == DisguiseType.SHEEP || disguise.getType() == DisguiseType.WOLF)) + { + AnimalColor color = AnimalColor.getColor(item.getDurability()); + + if (disguise.getType() == DisguiseType.SHEEP) + { + SheepWatcher watcher = (SheepWatcher) disguise.getWatcher(); + + watcher.setColor(DisguiseConfig.isSheepDyeable() ? color : watcher.getColor()); + } + else + { + WolfWatcher watcher = (WolfWatcher) disguise.getWatcher(); + + watcher.setCollarColor(DisguiseConfig.isWolfDyeable() ? color : watcher.getCollarColor()); + } + } + } + } + catch (Exception e) + { + e.printStackTrace(); + } + } +} diff --git a/src/me/libraryaddict/disguise/utilities/packetlisteners/PacketListenerInventory.java b/src/me/libraryaddict/disguise/utilities/packetlisteners/PacketListenerInventory.java new file mode 100644 index 00000000..43438c06 --- /dev/null +++ b/src/me/libraryaddict/disguise/utilities/packetlisteners/PacketListenerInventory.java @@ -0,0 +1,390 @@ +package me.libraryaddict.disguise.utilities.packetlisteners; + +import java.lang.reflect.InvocationTargetException; + +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; + +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.PacketType.Play.Server; +import com.comphenix.protocol.ProtocolLibrary; +import com.comphenix.protocol.events.ListenerPriority; +import com.comphenix.protocol.events.PacketAdapter; +import com.comphenix.protocol.events.PacketContainer; +import com.comphenix.protocol.events.PacketEvent; +import com.comphenix.protocol.reflect.StructureModifier; + +import me.libraryaddict.disguise.DisguiseAPI; +import me.libraryaddict.disguise.LibsDisguises; +import me.libraryaddict.disguise.disguisetypes.Disguise; +import me.libraryaddict.disguise.utilities.ReflectionManager; + +public class PacketListenerInventory extends PacketAdapter +{ + private LibsDisguises libsDisguises; + + public PacketListenerInventory(LibsDisguises plugin) + { + super(plugin, ListenerPriority.HIGH, Server.SET_SLOT, Server.WINDOW_ITEMS, PacketType.Play.Client.HELD_ITEM_SLOT, + PacketType.Play.Client.SET_CREATIVE_SLOT, PacketType.Play.Client.WINDOW_CLICK); + + libsDisguises = plugin; + } + + @Override + public void onPacketReceiving(final PacketEvent event) + { + if (event.isCancelled()) + return; + + if (event.getPlayer().getName().contains("UNKNOWN[")) // If the player is temporary + return; + + if (!(event.getPlayer() instanceof com.comphenix.net.sf.cglib.proxy.Factory) && 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 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); + + if (slot >= 5 && slot <= 8) + { + if (disguise.isHidingArmorFromSelf()) + { + int armorSlot = Math.abs((slot - 5) - 3); + + org.bukkit.inventory.ItemStack item = event.getPlayer().getInventory().getArmorContents()[armorSlot]; + + if (item != null && item.getType() != Material.AIR) + { + PacketContainer packet = new PacketContainer(Server.SET_SLOT); + + StructureModifier mods = packet.getModifier(); + + mods.write(0, 0); + mods.write(1, slot); + mods.write(2, ReflectionManager.getNmsItem(new org.bukkit.inventory.ItemStack(0))); + + try + { + ProtocolLibrary.getProtocolManager().sendServerPacket(event.getPlayer(), packet, false); + } + catch (InvocationTargetException e) + { + e.printStackTrace(); + } + } + } + } + else if (slot >= 36 && slot <= 44) + { + if (disguise.isHidingHeldItemFromSelf()) + { + int currentSlot = event.getPlayer().getInventory().getHeldItemSlot(); + + if (slot + 36 == currentSlot) + { + org.bukkit.inventory.ItemStack item = event.getPlayer().getItemInHand(); + + if (item != null && item.getType() != Material.AIR) + { + PacketContainer packet = new PacketContainer(Server.SET_SLOT); + + StructureModifier mods = packet.getModifier(); + mods.write(0, 0); + mods.write(1, slot); + mods.write(2, ReflectionManager.getNmsItem(new org.bukkit.inventory.ItemStack(0))); + + try + { + ProtocolLibrary.getProtocolManager().sendServerPacket(event.getPlayer(), packet, false); + } + catch (InvocationTargetException e) + { + e.printStackTrace(); + } + } + } + } + } + } + // If the player switched item, aka he moved from slot 1 to slot 2 + else if (event.getPacketType() == PacketType.Play.Client.HELD_ITEM_SLOT) + { + if (disguise.isHidingHeldItemFromSelf()) + { + // From logging, it seems that both bukkit and nms uses the same thing for the slot switching. + // 0 1 2 3 - 8 + // If the packet is coming, then I need to replace the item they are switching to + // As for the old item, I need to restore it. + org.bukkit.inventory.ItemStack currentlyHeld = event.getPlayer().getItemInHand(); + // If his old weapon isn't air + if (currentlyHeld != null && currentlyHeld.getType() != Material.AIR) + { + PacketContainer packet = new PacketContainer(Server.SET_SLOT); + + StructureModifier mods = packet.getModifier(); + + mods.write(0, 0); + mods.write(1, event.getPlayer().getInventory().getHeldItemSlot() + 36); + mods.write(2, ReflectionManager.getNmsItem(currentlyHeld)); + + try + { + ProtocolLibrary.getProtocolManager().sendServerPacket(event.getPlayer(), packet, false); + } + catch (InvocationTargetException e) + { + e.printStackTrace(); + } + } + + org.bukkit.inventory.ItemStack newHeld = event.getPlayer().getInventory() + .getItem(event.getPacket().getIntegers().read(0)); + + // If his new weapon isn't air either! + if (newHeld != null && newHeld.getType() != Material.AIR) + { + PacketContainer packet = new PacketContainer(Server.SET_SLOT); + + StructureModifier mods = packet.getModifier(); + + mods.write(0, 0); + mods.write(1, event.getPacket().getIntegers().read(0) + 36); + mods.write(2, ReflectionManager.getNmsItem(new org.bukkit.inventory.ItemStack(0))); + + try + { + ProtocolLibrary.getProtocolManager().sendServerPacket(event.getPlayer(), packet, false); + } + catch (InvocationTargetException e) + { + e.printStackTrace(); + } + } + } + } + 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(0) == 1) + { + // Its a shift click + clickedItem = event.getPacket().getItemModifier().read(0); + + if (clickedItem != null && clickedItem.getType() != Material.AIR) + { + // Rather than predict the clients actions + // Lets just update the entire inventory.. + Bukkit.getScheduler().runTask(libsDisguises, new Runnable() + { + public void run() + { + event.getPlayer().updateInventory(); + } + }); + } + + return; + } + else + { + // If its not a player inventory click + // Shift clicking is exempted for the item in hand.. + if (event.getPacket().getIntegers().read(0) != 0) + { + return; + } + + clickedItem = event.getPlayer().getItemOnCursor(); + } + + if (clickedItem != null && clickedItem.getType() != Material.AIR) + { + // If the slot is a armor slot + if (slot >= 5 && slot <= 8) + { + if (disguise.isHidingArmorFromSelf()) + { + PacketContainer packet = new PacketContainer(Server.SET_SLOT); + + StructureModifier mods = packet.getModifier(); + + mods.write(0, 0); + mods.write(1, slot); + mods.write(2, ReflectionManager.getNmsItem(new org.bukkit.inventory.ItemStack(0))); + + try + { + ProtocolLibrary.getProtocolManager().sendServerPacket(event.getPlayer(), packet, false); + } + catch (InvocationTargetException e) + { + e.printStackTrace(); + } + } + // Else if its a hotbar slot + } + else if (slot >= 36 && slot <= 44) + { + if (disguise.isHidingHeldItemFromSelf()) + { + int currentSlot = event.getPlayer().getInventory().getHeldItemSlot(); + + // Check if the player is on the same slot as the slot that its setting + if (slot == currentSlot + 36) + { + PacketContainer packet = new PacketContainer(Server.SET_SLOT); + + StructureModifier mods = packet.getModifier(); + mods.write(0, 0); + mods.write(1, slot); + mods.write(2, ReflectionManager.getNmsItem(new org.bukkit.inventory.ItemStack(0))); + + try + { + ProtocolLibrary.getProtocolManager().sendServerPacket(event.getPlayer(), packet, false); + } + catch (InvocationTargetException e) + { + e.printStackTrace(); + } + } + } + } + } + } + } + } + } + + @Override + public void onPacketSending(PacketEvent event) + { + // If the inventory is the players inventory + if (!(event.getPlayer() instanceof com.comphenix.net.sf.cglib.proxy.Factory) && event.getPlayer().getVehicle() == null + && event.getPacket().getIntegers().read(0) == 0) + { + + Disguise disguise = DisguiseAPI.getDisguise(event.getPlayer(), event.getPlayer()); + + // If the player is disguised, views self disguises and is hiding a item. + if (disguise != null && disguise.isSelfDisguiseVisible() + && (disguise.isHidingArmorFromSelf() || disguise.isHidingHeldItemFromSelf())) + { + // If the server is setting the slot + // Need to set it to air if its in a place it shouldn't be. + // Things such as picking up a item, spawned in item. Plugin sets the item. etc. Will fire this + /** + * Done + */ + if (event.getPacketType() == Server.SET_SLOT) + { + // The raw slot + // nms code has the start of the hotbar being 36. + int slot = event.getPacket().getIntegers().read(1); + + // If the slot is a armor slot + if (slot >= 5 && slot <= 8) + { + if (disguise.isHidingArmorFromSelf()) + { + // Get the bukkit armor slot! + int armorSlot = Math.abs((slot - 5) - 3); + + org.bukkit.inventory.ItemStack item = event.getPlayer().getInventory().getArmorContents()[armorSlot]; + + if (item != null && item.getType() != Material.AIR) + { + event.setPacket(event.getPacket().shallowClone()); + + event.getPacket().getModifier().write(2, + ReflectionManager.getNmsItem(new org.bukkit.inventory.ItemStack(0))); + } + } + // Else if its a hotbar slot + } + else if (slot >= 36 && slot <= 44) + { + if (disguise.isHidingHeldItemFromSelf()) + { + int currentSlot = event.getPlayer().getInventory().getHeldItemSlot(); + + // Check if the player is on the same slot as the slot that its setting + if (slot == currentSlot + 36) + { + org.bukkit.inventory.ItemStack item = event.getPlayer().getItemInHand(); + + if (item != null && item.getType() != Material.AIR) + { + event.setPacket(event.getPacket().shallowClone()); + event.getPacket().getModifier().write(2, + ReflectionManager.getNmsItem(new org.bukkit.inventory.ItemStack(0))); + } + } + } + } + } + else if (event.getPacketType() == Server.WINDOW_ITEMS) + { + event.setPacket(event.getPacket().deepClone()); + + StructureModifier mods = event.getPacket().getItemArrayModifier(); + ItemStack[] items = mods.read(0); + + for (int slot = 0; slot < items.length; slot++) + { + if (slot >= 5 && slot <= 8) + { + if (disguise.isHidingArmorFromSelf()) + { + // Get the bukkit armor slot! + int armorSlot = Math.abs((slot - 5) - 3); + + org.bukkit.inventory.ItemStack item = event.getPlayer().getInventory() + .getArmorContents()[armorSlot]; + + if (item != null && item.getType() != Material.AIR) + { + items[slot] = new org.bukkit.inventory.ItemStack(0); + } + } + // Else if its a hotbar slot + } + else if (slot >= 36 && slot <= 44) + { + if (disguise.isHidingHeldItemFromSelf()) + { + int currentSlot = event.getPlayer().getInventory().getHeldItemSlot(); + + // Check if the player is on the same slot as the slot that its setting + if (slot == currentSlot + 36) + { + org.bukkit.inventory.ItemStack item = event.getPlayer().getItemInHand(); + + if (item != null && item.getType() != Material.AIR) + { + items[slot] = new org.bukkit.inventory.ItemStack(0); + } + } + } + } + } + + mods.write(0, items); + } + } + } + } + +} diff --git a/src/me/libraryaddict/disguise/utilities/packetlisteners/PacketListenerMain.java b/src/me/libraryaddict/disguise/utilities/packetlisteners/PacketListenerMain.java new file mode 100644 index 00000000..01b37912 --- /dev/null +++ b/src/me/libraryaddict/disguise/utilities/packetlisteners/PacketListenerMain.java @@ -0,0 +1,97 @@ +package me.libraryaddict.disguise.utilities.packetlisteners; + +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; + +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.PacketType.Play.Server; +import com.comphenix.protocol.ProtocolLibrary; +import com.comphenix.protocol.events.ListenerPriority; +import com.comphenix.protocol.events.PacketAdapter; +import com.comphenix.protocol.events.PacketContainer; +import com.comphenix.protocol.events.PacketEvent; +import com.comphenix.protocol.reflect.StructureModifier; + +import me.libraryaddict.disguise.LibsDisguises; +import me.libraryaddict.disguise.utilities.PacketsManager; + +public class PacketListenerMain extends PacketAdapter +{ + private LibsDisguises libsDisguises; + + public PacketListenerMain(LibsDisguises plugin, ArrayList packetsToListen) + { + super(plugin, ListenerPriority.HIGH, packetsToListen); + + libsDisguises = plugin; + } + + @Override + public void onPacketSending(PacketEvent event) + { + if (event.isCancelled()) + return; + + if (event.getPlayer().getName().contains("UNKNOWN[")) // If the player is temporary + return; + + 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)); + + // 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) + return; + + PacketContainer[][] packets = PacketsManager.transformPacket(event.getPacket(), event.getPlayer(), entity); + + if (packets != null) + { + event.setCancelled(true); + + try + { + for (PacketContainer packet : packets[0]) + { + ProtocolLibrary.getProtocolManager().sendServerPacket(observer, packet, false); + } + + final PacketContainer[] delayed = packets[1]; + + if (delayed.length > 0) + { + Bukkit.getScheduler().scheduleSyncDelayedTask(libsDisguises, new Runnable() + { + public void run() + { + try + { + for (PacketContainer packet : delayed) + { + ProtocolLibrary.getProtocolManager().sendServerPacket(observer, packet, false); + } + } + catch (InvocationTargetException e) + { + e.printStackTrace(); + } + } + }, 2); + } + } + catch (InvocationTargetException ex) + { + ex.printStackTrace(); + } + } + } + +} diff --git a/src/me/libraryaddict/disguise/utilities/packetlisteners/PacketListenerSounds.java b/src/me/libraryaddict/disguise/utilities/packetlisteners/PacketListenerSounds.java new file mode 100644 index 00000000..42ff8301 --- /dev/null +++ b/src/me/libraryaddict/disguise/utilities/packetlisteners/PacketListenerSounds.java @@ -0,0 +1,406 @@ +package me.libraryaddict.disguise.utilities.packetlisteners; + +import java.lang.reflect.InvocationTargetException; + +import org.bukkit.Location; +import org.bukkit.entity.Ageable; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.entity.Zombie; + +import com.comphenix.protocol.PacketType.Play.Server; +import com.comphenix.protocol.ProtocolLibrary; +import com.comphenix.protocol.events.ListenerPriority; +import com.comphenix.protocol.events.PacketAdapter; +import com.comphenix.protocol.events.PacketContainer; +import com.comphenix.protocol.events.PacketEvent; +import com.comphenix.protocol.reflect.StructureModifier; + +import me.libraryaddict.disguise.DisguiseAPI; +import me.libraryaddict.disguise.LibsDisguises; +import me.libraryaddict.disguise.disguisetypes.Disguise; +import me.libraryaddict.disguise.disguisetypes.DisguiseType; +import me.libraryaddict.disguise.disguisetypes.MobDisguise; +import me.libraryaddict.disguise.utilities.DisguiseSound; +import me.libraryaddict.disguise.utilities.DisguiseSound.SoundType; +import me.libraryaddict.disguise.utilities.DisguiseUtilities; +import me.libraryaddict.disguise.utilities.ReflectionManager; + +public class PacketListenerSounds extends PacketAdapter +{ + /** + * This is a fix for the stupidity that is + * "I can't separate the sounds from the sounds the player heard, and the sounds of the entity tracker heard" + */ + private static boolean cancelSound; + + public PacketListenerSounds(LibsDisguises plugin) + { + super(plugin, ListenerPriority.NORMAL, Server.NAMED_SOUND_EFFECT, Server.ENTITY_STATUS); + } + + @Override + public void onPacketSending(PacketEvent event) + { + if (event.isCancelled()) + { + return; + } + if (event.isAsync()) + { + return; + } + + if (event.getPlayer().getName().contains("UNKNOWN[")) // If the player is temporary + return; + + event.setPacket(event.getPacket().deepClone()); + + StructureModifier mods = event.getPacket().getModifier(); + + Player observer = event.getPlayer(); + + if (event.getPacketType() == Server.NAMED_SOUND_EFFECT) + { + 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)); + mods.write(1, ReflectionManager.getSoundCategory(disguise.getType())); + } + } + 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)); + mods.write(1, ReflectionManager.getSoundCategory(disguise.getType())); + + // 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 = (DisguiseUtilities.random.nextFloat() + - DisguiseUtilities.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 = (DisguiseUtilities.random.nextFloat() + - DisguiseUtilities.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(disguise.getType())); // 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 = (DisguiseUtilities.random.nextFloat() - DisguiseUtilities.random.nextFloat()) * 0.2F + + 1.5F; + } + else + pitch = (DisguiseUtilities.random.nextFloat() - DisguiseUtilities.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, false); + } + catch (InvocationTargetException e) + { + e.printStackTrace(); + } + } + } + } + } + } + } + } +} diff --git a/src/me/libraryaddict/disguise/utilities/packetlisteners/PacketListenerViewDisguises.java b/src/me/libraryaddict/disguise/utilities/packetlisteners/PacketListenerViewDisguises.java new file mode 100644 index 00000000..f6dad140 --- /dev/null +++ b/src/me/libraryaddict/disguise/utilities/packetlisteners/PacketListenerViewDisguises.java @@ -0,0 +1,188 @@ +package me.libraryaddict.disguise.utilities.packetlisteners; + +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.List; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +import com.comphenix.protocol.PacketType.Play.Server; +import com.comphenix.protocol.ProtocolLibrary; +import com.comphenix.protocol.events.ListenerPriority; +import com.comphenix.protocol.events.PacketAdapter; +import com.comphenix.protocol.events.PacketContainer; +import com.comphenix.protocol.events.PacketEvent; +import com.comphenix.protocol.reflect.StructureModifier; +import com.comphenix.protocol.wrappers.WrappedWatchableObject; + +import me.libraryaddict.disguise.DisguiseAPI; +import me.libraryaddict.disguise.LibsDisguises; +import me.libraryaddict.disguise.disguisetypes.Disguise; +import me.libraryaddict.disguise.utilities.PacketsManager; +import me.libraryaddict.disguise.utilities.ReflectionManager; + +public class PacketListenerViewDisguises extends PacketAdapter +{ + private LibsDisguises libsDisguises; + + public PacketListenerViewDisguises(LibsDisguises plugin) + { + super(plugin, ListenerPriority.HIGH, Server.NAMED_ENTITY_SPAWN, Server.ATTACH_ENTITY, Server.REL_ENTITY_MOVE, + Server.REL_ENTITY_MOVE_LOOK, Server.ENTITY_LOOK, Server.ENTITY_TELEPORT, Server.ENTITY_HEAD_ROTATION, + Server.ENTITY_METADATA, Server.ENTITY_EQUIPMENT, Server.ANIMATION, Server.BED, Server.ENTITY_EFFECT, + Server.ENTITY_VELOCITY, Server.UPDATE_ATTRIBUTES, Server.ENTITY_STATUS); + + libsDisguises = plugin; + } + + @Override + public void onPacketSending(PacketEvent event) + { + if (event.isCancelled()) + return; + + final Player observer = event.getPlayer(); + + if (observer.getName().contains("UNKNOWN[")) // If the player is temporary + return; + + if (event.getPacket().getIntegers().read(0) == observer.getEntityId()) + { + if (DisguiseAPI.isSelfDisguised(observer)) + { + // Here I grab the packets to convert them to, So I can display them as if the disguise sent them. + PacketContainer[][] transformed = PacketsManager.transformPacket(event.getPacket(), observer, observer); + + PacketContainer[] packets = transformed == null ? null : transformed[0]; + + final PacketContainer[] delayedPackets = transformed == null ? null : transformed[1]; + + if (packets == null) + { + packets = new PacketContainer[] + { + event.getPacket() + }; + } + + for (PacketContainer packet : packets) + { + if (packet.getType() != Server.PLAYER_INFO) + { + if (packet.equals(event.getPacket())) + { + packet = packet.shallowClone(); + } + + packet.getIntegers().write(0, DisguiseAPI.getSelfDisguiseId()); + } + + try + { + ProtocolLibrary.getProtocolManager().sendServerPacket(observer, packet, false); + } + catch (InvocationTargetException e) + { + e.printStackTrace(); + } + } + + if (delayedPackets != null && delayedPackets.length > 0) + { + Bukkit.getScheduler().scheduleSyncDelayedTask(libsDisguises, new Runnable() + { + public void run() + { + try + { + for (PacketContainer packet : delayedPackets) + { + ProtocolLibrary.getProtocolManager().sendServerPacket(observer, packet, false); + } + } + catch (InvocationTargetException e) + { + e.printStackTrace(); + } + } + }, 2); + } + + if (event.getPacketType() == Server.ENTITY_METADATA) + { + event.setPacket(event.getPacket().deepClone()); + + for (WrappedWatchableObject watch : event.getPacket().getWatchableCollectionModifier().read(0)) + { + if (watch.getIndex() == 0) + { + byte b = (byte) watch.getValue(); + + byte a = (byte) (b | 1 << 5); + + if ((b & 1 << 3) != 0) + a = (byte) (a | 1 << 3); + + watch.setValue(a); + } + } + } + else if (event.getPacketType() == Server.NAMED_ENTITY_SPAWN) + { + event.setCancelled(true); + + PacketContainer packet = new PacketContainer(Server.ENTITY_METADATA); + + StructureModifier mods = packet.getModifier(); + + mods.write(0, observer.getEntityId()); + + List watchableList = new ArrayList<>(); + Byte b = 1 << 5; + + if (observer.isSprinting()) + b = (byte) (b | 1 << 3); + + WrappedWatchableObject watch = new WrappedWatchableObject(ReflectionManager.createDataWatcherItem(0, b)); + + watchableList.add(watch); + packet.getWatchableCollectionModifier().write(0, watchableList); + + try + { + ProtocolLibrary.getProtocolManager().sendServerPacket(observer, packet); + } + catch (InvocationTargetException e) + { + e.printStackTrace(); + } + } + else if (event.getPacketType() == Server.ANIMATION) + { + if (event.getPacket().getIntegers().read(1) != 2) + { + event.setCancelled(true); + } + } + else if (event.getPacketType() == Server.ATTACH_ENTITY || event.getPacketType() == Server.REL_ENTITY_MOVE + || event.getPacketType() == Server.REL_ENTITY_MOVE_LOOK || event.getPacketType() == Server.ENTITY_LOOK + || event.getPacketType() == Server.ENTITY_TELEPORT || event.getPacketType() == Server.ENTITY_HEAD_ROTATION + || event.getPacketType() == Server.ENTITY_EFFECT || event.getPacketType() == Server.ENTITY_EQUIPMENT) + { + event.setCancelled(true); + } + else if (event.getPacketType() == Server.ENTITY_STATUS) + { + Disguise disguise = DisguiseAPI.getDisguise(event.getPlayer(), event.getPlayer()); + + if (disguise.isSelfDisguiseSoundsReplaced() && !disguise.getType().isPlayer() + && event.getPacket().getBytes().read(0) == 2) + { + event.setCancelled(true); + } + } + } + } + } +}