Skip to content

Commit b1efed0

Browse files
committed
Fix get entity by ID with Citizens and HD
Fixes #729 Addresses filoghost/HolographicDisplays#135
1 parent 524fb1b commit b1efed0

File tree

1 file changed

+31
-12
lines changed

1 file changed

+31
-12
lines changed

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

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,8 @@
1717

1818
package com.comphenix.protocol.injector;
1919

20-
import java.util.ArrayList;
21-
import java.util.Collection;
22-
import java.util.HashMap;
23-
import java.util.List;
24-
import java.util.Map;
20+
import java.util.*;
21+
import java.util.concurrent.ConcurrentHashMap;
2522

2623
import com.comphenix.protocol.reflect.FieldAccessException;
2724
import com.comphenix.protocol.reflect.FuzzyReflection;
@@ -46,7 +43,7 @@
4643
* @author Kristian
4744
*/
4845
class EntityUtilities {
49-
private static final boolean NEW_TRACKER = MinecraftVersion.atOrAbove(MinecraftVersion.VILLAGE_UPDATE);
46+
private static final boolean NEW_TRACKER = MinecraftVersion.VILLAGE_UPDATE.atOrAbove();
5047
private static final EntityUtilities INSTANCE = new EntityUtilities();
5148

5249
public static EntityUtilities getInstance() {
@@ -58,7 +55,6 @@ private EntityUtilities() { }
5855
private FieldAccessor entityTrackerField;
5956
private FieldAccessor trackedEntitiesField;
6057
private FieldAccessor trackedPlayersField;
61-
private FieldAccessor trackerField;
6258

6359
private Map<Class<?>, MethodAccessor> scanPlayersMethods = new HashMap<>();
6460

@@ -196,6 +192,9 @@ private Object getEntityTrackerEntry(World world, int entityID) {
196192
return WrappedIntHashMap.fromHandle(trackedEntities).get(entityID);
197193
}
198194

195+
private Map<Class<?>, FieldAccessor> trackerFields = new ConcurrentHashMap<>();
196+
private MethodAccessor getEntityFromId;
197+
199198
/**
200199
* Retrieve entity from a ID, even it it's newly created.
201200
* @return The associated entity.
@@ -206,20 +205,40 @@ public Entity getEntityFromID(World world, int entityID) {
206205
Validate.isTrue(entityID >= 0, "entityID cannot be negative");
207206

208207
try {
208+
// first, try to read from the world
209+
// this should be good enough for most cases, but only exists in 1.14+
210+
if (NEW_TRACKER) {
211+
Object worldServer = BukkitUnwrapper.getInstance().unwrapItem(world);
212+
213+
if (getEntityFromId == null) {
214+
FuzzyReflection fuzzy = FuzzyReflection.fromClass(worldServer.getClass(), false);
215+
getEntityFromId = Accessors.getMethodAccessor(fuzzy.getMethod(FuzzyMethodContract.newBuilder()
216+
.parameterExactArray(int.class)
217+
.returnTypeExact(MinecraftReflection.getEntityClass())
218+
.build()));
219+
}
220+
221+
Object entity = getEntityFromId.invoke(worldServer, entityID);
222+
if (entity != null) {
223+
return (Entity) MinecraftReflection.getBukkitEntity(entity);
224+
}
225+
}
226+
227+
// then go into the trackers
209228
Object trackerEntry = getEntityTrackerEntry(world, entityID);
210229
Object tracker = null;
211230

212-
// Handle NULL cases
213231
if (trackerEntry != null) {
214-
if (trackerField == null) {
232+
// plugins like citizens will use their own tracker
233+
FieldAccessor trackerField = trackerFields.computeIfAbsent(trackerEntry.getClass(), x -> {
215234
try {
216-
trackerField = Accessors.getFieldAccessor(trackerEntry.getClass(), "tracker", true);
235+
return Accessors.getFieldAccessor(trackerEntry.getClass(), "tracker", true);
217236
} catch (Exception e) {
218237
// Assume it's the first entity field then
219-
trackerField = Accessors.getFieldAccessor(FuzzyReflection.fromObject(trackerEntry, true)
238+
return Accessors.getFieldAccessor(FuzzyReflection.fromObject(trackerEntry, true)
220239
.getFieldByType("tracker", MinecraftReflection.getEntityClass()));
221240
}
222-
}
241+
});
223242

224243
tracker = trackerField.get(trackerEntry);
225244
}

0 commit comments

Comments
 (0)