Created
June 10, 2016 13:52
-
-
Save vemacs/8dd11e9518e1d4a1eef61a71b14d91fa to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package net.ess3.nms.refl; | |
import com.google.common.collect.HashBasedTable; | |
import com.google.common.collect.Table; | |
import org.bukkit.Bukkit; | |
import java.lang.reflect.Constructor; | |
import java.lang.reflect.Field; | |
import java.lang.reflect.Method; | |
import java.util.Arrays; | |
import java.util.HashMap; | |
import java.util.Map; | |
public class ReflUtil { | |
private static String nmsVersion; | |
public static String getNMSVersion() { | |
if (nmsVersion == null) { | |
String name = Bukkit.getServer().getClass().getName(); | |
String[] parts = name.split("\\."); | |
nmsVersion = parts[3]; | |
} | |
return nmsVersion; | |
} | |
public static Class<?> getNMSClass(String className) { | |
return getClassCached("net.minecraft.server." + getNMSVersion() + "." + className); | |
} | |
public static Class<?> getOBCClass(String className) { | |
return getClassCached("org.bukkit.craftbukkit." + getNMSVersion() + "." + className); | |
} | |
private static Map<String, Class<?>> classCache = new HashMap<>(); | |
public static Class<?> getClassCached(String className) { | |
if (classCache.containsKey(className)) { | |
return classCache.get(className); | |
} | |
try { | |
Class<?> classForName = Class.forName(className); | |
classCache.put(className, classForName); | |
return classForName; | |
} catch (ClassNotFoundException e) { | |
return null; | |
} | |
} | |
private static Table<Class<?>, String, Method> methodCache = HashBasedTable.create(); | |
public static Method getMethodCached(Class<?> clazz, String methodName) { | |
if (methodCache.contains(clazz, methodName)) { | |
return methodCache.get(clazz, methodName); | |
} | |
try { | |
Method method = clazz.getDeclaredMethod(methodName); | |
method.setAccessible(true); | |
methodCache.put(clazz, methodName, method); | |
return method; | |
} catch (NoSuchMethodException e) { | |
return null; | |
} | |
} | |
private static Table<Class<?>, MethodParams, Method> methodParamCache = HashBasedTable.create(); | |
public static Method getMethodCached(Class<?> clazz, String methodName, Class<?>... params) { | |
MethodParams methodParams = new MethodParams(methodName, params); | |
if (methodParamCache.contains(clazz, methodParams)) { | |
return methodParamCache.get(clazz, methodParams); | |
} | |
try { | |
Method method = clazz.getDeclaredMethod(methodName, params); | |
method.setAccessible(true); | |
methodParamCache.put(clazz, methodParams, method); | |
return method; | |
} catch (NoSuchMethodException e) { | |
return null; | |
} | |
} | |
private static Table<Class<?>, String, Field> fieldCache = HashBasedTable.create(); | |
public static Field getFieldCached(Class<?> clazz, String fieldName) { | |
if (fieldCache.contains(clazz, fieldName)) { | |
return fieldCache.get(clazz, fieldName); | |
} | |
try { | |
Field field = clazz.getDeclaredField(fieldName); | |
field.setAccessible(true); | |
fieldCache.put(clazz, fieldName, field); | |
return field; | |
} catch (NoSuchFieldException e) { | |
return null; | |
} | |
} | |
private static Map<Class<?>, Constructor<?>> constructorCache = new HashMap<>(); | |
public static Constructor<?> getConstructorCached(Class<?> clazz) { | |
if (constructorCache.containsKey(clazz)) { | |
return constructorCache.get(clazz); | |
} | |
try { | |
Constructor<?> constructor = clazz.getDeclaredConstructor(); | |
constructor.setAccessible(true); | |
constructorCache.put(clazz, constructor); | |
return constructor; | |
} catch (NoSuchMethodException e) { | |
return null; | |
} | |
} | |
private static Table<Class<?>, ConstructorParams, Constructor<?>> constructorParamCache = HashBasedTable.create(); | |
public static Constructor<?> getConstructorCached(Class<?> clazz, Class<?>... params) { | |
ConstructorParams constructorParams = new ConstructorParams(params); | |
if (constructorParamCache.contains(clazz, constructorParams)) { | |
return constructorParamCache.get(clazz, constructorParams); | |
} | |
try { | |
Constructor<?> constructor = clazz.getDeclaredConstructor(params); | |
constructor.setAccessible(true); | |
constructorParamCache.put(clazz, constructorParams, constructor); | |
return constructor; | |
} catch (NoSuchMethodException e) { | |
return null; | |
} | |
} | |
// Adapted from @minecrafter | |
private static class MethodParams { | |
private final String name; | |
private final Class<?>[] params; | |
public MethodParams(final String name, final Class<?>[] params) { | |
this.name = name; | |
this.params = params; | |
} | |
// Ugly autogenned Lombok code | |
@Override | |
public boolean equals(final Object o) { | |
if (o == this) { | |
return true; | |
} | |
if (!(o instanceof MethodParams)) { | |
return false; | |
} | |
final MethodParams that = (MethodParams) o; | |
if (!that.canEqual(this)) { | |
return false; | |
} | |
final Object thisName = this.name; | |
final Object thatName = that.name; | |
if (thisName == null) { | |
if (thatName == null) { | |
return Arrays.deepEquals(this.params, that.params); | |
} | |
} else if (thisName.equals(thatName)) { | |
return Arrays.deepEquals(this.params, that.params); | |
} | |
return false; | |
} | |
boolean canEqual(final Object that) { | |
return that instanceof MethodParams; | |
} | |
@Override | |
public int hashCode() { | |
int result = 1; | |
final Object thisName = this.name; | |
result = result * 31 + ((thisName == null) ? 0 : thisName.hashCode()); | |
result = result * 31 + Arrays.deepHashCode(this.params); | |
return result; | |
} | |
} | |
// Necessary for deepequals | |
private static class ConstructorParams { | |
private final Class<?>[] params; | |
public ConstructorParams(Class<?>[] params) { | |
this.params = params; | |
} | |
@Override | |
public boolean equals(Object o) { | |
if (this == o) return true; | |
if (o == null || getClass() != o.getClass()) return false; | |
ConstructorParams that = (ConstructorParams) o; | |
return Arrays.deepEquals(params, that.params); | |
} | |
@Override | |
public int hashCode() { | |
return Arrays.deepHashCode(params); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment