Fixed a bug preventing the entity modifier from reading entities.
Dieser Commit ist enthalten in:
Ursprung
fec2734fe2
Commit
528468a342
@ -19,7 +19,6 @@ import com.comphenix.protocol.reflect.compiler.StructureCompiler;
|
|||||||
import com.comphenix.protocol.reflect.instances.CollectionGenerator;
|
import com.comphenix.protocol.reflect.instances.CollectionGenerator;
|
||||||
import com.comphenix.protocol.reflect.instances.DefaultInstances;
|
import com.comphenix.protocol.reflect.instances.DefaultInstances;
|
||||||
import com.comphenix.protocol.reflect.instances.PrimitiveGenerator;
|
import com.comphenix.protocol.reflect.instances.PrimitiveGenerator;
|
||||||
import com.comphenix.protocol.wrappers.BukkitConverters;
|
|
||||||
import com.comphenix.protocol.wrappers.ChunkPosition;
|
import com.comphenix.protocol.wrappers.ChunkPosition;
|
||||||
import com.comphenix.protocol.wrappers.WrappedDataWatcher;
|
import com.comphenix.protocol.wrappers.WrappedDataWatcher;
|
||||||
import com.comphenix.protocol.wrappers.WrappedWatchableObject;
|
import com.comphenix.protocol.wrappers.WrappedWatchableObject;
|
||||||
@ -50,8 +49,7 @@ class CleanupStaticMembers {
|
|||||||
PrimitiveGenerator.class, FuzzyReflection.class, MethodUtils.class,
|
PrimitiveGenerator.class, FuzzyReflection.class, MethodUtils.class,
|
||||||
BackgroundCompiler.class, StructureCompiler.class,
|
BackgroundCompiler.class, StructureCompiler.class,
|
||||||
ObjectCloner.class, Packets.Server.class, Packets.Client.class,
|
ObjectCloner.class, Packets.Server.class, Packets.Client.class,
|
||||||
ChunkPosition.class, WrappedDataWatcher.class, WrappedWatchableObject.class,
|
ChunkPosition.class, WrappedDataWatcher.class, WrappedWatchableObject.class
|
||||||
BukkitConverters.class
|
|
||||||
};
|
};
|
||||||
|
|
||||||
String[] internalClasses = {
|
String[] internalClasses = {
|
||||||
|
@ -20,6 +20,7 @@ package com.comphenix.protocol;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.bukkit.World;
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
@ -105,6 +106,15 @@ public interface ProtocolManager extends PacketStream {
|
|||||||
*/
|
*/
|
||||||
public void updateEntity(Entity entity, List<Player> observers) throws FieldAccessException;
|
public void updateEntity(Entity entity, List<Player> observers) throws FieldAccessException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the associated entity.
|
||||||
|
* @param container - the world the entity belongs to.
|
||||||
|
* @param id - the unique ID of the entity.
|
||||||
|
* @return The associated entity.
|
||||||
|
* @throws FieldAccessException Reflection failed.
|
||||||
|
*/
|
||||||
|
public Entity getEntityFromID(World container, int id) throws FieldAccessException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves a immutable set containing the ID of the sent server packets that will be observed by listeners.
|
* Retrieves a immutable set containing the ID of the sent server packets that will be observed by listeners.
|
||||||
* @return Every filtered server packet.
|
* @return Every filtered server packet.
|
||||||
|
@ -27,6 +27,8 @@ import java.util.HashSet;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import net.minecraft.server.EntityTrackerEntry;
|
||||||
|
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.craftbukkit.CraftWorld;
|
import org.bukkit.craftbukkit.CraftWorld;
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
@ -83,8 +85,51 @@ class EntityUtilities {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public static void updateEntity(Entity entity, List<Player> observers) throws FieldAccessException {
|
public static void updateEntity(Entity entity, List<Player> observers) throws FieldAccessException {
|
||||||
|
try {
|
||||||
|
//EntityTrackerEntry trackEntity = (EntityTrackerEntry) tracker.trackedEntities.get(entity.getEntityId());
|
||||||
|
Object trackerEntry = getEntityTrackerEntry(entity.getWorld(), entity.getEntityId());
|
||||||
|
|
||||||
World world = entity.getWorld();
|
if (trackedPlayersField == null) {
|
||||||
|
// This one is fairly easy
|
||||||
|
trackedPlayersField = FuzzyReflection.fromObject(trackerEntry).getFieldByType("java\\.util\\..*");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Phew, finally there.
|
||||||
|
Collection<?> trackedPlayers = (Collection<?>) FieldUtils.readField(trackedPlayersField, trackerEntry, false);
|
||||||
|
List<Object> nmsPlayers = unwrapBukkit(observers);
|
||||||
|
|
||||||
|
// trackEntity.trackedPlayers.clear();
|
||||||
|
trackedPlayers.removeAll(nmsPlayers);
|
||||||
|
|
||||||
|
// We have to rely on a NAME once again. Damn it.
|
||||||
|
if (scanPlayersMethod == null) {
|
||||||
|
scanPlayersMethod = trackerEntry.getClass().getMethod("scanPlayers", List.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
//trackEntity.scanPlayers(server.players);
|
||||||
|
scanPlayersMethod.invoke(trackerEntry, nmsPlayers);
|
||||||
|
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw e;
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
throw new FieldAccessException("Security limitation prevents access to 'get' method in IntHashMap", e);
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
throw new RuntimeException("Exception occurred in Minecraft.", e);
|
||||||
|
} catch (SecurityException e) {
|
||||||
|
throw new FieldAccessException("Security limitation prevents access to 'scanPlayers' method in trackerEntry.", e);
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
throw new FieldAccessException("Canot find 'scanPlayers' method. Is ProtocolLib up to date?", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the entity tracker entry given a ID.
|
||||||
|
* @param world - world server.
|
||||||
|
* @param entityID - entity ID.
|
||||||
|
* @return The entity tracker entry.
|
||||||
|
* @throws FieldAccessException
|
||||||
|
*/
|
||||||
|
private static Object getEntityTrackerEntry(World world, int entityID) throws FieldAccessException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
|
||||||
Object worldServer = ((CraftWorld) world).getHandle();
|
Object worldServer = ((CraftWorld) world).getHandle();
|
||||||
|
|
||||||
// We have to rely on the class naming here.
|
// We have to rely on the class naming here.
|
||||||
@ -149,40 +194,36 @@ class EntityUtilities {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Wrap exceptions
|
||||||
try {
|
try {
|
||||||
//EntityTrackerEntry trackEntity = (EntityTrackerEntry) tracker.trackedEntities.get(entity.getEntityId());
|
return hashGetMethod.invoke(trackedEntities, entityID);
|
||||||
Object trackerEntry = hashGetMethod.invoke(trackedEntities, entity.getEntityId());
|
|
||||||
|
|
||||||
if (trackedPlayersField == null) {
|
|
||||||
// This one is fairly easy
|
|
||||||
trackedPlayersField = FuzzyReflection.fromObject(trackerEntry).getFieldByType("java\\.util\\..*");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Phew, finally there.
|
|
||||||
Collection<?> trackedPlayers = (Collection<?>) FieldUtils.readField(trackedPlayersField, trackerEntry, false);
|
|
||||||
List<Object> nmsPlayers = unwrapBukkit(observers);
|
|
||||||
|
|
||||||
// trackEntity.trackedPlayers.clear();
|
|
||||||
trackedPlayers.removeAll(nmsPlayers);
|
|
||||||
|
|
||||||
// We have to rely on a NAME once again. Damn it.
|
|
||||||
if (scanPlayersMethod == null) {
|
|
||||||
scanPlayersMethod = trackerEntry.getClass().getMethod("scanPlayers", List.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
//trackEntity.scanPlayers(server.players);
|
|
||||||
scanPlayersMethod.invoke(trackerEntry, nmsPlayers);
|
|
||||||
|
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
throw e;
|
throw e;
|
||||||
} catch (IllegalAccessException e) {
|
} catch (IllegalAccessException e) {
|
||||||
throw new FieldAccessException("Security limitation prevents access to 'get' method in IntHashMap", e);
|
throw new FieldAccessException("Security limitation prevents access to 'get' method in IntHashMap", e);
|
||||||
} catch (InvocationTargetException e) {
|
} catch (InvocationTargetException e) {
|
||||||
throw new RuntimeException("Exception occurred in Minecraft.", e);
|
throw new RuntimeException("Exception occurred in Minecraft.", e);
|
||||||
} catch (SecurityException e) {
|
}
|
||||||
throw new FieldAccessException("Security limitation prevents access to 'scanPlayers' method in trackerEntry.", e);
|
}
|
||||||
} catch (NoSuchMethodException e) {
|
|
||||||
throw new FieldAccessException("Canot find 'scanPlayers' method. Is ProtocolLib up to date?", e);
|
/**
|
||||||
|
* Retrieve entity from a ID, even it it's newly created.
|
||||||
|
* @return The asssociated entity.
|
||||||
|
* @throws FieldAccessException Reflection error.
|
||||||
|
*/
|
||||||
|
public static Entity getEntityFromID(World world, int entityID) throws FieldAccessException {
|
||||||
|
try {
|
||||||
|
EntityTrackerEntry trackerEntry = (EntityTrackerEntry) getEntityTrackerEntry(world, entityID);
|
||||||
|
|
||||||
|
// Handle NULL cases
|
||||||
|
if (trackerEntry != null && trackerEntry.tracker != null) {
|
||||||
|
return trackerEntry.tracker.getBukkitEntity();
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new FieldAccessException("Cannot find entity from ID.", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,6 +34,7 @@ import net.sf.cglib.proxy.MethodInterceptor;
|
|||||||
import net.sf.cglib.proxy.MethodProxy;
|
import net.sf.cglib.proxy.MethodProxy;
|
||||||
|
|
||||||
import org.bukkit.Server;
|
import org.bukkit.Server;
|
||||||
|
import org.bukkit.World;
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
@ -565,6 +566,11 @@ public final class PacketFilterManager implements ProtocolManager, ListenerInvok
|
|||||||
EntityUtilities.updateEntity(entity, observers);
|
EntityUtilities.updateEntity(entity, observers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Entity getEntityFromID(World container, int id) throws FieldAccessException {
|
||||||
|
return EntityUtilities.getEntityFromID(container, id);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the packet injection for every player.
|
* Initialize the packet injection for every player.
|
||||||
* @param players - list of players to inject.
|
* @param players - list of players to inject.
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package com.comphenix.protocol.wrappers;
|
package com.comphenix.protocol.wrappers;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.ref.WeakReference;
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -9,18 +8,16 @@ import java.util.List;
|
|||||||
import net.minecraft.server.DataWatcher;
|
import net.minecraft.server.DataWatcher;
|
||||||
import net.minecraft.server.WatchableObject;
|
import net.minecraft.server.WatchableObject;
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.Server;
|
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.WorldType;
|
import org.bukkit.WorldType;
|
||||||
import org.bukkit.craftbukkit.CraftWorld;
|
|
||||||
import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
|
import com.comphenix.protocol.ProtocolLibrary;
|
||||||
|
import com.comphenix.protocol.ProtocolManager;
|
||||||
import com.comphenix.protocol.reflect.EquivalentConverter;
|
import com.comphenix.protocol.reflect.EquivalentConverter;
|
||||||
import com.comphenix.protocol.reflect.FuzzyReflection;
|
import com.comphenix.protocol.reflect.FieldAccessException;
|
||||||
import com.comphenix.protocol.reflect.instances.DefaultInstances;
|
import com.comphenix.protocol.reflect.instances.DefaultInstances;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -32,9 +29,6 @@ public class BukkitConverters {
|
|||||||
// Check whether or not certain classes exists
|
// Check whether or not certain classes exists
|
||||||
private static boolean hasWorldType = false;
|
private static boolean hasWorldType = false;
|
||||||
|
|
||||||
// The getEntity method
|
|
||||||
private static Method getEntity;
|
|
||||||
|
|
||||||
static {
|
static {
|
||||||
try {
|
try {
|
||||||
Class.forName("net.minecraft.server.WorldType");
|
Class.forName("net.minecraft.server.WorldType");
|
||||||
@ -183,12 +177,9 @@ public class BukkitConverters {
|
|||||||
* @return A converter between the underlying NMS entity and Bukkit's wrapper.
|
* @return A converter between the underlying NMS entity and Bukkit's wrapper.
|
||||||
*/
|
*/
|
||||||
public static EquivalentConverter<Entity> getEntityConverter(World world) {
|
public static EquivalentConverter<Entity> getEntityConverter(World world) {
|
||||||
final Object worldServer = ((CraftWorld) world).getHandle();
|
final World container = world;
|
||||||
final Class<?> nmsEntityClass = net.minecraft.server.Entity.class;
|
final WeakReference<ProtocolManager> managerRef =
|
||||||
|
new WeakReference<ProtocolManager>(ProtocolLibrary.getProtocolManager());
|
||||||
if (getEntity == null)
|
|
||||||
getEntity = FuzzyReflection.fromObject(worldServer).getMethodByParameters(
|
|
||||||
"getEntity", nmsEntityClass, new Class[] { int.class });
|
|
||||||
|
|
||||||
return getIgnoreNull(new EquivalentConverter<Entity>() {
|
return getIgnoreNull(new EquivalentConverter<Entity>() {
|
||||||
|
|
||||||
@ -201,34 +192,17 @@ public class BukkitConverters {
|
|||||||
@Override
|
@Override
|
||||||
public Entity getSpecific(Object generic) {
|
public Entity getSpecific(Object generic) {
|
||||||
try {
|
try {
|
||||||
net.minecraft.server.Entity nmsEntity = (net.minecraft.server.Entity)
|
|
||||||
getEntity.invoke(worldServer, generic);
|
|
||||||
Integer id = (Integer) generic;
|
Integer id = (Integer) generic;
|
||||||
|
|
||||||
// Attempt to get the Bukkit entity
|
// Use the
|
||||||
if (nmsEntity != null) {
|
if (id != null && managerRef.get() != null) {
|
||||||
return nmsEntity.getBukkitEntity();
|
return managerRef.get().getEntityFromID(container, id);
|
||||||
} else {
|
} else {
|
||||||
Server server = Bukkit.getServer();
|
|
||||||
|
|
||||||
// Maybe it's a player that has just logged in? Try a search
|
|
||||||
if (server != null) {
|
|
||||||
for (Player player : server.getOnlinePlayers()) {
|
|
||||||
if (player.getEntityId() == id) {
|
|
||||||
return player;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (FieldAccessException e) {
|
||||||
throw new RuntimeException("Incorrect arguments detected.", e);
|
throw new RuntimeException("Cannot retrieve entity from ID.", e);
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
throw new RuntimeException("Cannot read field due to a security limitation.", e);
|
|
||||||
} catch (InvocationTargetException e) {
|
|
||||||
throw new RuntimeException("Error occured in Minecraft method.", e.getCause());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
|
|||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
|
import com.comphenix.protocol.injector.BukkitUnwrapper;
|
||||||
import com.comphenix.protocol.reflect.FieldAccessException;
|
import com.comphenix.protocol.reflect.FieldAccessException;
|
||||||
import com.comphenix.protocol.reflect.FieldUtils;
|
import com.comphenix.protocol.reflect.FieldUtils;
|
||||||
import com.comphenix.protocol.reflect.FuzzyReflection;
|
import com.comphenix.protocol.reflect.FuzzyReflection;
|
||||||
@ -414,10 +415,13 @@ public class WrappedDataWatcher {
|
|||||||
*/
|
*/
|
||||||
public static WrappedDataWatcher getEntityWatcher(Entity entity) throws FieldAccessException {
|
public static WrappedDataWatcher getEntityWatcher(Entity entity) throws FieldAccessException {
|
||||||
if (entityDataField == null)
|
if (entityDataField == null)
|
||||||
entityDataField = FuzzyReflection.fromClass(Entity.class, true).getFieldByType("datawatcher", DataWatcher.class);
|
entityDataField = FuzzyReflection.fromClass(net.minecraft.server.Entity.class, true).
|
||||||
|
getFieldByType("datawatcher", DataWatcher.class);
|
||||||
|
|
||||||
|
BukkitUnwrapper unwrapper = new BukkitUnwrapper();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Object nsmWatcher = FieldUtils.readField(entityDataField, entity, true);
|
Object nsmWatcher = FieldUtils.readField(entityDataField, unwrapper.unwrapItem(entity), true);
|
||||||
|
|
||||||
if (nsmWatcher != null)
|
if (nsmWatcher != null)
|
||||||
return new WrappedDataWatcher((DataWatcher) nsmWatcher);
|
return new WrappedDataWatcher((DataWatcher) nsmWatcher);
|
||||||
|
In neuem Issue referenzieren
Einen Benutzer sperren