Skip to content

Commit a88347d

Browse files
committed
Add some more specific error messages for entity tracking
Addresses #229
1 parent 4f404a4 commit a88347d

File tree

1 file changed

+38
-69
lines changed

1 file changed

+38
-69
lines changed

modules/ProtocolLib/src/main/java/com/comphenix/protocol/injector/EntityUtilities.java

Lines changed: 38 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,15 @@
1717

1818
package com.comphenix.protocol.injector;
1919

20-
import java.lang.reflect.Constructor;
2120
import java.lang.reflect.Field;
2221
import java.lang.reflect.InvocationTargetException;
2322
import java.lang.reflect.Method;
2423
import java.util.ArrayList;
2524
import java.util.Collection;
26-
import java.util.HashSet;
2725
import java.util.List;
2826
import java.util.Map;
29-
import java.util.Set;
3027

28+
import org.apache.commons.lang.Validate;
3129
import org.bukkit.World;
3230
import org.bukkit.entity.Entity;
3331
import org.bukkit.entity.Player;
@@ -54,62 +52,40 @@ class EntityUtilities {
5452
private static Method scanPlayersMethod;
5553

5654
/*
57-
* While this function may look pretty bad, it's essentially just a reflection-warped
58-
* version of the following:
59-
*
60-
* @SuppressWarnings("unchecked")
61-
* public static void updateEntity2(Entity entity, List<Player> observers) {
62-
*
63-
* World world = entity.getWorld();
64-
* WorldServer worldServer = ((CraftWorld) world).getHandle();
65-
*
66-
* EntityTracker tracker = worldServer.tracker;
67-
* EntityTrackerEntry entry = (EntityTrackerEntry) tracker.trackedEntities.get(entity.getEntityId());
68-
*
69-
* List<EntityPlayer> nmsPlayers = getNmsPlayers(observers);
70-
*
71-
* entry.trackedPlayers.removeAll(nmsPlayers);
72-
* entry.scanPlayers(nmsPlayers);
73-
* }
74-
*
75-
* private static List<EntityPlayer> getNmsPlayers(List<Player> players) {
76-
* List<EntityPlayer> nsmPlayers = new ArrayList<EntityPlayer>();
77-
*
78-
* for (Player bukkitPlayer : players) {
79-
* CraftPlayer craftPlayer = (CraftPlayer) bukkitPlayer;
80-
* nsmPlayers.add(craftPlayer.getHandle());
81-
* }
82-
*
83-
* return nsmPlayers;
84-
* }
85-
*
86-
*/
55+
public static void updateEntity2(Entity entity, List<Player> observers) {
56+
EntityTrackerEntry entry = getEntityTrackerEntry(entity.getWorld(), entity.getEntityId());
57+
58+
List<EntityPlayer> nmsPlayers = getNmsPlayers(observers);
59+
60+
entry.trackedPlayers.removeAll(nmsPlayers);
61+
entry.scanPlayers(nmsPlayers);
62+
}
63+
*/
64+
8765
public static void updateEntity(Entity entity, List<Player> observers) throws FieldAccessException {
8866
try {
89-
//EntityTrackerEntry trackEntity = (EntityTrackerEntry) tracker.trackedEntities.get(entity.getEntityId());
9067
Object trackerEntry = getEntityTrackerEntry(entity.getWorld(), entity.getEntityId());
68+
if (trackerEntry == null) {
69+
throw new IllegalArgumentException("Cannot find entity trackers for " + entity + (entity.isDead() ? " - entity is dead." : "."));
70+
}
9171

9272
if (trackedPlayersField == null) {
93-
// This one is fairly easy
9473
trackedPlayersField = FuzzyReflection.fromObject(trackerEntry).getFieldByType("java\\.util\\..*");
9574
}
9675

9776
// Phew, finally there.
9877
Collection<?> trackedPlayers = getTrackedPlayers(trackedPlayersField, trackerEntry);
9978
List<Object> nmsPlayers = unwrapBukkit(observers);
100-
101-
// trackEntity.trackedPlayers.clear();
79+
10280
trackedPlayers.removeAll(nmsPlayers);
10381

10482
// We have to rely on a NAME once again. Damn it.
10583
// TODO: Make sure this stays up to date with version changes - 1.8 - 1.10
10684
if (scanPlayersMethod == null) {
10785
scanPlayersMethod = trackerEntry.getClass().getMethod("scanPlayers", List.class);
10886
}
109-
110-
//trackEntity.scanPlayers(server.players);
111-
scanPlayersMethod.invoke(trackerEntry, nmsPlayers);
112-
87+
88+
scanPlayersMethod.invoke(trackerEntry, nmsPlayers);
11389
} catch (IllegalArgumentException e) {
11490
throw e;
11591
} catch (IllegalAccessException e) {
@@ -132,8 +108,8 @@ public static void updateEntity(Entity entity, List<Player> observers) throws Fi
132108
public static List<Player> getEntityTrackers(Entity entity) {
133109
try {
134110
List<Player> result = new ArrayList<Player>();
135-
Object trackerEntry = getEntityTrackerEntry(entity.getWorld(), entity.getEntityId());
136111

112+
Object trackerEntry = getEntityTrackerEntry(entity.getWorld(), entity.getEntityId());
137113
if (trackerEntry == null) {
138114
throw new IllegalArgumentException("Cannot find entity trackers for " + entity + (entity.isDead() ? " - entity is dead." : "."));
139115
}
@@ -150,15 +126,18 @@ public static List<Player> getEntityTrackers(Entity entity) {
150126
result.add((Player) MinecraftReflection.getBukkitEntity(tracker));
151127
}
152128
}
153-
return result;
154129

130+
return result;
155131
} catch (IllegalAccessException e) {
156132
throw new FieldAccessException("Security limitation prevented access to the list of tracked players.", e);
157133
}
158134
}
159135

160136
// Damn you, Paper
161137
private static Collection<?> getTrackedPlayers(Field field, Object entry) throws IllegalAccessException {
138+
Validate.notNull(field, "Cannot find 'trackedPlayers' field.");
139+
Validate.notNull(entry, "entry cannot be null!");
140+
162141
Object value = FieldUtils.readField(field, entry, false);
163142

164143
if (value instanceof Collection) {
@@ -171,13 +150,14 @@ private static Collection<?> getTrackedPlayers(Field field, Object entry) throws
171150
}
172151
}
173152

174-
/**
175-
* Retrieve the entity tracker entry given a ID.
176-
* @param world - world server.
177-
* @param entityID - entity ID.
178-
* @return The entity tracker entry.
179-
* @throws FieldAccessException
180-
*/
153+
/*
154+
private static EntityTrackerEntry getEntityTrackerEntry2(World world, int entityID) {
155+
WorldServer worldServer = ((CraftWorld) world).getHandle();
156+
EntityTracker tracker = worldServer.tracker;
157+
return tracker.trackedEntities.get(entityID);
158+
}
159+
*/
160+
181161
private static Object getEntityTrackerEntry(World world, int entityID) throws FieldAccessException, IllegalArgumentException {
182162
BukkitUnwrapper unwrapper = new BukkitUnwrapper();
183163
Object worldServer = unwrapper.unwrapItem(world);
@@ -194,29 +174,18 @@ private static Object getEntityTrackerEntry(World world, int entityID) throws Fi
194174
} catch (IllegalAccessException e) {
195175
throw new FieldAccessException("Cannot access 'tracker' field due to security limitations.", e);
196176
}
197-
177+
178+
// Looking for an IntHashMap in the tracker entry
198179
if (trackedEntitiesField == null) {
199-
@SuppressWarnings("rawtypes")
200-
Set<Class> ignoredTypes = new HashSet<Class>();
201-
202-
// Well, this is more difficult. But we're looking for a Minecraft object that is not
203-
// created by the constructor(s).
204-
for (Constructor<?> constructor : tracker.getClass().getConstructors()) {
205-
for (Class<?> type : constructor.getParameterTypes()) {
206-
ignoredTypes.add(type);
207-
}
208-
}
209-
210-
// The Minecraft field that's NOT filled in by the constructor
211-
trackedEntitiesField = FuzzyReflection.fromObject(tracker, true).
212-
getFieldByType(MinecraftReflection.getMinecraftObjectRegex(), ignoredTypes);
180+
trackedEntitiesField = FuzzyReflection.fromObject(tracker, false)
181+
.getFieldByType("trackedEntities", MinecraftReflection.getIntHashMapClass());
213182
}
214-
215-
// Read the entity hashmap
183+
184+
// Read the map
216185
Object trackedEntities = null;
217186

218187
try {
219-
trackedEntities = FieldUtils.readField(trackedEntitiesField, tracker, true);
188+
trackedEntities = FieldUtils.readField(trackedEntitiesField, tracker, false);
220189
} catch (IllegalAccessException e) {
221190
throw new FieldAccessException("Cannot access 'trackedEntities' field due to security limitations.", e);
222191
}
@@ -226,7 +195,7 @@ private static Object getEntityTrackerEntry(World world, int entityID) throws Fi
226195

227196
/**
228197
* Retrieve entity from a ID, even it it's newly created.
229-
* @return The asssociated entity.
198+
* @return The associated entity.
230199
* @throws FieldAccessException Reflection error.
231200
*/
232201
public static Entity getEntityFromID(World world, int entityID) throws FieldAccessException {

0 commit comments

Comments
 (0)