Support multiple EntityTrackerEntryImpls, fixes #732 (#733)

This commit is contained in:
MiniDigger 2019-12-16 18:32:26 +01:00 committed by Dan Mulloy
parent 3ff2ccf1b3
commit 524fb1ba68

View File

@ -19,6 +19,7 @@ package com.comphenix.protocol.injector;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -41,13 +42,13 @@ import org.bukkit.entity.Player;
/** /**
* Used to perform certain operations on entities. * Used to perform certain operations on entities.
* *
* @author Kristian * @author Kristian
*/ */
class EntityUtilities { class EntityUtilities {
private static final boolean NEW_TRACKER = MinecraftVersion.atOrAbove(MinecraftVersion.VILLAGE_UPDATE); private static final boolean NEW_TRACKER = MinecraftVersion.atOrAbove(MinecraftVersion.VILLAGE_UPDATE);
private static final EntityUtilities INSTANCE = new EntityUtilities(); private static final EntityUtilities INSTANCE = new EntityUtilities();
public static EntityUtilities getInstance() { public static EntityUtilities getInstance() {
return INSTANCE; return INSTANCE;
} }
@ -58,8 +59,8 @@ class EntityUtilities {
private FieldAccessor trackedEntitiesField; private FieldAccessor trackedEntitiesField;
private FieldAccessor trackedPlayersField; private FieldAccessor trackedPlayersField;
private FieldAccessor trackerField; private FieldAccessor trackerField;
private MethodAccessor scanPlayersMethod; private Map<Class<?>, MethodAccessor> scanPlayersMethods = new HashMap<>();
public void updateEntity(Entity entity, List<Player> observers) { public void updateEntity(Entity entity, List<Player> observers) {
if (entity == null || !entity.isValid()) { if (entity == null || !entity.isValid()) {
@ -73,11 +74,8 @@ class EntityUtilities {
Object trackerEntry = getEntityTrackerEntry(entity.getWorld(), entity.getEntityId()); Object trackerEntry = getEntityTrackerEntry(entity.getWorld(), entity.getEntityId());
if (scanPlayersMethod == null) { // there can be multiple different entity tracker entry impls, see GH-732....
scanPlayersMethod = findScanPlayers(trackerEntry.getClass()); scanPlayersMethods.computeIfAbsent(trackerEntry.getClass(), this::findScanPlayers).invoke(trackerEntry, nmsPlayers);
}
scanPlayersMethod.invoke(trackerEntry, nmsPlayers);
} }
private MethodAccessor findScanPlayers(Class<?> trackerClass) { private MethodAccessor findScanPlayers(Class<?> trackerClass) {
@ -138,7 +136,7 @@ class EntityUtilities {
throw new IllegalStateException("trackedPlayers field was an unknown type: expected Collection or Map, but got " + value.getClass()); throw new IllegalStateException("trackedPlayers field was an unknown type: expected Collection or Map, but got " + value.getClass());
} }
} }
private MethodAccessor getChunkProvider; private MethodAccessor getChunkProvider;
private FieldAccessor chunkMapField; private FieldAccessor chunkMapField;
@ -150,7 +148,7 @@ class EntityUtilities {
FuzzyReflection.fromClass(worldServer.getClass(), false).getMethod( FuzzyReflection.fromClass(worldServer.getClass(), false).getMethod(
FuzzyMethodContract.newBuilder().parameterCount(0).returnTypeExact(chunkProviderClass).build())); FuzzyMethodContract.newBuilder().parameterCount(0).returnTypeExact(chunkProviderClass).build()));
} }
Object chunkProvider = getChunkProvider.invoke(worldServer); Object chunkProvider = getChunkProvider.invoke(worldServer);
if (chunkMapField == null) { if (chunkMapField == null) {
@ -159,7 +157,7 @@ class EntityUtilities {
FuzzyReflection.fromClass(chunkProvider.getClass(), false).getField( FuzzyReflection.fromClass(chunkProvider.getClass(), false).getField(
FuzzyFieldContract.newBuilder().typeExact(chunkMapClass).build())); FuzzyFieldContract.newBuilder().typeExact(chunkMapClass).build()));
} }
Object playerChunkMap = chunkMapField.get(chunkProvider); Object playerChunkMap = chunkMapField.get(chunkProvider);
if (trackedEntitiesField == null) { if (trackedEntitiesField == null) {
@ -183,7 +181,7 @@ class EntityUtilities {
if (entityTrackerField == null) if (entityTrackerField == null)
entityTrackerField = Accessors.getFieldAccessor(FuzzyReflection.fromObject(worldServer). entityTrackerField = Accessors.getFieldAccessor(FuzzyReflection.fromObject(worldServer).
getFieldByType("tracker", MinecraftReflection.getEntityTrackerClass())); getFieldByType("tracker", MinecraftReflection.getEntityTrackerClass()));
// Get the tracker // Get the tracker
Object tracker = entityTrackerField.get(worldServer); Object tracker = entityTrackerField.get(worldServer);
@ -236,17 +234,17 @@ class EntityUtilities {
private List<Object> unwrapBukkit(List<Player> players) { private List<Object> unwrapBukkit(List<Player> players) {
List<Object> output = Lists.newArrayList(); List<Object> output = Lists.newArrayList();
BukkitUnwrapper unwrapper = new BukkitUnwrapper(); BukkitUnwrapper unwrapper = new BukkitUnwrapper();
// Get the NMS equivalent // Get the NMS equivalent
for (Player player : players) { for (Player player : players) {
Object result = unwrapper.unwrapItem(player); Object result = unwrapper.unwrapItem(player);
if (result != null) if (result != null)
output.add(result); output.add(result);
else else
throw new IllegalArgumentException("Cannot unwrap item " + player); throw new IllegalArgumentException("Cannot unwrap item " + player);
} }
return output; return output;
} }
} }