Adding a entity structure modifier.
Dieser Commit ist enthalten in:
Ursprung
286e1159e9
Commit
455ffca63f
@ -17,12 +17,19 @@
|
|||||||
|
|
||||||
package com.comphenix.protocol.events;
|
package com.comphenix.protocol.events;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
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.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
import com.comphenix.protocol.injector.StructureCache;
|
import com.comphenix.protocol.injector.StructureCache;
|
||||||
import com.comphenix.protocol.reflect.EquivalentConverter;
|
import com.comphenix.protocol.reflect.EquivalentConverter;
|
||||||
|
import com.comphenix.protocol.reflect.FuzzyReflection;
|
||||||
import com.comphenix.protocol.reflect.StructureModifier;
|
import com.comphenix.protocol.reflect.StructureModifier;
|
||||||
|
|
||||||
import net.minecraft.server.Packet;
|
import net.minecraft.server.Packet;
|
||||||
@ -39,10 +46,13 @@ public class PacketContainer {
|
|||||||
|
|
||||||
// Current structure modifier
|
// Current structure modifier
|
||||||
protected StructureModifier<Object> structureModifier;
|
protected StructureModifier<Object> structureModifier;
|
||||||
|
|
||||||
// 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");
|
||||||
@ -192,6 +202,57 @@ public class PacketContainer {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a read/write structure for entity objects.
|
||||||
|
* <p>
|
||||||
|
* Note that entities are transmitted by integer ID, and the type may not be enough
|
||||||
|
* to distinguish between entities and other values. Thus, this structure modifier
|
||||||
|
* MAY return null or invalid entities for certain fields. Using the correct index
|
||||||
|
* is essential.
|
||||||
|
*
|
||||||
|
* @return A modifier entity types.
|
||||||
|
*/
|
||||||
|
public StructureModifier<Entity> getEntityModifier(World world) {
|
||||||
|
|
||||||
|
final Object worldServer = ((CraftWorld) world).getHandle();
|
||||||
|
final Class<?> nmsEntityClass = net.minecraft.server.Entity.class;
|
||||||
|
|
||||||
|
if (getEntity == null)
|
||||||
|
getEntity = FuzzyReflection.fromObject(worldServer).getMethodByParameters(
|
||||||
|
"getEntity", nmsEntityClass, new Class[] { int.class });
|
||||||
|
|
||||||
|
// Convert to and from the Bukkit wrapper
|
||||||
|
return structureModifier.<Entity>withType(int.class, new EquivalentConverter<Entity>() {
|
||||||
|
@Override
|
||||||
|
public Object getGeneric(Entity specific) {
|
||||||
|
// Simple enough
|
||||||
|
return specific.getEntityId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Entity getSpecific(Object generic) {
|
||||||
|
try {
|
||||||
|
net.minecraft.server.Entity nmsEntity = (net.minecraft.server.Entity)
|
||||||
|
getEntity.invoke(worldServer, generic);
|
||||||
|
|
||||||
|
// Attempt to get the Bukkit entity
|
||||||
|
if (nmsEntity != null) {
|
||||||
|
return nmsEntity.getBukkitEntity();
|
||||||
|
} else {
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the ID of this packet.
|
* Retrieves the ID of this packet.
|
||||||
* @return Packet ID.
|
* @return Packet ID.
|
||||||
|
@ -131,6 +131,26 @@ public class FuzzyReflection {
|
|||||||
throw new RuntimeException("Unable to find " + name + " in " + source.getName());
|
throw new RuntimeException("Unable to find " + name + " in " + source.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a method by looking at the parameter types and return type only.
|
||||||
|
* @param name - potential name of the method. Only used by the error mechanism.
|
||||||
|
* @param returnType - return type of the method to find.
|
||||||
|
* @param args - parameter types of the method to find.
|
||||||
|
* @return The first method that satisfies the parameter types.
|
||||||
|
*/
|
||||||
|
public Method getMethodByParameters(String name, Class<?> returnType, Class<?>[] args) {
|
||||||
|
|
||||||
|
// Find the correct method to call
|
||||||
|
for (Method method : getMethods()) {
|
||||||
|
if (method.getReturnType().equals(returnType) && Arrays.equals(method.getParameterTypes(), args)) {
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// That sucks
|
||||||
|
throw new RuntimeException("Unable to find " + name + " in " + source.getName());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves a field by name.
|
* Retrieves a field by name.
|
||||||
* @param nameRegex - regular expression that will match a field name.
|
* @param nameRegex - regular expression that will match a field name.
|
||||||
|
In neuem Issue referenzieren
Einen Benutzer sperren