mirror of
https://github.com/dmulloy2/ProtocolLib.git
synced 2024-11-27 13:15:52 +01:00
Fix entity tracker methods for 1.17 (#1354)
- In 1.17, EntityTrackerEntries use ServerPlayerConnections instead of EntityPlayers as they did before. This caused the updateEntity to silently fail when removing the players from the trackedPlayers collection (of connections). This was resolved by retrieving the connections of the players before removing them from the list on 1.17+. The getEntityTrackers method failed because it could not find any players for the same reason. This was resolved by retrieving the player from the connection before retrieving the Bukkit player from the EntityPlayer object when running on 1.17+. - This fixes dmulloy2/ProtocolLib#1340
This commit is contained in:
parent
4c0c18d7c6
commit
5dda8c8ab1
@ -28,6 +28,7 @@ import com.comphenix.protocol.reflect.accessors.FieldAccessor;
|
||||
import com.comphenix.protocol.reflect.accessors.MethodAccessor;
|
||||
import com.comphenix.protocol.reflect.fuzzy.FuzzyFieldContract;
|
||||
import com.comphenix.protocol.reflect.fuzzy.FuzzyMethodContract;
|
||||
import com.comphenix.protocol.utility.MinecraftFields;
|
||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||
import com.comphenix.protocol.utility.MinecraftVersion;
|
||||
import com.comphenix.protocol.wrappers.WrappedIntHashMap;
|
||||
@ -67,7 +68,10 @@ class EntityUtilities {
|
||||
Collection<?> trackedPlayers = getTrackedPlayers(entity);
|
||||
List<Object> nmsPlayers = unwrapBukkit(observers);
|
||||
|
||||
trackedPlayers.removeAll(nmsPlayers);
|
||||
List<Object> removingEntries = MinecraftVersion.CAVES_CLIFFS_1.atOrAbove() ?
|
||||
getPlayerConnections(nmsPlayers) : nmsPlayers;
|
||||
|
||||
trackedPlayers.removeAll(removingEntries);
|
||||
|
||||
Object trackerEntry = getEntityTrackerEntry(entity.getWorld(), entity.getEntityId());
|
||||
|
||||
@ -103,7 +107,9 @@ class EntityUtilities {
|
||||
|
||||
// Wrap every player - we also ensure that the underlying tracker list is immutable
|
||||
for (Object tracker : trackedPlayers) {
|
||||
if (MinecraftReflection.isMinecraftPlayer(tracker)) {
|
||||
if (MinecraftVersion.CAVES_CLIFFS_1.atOrAbove() && MinecraftReflection.isServerHandler(tracker)) {
|
||||
result.add(MinecraftReflection.getBukkitPlayerFromConnection(tracker));
|
||||
} else if (MinecraftReflection.isMinecraftPlayer(tracker)) {
|
||||
result.add((Player) MinecraftReflection.getBukkitEntity(tracker));
|
||||
}
|
||||
}
|
||||
@ -266,6 +272,12 @@ class EntityUtilities {
|
||||
}
|
||||
}
|
||||
|
||||
private List<Object> getPlayerConnections(List<Object> nmsPlayers) {
|
||||
List<Object> connections = new ArrayList<>(nmsPlayers.size());
|
||||
nmsPlayers.forEach(nmsPlayer -> connections.add(MinecraftFields.getPlayerConnection(nmsPlayer)));
|
||||
return connections;
|
||||
}
|
||||
|
||||
private List<Object> unwrapBukkit(List<Player> players) {
|
||||
List<Object> output = Lists.newArrayList();
|
||||
BukkitUnwrapper unwrapper = new BukkitUnwrapper();
|
||||
|
@ -15,15 +15,16 @@ public class MinecraftFields {
|
||||
// Cached accessors
|
||||
private static volatile FieldAccessor CONNECTION_ACCESSOR;
|
||||
private static volatile FieldAccessor NETWORK_ACCESSOR;
|
||||
|
||||
private static volatile FieldAccessor CONNECTION_ENTITY_ACCESSOR;
|
||||
|
||||
private MinecraftFields() {
|
||||
// Not constructable
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the network mananger associated with a particular player.
|
||||
* Retrieve the network manager associated with a particular player.
|
||||
* @param player - the player.
|
||||
* @return The network manager, or NULL if no network manager has been asssociated yet.
|
||||
* @return The network manager, or NULL if no network manager has been associated yet.
|
||||
*/
|
||||
public static Object getNetworkManager(Player player) {
|
||||
Object nmsPlayer = BukkitUnwrapper.getInstance().unwrapItem(player);
|
||||
@ -50,9 +51,13 @@ public class MinecraftFields {
|
||||
Preconditions.checkNotNull(player, "player cannot be null!");
|
||||
return getPlayerConnection(BukkitUnwrapper.getInstance().unwrapItem(player));
|
||||
}
|
||||
|
||||
// Retrieve player connection from a native instance
|
||||
private static Object getPlayerConnection(Object nmsPlayer) {
|
||||
|
||||
/**
|
||||
* Retrieve the PlayerConnection (or NetServerHandler) associated with a player.
|
||||
* @param nmsPlayer - the NMS player.
|
||||
* @return The player connection.
|
||||
*/
|
||||
public static Object getPlayerConnection(Object nmsPlayer) {
|
||||
Preconditions.checkNotNull(nmsPlayer, "nmsPlayer cannot be null!");
|
||||
|
||||
if (CONNECTION_ACCESSOR == null) {
|
||||
@ -61,4 +66,21 @@ public class MinecraftFields {
|
||||
}
|
||||
return CONNECTION_ACCESSOR.get(nmsPlayer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the EntityPlayer player field from a PlayerConnection.
|
||||
*
|
||||
* @param playerConnection The PlayerConnection object from which to retrieve the EntityPlayer field.
|
||||
* @return The value of the EntityPlayer field in the PlayerConnection.
|
||||
*/
|
||||
public static Object getPlayerFromConnection(Object playerConnection) {
|
||||
Preconditions.checkNotNull(playerConnection, "playerConnection cannot be null!");
|
||||
|
||||
if (CONNECTION_ENTITY_ACCESSOR == null) {
|
||||
Class<?> connectionClass = MinecraftReflection.getPlayerConnectionClass();
|
||||
Class<?> entityPlayerClass = MinecraftReflection.getEntityPlayerClass();
|
||||
CONNECTION_ENTITY_ACCESSOR = Accessors.getFieldAccessor(connectionClass, entityPlayerClass, true);
|
||||
}
|
||||
return CONNECTION_ENTITY_ACCESSOR.get(playerConnection);
|
||||
}
|
||||
}
|
||||
|
@ -41,6 +41,7 @@ import javax.annotation.Nonnull;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import com.comphenix.protocol.PacketType;
|
||||
@ -376,6 +377,21 @@ public class MinecraftReflection {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the Bukkit player from a given PlayerConnection.
|
||||
* @param playerConnection The PlayerConnection.
|
||||
* @return A bukkit player.
|
||||
* @throws RuntimeException If we were unable to retrieve the Bukkit player.
|
||||
*/
|
||||
public static Player getBukkitPlayerFromConnection(Object playerConnection)
|
||||
{
|
||||
try {
|
||||
return (Player) getBukkitEntity(MinecraftFields.getPlayerFromConnection(playerConnection));
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException("Cannot get Bukkit entity from connection " + playerConnection, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a given object can be found within the package net.minecraft.server.
|
||||
* @param obj - the object to test.
|
||||
|
Loading…
Reference in New Issue
Block a user