From 24b6ed702bcb9f804acf784e400bdb04eb853bf4 Mon Sep 17 00:00:00 2001 From: NavidK0 Date: Mon, 14 Mar 2016 00:55:36 -0400 Subject: [PATCH] Fixed Player disguises Fixed all disguises Fixed issue where players would crash upon joining Fixed issue where disguises would crash when player left and reentered a location where a disguise previously was This is basically a beta build, FIND BUGS FOR ME! :D --- .../libraryaddict/disguise/LibsDisguises.java | 18 ++--- .../disguise/disguisetypes/Disguise.java | 2 +- .../disguisetypes/TargetedDisguise.java | 1 - .../disguise/utilities/DisguiseSound.java | 8 +- .../disguise/utilities/DisguiseUtilities.java | 18 +++-- .../disguise/utilities/PacketsManager.java | 80 +++++++++++-------- .../disguise/utilities/ReflectionManager.java | 59 +++++++++++--- 7 files changed, 120 insertions(+), 66 deletions(-) diff --git a/src/main/java/me/libraryaddict/disguise/LibsDisguises.java b/src/main/java/me/libraryaddict/disguise/LibsDisguises.java index 2bfe8e6e..6fdec2ed 100644 --- a/src/main/java/me/libraryaddict/disguise/LibsDisguises.java +++ b/src/main/java/me/libraryaddict/disguise/LibsDisguises.java @@ -236,15 +236,15 @@ public class LibsDisguises extends JavaPlugin { for (WrappedWatchableObject watch : watcher.getWatchableObjects()) { disguiseValues.setMetaValue(watch.getIndex(), watch.getValue()); // Uncomment when I need to find the new datawatcher values for a class.. - int id = watch.getIndex(); - Object val = watch.getValue(); - Class valClazz = val != null ? watch.getValue().getClass() : null; - try { - val = val.toString(); - } catch (Exception e) { - val = val != null ? val.getClass() : "null"; - } - System.out.println("Disguise: " + disguiseType + ", ID: " + id + ", Class: " + (val == null ? "null" : valClazz) + ", Value: " + val); +// int id = watch.getIndex(); +// Object val = watch.getValue(); +// Class valClazz = val != null ? watch.getValue().getClass() : null; +// try { +// val = val.toString(); +// } catch (Exception e) { +// val = val != null ? val.getClass() : "null"; +// } +// System.out.println("Disguise: " + disguiseType + ", ID: " + id + ", Class: " + (val == null ? "null" : valClazz) + ", Value: " + val); } DisguiseSound sound = DisguiseSound.getType(disguiseType.name()); if (sound != null) { diff --git a/src/main/java/me/libraryaddict/disguise/disguisetypes/Disguise.java b/src/main/java/me/libraryaddict/disguise/disguisetypes/Disguise.java index d9bfc6cc..18baec28 100644 --- a/src/main/java/me/libraryaddict/disguise/disguisetypes/Disguise.java +++ b/src/main/java/me/libraryaddict/disguise/disguisetypes/Disguise.java @@ -508,7 +508,7 @@ public abstract class Disguise { } if (isMiscDisguise() && !DisguiseConfig.isMiscDisguisesForLivingEnabled() && entity instanceof LivingEntity) { throw new RuntimeException( - "Cannot disguise a living entity with a misc disguise. Renable MiscDisguisesForLiving in the config to do this"); + "Cannot disguise a living entity with a misc disguise. Reenable MiscDisguisesForLiving in the config to do this"); } this.entity = entity; setupWatcher(); diff --git a/src/main/java/me/libraryaddict/disguise/disguisetypes/TargetedDisguise.java b/src/main/java/me/libraryaddict/disguise/disguisetypes/TargetedDisguise.java index 02a05d1b..1a21b577 100644 --- a/src/main/java/me/libraryaddict/disguise/disguisetypes/TargetedDisguise.java +++ b/src/main/java/me/libraryaddict/disguise/disguisetypes/TargetedDisguise.java @@ -11,7 +11,6 @@ import java.util.List; public abstract class TargetedDisguise extends Disguise { public enum TargetType { - HIDE_DISGUISE_TO_EVERYONE_BUT_THESE_PLAYERS, SHOW_TO_EVERYONE_BUT_THESE_PLAYERS } diff --git a/src/main/java/me/libraryaddict/disguise/utilities/DisguiseSound.java b/src/main/java/me/libraryaddict/disguise/utilities/DisguiseSound.java index cca56e24..f06a2797 100644 --- a/src/main/java/me/libraryaddict/disguise/utilities/DisguiseSound.java +++ b/src/main/java/me/libraryaddict/disguise/utilities/DisguiseSound.java @@ -10,6 +10,7 @@ import java.util.HashSet; */ public enum DisguiseSound { + //TODO: Sounds need to be updated to reflect new 1.9 sounds... oh god... ARROW(null, null, null, null, "random.bowhit"), BAT("entity.bat.hurt", null, "entity.bat.death", "entity.bat.idle", "damage.fallsmall", "entity.bat.loop", "damage.fallbig", "entity.bat.takeoff"), @@ -25,9 +26,8 @@ public enum DisguiseSound { ELDER_GUARDIAN("entity.guardian.elder.hit", null, "entity.guardian.elder.death", "entity.guardian.elder.death"), ENDER_DRAGON("entity.enderdragon.hit", null, "entity.enderdragon.end", "entity.enderdragon.growl", "damage.fallsmall", "entity.enderdragon.wings", "damage.fallbig"), - //TODO: Fix enderman sounds -// ENDERMAN("entity.endermen.hit", "step.grass", "entity.endermen.death", "entity.endermen.idle", "entity.endermen.scream", -// "entity.endermen.portal", "entity.endermen.stare"), + ENDERMAN("entity.endermen.hit", "step.grass", "entity.endermen.death", "entity.endermen.idle", "entity.endermen.scream", + "entity.endermen.portal", "entity.endermen.stare"), ENDERMITE("entity.silverfish.hit", "entity.silverfish.step", "entity.silverfish.kill", "entity.silverfish.ambient"), GHAST("entity.ghast.scream", null, "entity.ghast.death", "entity.ghast.moan", "damage.fallsmall", "entity.ghast.fireball", "damage.fallbig", "entity.ghast.affectionate_scream", "entity.ghast.charge"), @@ -43,7 +43,7 @@ public enum DisguiseSound { OCELOT("entity.cat.hitt", "step.grass", "entity.cat.hitt", "entity.cat.meow", "entity.cat.purreow", "entity.cat.purr"), PIG("entity.pig.ambient", "entity.pig.step", "entity.pig.death", "entity.pig.ambient"), PIG_ZOMBIE("entity.zombiepig.zpighurt", null, "entity.zombiepig.zpigdeath", "entity.zombiepig.zpig", "entity.zombiepig.zpigangry"), - PLAYER("game.player.hurt", "step.grass", "game.player.hurt", null), + PLAYER("entity.player.hurt", "step.grass", "entity.player.hurt", null), RABBIT("entity.rabbit.hurt", "entity.rabbit.hop", "entity.rabbit.death", "entity.rabbit.idle"), SHEEP("entity.sheep.ambient", "entity.sheep.step", null, "entity.sheep.ambient", "entity.sheep.shear"), SHULKER("entity.shulker.hurt", null, "entity.shulker.death", "entity.shulker.ambient", "entity.shulker.open", diff --git a/src/main/java/me/libraryaddict/disguise/utilities/DisguiseUtilities.java b/src/main/java/me/libraryaddict/disguise/utilities/DisguiseUtilities.java index 2eed3c2f..c514af6b 100644 --- a/src/main/java/me/libraryaddict/disguise/utilities/DisguiseUtilities.java +++ b/src/main/java/me/libraryaddict/disguise/utilities/DisguiseUtilities.java @@ -256,7 +256,7 @@ public class DisguiseUtilities { if (entityTrackerEntry != null) { Set trackedPlayers = (Set) ReflectionManager.getNmsField("EntityTrackerEntry", "trackedPlayers").get(entityTrackerEntry); // If the tracker exists. Remove himself from his tracker - trackedPlayers = new HashSet(trackedPlayers); //Copy before iterating to prevent ConcurrentModificationException + trackedPlayers = (Set) new HashSet(trackedPlayers).clone(); //Copy before iterating to prevent ConcurrentModificationException PacketContainer destroyPacket = new PacketContainer(Server.ENTITY_DESTROY); destroyPacket.getIntegerArrays().write(0, new int[]{disguise.getEntity().getEntityId()}); for (Object p : trackedPlayers) { @@ -435,18 +435,18 @@ public class DisguiseUtilities { } /** - * Get all EntityPlayers who have this entity in their Entity Tracker And they are in the targetted disguise. + * Get all EntityPlayers who have this entity in their Entity Tracker And they are in the targeted disguise. * * @param disguise * @return */ - public static ArrayList getPerverts(Disguise disguise) { - ArrayList players = new ArrayList<>(); + public static List getPerverts(Disguise disguise) { + List players = new ArrayList<>(); try { Object entityTrackerEntry = ReflectionManager.getEntityTrackerEntry(disguise.getEntity()); if (entityTrackerEntry != null) { Set trackedPlayers = (Set) ReflectionManager.getNmsField("EntityTrackerEntry", "trackedPlayers").get(entityTrackerEntry); - trackedPlayers = new HashSet(trackedPlayers); //Copy before iterating to prevent ConcurrentModificationException + trackedPlayers = (Set) new HashSet(trackedPlayers).clone(); //Copy before iterating to prevent ConcurrentModificationException for (Object p : trackedPlayers) { Player player = (Player) ReflectionManager.getBukkitEntity(p); if (((TargetedDisguise) disguise).canSee(player)) { @@ -630,7 +630,7 @@ public class DisguiseUtilities { ReflectionManager.getNmsClass("EntityPlayer")); final Method updatePlayer = ReflectionManager.getNmsMethod("EntityTrackerEntry", "updatePlayer", ReflectionManager.getNmsClass("EntityPlayer")); - trackedPlayers = new HashSet(trackedPlayers); //Copy before iterating to prevent ConcurrentModificationException + trackedPlayers = (Set) new HashSet(trackedPlayers).clone(); //Copy before iterating to prevent ConcurrentModificationException for (final Object p : trackedPlayers) { Player pl = (Player) ReflectionManager.getBukkitEntity(p); if (player.equalsIgnoreCase((pl).getName())) { @@ -672,7 +672,7 @@ public class DisguiseUtilities { ReflectionManager.getNmsClass("EntityPlayer")); final Method updatePlayer = ReflectionManager.getNmsMethod("EntityTrackerEntry", "updatePlayer", ReflectionManager.getNmsClass("EntityPlayer")); - trackedPlayers = new HashSet(trackedPlayers); //Copy before iterating to prevent ConcurrentModificationException + trackedPlayers = (Set) new HashSet(trackedPlayers).clone(); //Copy before iterating to prevent ConcurrentModificationException for (final Object p : trackedPlayers) { Player player = (Player) ReflectionManager.getBukkitEntity(p); if (player != entity) { @@ -725,7 +725,7 @@ public class DisguiseUtilities { Set trackedPlayers = (Set) ReflectionManager.getNmsField("EntityTrackerEntry", "trackedPlayers").get(entityTrackerEntry); final Method clear = ReflectionManager.getNmsMethod("EntityTrackerEntry", "clear", ReflectionManager.getNmsClass("EntityPlayer")); final Method updatePlayer = ReflectionManager.getNmsMethod("EntityTrackerEntry", "updatePlayer", ReflectionManager.getNmsClass("EntityPlayer")); - trackedPlayers = new HashSet(trackedPlayers); //Copy before iterating to prevent ConcurrentModificationException + trackedPlayers = (Set) new HashSet(trackedPlayers).clone(); for (final Object p : trackedPlayers) { Player player = (Player) ReflectionManager.getBukkitEntity(p); if (disguise.getEntity() != player && disguise.canSee(player)) { @@ -785,6 +785,7 @@ public class DisguiseUtilities { t.removeEntry(player.getName()); t.unregister(); } +// player.spigot().setCollidesWithEntities(true); //Finish up // Remove the fake entity ID from the disguise bin selfDisguised.remove(player.getUniqueId()); @@ -1030,6 +1031,7 @@ public class DisguiseUtilities { t.setOption(Option.COLLISION_RULE, OptionStatus.NEVER); t.addEntry(player.getName()); } +// player.spigot().setCollidesWithEntities(false); //Finish up selfDisguised.add(player.getUniqueId()); sendSelfDisguise(player, (TargetedDisguise) disguise); diff --git a/src/main/java/me/libraryaddict/disguise/utilities/PacketsManager.java b/src/main/java/me/libraryaddict/disguise/utilities/PacketsManager.java index 6411dee9..55ee7acc 100644 --- a/src/main/java/me/libraryaddict/disguise/utilities/PacketsManager.java +++ b/src/main/java/me/libraryaddict/disguise/utilities/PacketsManager.java @@ -29,7 +29,6 @@ import me.libraryaddict.disguise.disguisetypes.PlayerDisguise; import me.libraryaddict.disguise.disguisetypes.watchers.LivingWatcher; import me.libraryaddict.disguise.disguisetypes.watchers.PlayerWatcher; import me.libraryaddict.disguise.disguisetypes.watchers.SheepWatcher; -import me.libraryaddict.disguise.disguisetypes.watchers.SlimeWatcher; import me.libraryaddict.disguise.disguisetypes.watchers.WolfWatcher; import me.libraryaddict.disguise.utilities.DisguiseSound.SoundType; import org.bukkit.Art; @@ -45,13 +44,11 @@ import org.bukkit.entity.ExperienceOrb; import org.bukkit.entity.Item; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; -import org.bukkit.entity.Slime; import org.bukkit.entity.Zombie; import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemStack; import org.bukkit.metadata.FixedMetadataValue; -import org.bukkit.potion.PotionEffect; -import org.bukkit.potion.PotionEffectType; +import org.bukkit.util.Vector; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; @@ -207,7 +204,6 @@ public class PacketsManager { mods.write(5, pitch); } else if (disguise.getType().isPlayer()) { //TODO: Make player disguises visible again - spawnPackets[0] = new PacketContainer(Server.NAMED_ENTITY_SPAWN); PlayerDisguise playerDisguise = (PlayerDisguise) disguise; String name = playerDisguise.getSkin() != null ? playerDisguise.getSkin() : playerDisguise.getName(); int entityId = disguisedEntity.getEntityId(); @@ -215,23 +211,25 @@ public class PacketsManager { 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].getSpecificModifier(UUID.class).write(0, gameProfile.getUUID()); //UUID - StructureModifier doubleMods = spawnPackets[0].getDoubles(); - doubleMods.write(0, Math.floor(loc.getX() * 32)); //x - doubleMods.write(1, Math.floor(loc.getY() * 32)); //y - doubleMods.write(2, Math.floor(loc.getZ() * 32)); //z - StructureModifier byteMods = spawnPackets[0].getBytes(); - byteMods.write(0, yaw); //yaw - byteMods.write(1, pitch); //pitch + 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); @@ -266,21 +264,41 @@ public class PacketsManager { delayedPacket.getModifier().write(0, ReflectionManager.getEnumPlayerInfoAction(4)); delayedPackets = new PacketContainer[]{delayedPacket}; } else if (disguise.getType().isMob() || disguise.getType() == DisguiseType.ARMOR_STAND) { - int entityId = disguisedEntity.getEntityId(); - LivingEntity entity = (LivingEntity) disguisedEntity.getWorld().spawnEntity(loc, disguise.getType().getEntityType()); - entity.setVelocity(disguisedEntity.getVelocity()); - if (disguise.getType() == DisguiseType.SLIME || disguise.getType() == DisguiseType.MAGMA_CUBE) { - ((Slime) entity).setSize(((SlimeWatcher) disguise.getWatcher()).getSize()); - } - Object nms = ReflectionManager.getNmsEntity(entity); - PacketContainer packet = ProtocolLibrary.getProtocolManager().createPacketConstructor(Server.SPAWN_ENTITY_LIVING, nms).createPacket(nms).deepClone(); - spawnPackets[0] = packet; - spawnPackets[0].getIntegers().write(0, entityId); - spawnPackets[0].getDataWatcherModifier().write(0, createDataWatcher(WrappedDataWatcher.getEntityWatcher(disguisedEntity), disguise.getWatcher())); - entity.addPotionEffect(new PotionEffect(PotionEffectType.INVISIBILITY, 1, Integer.MAX_VALUE, true, false)); - entity.remove(); + 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()) { - //TODO: Fix falling blocks, BlockPosition Serializer in ProtocolLib int objectId = disguise.getType().getObjectId(); int data = ((MiscDisguise) disguise).getData(); if (disguise.getType() == DisguiseType.FALLING_BLOCK) { @@ -922,7 +940,6 @@ public class PacketsManager { } else if (event.getPacketType() == PacketType.Play.Client.WINDOW_CLICK) { int slot = event.getPacket().getIntegers().read(1); org.bukkit.inventory.ItemStack clickedItem; - //TODO: Check this to make sure it is accurate if (event.getPacket().getShorts().read(0) == 1) { // Its a shift click clickedItem = event.getPacket().getItemModifier().read(0); @@ -1390,7 +1407,6 @@ public class PacketsManager { packets[0] = packets[0].shallowClone(); packets[0].getModifier().write(2, (itemStack.getTypeId() == 0 ? null : ReflectionManager.getNmsItem(itemStack))); } - //TODO: Add left hand here if (disguise.getWatcher().isRightClicking() && slot == EquipmentSlot.HAND) { ItemStack heldItem = packets[0].getItemModifier().read(0); if (heldItem != null && heldItem.getType() != Material.AIR) { @@ -1456,8 +1472,8 @@ public class PacketsManager { mods.write(1, yaw); PacketContainer look = new PacketContainer(Server.ENTITY_LOOK); look.getIntegers().write(0, entity.getEntityId()); - look.getBytes().write(3, yaw); - look.getBytes().write(4, pitch); + look.getBytes().write(0, yaw); + look.getBytes().write(1, pitch); packets = new PacketContainer[]{look, rotation}; } } diff --git a/src/main/java/me/libraryaddict/disguise/utilities/ReflectionManager.java b/src/main/java/me/libraryaddict/disguise/utilities/ReflectionManager.java index 7af6c513..49819cf7 100644 --- a/src/main/java/me/libraryaddict/disguise/utilities/ReflectionManager.java +++ b/src/main/java/me/libraryaddict/disguise/utilities/ReflectionManager.java @@ -6,6 +6,7 @@ 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 org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; import org.bukkit.Art; @@ -90,7 +91,7 @@ public class ReflectionManager { try { Class entityClass = getNmsClass("Entity" + entityName); Object entityObject; - Object world = getWorld(Bukkit.getWorlds().get(0)); + Object world = getWorldServer(Bukkit.getWorlds().get(0)); switch (entityName) { case "Player": Object minecraftServer = getNmsMethod("MinecraftServer", "getServer").invoke(null); @@ -223,12 +224,21 @@ public class ReflectionManager { } public static Object getEntityTrackerEntry(Entity target) throws Exception { - Object world = getWorld(target.getWorld()); + 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); @@ -442,15 +452,6 @@ public class ReflectionManager { return null; } - public static Object getWorld(World world) { - try { - return getCraftClass("CraftWorld").getDeclaredMethod("getHandle").invoke(world); - } catch (Exception e) { - e.printStackTrace(System.out); - } - return null; - } - public static WrappedGameProfile grabProfileAddUUID(String playername) { try { Object minecraftServer = getNmsMethod("MinecraftServer", "getServer").invoke(null); @@ -679,4 +680,40 @@ public class ReflectionManager { 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; + } + + }