diff --git a/src/me/libraryaddict/disguise/DisguiseAPI.java b/src/me/libraryaddict/disguise/DisguiseAPI.java index 90358359..e9295c1a 100644 --- a/src/me/libraryaddict/disguise/DisguiseAPI.java +++ b/src/me/libraryaddict/disguise/DisguiseAPI.java @@ -28,37 +28,6 @@ public class DisguiseAPI { return hearSelfDisguise; } - public static void disguiseToPlayers(Entity entity, Disguise disguise, List players) { - ((TargetedDisguise) disguise).setTargetType(TargetType.HIDE_DISGUISE_TO_EVERYONE_BUT_THESE_PLAYERS); - ((TargetedDisguise) disguise).getObservers().addAll(players); - disguiseEntity(entity, disguise); - } - - public static void disguiseToEveryoneButThese(Entity entity, Disguise disguise, List players) { - ((TargetedDisguise) disguise).setTargetType(TargetType.SHOW_TO_EVERYONE_BUT_THESE_PLAYERS); - ((TargetedDisguise) disguise).getObservers().addAll(players); - disguiseEntity(entity, disguise); - } - - /** - * Disguise the next entity to spawn with this disguise. This may not work however if the entity doesn't actually spawn. - */ - public static void disguiseNextEntity(Disguise disguise) { - if (disguise == null) - return; - if (disguise.getEntity() != null || DisguiseUtilities.getDisguises().containsValue(disguise)) { - disguise = disguise.clone(); - } - try { - Field field = ReflectionManager.getNmsClass("Entity").getDeclaredField("entityCount"); - field.setAccessible(true); - int id = field.getInt(null); - DisguiseUtilities.addDisguise(id, (TargetedDisguise) disguise); - } catch (Exception ex) { - ex.printStackTrace(); - } - } - private static void disguiseEntity(Entity entity, Disguise disguise) { // If they are trying to disguise a null entity or use a null disguise // Just return. @@ -90,6 +59,33 @@ public class DisguiseAPI { DisguiseUtilities.setupFakeDisguise(disguise); } + public static void disguiseIgnorePlayers(Entity entity, Disguise disguise, List players) { + ((TargetedDisguise) disguise).setTargetType(TargetType.SHOW_TO_EVERYONE_BUT_THESE_PLAYERS); + for (String name : players) { + ((TargetedDisguise) disguise).setViewDisguise(name); + } + disguiseEntity(entity, disguise); + } + + /** + * Disguise the next entity to spawn with this disguise. This may not work however if the entity doesn't actually spawn. + */ + public static void disguiseNextEntity(Disguise disguise) { + if (disguise == null) + return; + if (disguise.getEntity() != null || DisguiseUtilities.getDisguises().containsValue(disguise)) { + disguise = disguise.clone(); + } + try { + Field field = ReflectionManager.getNmsClass("Entity").getDeclaredField("entityCount"); + field.setAccessible(true); + int id = field.getInt(null); + DisguiseUtilities.addDisguise(id, (TargetedDisguise) disguise); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + /** * Disguise this entity with this disguise */ @@ -101,6 +97,14 @@ public class DisguiseAPI { disguiseEntity(entity, disguise); } + public static void disguiseToPlayers(Entity entity, Disguise disguise, List players) { + ((TargetedDisguise) disguise).setTargetType(TargetType.HIDE_DISGUISE_TO_EVERYONE_BUT_THESE_PLAYERS); + for (String name : players) { + ((TargetedDisguise) disguise).setViewDisguise(name); + } + disguiseEntity(entity, disguise); + } + /** * Get the disguise of a entity */ @@ -111,15 +115,6 @@ public class DisguiseAPI { return DisguiseUtilities.getDisguise(disguised.getEntityId()); } - /** - * Get the disguises of a entity - */ - public static Disguise[] getDisguises(Entity disguised) { - if (disguised == null) - return null; - return DisguiseUtilities.getDisguises(disguised.getEntityId()); - } - /** * Get the disguise of a entity */ @@ -129,6 +124,15 @@ public class DisguiseAPI { return DisguiseUtilities.getDisguise(observer, disguised.getEntityId()); } + /** + * Get the disguises of a entity + */ + public static Disguise[] getDisguises(Entity disguised) { + if (disguised == null) + return null; + return DisguiseUtilities.getDisguises(disguised.getEntityId()); + } + /** * Get the ID of a fake disguise for a entityplayer */ @@ -146,10 +150,6 @@ public class DisguiseAPI { return getDisguise(disguised) != null; } - public static boolean isDisguiseInUse(Disguise disguise) { - return DisguiseUtilities.isDisguiseInUse(disguise); - } - /** * Is this entity disguised */ @@ -157,6 +157,10 @@ public class DisguiseAPI { return getDisguise(observer, disguised) != null; } + public static boolean isDisguiseInUse(Disguise disguise) { + return DisguiseUtilities.isDisguiseInUse(disguise); + } + public static boolean isEntityAnimationsAdded() { return isEntityAnimationsAdded; } diff --git a/src/me/libraryaddict/disguise/disguisetypes/MiscDisguise.java b/src/me/libraryaddict/disguise/disguisetypes/MiscDisguise.java index fa5a647d..d8df35fd 100644 --- a/src/me/libraryaddict/disguise/disguisetypes/MiscDisguise.java +++ b/src/me/libraryaddict/disguise/disguisetypes/MiscDisguise.java @@ -29,10 +29,6 @@ public class MiscDisguise extends TargetedDisguise { || disguiseType == DisguiseType.DROPPED_ITEM ? -1 : addictionalData)); } - public boolean isMiscDisguise() { - return true; - } - public MiscDisguise(DisguiseType disguiseType, boolean replaceSounds, int id, int data) { createDisguise(disguiseType, replaceSounds); switch (disguiseType) { @@ -145,4 +141,8 @@ public class MiscDisguise extends TargetedDisguise { return id; } + public boolean isMiscDisguise() { + return true; + } + } \ No newline at end of file diff --git a/src/me/libraryaddict/disguise/disguisetypes/MobDisguise.java b/src/me/libraryaddict/disguise/disguisetypes/MobDisguise.java index 1afa9991..c8519478 100644 --- a/src/me/libraryaddict/disguise/disguisetypes/MobDisguise.java +++ b/src/me/libraryaddict/disguise/disguisetypes/MobDisguise.java @@ -23,16 +23,12 @@ public class MobDisguise extends TargetedDisguise { } - public boolean isMobDisguise() { - return true; - } - - @Deprecated public MobDisguise(EntityType entityType) { this(entityType, true); } + @Deprecated public MobDisguise(EntityType entityType, boolean isAdult) { this(entityType, isAdult, true); @@ -74,4 +70,8 @@ public class MobDisguise extends TargetedDisguise { } return isAdult; } + + public boolean isMobDisguise() { + return true; + } } \ No newline at end of file diff --git a/src/me/libraryaddict/disguise/disguisetypes/PlayerDisguise.java b/src/me/libraryaddict/disguise/disguisetypes/PlayerDisguise.java index 0647d3e5..f3dd8db8 100644 --- a/src/me/libraryaddict/disguise/disguisetypes/PlayerDisguise.java +++ b/src/me/libraryaddict/disguise/disguisetypes/PlayerDisguise.java @@ -14,11 +14,6 @@ public class PlayerDisguise extends TargetedDisguise { createDisguise(DisguiseType.PLAYER, replaceSounds); } - @Override - public boolean isPlayerDisguise() { - return true; - } - @Override public PlayerDisguise clone() { PlayerDisguise disguise = new PlayerDisguise(getName(), isSoundsReplaced()); @@ -35,4 +30,9 @@ public class PlayerDisguise extends TargetedDisguise { return playerName; } + @Override + public boolean isPlayerDisguise() { + return true; + } + } \ No newline at end of file diff --git a/src/me/libraryaddict/disguise/disguisetypes/TargetedDisguise.java b/src/me/libraryaddict/disguise/disguisetypes/TargetedDisguise.java index a38a9269..b4c8c573 100644 --- a/src/me/libraryaddict/disguise/disguisetypes/TargetedDisguise.java +++ b/src/me/libraryaddict/disguise/disguisetypes/TargetedDisguise.java @@ -2,9 +2,9 @@ package me.libraryaddict.disguise.disguisetypes; import java.util.ArrayList; import java.util.Collections; -import java.util.HashSet; import java.util.List; +import me.libraryaddict.disguise.DisguiseAPI; import me.libraryaddict.disguise.utilities.DisguiseUtilities; import org.bukkit.entity.Player; @@ -14,6 +14,31 @@ public abstract class TargetedDisguise extends Disguise { HIDE_DISGUISE_TO_EVERYONE_BUT_THESE_PLAYERS, SHOW_TO_EVERYONE_BUT_THESE_PLAYERS; } + private List disguiseViewers = new ArrayList(); + + private TargetType targetType = TargetType.SHOW_TO_EVERYONE_BUT_THESE_PLAYERS; + public boolean canSee(Player player) { + return canSee(player.getName()); + } + + public boolean canSee(String playername) { + boolean hasPlayer = disguiseViewers.contains(playername); + if (targetType == TargetType.SHOW_TO_EVERYONE_BUT_THESE_PLAYERS) { + System.out.print(playername + " can see 1: " + !hasPlayer); + return !hasPlayer; + } + System.out.print(playername + " can see 2: " + hasPlayer); + return hasPlayer; + } + + public List getObservers() { + return Collections.unmodifiableList(disguiseViewers); + } + + public TargetType getTargetType() { + return targetType; + } + public void setTargetType(TargetType newTargetType) { if (DisguiseUtilities.isDisguiseInUse(this)) { throw new RuntimeException("Cannot set the disguise target after the entity has been disguised"); @@ -21,40 +46,23 @@ public abstract class TargetedDisguise extends Disguise { targetType = newTargetType; } - private List disguiseViewers = new ArrayList(); - private TargetType targetType = TargetType.SHOW_TO_EVERYONE_BUT_THESE_PLAYERS; - - public boolean canSee(Player player) { - return canSee(player.getName()); - } - - public List getObservers() { - return Collections.unmodifiableList(disguiseViewers); - } - - public boolean canSee(String playername) { - boolean contains = disguiseViewers.contains(playername); - if (targetType == TargetType.SHOW_TO_EVERYONE_BUT_THESE_PLAYERS) { - return !contains; - } - return contains; - } - public void setViewDisguise(String playername) { if (!disguiseViewers.contains(playername)) { disguiseViewers.add(playername); - DisguiseUtilities.checkConflicts(this, playername); + if (DisguiseAPI.isDisguiseInUse(this)) { + DisguiseUtilities.checkConflicts(this, playername); + DisguiseUtilities.refreshTracker(this, playername); + } } } public void unsetViewDisguise(String playername) { if (disguiseViewers.contains(playername)) { disguiseViewers.remove(playername); - DisguiseUtilities.checkConflicts(this, playername); + if (DisguiseAPI.isDisguiseInUse(this)) { + DisguiseUtilities.checkConflicts(this, playername); + DisguiseUtilities.refreshTracker(this, playername); + } } } - - public TargetType getTargetType() { - return targetType; - } } diff --git a/src/me/libraryaddict/disguise/utilities/DisguiseUtilities.java b/src/me/libraryaddict/disguise/utilities/DisguiseUtilities.java index ab842dc9..2ee10ec6 100644 --- a/src/me/libraryaddict/disguise/utilities/DisguiseUtilities.java +++ b/src/me/libraryaddict/disguise/utilities/DisguiseUtilities.java @@ -2,6 +2,7 @@ package me.libraryaddict.disguise.utilities; import java.lang.reflect.Field; import java.lang.reflect.Method; +import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -28,17 +29,134 @@ import com.comphenix.protocol.events.PacketContainer; 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> targetedDisguises = 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(); + // Store the entity IDs instead of entitys because then I can disguise entitys even before they exist + private static HashMap> targetedDisguises = new HashMap>(); + + public static void addDisguise(int entityId, TargetedDisguise disguise) { + // TODO Make sure that the disguised entity doesn't have the player looking at other girls + // ^ Done? + if (!getDisguises().containsKey(entityId)) { + getDisguises().put(entityId, new HashSet()); + } + getDisguises().get(entityId).add(disguise); + checkConflicts(disguise, null); + } + + /** + * If name isn't null. Make sure that the name doesn't see any other disguise. Else if name is null. Make sure that the + * observers in the disguise don't see any other disguise. + */ + public static void checkConflicts(TargetedDisguise disguise, String name) { + if (DisguiseAPI.isDisguiseInUse(disguise)) { + Iterator disguiseItel = getDisguises().get(disguise.getEntity().getEntityId()).iterator(); + while (disguiseItel.hasNext()) { + TargetedDisguise d = disguiseItel.next(); + if (d != disguise) { + if (d.getTargetType() == TargetType.HIDE_DISGUISE_TO_EVERYONE_BUT_THESE_PLAYERS) { + // If player is a observer in the loop + if (disguise.getTargetType() == TargetType.HIDE_DISGUISE_TO_EVERYONE_BUT_THESE_PLAYERS) { + // If player is a observer in the disguise + // Remove them from the loop + if (name != null) { + d.unsetViewDisguise(name); + } else { + for (String playername : disguise.getObservers()) { + d.unsetViewDisguise(playername); + } + } + } else if (disguise.getTargetType() == TargetType.SHOW_TO_EVERYONE_BUT_THESE_PLAYERS) { + // If player is not a observer in the loop + if (name != null) { + if (!disguise.getObservers().contains(name)) { + d.unsetViewDisguise(name); + } + } else { + for (String playername : new ArrayList(d.getObservers())) { + if (!disguise.getObservers().contains(playername)) { + d.unsetViewDisguise(playername); + } + } + } + } + } else if (d.getTargetType() == TargetType.SHOW_TO_EVERYONE_BUT_THESE_PLAYERS) { + // Here you add it to the loop if they see the disguise + if (disguise.getTargetType() == TargetType.HIDE_DISGUISE_TO_EVERYONE_BUT_THESE_PLAYERS) { + // Everyone who is in the disguise needs to be added to the loop + if (name != null) { + d.setViewDisguise(name); + } else { + for (String playername : disguise.getObservers()) { + d.setViewDisguise(playername); + } + } + } else if (disguise.getTargetType() == TargetType.SHOW_TO_EVERYONE_BUT_THESE_PLAYERS) { + // This here is a paradox. + // If fed a name. I can do this. + // But the rest of the time.. Its going to conflict. + System.out.print("Cannot set more than one " + TargetType.SHOW_TO_EVERYONE_BUT_THESE_PLAYERS + + " on a entity. Removed the old disguise."); + disguiseItel.remove(); + /* if (name != null) { + if (!disguise.getObservers().contains(name)) { + d.setViewDisguise(name); + } + } else { + for (String playername : d.getObservers()) { + if (!disguise.getObservers().contains(playername)) { + d.setViewDisguise(playername); + } + } + }*/ + } + } + } + } + } + } + + @Deprecated + public static TargetedDisguise getDisguise(int entityId) { + TargetedDisguise toReturn = null; + if (getDisguises().containsKey(entityId)) { + for (TargetedDisguise disguise : getDisguises().get(entityId)) { + if (disguise.getTargetType() == TargetType.SHOW_TO_EVERYONE_BUT_THESE_PLAYERS + && disguise.getObservers().isEmpty()) { + return disguise; + } + if (toReturn == null) { + toReturn = disguise; + } + } + } + return toReturn; + } + + public static TargetedDisguise getDisguise(Player observer, int entityId) { + if (getDisguises().containsKey(entityId)) { + for (TargetedDisguise disguise : getDisguises().get(entityId)) { + if (disguise.canSee(observer)) { + return disguise; + } + } + } + return null; + } public static HashMap> getDisguises() { return targetedDisguises; } + public static TargetedDisguise[] getDisguises(int entityId) { + if (getDisguises().containsKey(entityId)) { + return getDisguises().get(entityId).toArray(new TargetedDisguise[getDisguises().get(entityId).size()]); + } + return new TargetedDisguise[0]; + } + public static HashMap getSelfDisguisesIds() { return selfDisguisesIds; } @@ -55,6 +173,36 @@ public class DisguiseUtilities { return false; } + /** + * @param Resends + * the entity to all the watching players, which is where the magic begins + */ + public static void refreshTracker(TargetedDisguise disguise, String player) { + try { + Object world = ReflectionManager.getWorld(disguise.getEntity().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, disguise.getEntity().getEntityId()); + if (entityTrackerEntry != null) { + HashSet trackedPlayers = (HashSet) entityTrackerEntry.getClass().getField("trackedPlayers") + .get(entityTrackerEntry); + Method clear = entityTrackerEntry.getClass().getMethod("clear", ReflectionManager.getNmsClass("EntityPlayer")); + Method updatePlayer = entityTrackerEntry.getClass().getMethod("updatePlayer", + ReflectionManager.getNmsClass("EntityPlayer")); + HashSet cloned = (HashSet) trackedPlayers.clone(); + for (Object p : cloned) { + if (player.equals(((Player) ReflectionManager.getBukkitEntity(p)).getName())) { + clear.invoke(entityTrackerEntry, p); + updatePlayer.invoke(entityTrackerEntry, p); + } + } + } + } catch (Exception ex) { + ex.printStackTrace(); + } + } + /** * @param Resends * the entity to all the watching players, which is where the magic begins @@ -89,6 +237,17 @@ public class DisguiseUtilities { } } + public static boolean removeDisguise(TargetedDisguise disguise) { + int entityId = disguise.getEntity().getEntityId(); + if (getDisguises().containsKey(entityId) && getDisguises().get(entityId).remove(disguise)) { + if (getDisguises().get(entityId).isEmpty()) { + getDisguises().remove(entityId); + } + return true; + } + return false; + } + public static void removeSelfDisguise(Player player) { if (selfDisguisesIds.containsKey(player.getEntityId())) { // Send a packet to destroy the fake entity @@ -237,134 +396,6 @@ public class DisguiseUtilities { } } - public static void addDisguise(int entityId, TargetedDisguise disguise) { - // TODO Make sure that the disguised entity doesn't have the player looking at other girls - // ^ Done? - if (!getDisguises().containsKey(entityId)) { - getDisguises().put(entityId, new HashSet()); - } - getDisguises().get(entityId).add(disguise); - checkConflicts(disguise, null); - } - - /** - * If name isn't null. Make sure that the name doesn't see any other disguise. Else if name is null. Make sure that the - * observers in the disguise don't see any other disguise. - */ - public static void checkConflicts(TargetedDisguise disguise, String name) { - if (DisguiseAPI.isDisguiseInUse(disguise)) { - Iterator disguiseItel = getDisguises().get(disguise.getEntity().getEntityId()).iterator(); - while (disguiseItel.hasNext()) { - TargetedDisguise d = disguiseItel.next(); - if (d != disguise) { - if (d.getTargetType() == TargetType.HIDE_DISGUISE_TO_EVERYONE_BUT_THESE_PLAYERS) { - // If player is a observer in the loop - if (disguise.getTargetType() == TargetType.HIDE_DISGUISE_TO_EVERYONE_BUT_THESE_PLAYERS) { - // If player is a observer in the disguise - // Remove them from the loop - if (name != null) { - d.unsetViewDisguise(name); - } else { - for (String playername : disguise.getObservers()) { - d.unsetViewDisguise(playername); - } - } - } else if (disguise.getTargetType() == TargetType.SHOW_TO_EVERYONE_BUT_THESE_PLAYERS) { - // If player is not a observer in the loop - if (name != null) { - if (!disguise.getObservers().contains(name)) { - d.unsetViewDisguise(name); - } - } else { - for (String playername : d.getObservers()) { - if (!disguise.getObservers().contains(playername)) { - d.unsetViewDisguise(playername); - } - } - } - } - } else if (d.getTargetType() == TargetType.SHOW_TO_EVERYONE_BUT_THESE_PLAYERS) { - // Here you add it to the loop if they see the disguise - if (disguise.getTargetType() == TargetType.HIDE_DISGUISE_TO_EVERYONE_BUT_THESE_PLAYERS) { - // Everyone who is in the disguise needs to be added to the loop - if (name != null) { - d.setViewDisguise(name); - } else { - for (String playername : disguise.getObservers()) { - d.setViewDisguise(playername); - } - } - } else if (disguise.getTargetType() == TargetType.SHOW_TO_EVERYONE_BUT_THESE_PLAYERS) { - // This here is a paradox. - // If fed a name. I can do this. - // But the rest of the time.. Its going to conflict. - System.out.print("Cannot set more than one " + TargetType.SHOW_TO_EVERYONE_BUT_THESE_PLAYERS - + " on a entity. Removed the old disguise."); - disguiseItel.remove(); - /* if (name != null) { - if (!disguise.getObservers().contains(name)) { - d.setViewDisguise(name); - } - } else { - for (String playername : d.getObservers()) { - if (!disguise.getObservers().contains(playername)) { - d.setViewDisguise(playername); - } - } - }*/ - } - } - } - } - } - } - - public static boolean removeDisguise(TargetedDisguise disguise) { - int entityId = disguise.getEntity().getEntityId(); - if (getDisguises().containsKey(entityId) && getDisguises().get(entityId).remove(disguise)) { - if (getDisguises().get(entityId).isEmpty()) { - getDisguises().remove(entityId); - } - return true; - } - return false; - } - - @Deprecated - public static TargetedDisguise getDisguise(int entityId) { - TargetedDisguise toReturn = null; - if (getDisguises().containsKey(entityId)) { - for (TargetedDisguise disguise : getDisguises().get(entityId)) { - if (disguise.getTargetType() == TargetType.SHOW_TO_EVERYONE_BUT_THESE_PLAYERS - && disguise.getObservers().isEmpty()) { - return disguise; - } - if (toReturn == null) { - toReturn = disguise; - } - } - } - return toReturn; - } - - public static TargetedDisguise[] getDisguises(int entityId) { - if (getDisguises().containsKey(entityId)) { - return getDisguises().get(entityId).toArray(new TargetedDisguise[getDisguises().get(entityId).size()]); - } - return new TargetedDisguise[0]; - } - - public static TargetedDisguise getDisguise(Player observer, int entityId) { - if (getDisguises().containsKey(entityId)) { - for (TargetedDisguise disguise : getDisguises().get(entityId)) { - if (disguise.canSee(observer)) { - return disguise; - } - } - } - return null; - } - /** * Setup it so he can see himself when disguised */ @@ -372,14 +403,20 @@ public class DisguiseUtilities { Entity e = disguise.getEntity(); // If the disguises entity is null, or the disguised entity isn't a player return if (e == null || !(e instanceof Player) || !getDisguises().containsKey(e.getEntityId()) - || !getDisguises().get(e.getEntityId()).contains(disguise)) + || !getDisguises().get(e.getEntityId()).contains(disguise)) { return; + } Player player = (Player) e; + // Check if he can even see this.. + if (!((TargetedDisguise) disguise).canSee(player)) { + return; + } // Remove the old disguise, else we have weird disguises around the place DisguiseUtilities.removeSelfDisguise(player); // If the disguised player can't see himself. Return - if (!disguise.isSelfDisguiseVisible() || !PacketsManager.isViewDisguisesListenerEnabled() || player.getVehicle() != null) + if (!disguise.isSelfDisguiseVisible() || !PacketsManager.isViewDisguisesListenerEnabled() || player.getVehicle() != null) { return; + } try { // Grab the entity ID the fake disguise will use Field field = ReflectionManager.getNmsClass("Entity").getDeclaredField("entityCount");