diff --git a/src/me/libraryaddict/disguise/LibsDisguises.java b/src/me/libraryaddict/disguise/LibsDisguises.java index 6516a5d7..5fa27dbf 100644 --- a/src/me/libraryaddict/disguise/LibsDisguises.java +++ b/src/me/libraryaddict/disguise/LibsDisguises.java @@ -17,6 +17,7 @@ import me.libraryaddict.disguise.disguisetypes.watchers.LivingWatcher; import me.libraryaddict.disguise.disguisetypes.watchers.MinecartWatcher; import me.libraryaddict.disguise.disguisetypes.watchers.SlimeWatcher; import me.libraryaddict.disguise.disguisetypes.watchers.ZombieWatcher; +import me.libraryaddict.disguise.utils.DisguiseUtilities; import me.libraryaddict.disguise.utils.PacketsManager; import me.libraryaddict.disguise.utils.ReflectionManager; @@ -57,6 +58,7 @@ public class LibsDisguises extends JavaPlugin { } } PacketsManager.init(this); + DisguiseUtilities.init(this); DisguiseAPI.setSoundsEnabled(getConfig().getBoolean("DisguiseSounds")); DisguiseAPI.setVelocitySent(getConfig().getBoolean("SendVelocity")); DisguiseAPI.setViewDisguises(getConfig().getBoolean("ViewSelfDisguises")); @@ -68,7 +70,7 @@ public class LibsDisguises extends JavaPlugin { } try { // Here I use reflection to set the plugin for Disguise.. - // Kinda stupid but I don't want open API calls. + // Kind of stupid but I don't want open API calls for a commonly used object. Field field = Disguise.class.getDeclaredField("plugin"); field.setAccessible(true); field.set(null, this); @@ -90,6 +92,10 @@ public class LibsDisguises extends JavaPlugin { registerValues(); } + /** + * Here we create a nms entity for each disguise. Then grab their default values in their datawatcher. Then their sound volume + * for mob noises. As well as setting their watcher class and entity size. + */ private void registerValues() { for (DisguiseType disguiseType : DisguiseType.values()) { if (disguiseType.getEntityType() == null) { @@ -135,7 +141,7 @@ public class LibsDisguises extends JavaPlugin { } } disguiseType.setWatcherClass(watcherClass); - String name = toReadable(disguiseType.name()); + String nmsEntityName = toReadable(disguiseType.name()); switch (disguiseType) { case WITHER_SKELETON: case ZOMBIE_VILLAGER: @@ -145,61 +151,62 @@ public class LibsDisguises extends JavaPlugin { case SKELETON_HORSE: continue; case PRIMED_TNT: - name = "TNTPrimed"; + nmsEntityName = "TNTPrimed"; break; case MINECART_TNT: - name = "MinecartTNT"; + nmsEntityName = "MinecartTNT"; break; case MINECART: - name = "MinecartRideable"; + nmsEntityName = "MinecartRideable"; break; case FIREWORK: - name = "Fireworks"; + nmsEntityName = "Fireworks"; break; case SPLASH_POTION: - name = "Potion"; + nmsEntityName = "Potion"; break; case GIANT: - name = "GiantZombie"; + nmsEntityName = "GiantZombie"; break; case DROPPED_ITEM: - name = "Item"; + nmsEntityName = "Item"; break; case FIREBALL: - name = "LargeFireball"; + nmsEntityName = "LargeFireball"; break; case LEASH_HITCH: - name = "Leash"; + nmsEntityName = "Leash"; break; default: break; } try { - Object entity = ReflectionManager.createEntityInstance(name); + Object nmsEntity = ReflectionManager.createEntityInstance(nmsEntityName); Entity bukkitEntity = (Entity) ReflectionManager.getNmsClass("Entity").getMethod("getBukkitEntity") - .invoke(entity); - int enumEntitySize = 0; + .invoke(nmsEntity); + int entitySize = 0; for (Field field : ReflectionManager.getNmsClass("Entity").getFields()) { if (field.getType().getName().equals("EnumEntitySize")) { - Enum a = (Enum) field.get(entity); - enumEntitySize = a.ordinal(); + Enum enumEntitySize = (Enum) field.get(nmsEntity); + entitySize = enumEntitySize.ordinal(); break; } } - Values disguiseValues = new Values(disguiseType, entity.getClass(), enumEntitySize); + Values disguiseValues = new Values(disguiseType, nmsEntity.getClass(), entitySize); WrappedDataWatcher dataWatcher = WrappedDataWatcher.getEntityWatcher(bukkitEntity); List watchers = dataWatcher.getWatchableObjects(); for (WrappedWatchableObject watch : watchers) disguiseValues.setMetaValue(watch.getIndex(), watch.getValue()); DisguiseSound sound = DisguiseSound.getType(disguiseType.name()); if (sound != null) { - Float soundStrength = ReflectionManager.getSoundModifier(entity); + Float soundStrength = ReflectionManager.getSoundModifier(nmsEntity); if (soundStrength != null) { sound.setDamageSoundVolume((Float) soundStrength); } } } catch (Exception ex) { - System.out.print("[LibsDisguises] Trouble while making values for " + name + ": " + ex.getMessage()); + System.out.print("[LibsDisguises] Trouble while making values for " + disguiseType.name() + ": " + + ex.getMessage()); System.out.print("[LibsDisguises] Please report this to LibsDisguises author"); ex.printStackTrace(); } diff --git a/src/me/libraryaddict/disguise/disguisetypes/FlagWatcher.java b/src/me/libraryaddict/disguise/disguisetypes/FlagWatcher.java index 9059a2ce..496370af 100644 --- a/src/me/libraryaddict/disguise/disguisetypes/FlagWatcher.java +++ b/src/me/libraryaddict/disguise/disguisetypes/FlagWatcher.java @@ -19,7 +19,7 @@ import com.comphenix.protocol.reflect.StructureModifier; import com.comphenix.protocol.wrappers.WrappedWatchableObject; import me.libraryaddict.disguise.DisguiseAPI; -import me.libraryaddict.disguise.utils.PacketsManager; +import me.libraryaddict.disguise.utils.DisguiseUtilities; import me.libraryaddict.disguise.utils.ReflectionManager; public class FlagWatcher { @@ -119,7 +119,7 @@ public class FlagWatcher { float newHealth = (Float) value; if (newHealth > 0 && hasDied) { hasDied = false; - PacketsManager.sendSelfDisguise((Player) disguise.getEntity()); + DisguiseUtilities.sendSelfDisguise((Player) disguise.getEntity()); } else if (newHealth <= 0 && !hasDied) { hasDied = true; } diff --git a/src/me/libraryaddict/disguise/utils/DisguiseUtilities.java b/src/me/libraryaddict/disguise/utils/DisguiseUtilities.java index 98b8f516..035ecc90 100644 --- a/src/me/libraryaddict/disguise/utils/DisguiseUtilities.java +++ b/src/me/libraryaddict/disguise/utils/DisguiseUtilities.java @@ -4,21 +4,30 @@ import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; +import me.libraryaddict.disguise.LibsDisguises; import me.libraryaddict.disguise.disguisetypes.Disguise; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.potion.PotionEffect; +import org.bukkit.util.Vector; import com.comphenix.protocol.Packets; import com.comphenix.protocol.ProtocolLibrary; +import com.comphenix.protocol.ProtocolManager; import com.comphenix.protocol.events.PacketContainer; -import com.comphenix.protocol.reflect.StructureModifier; import com.comphenix.protocol.wrappers.WrappedDataWatcher; public class DisguiseUtilities { // Store the entity IDs instead of entitys because then I can disguise entitys even before they exist private static HashMap disguises = new HashMap(); + private static LibsDisguises libsDisguises; // A internal storage of fake entity ID's I can use. // Realistically I could probably use a ID like "4" for everyone, seeing as no one shares the ID private static HashMap selfDisguisesIds = new HashMap(); @@ -31,6 +40,10 @@ public class DisguiseUtilities { return selfDisguisesIds; } + public static void init(LibsDisguises disguises) { + libsDisguises = disguises; + } + /** * @param Resends * the entity to all the watching players, which is where the magic begins @@ -89,14 +102,13 @@ public class DisguiseUtilities { } } catch (Exception ex) { ex.printStackTrace(); - }// Resend entity metadata else he will be invisible to himself until its resent - PacketContainer packetMetadata = new PacketContainer(Packets.Server.ENTITY_METADATA); - StructureModifier mods = packetMetadata.getModifier(); - mods.write(0, player.getEntityId()); - packetMetadata.getWatchableCollectionModifier().write(0, - WrappedDataWatcher.getEntityWatcher(player).getWatchableObjects()); + } + // Resend entity metadata else he will be invisible to himself until its resent try { - ProtocolLibrary.getProtocolManager().sendServerPacket(player, packetMetadata); + ProtocolLibrary.getProtocolManager().sendServerPacket( + player, + ProtocolLibrary.getProtocolManager().createPacketConstructor(Packets.Server.ENTITY_METADATA, player) + .createPacket(player)); } catch (Exception ex) { ex.printStackTrace(); } @@ -104,6 +116,114 @@ public class DisguiseUtilities { } } + /** + * Sends the self disguise to the player + */ + public static void sendSelfDisguise(final Player player) { + try { + Object world = ReflectionManager.getWorld(player.getWorld()); + Object tracker = world.getClass().getField("tracker").get(world); + Object trackedEntities = tracker.getClass().getField("trackedEntities").get(tracker); + Object entityTrackerEntry = trackedEntities.getClass().getMethod("get", int.class) + .invoke(trackedEntities, player.getEntityId()); + if (entityTrackerEntry == null) { + // A check incase the tracker is null. + // If it is, then this method will be run again in one tick. Which is when it should be constructed. + // Else its going to run in a infinite loop hue hue hue.. + Bukkit.getScheduler().scheduleSyncDelayedTask(libsDisguises, new Runnable() { + public void run() { + sendSelfDisguise(player); + } + }); + return; + } + // Add himself to his own entity tracker + ((HashSet) entityTrackerEntry.getClass().getField("trackedPlayers").get(entityTrackerEntry)).add(ReflectionManager + .getNmsEntity(player)); + ProtocolManager manager = ProtocolLibrary.getProtocolManager(); + // Send the player a packet with himself being spawned + manager.sendServerPacket(player, manager.createPacketConstructor(Packets.Server.NAMED_ENTITY_SPAWN, player) + .createPacket(player)); + manager.sendServerPacket( + player, + manager.createPacketConstructor(Packets.Server.ENTITY_METADATA, player.getEntityId(), + WrappedDataWatcher.getEntityWatcher(player), true).createPacket(player.getEntityId(), + WrappedDataWatcher.getEntityWatcher(player), true)); + + boolean isMoving = false; + try { + Field field = ReflectionManager.getNmsClass("EntityTrackerEntry").getDeclaredField("isMoving"); + field.setAccessible(true); + isMoving = field.getBoolean(entityTrackerEntry); + } catch (Exception ex) { + ex.printStackTrace(); + } + // Send the velocity packets + if (isMoving) { + Vector velocity = player.getVelocity(); + manager.sendServerPacket( + player, + manager.createPacketConstructor(Packets.Server.ENTITY_VELOCITY, player.getEntityId(), velocity.getX(), + velocity.getY(), velocity.getZ()).createPacket(player.getEntityId(), velocity.getX(), + velocity.getY(), velocity.getZ())); + } + + // Why the hell would he even need this. Meh. + if (player.getVehicle() != null && player.getEntityId() > player.getVehicle().getEntityId()) { + manager.sendServerPacket(player, + manager.createPacketConstructor(Packets.Server.ATTACH_ENTITY, 0, player, player.getVehicle()) + .createPacket(0, player, player.getVehicle())); + } else if (player.getPassenger() != null && player.getEntityId() > player.getPassenger().getEntityId()) { + manager.sendServerPacket(player, + manager.createPacketConstructor(Packets.Server.ATTACH_ENTITY, 0, player.getPassenger(), player) + .createPacket(0, player.getPassenger(), player)); + } + + // Resend the armor + for (int i = 0; i < 5; i++) { + ItemStack item; + if (i == 0) { + item = player.getItemInHand(); + } else { + item = player.getInventory().getArmorContents()[i - 1]; + } + + if (item != null && item.getType() != Material.AIR) { + manager.sendServerPacket(player, + manager.createPacketConstructor(Packets.Server.ENTITY_EQUIPMENT, player.getEntityId(), i, item) + .createPacket(player.getEntityId(), i, item)); + } + } + Location loc = player.getLocation(); + // If the disguised is sleeping for w/e reason + if (player.isSleeping()) { + manager.sendServerPacket( + player, + manager.createPacketConstructor(Packets.Server.ENTITY_LOCATION_ACTION, player, 0, loc.getBlockX(), + loc.getBlockY(), loc.getBlockZ()).createPacket(player, 0, loc.getBlockX(), loc.getBlockY(), + loc.getBlockZ())); + } + // TODO Fix this cos it doesn't move the disguise? + byte yaw = (byte) (loc.getYaw() * 256.0F / 360.0F); + byte pitch = (byte) (loc.getPitch() * 256.0F / 360.0F); + manager.sendServerPacket( + player, + manager.createPacketConstructor(Packets.Server.ENTITY_LOOK, player.getEntityId(), yaw, pitch).createPacket( + player.getEntityId(), yaw, pitch)); + + // Resend any active potion effects + Iterator iterator = player.getActivePotionEffects().iterator(); + while (iterator.hasNext()) { + PotionEffect potionEffect = (PotionEffect) iterator.next(); + manager.sendServerPacket(player, + manager.createPacketConstructor(Packets.Server.MOB_EFFECT, player.getEntityId(), potionEffect) + .createPacket(player.getEntityId(), potionEffect)); + } + } catch (Exception ex) { + ex.printStackTrace(); + } + } + /** * Setup it so he can see himself when disguised */ @@ -128,7 +248,7 @@ public class DisguiseUtilities { } catch (Exception ex) { ex.printStackTrace(); } - PacketsManager.sendSelfDisguise(player); + sendSelfDisguise(player); if (disguise.isHidingArmorFromSelf() || disguise.isHidingHeldItemFromSelf()) { if (PacketsManager.isInventoryListenerEnabled()) { player.updateInventory(); diff --git a/src/me/libraryaddict/disguise/utils/PacketsManager.java b/src/me/libraryaddict/disguise/utils/PacketsManager.java index 9d0d9f1c..26874601 100644 --- a/src/me/libraryaddict/disguise/utils/PacketsManager.java +++ b/src/me/libraryaddict/disguise/utils/PacketsManager.java @@ -1,9 +1,7 @@ package me.libraryaddict.disguise.utils; -import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; -import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Random; @@ -34,7 +32,6 @@ import org.bukkit.entity.Player; import org.bukkit.entity.Zombie; import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.java.JavaPlugin; -import org.bukkit.potion.PotionEffect; import org.bukkit.util.Vector; import com.comphenix.protocol.Packets; @@ -958,114 +955,6 @@ public class PacketsManager { return viewDisguisesListenerEnabled; } - /** - * Sends the self disguise to the player - */ - public static void sendSelfDisguise(final Player player) { - try { - Object world = ReflectionManager.getWorld(player.getWorld()); - Object tracker = world.getClass().getField("tracker").get(world); - Object trackedEntities = tracker.getClass().getField("trackedEntities").get(tracker); - Object entityTrackerEntry = trackedEntities.getClass().getMethod("get", int.class) - .invoke(trackedEntities, player.getEntityId()); - if (entityTrackerEntry == null) { - // A check incase the tracker is null. - // If it is, then this method will be run again in one tick. Which is when it should be constructed. - // Else its going to run in a infinite loop hue hue hue.. - Bukkit.getScheduler().scheduleSyncDelayedTask(libsDisguises, new Runnable() { - public void run() { - sendSelfDisguise(player); - } - }); - return; - } - // Add himself to his own entity tracker - ((HashSet) entityTrackerEntry.getClass().getField("trackedPlayers").get(entityTrackerEntry)).add(ReflectionManager - .getNmsEntity(player)); - ProtocolManager manager = ProtocolLibrary.getProtocolManager(); - // Send the player a packet with himself being spawned - manager.sendServerPacket(player, manager.createPacketConstructor(Packets.Server.NAMED_ENTITY_SPAWN, player) - .createPacket(player)); - manager.sendServerPacket( - player, - manager.createPacketConstructor(Packets.Server.ENTITY_METADATA, player.getEntityId(), - WrappedDataWatcher.getEntityWatcher(player), true).createPacket(player.getEntityId(), - WrappedDataWatcher.getEntityWatcher(player), true)); - - boolean isMoving = false; - try { - Field field = ReflectionManager.getNmsClass("EntityTrackerEntry").getDeclaredField("isMoving"); - field.setAccessible(true); - isMoving = field.getBoolean(entityTrackerEntry); - } catch (Exception ex) { - ex.printStackTrace(); - } - // Send the velocity packets - if (isMoving) { - Vector velocity = player.getVelocity(); - manager.sendServerPacket( - player, - manager.createPacketConstructor(Packets.Server.ENTITY_VELOCITY, player.getEntityId(), velocity.getX(), - velocity.getY(), velocity.getZ()).createPacket(player.getEntityId(), velocity.getX(), - velocity.getY(), velocity.getZ())); - } - - // Why the hell would he even need this. Meh. - if (player.getVehicle() != null && player.getEntityId() > player.getVehicle().getEntityId()) { - manager.sendServerPacket(player, - manager.createPacketConstructor(Packets.Server.ATTACH_ENTITY, 0, player, player.getVehicle()) - .createPacket(0, player, player.getVehicle())); - } else if (player.getPassenger() != null && player.getEntityId() > player.getPassenger().getEntityId()) { - manager.sendServerPacket(player, - manager.createPacketConstructor(Packets.Server.ATTACH_ENTITY, 0, player.getPassenger(), player) - .createPacket(0, player.getPassenger(), player)); - } - - // Resend the armor - for (int i = 0; i < 5; i++) { - ItemStack item; - if (i == 0) { - item = player.getItemInHand(); - } else { - item = player.getInventory().getArmorContents()[i - 1]; - } - - if (item != null && item.getType() != Material.AIR) { - manager.sendServerPacket(player, - manager.createPacketConstructor(Packets.Server.ENTITY_EQUIPMENT, player.getEntityId(), i, item) - .createPacket(player.getEntityId(), i, item)); - } - } - Location loc = player.getLocation(); - // If the disguised is sleeping for w/e reason - if (player.isSleeping()) { - manager.sendServerPacket( - player, - manager.createPacketConstructor(Packets.Server.ENTITY_LOCATION_ACTION, player, 0, loc.getBlockX(), - loc.getBlockY(), loc.getBlockZ()).createPacket(player, 0, loc.getBlockX(), loc.getBlockY(), - loc.getBlockZ())); - } - // TODO Fix this cos it doesn't move the disguise? - byte yaw = (byte) (loc.getYaw() * 256.0F / 360.0F); - byte pitch = (byte) (loc.getPitch() * 256.0F / 360.0F); - manager.sendServerPacket( - player, - manager.createPacketConstructor(Packets.Server.ENTITY_LOOK, player.getEntityId(), yaw, pitch).createPacket( - player.getEntityId(), yaw, pitch)); - - // Resend any active potion effects - Iterator iterator = player.getActivePotionEffects().iterator(); - while (iterator.hasNext()) { - PotionEffect potionEffect = (PotionEffect) iterator.next(); - manager.sendServerPacket(player, - manager.createPacketConstructor(Packets.Server.MOB_EFFECT, player.getEntityId(), potionEffect) - .createPacket(player.getEntityId(), potionEffect)); - } - } catch (Exception ex) { - ex.printStackTrace(); - } - } - public static void setHearDisguisesListener(boolean enabled) { if (soundsListenerEnabled != enabled) { soundsListenerEnabled = enabled;