diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/ProtocolManager.java b/ProtocolLib/src/main/java/com/comphenix/protocol/ProtocolManager.java
index 3e319249..741c54bc 100644
--- a/ProtocolLib/src/main/java/com/comphenix/protocol/ProtocolManager.java
+++ b/ProtocolLib/src/main/java/com/comphenix/protocol/ProtocolManager.java
@@ -130,7 +130,7 @@ public interface ProtocolManager extends PacketStream {
public PacketConstructor createPacketConstructor(int id, Object... arguments);
/**
- * Completely refresh all clients about an entity.
+ * Completely resend an entity to a list of clients.
*
* Note that this method is NOT thread safe. If you call this method from anything
* but the main thread, it will throw an exception.
@@ -148,6 +148,14 @@ public interface ProtocolManager extends PacketStream {
*/
public Entity getEntityFromID(World container, int id) throws FieldAccessException;
+ /**
+ * Retrieve every client that is receiving information about a given entity.
+ * @param entity - the entity that is being tracked.
+ * @return Every client/player that is tracking the given entity.
+ * @throws FieldAccessException If reflection failed.
+ */
+ public List getEntityTrackers(Entity entity) throws FieldAccessException;
+
/**
* Retrieves a immutable set containing the ID of the sent server packets that will be observed by listeners.
* @return Every filtered server packet.
diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/EntityUtilities.java b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/EntityUtilities.java
index 9671c6ce..ef9c9e8c 100644
--- a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/EntityUtilities.java
+++ b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/EntityUtilities.java
@@ -21,12 +21,14 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import net.minecraft.server.EntityPlayer;
import net.minecraft.server.EntityTrackerEntry;
import org.bukkit.World;
@@ -118,7 +120,39 @@ class EntityUtilities {
} catch (SecurityException e) {
throw new FieldAccessException("Security limitation prevents access to 'scanPlayers' method in trackerEntry.", e);
} catch (NoSuchMethodException e) {
- throw new FieldAccessException("Canot find 'scanPlayers' method. Is ProtocolLib up to date?", e);
+ throw new FieldAccessException("Cannot find 'scanPlayers' method. Is ProtocolLib up to date?", e);
+ }
+ }
+
+ /**
+ * Retrieve every client that is receiving information about a given entity.
+ * @param entity - the entity that is being tracked.
+ * @return Every client/player that is tracking the given entity.
+ * @throws FieldAccessException If reflection failed.
+ */
+ public static List getEntityTrackers(Entity entity) {
+ try {
+ List result = new ArrayList();
+ Object trackerEntry = getEntityTrackerEntry(entity.getWorld(), entity.getEntityId());
+
+ if (trackedPlayersField == null)
+ trackedPlayersField = FuzzyReflection.fromObject(trackerEntry).getFieldByType("java\\.util\\..*");
+
+ Collection> trackedPlayers = (Collection>) FieldUtils.readField(trackedPlayersField, trackerEntry, false);
+
+ // Wrap every player - we also ensure that the underlying tracker list is immutable
+ for (Object tracker : trackedPlayers) {
+ if (tracker instanceof EntityPlayer) {
+ EntityPlayer nmsPlayer = (EntityPlayer) tracker;
+ result.add(nmsPlayer.getBukkitEntity());
+ }
+ }
+ return result;
+
+ } catch (IllegalAccessException e) {
+ throw new FieldAccessException("Security limitation prevented access to the list of tracked players.", e);
+ } catch (InvocationTargetException e) {
+ throw new FieldAccessException("Exception occurred in Minecraft.", e);
}
}
diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/PacketFilterManager.java b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/PacketFilterManager.java
index a8706e90..663b4c09 100644
--- a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/PacketFilterManager.java
+++ b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/PacketFilterManager.java
@@ -55,6 +55,7 @@ import com.comphenix.protocol.events.*;
import com.comphenix.protocol.injector.player.PlayerInjectionHandler;
import com.comphenix.protocol.reflect.FieldAccessException;
import com.comphenix.protocol.reflect.FuzzyReflection;
+import com.comphenix.protocol.wrappers.BukkitConverters;
import com.google.common.base.Objects;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableSet;
@@ -571,6 +572,11 @@ public final class PacketFilterManager implements ProtocolManager, ListenerInvok
return EntityUtilities.getEntityFromID(container, id);
}
+ @Override
+ public List getEntityTrackers(Entity entity) throws FieldAccessException {
+ return EntityUtilities.getEntityTrackers(entity);
+ }
+
/**
* Initialize the packet injection for every player.
* @param players - list of players to inject.