Archiviert
13
0

Adding a entity structure modifier.

Dieser Commit ist enthalten in:
Kristian S. Stangeland 2012-09-17 01:34:10 +02:00
Ursprung 286e1159e9
Commit 455ffca63f
2 geänderte Dateien mit 82 neuen und 1 gelöschten Zeilen

Datei anzeigen

@ -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;
@ -43,6 +50,9 @@ public class PacketContainer {
// 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.

Datei anzeigen

@ -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.