19
19
20
20
import java .util .ArrayList ;
21
21
import java .util .Collection ;
22
+ import java .util .HashMap ;
22
23
import java .util .List ;
23
24
import java .util .Map ;
24
25
41
42
42
43
/**
43
44
* Used to perform certain operations on entities.
44
- *
45
+ *
45
46
* @author Kristian
46
47
*/
47
48
class EntityUtilities {
48
49
private static final boolean NEW_TRACKER = MinecraftVersion .atOrAbove (MinecraftVersion .VILLAGE_UPDATE );
49
50
private static final EntityUtilities INSTANCE = new EntityUtilities ();
50
-
51
+
51
52
public static EntityUtilities getInstance () {
52
53
return INSTANCE ;
53
54
}
@@ -58,8 +59,8 @@ private EntityUtilities() { }
58
59
private FieldAccessor trackedEntitiesField ;
59
60
private FieldAccessor trackedPlayersField ;
60
61
private FieldAccessor trackerField ;
61
-
62
- private MethodAccessor scanPlayersMethod ;
62
+
63
+ private Map < Class <?>, MethodAccessor > scanPlayersMethods = new HashMap <>() ;
63
64
64
65
public void updateEntity (Entity entity , List <Player > observers ) {
65
66
if (entity == null || !entity .isValid ()) {
@@ -73,11 +74,8 @@ public void updateEntity(Entity entity, List<Player> observers) {
73
74
74
75
Object trackerEntry = getEntityTrackerEntry (entity .getWorld (), entity .getEntityId ());
75
76
76
- if (scanPlayersMethod == null ) {
77
- scanPlayersMethod = findScanPlayers (trackerEntry .getClass ());
78
- }
79
-
80
- scanPlayersMethod .invoke (trackerEntry , nmsPlayers );
77
+ // there can be multiple different entity tracker entry impls, see GH-732....
78
+ scanPlayersMethods .computeIfAbsent (trackerEntry .getClass (), this ::findScanPlayers ).invoke (trackerEntry , nmsPlayers );
81
79
}
82
80
83
81
private MethodAccessor findScanPlayers (Class <?> trackerClass ) {
@@ -138,7 +136,7 @@ private Collection<?> getTrackedPlayers(Entity entity) {
138
136
throw new IllegalStateException ("trackedPlayers field was an unknown type: expected Collection or Map, but got " + value .getClass ());
139
137
}
140
138
}
141
-
139
+
142
140
private MethodAccessor getChunkProvider ;
143
141
private FieldAccessor chunkMapField ;
144
142
@@ -150,7 +148,7 @@ private Object getNewEntityTracker(Object worldServer, int entityId) {
150
148
FuzzyReflection .fromClass (worldServer .getClass (), false ).getMethod (
151
149
FuzzyMethodContract .newBuilder ().parameterCount (0 ).returnTypeExact (chunkProviderClass ).build ()));
152
150
}
153
-
151
+
154
152
Object chunkProvider = getChunkProvider .invoke (worldServer );
155
153
156
154
if (chunkMapField == null ) {
@@ -159,7 +157,7 @@ private Object getNewEntityTracker(Object worldServer, int entityId) {
159
157
FuzzyReflection .fromClass (chunkProvider .getClass (), false ).getField (
160
158
FuzzyFieldContract .newBuilder ().typeExact (chunkMapClass ).build ()));
161
159
}
162
-
160
+
163
161
Object playerChunkMap = chunkMapField .get (chunkProvider );
164
162
165
163
if (trackedEntitiesField == null ) {
@@ -183,7 +181,7 @@ private Object getEntityTrackerEntry(World world, int entityID) {
183
181
if (entityTrackerField == null )
184
182
entityTrackerField = Accessors .getFieldAccessor (FuzzyReflection .fromObject (worldServer ).
185
183
getFieldByType ("tracker" , MinecraftReflection .getEntityTrackerClass ()));
186
-
184
+
187
185
// Get the tracker
188
186
Object tracker = entityTrackerField .get (worldServer );
189
187
@@ -236,17 +234,17 @@ public Entity getEntityFromID(World world, int entityID) {
236
234
private List <Object > unwrapBukkit (List <Player > players ) {
237
235
List <Object > output = Lists .newArrayList ();
238
236
BukkitUnwrapper unwrapper = new BukkitUnwrapper ();
239
-
237
+
240
238
// Get the NMS equivalent
241
239
for (Player player : players ) {
242
240
Object result = unwrapper .unwrapItem (player );
243
-
241
+
244
242
if (result != null )
245
243
output .add (result );
246
244
else
247
245
throw new IllegalArgumentException ("Cannot unwrap item " + player );
248
246
}
249
-
247
+
250
248
return output ;
251
249
}
252
250
}
0 commit comments