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.DefaultInstances;
|
||||
import com.comphenix.protocol.reflect.instances.PrimitiveGenerator;
|
||||
import com.comphenix.protocol.wrappers.BukkitConverters;
|
||||
import com.comphenix.protocol.wrappers.ChunkPosition;
|
||||
import com.comphenix.protocol.wrappers.WrappedDataWatcher;
|
||||
import com.comphenix.protocol.wrappers.WrappedWatchableObject;
|
||||
@ -50,8 +49,7 @@ class CleanupStaticMembers {
|
||||
PrimitiveGenerator.class, FuzzyReflection.class, MethodUtils.class,
|
||||
BackgroundCompiler.class, StructureCompiler.class,
|
||||
ObjectCloner.class, Packets.Server.class, Packets.Client.class,
|
||||
ChunkPosition.class, WrappedDataWatcher.class, WrappedWatchableObject.class,
|
||||
BukkitConverters.class
|
||||
ChunkPosition.class, WrappedDataWatcher.class, WrappedWatchableObject.class
|
||||
};
|
||||
|
||||
String[] internalClasses = {
|
||||
|
@ -20,6 +20,7 @@ package com.comphenix.protocol;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
@ -105,6 +106,15 @@ public interface ProtocolManager extends PacketStream {
|
||||
*/
|
||||
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.
|
||||
* @return Every filtered server packet.
|
||||
|
@ -27,6 +27,8 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import net.minecraft.server.EntityTrackerEntry;
|
||||
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.craftbukkit.CraftWorld;
|
||||
import org.bukkit.entity.Entity;
|
||||
@ -83,8 +85,51 @@ class EntityUtilities {
|
||||
*
|
||||
*/
|
||||
public static void updateEntity(Entity entity, List<Player> observers) throws FieldAccessException {
|
||||
|
||||
World world = entity.getWorld();
|
||||
try {
|
||||
//EntityTrackerEntry trackEntity = (EntityTrackerEntry) tracker.trackedEntities.get(entity.getEntityId());
|
||||
Object trackerEntry = getEntityTrackerEntry(entity.getWorld(), 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) {
|
||||
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();
|
||||
|
||||
// We have to rely on the class naming here.
|
||||
@ -148,41 +193,37 @@ class EntityUtilities {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Wrap exceptions
|
||||
try {
|
||||
//EntityTrackerEntry trackEntity = (EntityTrackerEntry) tracker.trackedEntities.get(entity.getEntityId());
|
||||
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);
|
||||
|
||||
return hashGetMethod.invoke(trackedEntities, entityID);
|
||||
} 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 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 org.bukkit.Server;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
@ -565,6 +566,11 @@ public final class PacketFilterManager implements ProtocolManager, ListenerInvok
|
||||
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.
|
||||
* @param players - list of players to inject.
|
||||
|
@ -1,7 +1,6 @@
|
||||
package com.comphenix.protocol.wrappers;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
@ -9,18 +8,16 @@ import java.util.List;
|
||||
import net.minecraft.server.DataWatcher;
|
||||
import net.minecraft.server.WatchableObject;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.WorldType;
|
||||
import org.bukkit.craftbukkit.CraftWorld;
|
||||
import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
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.FuzzyReflection;
|
||||
import com.comphenix.protocol.reflect.FieldAccessException;
|
||||
import com.comphenix.protocol.reflect.instances.DefaultInstances;
|
||||
|
||||
/**
|
||||
@ -32,9 +29,6 @@ public class BukkitConverters {
|
||||
// Check whether or not certain classes exists
|
||||
private static boolean hasWorldType = false;
|
||||
|
||||
// The getEntity method
|
||||
private static Method getEntity;
|
||||
|
||||
static {
|
||||
try {
|
||||
Class.forName("net.minecraft.server.WorldType");
|
||||
@ -183,13 +177,10 @@ public class BukkitConverters {
|
||||
* @return A converter between the underlying NMS entity and Bukkit's wrapper.
|
||||
*/
|
||||
public static EquivalentConverter<Entity> getEntityConverter(World world) {
|
||||
final Object worldServer = ((CraftWorld) world).getHandle();
|
||||
final Class<?> nmsEntityClass = net.minecraft.server.Entity.class;
|
||||
final World container = world;
|
||||
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>() {
|
||||
|
||||
@Override
|
||||
@ -201,34 +192,17 @@ public class BukkitConverters {
|
||||
@Override
|
||||
public Entity getSpecific(Object generic) {
|
||||
try {
|
||||
net.minecraft.server.Entity nmsEntity = (net.minecraft.server.Entity)
|
||||
getEntity.invoke(worldServer, generic);
|
||||
Integer id = (Integer) generic;
|
||||
|
||||
// Attempt to get the Bukkit entity
|
||||
if (nmsEntity != null) {
|
||||
return nmsEntity.getBukkitEntity();
|
||||
// Use the
|
||||
if (id != null && managerRef.get() != null) {
|
||||
return managerRef.get().getEntityFromID(container, id);
|
||||
} 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;
|
||||
}
|
||||
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new RuntimeException("Incorrect arguments detected.", 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());
|
||||
} catch (FieldAccessException e) {
|
||||
throw new RuntimeException("Cannot retrieve entity from ID.", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import com.comphenix.protocol.injector.BukkitUnwrapper;
|
||||
import com.comphenix.protocol.reflect.FieldAccessException;
|
||||
import com.comphenix.protocol.reflect.FieldUtils;
|
||||
import com.comphenix.protocol.reflect.FuzzyReflection;
|
||||
@ -414,10 +415,13 @@ public class WrappedDataWatcher {
|
||||
*/
|
||||
public static WrappedDataWatcher getEntityWatcher(Entity entity) throws FieldAccessException {
|
||||
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 {
|
||||
Object nsmWatcher = FieldUtils.readField(entityDataField, entity, true);
|
||||
Object nsmWatcher = FieldUtils.readField(entityDataField, unwrapper.unwrapItem(entity), true);
|
||||
|
||||
if (nsmWatcher != null)
|
||||
return new WrappedDataWatcher((DataWatcher) nsmWatcher);
|
||||
|
In neuem Issue referenzieren
Einen Benutzer sperren