Quick getEntity Method and ReflectionUtil improvements
This commit is contained in:
parent
8dbded4192
commit
89eea76365
@ -147,14 +147,13 @@ public class EngineMassiveCoreCommandRegistration extends EngineAbstract
|
||||
public static SimpleCommandMap getSimpleCommandMap()
|
||||
{
|
||||
Server server = Bukkit.getServer();
|
||||
return (SimpleCommandMap) ReflectionUtil.getField(SERVER_DOT_COMMAND_MAP, server);
|
||||
return ReflectionUtil.getField(SERVER_DOT_COMMAND_MAP, server);
|
||||
}
|
||||
|
||||
protected static Field SIMPLE_COMMAND_MAP_DOT_KNOWN_COMMANDS = ReflectionUtil.getField(SimpleCommandMap.class, "knownCommands");
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Map<String, Command> getSimpleCommandMapDotKnownCommands(SimpleCommandMap simpleCommandMap)
|
||||
{
|
||||
return (Map<String, Command>) ReflectionUtil.getField(SIMPLE_COMMAND_MAP_DOT_KNOWN_COMMANDS, simpleCommandMap);
|
||||
return ReflectionUtil.getField(SIMPLE_COMMAND_MAP_DOT_KNOWN_COMMANDS, simpleCommandMap);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
|
145
src/com/massivecraft/massivecore/nms/NmsEntity.java
Normal file
145
src/com/massivecraft/massivecore/nms/NmsEntity.java
Normal file
@ -0,0 +1,145 @@
|
||||
package com.massivecraft.massivecore.nms;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Entity;
|
||||
|
||||
import com.massivecraft.massivecore.particleeffect.ReflectionUtils.PackageType;
|
||||
import com.massivecraft.massivecore.util.ReflectionUtil;
|
||||
|
||||
public class NmsEntity extends NmsAbstract
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// INSTANCE & CONSTRUCT
|
||||
// -------------------------------------------- //
|
||||
|
||||
private static NmsEntity i = new NmsEntity();
|
||||
public static NmsEntity get () { return i; }
|
||||
|
||||
// -------------------------------------------- //
|
||||
// FIELDS
|
||||
// -------------------------------------------- //
|
||||
|
||||
// org.bukkit.craftbukkit.CraftWorld#world
|
||||
public static Class<?> classCraftWorld;
|
||||
public static Field fieldCraftWorldDotWorld;
|
||||
|
||||
// net.minecraft.server.WorldServer#entitiesByUUID
|
||||
public static Class<?> classWorldServer;
|
||||
public static Field fieldWorldServerDotEntitiesByUUID;
|
||||
|
||||
// net.minecraft.server.Entity#getBukkitEntity()
|
||||
public static Class<?> classEntity;
|
||||
public static Method methodEntityDotGetBukkitEntity;
|
||||
|
||||
// -------------------------------------------- //
|
||||
// OVERRIDE
|
||||
// -------------------------------------------- //
|
||||
|
||||
// NOTE: This has been properly researched.
|
||||
// NOTE: The field "WorldServer.entitiesByUUID" was added in 1.8.
|
||||
@Override
|
||||
public int getRequiredVersion()
|
||||
{
|
||||
return 8;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setup() throws Throwable
|
||||
{
|
||||
classCraftWorld = PackageType.CRAFTBUKKIT.getClass("CraftWorld");
|
||||
fieldCraftWorldDotWorld = ReflectionUtil.getField(classCraftWorld, "world");
|
||||
|
||||
classWorldServer = PackageType.MINECRAFT_SERVER.getClass("WorldServer");
|
||||
fieldWorldServerDotEntitiesByUUID = ReflectionUtil.getField(classWorldServer, "entitiesByUUID");
|
||||
|
||||
classEntity = PackageType.MINECRAFT_SERVER.getClass("Entity");
|
||||
methodEntityDotGetBukkitEntity = ReflectionUtil.getMethod(classEntity, "getBukkitEntity");
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// REFLECTION METHODS > WORLD MAP
|
||||
// -------------------------------------------- //
|
||||
|
||||
public Object getNmsWorld(World world)
|
||||
{
|
||||
if (world == null) throw new NullPointerException("world");
|
||||
|
||||
return ReflectionUtil.getField(fieldCraftWorldDotWorld, world);
|
||||
}
|
||||
|
||||
public Map<UUID, Object> getNmsWorldMap(Object nmsWorld)
|
||||
{
|
||||
if (nmsWorld == null) throw new NullPointerException("nmsWorld");
|
||||
|
||||
return ReflectionUtil.getField(fieldWorldServerDotEntitiesByUUID, nmsWorld);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// REFLECTION METHODS > ENTITY
|
||||
// -------------------------------------------- //
|
||||
|
||||
public Entity getBukkitEntity(Object nmsEntity)
|
||||
{
|
||||
if (nmsEntity == null) throw new NullPointerException("nmsEntity");
|
||||
|
||||
return ReflectionUtil.invokeMethod(methodEntityDotGetBukkitEntity, nmsEntity);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// WORLD MAP
|
||||
// -------------------------------------------- //
|
||||
|
||||
protected Map<World, Map<UUID, Object>> worldMaps = new WeakHashMap<World, Map<UUID, Object>>();
|
||||
|
||||
public Map<UUID, Object> getWorldMap(World world)
|
||||
{
|
||||
if (world == null) throw new NullPointerException("world");
|
||||
|
||||
Map<UUID, Object> ret = this.worldMaps.get(world);
|
||||
if (ret == null)
|
||||
{
|
||||
Object nmsWorld = this.getNmsWorld(world);
|
||||
ret = this.getNmsWorldMap(nmsWorld);
|
||||
this.worldMaps.put(world, ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// GET ENTITY
|
||||
// -------------------------------------------- //
|
||||
|
||||
public Entity getEntity(World world, UUID uuid)
|
||||
{
|
||||
if (world == null) throw new NullPointerException("world");
|
||||
if (uuid == null) return null;
|
||||
|
||||
Map<UUID, Object> worldMap = this.getWorldMap(world);
|
||||
|
||||
Object nmsEntity = worldMap.get(uuid);
|
||||
if (nmsEntity == null) return null;
|
||||
|
||||
return this.getBukkitEntity(nmsEntity);
|
||||
}
|
||||
|
||||
public Entity getEntity(UUID uuid)
|
||||
{
|
||||
if (uuid == null) return null;
|
||||
|
||||
for (World world : Bukkit.getWorlds())
|
||||
{
|
||||
Entity ret = this.getEntity(world, uuid);
|
||||
if (ret != null) return ret;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -22,7 +22,7 @@ public class NmsHead extends NmsAbstract
|
||||
public static NmsHead get () { return i; }
|
||||
|
||||
// -------------------------------------------- //
|
||||
// REFLECTION CACHE
|
||||
// FIELDS
|
||||
// -------------------------------------------- //
|
||||
|
||||
public static Class<?> classCraftMetaSkull;
|
||||
@ -73,12 +73,12 @@ public class NmsHead extends NmsAbstract
|
||||
|
||||
public static String getGameProfileName(Object gameProfile)
|
||||
{
|
||||
return (String) ReflectionUtil.getField(fieldGameProfileDotName, gameProfile);
|
||||
return ReflectionUtil.getField(fieldGameProfileDotName, gameProfile);
|
||||
}
|
||||
|
||||
public static UUID getGameProfileId(Object gameProfile)
|
||||
{
|
||||
return (UUID) ReflectionUtil.getField(fieldGameProfileDotId, gameProfile);
|
||||
return ReflectionUtil.getField(fieldGameProfileDotId, gameProfile);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
|
@ -68,6 +68,7 @@ import com.massivecraft.massivecore.collections.MassiveTreeSet;
|
||||
import com.massivecraft.massivecore.engine.EngineMassiveCoreDatabase;
|
||||
import com.massivecraft.massivecore.engine.EngineMassiveCoreMain;
|
||||
import com.massivecraft.massivecore.engine.EngineMassiveCoreWorldNameSet;
|
||||
import com.massivecraft.massivecore.nms.NmsEntity;
|
||||
import com.massivecraft.massivecore.util.extractor.Extractor;
|
||||
import com.massivecraft.massivecore.util.extractor.ExtractorPlayer;
|
||||
import com.massivecraft.massivecore.util.extractor.ExtractorPlayerName;
|
||||
@ -174,6 +175,65 @@ public class MUtil
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// GET ENTITY
|
||||
// -------------------------------------------- //
|
||||
|
||||
public static Entity getEntity(World world, UUID uuid)
|
||||
{
|
||||
if (world == null) throw new NullPointerException("world");
|
||||
if (uuid == null) return null;
|
||||
|
||||
if (NmsEntity.get().isAvailable())
|
||||
{
|
||||
return NmsEntity.get().getEntity(world, uuid);
|
||||
}
|
||||
else
|
||||
{
|
||||
return getEntityFallback(world, uuid);
|
||||
}
|
||||
}
|
||||
|
||||
public static Entity getEntity(UUID uuid)
|
||||
{
|
||||
if (uuid == null) return null;
|
||||
|
||||
if (NmsEntity.get().isAvailable())
|
||||
{
|
||||
return NmsEntity.get().getEntity(uuid);
|
||||
}
|
||||
else
|
||||
{
|
||||
return getEntityFallback(uuid);
|
||||
}
|
||||
}
|
||||
|
||||
private static Entity getEntityFallback(World world, UUID uuid)
|
||||
{
|
||||
if (world == null) throw new NullPointerException("world");
|
||||
if (uuid == null) return null;
|
||||
|
||||
for (Entity entity : world.getEntities())
|
||||
{
|
||||
if (entity.getUniqueId().equals(uuid)) return entity;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Entity getEntityFallback(UUID uuid)
|
||||
{
|
||||
if (uuid == null) return null;
|
||||
|
||||
for (World world : Bukkit.getWorlds())
|
||||
{
|
||||
Entity ret = getEntityFallback(world, uuid);
|
||||
if (ret != null) return ret;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// IS VALID PLAYER NAME
|
||||
// -------------------------------------------- //
|
||||
|
@ -1,8 +1,11 @@
|
||||
package com.massivecraft.massivecore.util;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.UndeclaredThrowableException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@ -33,60 +36,127 @@ public class ReflectionUtil
|
||||
// MAKE ACCESSIBLE
|
||||
// -------------------------------------------- //
|
||||
|
||||
public static boolean makeAccessible(Field field)
|
||||
public static void makeAccessible(Field field)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Mark the field as accessible using reflection.
|
||||
// Mark as accessible using reflection.
|
||||
field.setAccessible(true);
|
||||
|
||||
// Remove the final modifier from the field.
|
||||
// http://stackoverflow.com/questions/2474017/using-reflection-to-change-static-final-file-separatorchar-for-unit-testing
|
||||
FIELD_DOT_MODIFIERS.setInt(field, field.getModifiers() & ~Modifier.FINAL);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
rethrow(e);
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// FIELD GET
|
||||
// -------------------------------------------- //
|
||||
|
||||
public static Field getField(Class<?> clazz, String fieldName)
|
||||
public static void makeAccessible(Method method)
|
||||
{
|
||||
try
|
||||
{
|
||||
Field field = clazz.getDeclaredField(fieldName);
|
||||
makeAccessible(field);
|
||||
return field;
|
||||
// Mark as accessible using reflection.
|
||||
method.setAccessible(true);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
rethrow(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static Object getField(Field field, Object object)
|
||||
public static void makeAccessible(Constructor<?> constructor)
|
||||
{
|
||||
try
|
||||
{
|
||||
return field.get(object);
|
||||
// Mark as accessible using reflection.
|
||||
constructor.setAccessible(true);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
rethrow(e);
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// FIELD SET
|
||||
// METHOD
|
||||
// -------------------------------------------- //
|
||||
|
||||
public static Method getMethod(Class<?> clazz, String name, Class<?>... parameterTypes)
|
||||
{
|
||||
try
|
||||
{
|
||||
Method ret = clazz.getMethod(name, parameterTypes);
|
||||
makeAccessible(ret);
|
||||
return ret;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
rethrow(e);
|
||||
}
|
||||
throw new RuntimeException();
|
||||
}
|
||||
public static Method getMethod(Class<?> clazz, String name)
|
||||
{
|
||||
return getMethod(clazz, name, new Class<?>[0]);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T invokeMethod(Method method, Object target, Object... arguments)
|
||||
{
|
||||
try
|
||||
{
|
||||
return (T) method.invoke(target, arguments);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
rethrow(e);
|
||||
}
|
||||
throw new RuntimeException();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T invokeMethod(Method method, Object target)
|
||||
{
|
||||
return (T) invokeMethod(method, target, new Object[0]);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// FIELD > GET
|
||||
// -------------------------------------------- //
|
||||
|
||||
public static Field getField(Class<?> clazz, String name)
|
||||
{
|
||||
try
|
||||
{
|
||||
Field ret = clazz.getDeclaredField(name);
|
||||
makeAccessible(ret);
|
||||
return ret;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
rethrow(e);
|
||||
}
|
||||
throw new RuntimeException();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T getField(Field field, Object object)
|
||||
{
|
||||
try
|
||||
{
|
||||
return (T) field.get(object);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
rethrow(e);
|
||||
}
|
||||
throw new RuntimeException();
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// FIELD > SET
|
||||
// -------------------------------------------- //
|
||||
|
||||
public static void setField(Field field, Object object, Object value)
|
||||
@ -97,63 +167,38 @@ public class ReflectionUtil
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
rethrow(e);
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// FIELD SIMPLE: GET & SET & TRANSFER
|
||||
// FIELD > SIMPLE
|
||||
// -------------------------------------------- //
|
||||
|
||||
public static Object getField(Class<?> clazz, String fieldName, Object object)
|
||||
public static <T> T getField(Class<?> clazz, String name, Object object)
|
||||
{
|
||||
try
|
||||
{
|
||||
Field field = clazz.getDeclaredField(fieldName);
|
||||
makeAccessible(field);
|
||||
return field.get(object);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
Field field = getField(clazz, name);
|
||||
return getField(field, object);
|
||||
}
|
||||
|
||||
public static boolean setField(Class<?> clazz, String fieldName, Object object, Object value)
|
||||
public static void setField(Class<?> clazz, String name, Object object, Object value)
|
||||
{
|
||||
try
|
||||
{
|
||||
Field field = clazz.getDeclaredField(fieldName);
|
||||
makeAccessible(field);
|
||||
field.set(object, value);
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
Field field = getField(clazz, name);
|
||||
setField(field, object, value);
|
||||
}
|
||||
|
||||
public static boolean transferField(Class<?> clazz, Object from, Object to, String fieldName)
|
||||
// -------------------------------------------- //
|
||||
// FIELD > TRANSFER
|
||||
// -------------------------------------------- //
|
||||
|
||||
public static void transferField(Class<?> clazz, Object from, Object to, String name)
|
||||
{
|
||||
try
|
||||
{
|
||||
Field field = clazz.getDeclaredField(fieldName);
|
||||
makeAccessible(field);
|
||||
Object value = field.get(from);
|
||||
field.set(to, value);
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
Field field = getField(clazz, name);
|
||||
Object value = getField(field, from);
|
||||
setField(field, to, value);
|
||||
}
|
||||
|
||||
public static boolean transferFields(Class<?> clazz, Object from, Object to, List<String> fieldNames)
|
||||
public static void transferFields(Class<?> clazz, Object from, Object to, List<String> fieldNames)
|
||||
{
|
||||
if (fieldNames == null)
|
||||
{
|
||||
@ -166,15 +211,13 @@ public class ReflectionUtil
|
||||
|
||||
for (String fieldName : fieldNames)
|
||||
{
|
||||
if ( ! transferField(clazz, from, to, fieldName)) return false;
|
||||
transferField(clazz, from, to, fieldName);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean transferFields(Class<?> clazz, Object from, Object to)
|
||||
public static void transferFields(Class<?> clazz, Object from, Object to)
|
||||
{
|
||||
return transferFields(clazz, from, to, null);
|
||||
transferFields(clazz, from, to, null);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
@ -223,4 +266,34 @@ public class ReflectionUtil
|
||||
});
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// RETHROW
|
||||
// -------------------------------------------- //
|
||||
// This method is used to convert throwables into nicer runtime versions.
|
||||
|
||||
public static void rethrow(Throwable e)
|
||||
{
|
||||
// Error
|
||||
if (e instanceof Error) throw (Error)e;
|
||||
|
||||
// Not Found
|
||||
if (e instanceof ClassNotFoundException) throw new IllegalStateException("Class not Found: " + e.getMessage());
|
||||
if (e instanceof NoSuchMethodException) throw new IllegalStateException("Method not Found: " + e.getMessage());
|
||||
if (e instanceof NoSuchFieldException) throw new IllegalStateException("Field not Found: " + e.getMessage());
|
||||
|
||||
// Security
|
||||
if (e instanceof SecurityException) throw new IllegalStateException("Security was Violated: " + e.getMessage());
|
||||
|
||||
// Derp
|
||||
if (e instanceof IllegalAccessException) throw new IllegalStateException("Access was Illegal: " + e.getMessage());
|
||||
if (e instanceof IllegalArgumentException) throw new IllegalStateException("Inappropriate Arguments: " + e.getMessage());
|
||||
if (e instanceof InvocationTargetException) rethrow(((InvocationTargetException)e).getCause());
|
||||
|
||||
// Runtime
|
||||
if (e instanceof RuntimeException) throw (RuntimeException)e;
|
||||
|
||||
// Other
|
||||
throw new UndeclaredThrowableException(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user