diff --git a/src/main/java/net/aufdemrand/denizen/objects/dPlayer.java b/src/main/java/net/aufdemrand/denizen/objects/dPlayer.java index 8481682e75..08b93606c8 100644 --- a/src/main/java/net/aufdemrand/denizen/objects/dPlayer.java +++ b/src/main/java/net/aufdemrand/denizen/objects/dPlayer.java @@ -9,6 +9,7 @@ import net.aufdemrand.denizen.utilities.PlayerProfileEditor; import net.aufdemrand.denizen.utilities.debugging.dB; import net.aufdemrand.denizen.utilities.depends.Depends; +import net.aufdemrand.denizen.utilities.entity.HideEntity; import net.aufdemrand.denizen.utilities.nbt.ImprovedOfflinePlayer; import net.aufdemrand.denizen.utilities.packets.*; import net.aufdemrand.denizencore.objects.*; @@ -2454,10 +2455,10 @@ public void adjust(Mechanism mechanism) { // @name show_entity // @input dEntity // @description - // Shows the player an entity. (Must be a player or player NPC). + // Shows the player an entity. // --> if (mechanism.matches("show_entity") && mechanism.requireObject(dEntity.class)) { - getPlayerEntity().showPlayer((Player) value.asType(dEntity.class).getLivingEntity()); + HideEntity.showEntity(getPlayerEntity(), value.asType(dEntity.class).getBukkitEntity()); } // <--[mechanism] @@ -2465,10 +2466,10 @@ public void adjust(Mechanism mechanism) { // @name hide_entity // @input dEntity // @description - // Hides an entity from the player. (Must be a player or player NPC). + // Hides an entity from the player. // --> if (mechanism.matches("hide_entity") && mechanism.requireObject(dEntity.class)) { - getPlayerEntity().hidePlayer((Player) value.asType(dEntity.class).getLivingEntity()); + HideEntity.hideEntity(getPlayerEntity(), value.asType(dEntity.class).getBukkitEntity()); } // <--[mechanism] diff --git a/src/main/java/net/aufdemrand/denizen/utilities/entity/HideEntity.java b/src/main/java/net/aufdemrand/denizen/utilities/entity/HideEntity.java new file mode 100644 index 0000000000..fee0ff8015 --- /dev/null +++ b/src/main/java/net/aufdemrand/denizen/utilities/entity/HideEntity.java @@ -0,0 +1,70 @@ +package net.aufdemrand.denizen.utilities.entity; + +import net.aufdemrand.denizen.objects.dEntity; +import net.minecraft.server.v1_8_R3.EntityPlayer; +import net.minecraft.server.v1_8_R3.EntityTracker; +import net.minecraft.server.v1_8_R3.EntityTrackerEntry; +import net.minecraft.server.v1_8_R3.WorldServer; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + + +public class HideEntity { + + public static Map> hiddenEntities = new HashMap>(); + + public static void hideEntity(Player player, Entity entity) { + if (dEntity.isPlayer(entity)) { + player.hidePlayer((Player)entity); + } + CraftPlayer craftPlayer = (CraftPlayer)player; + EntityPlayer entityPlayer = craftPlayer.getHandle(); + UUID playerUUID = player.getUniqueId(); + if (entityPlayer.playerConnection != null && !craftPlayer.equals(entity)) { + if (!hiddenEntities.containsKey(playerUUID)) { + hiddenEntities.put(playerUUID, new HashSet()); + } + Set hidden = hiddenEntities.get(playerUUID); + UUID entityUUID = entity.getUniqueId(); + if (!hidden.contains(entityUUID)) { + hidden.add(entityUUID); + EntityTracker tracker = ((WorldServer)craftPlayer.getHandle().world).tracker; + net.minecraft.server.v1_8_R3.Entity other = ((CraftEntity)entity).getHandle(); + EntityTrackerEntry entry = tracker.trackedEntities.get(other.getId()); + if (entry != null) { + entry.clear(entityPlayer); + } + } + } + } + + public static void showEntity(Player player, Entity entity) { + if (dEntity.isPlayer(entity)) { + player.showPlayer((Player)entity); + } + CraftPlayer craftPlayer = (CraftPlayer)player; + EntityPlayer entityPlayer = craftPlayer.getHandle(); + UUID playerUUID = player.getUniqueId(); + if (entityPlayer.playerConnection != null && !craftPlayer.equals(entity) && hiddenEntities.containsKey(playerUUID)) { + Set hidden = hiddenEntities.get(playerUUID); + UUID entityUUID = entity.getUniqueId(); + if (hidden.contains(entityUUID)) { + hidden.remove(entityUUID); + EntityTracker tracker = ((WorldServer)craftPlayer.getHandle().world).tracker; + net.minecraft.server.v1_8_R3.Entity other = ((CraftEntity)entity).getHandle(); + EntityTrackerEntry entry = tracker.trackedEntities.get(other.getId()); + if(entry != null && !entry.trackedPlayers.contains(entityPlayer)) { + entry.updatePlayer(entityPlayer); + } + } + } + } +} diff --git a/src/main/java/net/aufdemrand/denizen/utilities/packets/intercept/PacketOutHandler.java b/src/main/java/net/aufdemrand/denizen/utilities/packets/intercept/PacketOutHandler.java index af7561dc88..cd9ff00b7e 100644 --- a/src/main/java/net/aufdemrand/denizen/utilities/packets/intercept/PacketOutHandler.java +++ b/src/main/java/net/aufdemrand/denizen/utilities/packets/intercept/PacketOutHandler.java @@ -7,6 +7,7 @@ import net.aufdemrand.denizen.utilities.PlayerProfileEditor; import net.aufdemrand.denizen.utilities.debugging.dB; import net.aufdemrand.denizen.utilities.entity.EntityFakePlayer; +import net.aufdemrand.denizen.utilities.entity.HideEntity; import net.aufdemrand.denizen.utilities.packets.PacketHelper; import net.minecraft.server.v1_8_R3.*; import org.bukkit.Bukkit; @@ -66,6 +67,26 @@ public void run() { }, 5); } } + else if (packet instanceof PacketPlayOutSpawnEntity) { + PacketPlayOutSpawnEntity sePacket = (PacketPlayOutSpawnEntity) packet; + int entityId = spawn_entityId.getInt(sePacket); + return entityIsHiding(player, entityId); + } + else if (packet instanceof PacketPlayOutSpawnEntityLiving) { + PacketPlayOutSpawnEntityLiving selPacket = (PacketPlayOutSpawnEntityLiving) packet; + int entityId = spawn_living_entityId.getInt(selPacket); + return entityIsHiding(player, entityId); + } + else if (packet instanceof PacketPlayOutSpawnEntityPainting) { + PacketPlayOutSpawnEntityPainting sepPacket = (PacketPlayOutSpawnEntityPainting) packet; + int entityId = spawn_painting_entityId.getInt(sepPacket); + return entityIsHiding(player, entityId); + } + else if (packet instanceof PacketPlayOutSpawnEntityExperienceOrb) { + PacketPlayOutSpawnEntityExperienceOrb seePacket = (PacketPlayOutSpawnEntityExperienceOrb) packet; + int entityId = spawn_experience_entityId.getInt(seePacket); + return entityIsHiding(player, entityId); + } else if (packet instanceof PacketPlayOutPlayerInfo) { PlayerProfileEditor.updatePlayerProfiles((PacketPlayOutPlayerInfo) packet); } @@ -143,6 +164,24 @@ private static ItemStack removeItemScriptLore(ItemStack itemStack) throws Except return itemStack; } + private static boolean entityIsHiding(EntityPlayer player, int entityId) { + UUID playerUUID = player.getUniqueID(); + if (!HideEntity.hiddenEntities.containsKey(playerUUID)) { + return false; + } + EntityTracker tracker = ((WorldServer) player.world).tracker; + EntityTrackerEntry entry = tracker.trackedEntities.get(entityId); + if (entry == null) { + return false; + } + UUID entityUUID = entry.tracker.getUniqueID(); + if (HideEntity.hiddenEntities.get(playerUUID).contains(entityUUID)) { + entry.clear(player); + return true; + } + return false; + } + ////////////////////////////////// //// Packet Fields @@ -151,6 +190,10 @@ private static ItemStack removeItemScriptLore(ItemStack itemStack) throws Except private static final Field set_slot_windowId, set_slot_slotId, set_slot_itemStack; private static final Field window_items_windowId, window_items_itemStackArray; private static final Field named_spawn_entityId, named_spawn_entityUUID; + private static final Field spawn_entityId; + private static final Field spawn_living_entityId; + private static final Field spawn_painting_entityId; + private static final Field spawn_experience_entityId; private static final Field custom_name, custom_serializer; static { @@ -167,6 +210,18 @@ private static ItemStack removeItemScriptLore(ItemStack itemStack) throws Except named_spawn_entityId = fields.get("a"); named_spawn_entityUUID = fields.get("b"); + fields = PacketHelper.registerFields(PacketPlayOutSpawnEntity.class); + spawn_entityId = fields.get("a"); // Other fields currently irrelevant + + fields = PacketHelper.registerFields(PacketPlayOutSpawnEntityLiving.class); + spawn_living_entityId = fields.get("a"); // Other fields currently irrelevant + + fields = PacketHelper.registerFields(PacketPlayOutSpawnEntityPainting.class); + spawn_painting_entityId = fields.get("a"); // Other fields currently irrelevant + + fields = PacketHelper.registerFields(PacketPlayOutSpawnEntityExperienceOrb.class); + spawn_experience_entityId = fields.get("a"); // Other fields currently irrelevant + fields = PacketHelper.registerFields(PacketPlayOutCustomPayload.class); custom_name = fields.get("a"); custom_serializer = fields.get("b");