17
17
18
18
package com .comphenix .protocol .injector ;
19
19
20
- import java .lang .reflect .Constructor ;
21
20
import java .lang .reflect .Field ;
22
21
import java .lang .reflect .InvocationTargetException ;
23
22
import java .lang .reflect .Method ;
24
23
import java .util .ArrayList ;
25
24
import java .util .Collection ;
26
- import java .util .HashSet ;
27
25
import java .util .List ;
28
26
import java .util .Map ;
29
- import java .util .Set ;
30
27
28
+ import org .apache .commons .lang .Validate ;
31
29
import org .bukkit .World ;
32
30
import org .bukkit .entity .Entity ;
33
31
import org .bukkit .entity .Player ;
@@ -54,62 +52,40 @@ class EntityUtilities {
54
52
private static Method scanPlayersMethod ;
55
53
56
54
/*
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
+
87
65
public static void updateEntity (Entity entity , List <Player > observers ) throws FieldAccessException {
88
66
try {
89
- //EntityTrackerEntry trackEntity = (EntityTrackerEntry) tracker.trackedEntities.get(entity.getEntityId());
90
67
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
+ }
91
71
92
72
if (trackedPlayersField == null ) {
93
- // This one is fairly easy
94
73
trackedPlayersField = FuzzyReflection .fromObject (trackerEntry ).getFieldByType ("java\\ .util\\ ..*" );
95
74
}
96
75
97
76
// Phew, finally there.
98
77
Collection <?> trackedPlayers = getTrackedPlayers (trackedPlayersField , trackerEntry );
99
78
List <Object > nmsPlayers = unwrapBukkit (observers );
100
-
101
- // trackEntity.trackedPlayers.clear();
79
+
102
80
trackedPlayers .removeAll (nmsPlayers );
103
81
104
82
// We have to rely on a NAME once again. Damn it.
105
83
// TODO: Make sure this stays up to date with version changes - 1.8 - 1.10
106
84
if (scanPlayersMethod == null ) {
107
85
scanPlayersMethod = trackerEntry .getClass ().getMethod ("scanPlayers" , List .class );
108
86
}
109
-
110
- //trackEntity.scanPlayers(server.players);
111
- scanPlayersMethod .invoke (trackerEntry , nmsPlayers );
112
-
87
+
88
+ scanPlayersMethod .invoke (trackerEntry , nmsPlayers );
113
89
} catch (IllegalArgumentException e ) {
114
90
throw e ;
115
91
} catch (IllegalAccessException e ) {
@@ -132,8 +108,8 @@ public static void updateEntity(Entity entity, List<Player> observers) throws Fi
132
108
public static List <Player > getEntityTrackers (Entity entity ) {
133
109
try {
134
110
List <Player > result = new ArrayList <Player >();
135
- Object trackerEntry = getEntityTrackerEntry (entity .getWorld (), entity .getEntityId ());
136
111
112
+ Object trackerEntry = getEntityTrackerEntry (entity .getWorld (), entity .getEntityId ());
137
113
if (trackerEntry == null ) {
138
114
throw new IllegalArgumentException ("Cannot find entity trackers for " + entity + (entity .isDead () ? " - entity is dead." : "." ));
139
115
}
@@ -150,15 +126,18 @@ public static List<Player> getEntityTrackers(Entity entity) {
150
126
result .add ((Player ) MinecraftReflection .getBukkitEntity (tracker ));
151
127
}
152
128
}
153
- return result ;
154
129
130
+ return result ;
155
131
} catch (IllegalAccessException e ) {
156
132
throw new FieldAccessException ("Security limitation prevented access to the list of tracked players." , e );
157
133
}
158
134
}
159
135
160
136
// Damn you, Paper
161
137
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
+
162
141
Object value = FieldUtils .readField (field , entry , false );
163
142
164
143
if (value instanceof Collection ) {
@@ -171,13 +150,14 @@ private static Collection<?> getTrackedPlayers(Field field, Object entry) throws
171
150
}
172
151
}
173
152
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
+
181
161
private static Object getEntityTrackerEntry (World world , int entityID ) throws FieldAccessException , IllegalArgumentException {
182
162
BukkitUnwrapper unwrapper = new BukkitUnwrapper ();
183
163
Object worldServer = unwrapper .unwrapItem (world );
@@ -194,29 +174,18 @@ private static Object getEntityTrackerEntry(World world, int entityID) throws Fi
194
174
} catch (IllegalAccessException e ) {
195
175
throw new FieldAccessException ("Cannot access 'tracker' field due to security limitations." , e );
196
176
}
197
-
177
+
178
+ // Looking for an IntHashMap in the tracker entry
198
179
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 ());
213
182
}
214
-
215
- // Read the entity hashmap
183
+
184
+ // Read the map
216
185
Object trackedEntities = null ;
217
186
218
187
try {
219
- trackedEntities = FieldUtils .readField (trackedEntitiesField , tracker , true );
188
+ trackedEntities = FieldUtils .readField (trackedEntitiesField , tracker , false );
220
189
} catch (IllegalAccessException e ) {
221
190
throw new FieldAccessException ("Cannot access 'trackedEntities' field due to security limitations." , e );
222
191
}
@@ -226,7 +195,7 @@ private static Object getEntityTrackerEntry(World world, int entityID) throws Fi
226
195
227
196
/**
228
197
* Retrieve entity from a ID, even it it's newly created.
229
- * @return The asssociated entity.
198
+ * @return The associated entity.
230
199
* @throws FieldAccessException Reflection error.
231
200
*/
232
201
public static Entity getEntityFromID (World world , int entityID ) throws FieldAccessException {
0 commit comments