From 7c20a7c3a3ede108b60e4dbbf8c66c6b2213ccbb Mon Sep 17 00:00:00 2001 From: riking Date: Sat, 14 Jun 2014 22:38:16 -0700 Subject: [PATCH] More ReflectionManager stuff --- .../disguise/utilities/ReflectionManager.java | 197 +++++++++--------- .../utilities/ReflectionManagerTests.java | 29 --- 2 files changed, 95 insertions(+), 131 deletions(-) delete mode 100644 test/me/libraryaddict/disguise/utilities/ReflectionManagerTests.java diff --git a/src/me/libraryaddict/disguise/utilities/ReflectionManager.java b/src/me/libraryaddict/disguise/utilities/ReflectionManager.java index be373e2c..6ed9c3f1 100644 --- a/src/me/libraryaddict/disguise/utilities/ReflectionManager.java +++ b/src/me/libraryaddict/disguise/utilities/ReflectionManager.java @@ -7,15 +7,14 @@ import java.io.InputStreamReader; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import java.util.ArrayList; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.UUID; import java.util.regex.Matcher; import java.util.regex.Pattern; import com.google.common.collect.ImmutableMap; +import me.libraryaddict.disguise.disguisetypes.DisguiseType; import org.bukkit.Art; import org.bukkit.Bukkit; import org.bukkit.Location; @@ -76,36 +75,31 @@ public class ReflectionManager { */ private static Map> ForgeFieldMappings; /** - * Map of Forge fully qualified class names to a map from mc-dev method names to Forge method names. - * - * There may be a mapping from null in the innermost map, which may be ignored. + * Map of Forge fully qualified class names to a map from mc-dev method names to a map from method signatures to Forge method names. */ - private static Map[], String>>> ForgeMethodMappings; - private static Map> primitiveTypes; - private static Pattern signatureSegment; + private static Map>> ForgeMethodMappings; + private static Map, String> primitiveTypes; static { final String nameseg_class = "a-zA-Z0-9$_"; - final String fqn_class = "a-zA-Z0-9$_/"; - final String fqn_component = "L[" + fqn_class + "]+;"; + final String fqn_class = nameseg_class + "/"; - signatureSegment = Pattern.compile("\\[*(?:Z|B|C|S|I|J|F|D|V|" + fqn_component + ")"); - primitiveTypes = ImmutableMap.>builder() - .put("Z", boolean.class) - .put("B", byte.class) - .put("C", char.class) - .put("S", short.class) - .put("I", int.class) - .put("J", long.class) - .put("F", float.class) - .put("D", double.class) - .put("V", void.class).build(); + primitiveTypes = ImmutableMap., String>builder() + .put(boolean.class,"Z") + .put(byte.class, "B") + .put(char.class, "C") + .put(short.class, "S") + .put(int.class, "I") + .put(long.class, "J") + .put(float.class, "F") + .put(double.class, "D") + .put(void.class, "V").build(); if (isForge) { // Initialize the maps by reading the srg file ForgeClassMappings = new HashMap(); ForgeFieldMappings = new HashMap>(); - ForgeMethodMappings = new HashMap[], String>>>(); + ForgeMethodMappings = new HashMap>>(); try { InputStream stream = Class.forName("net.minecraftforge.common.MinecraftForge").getClassLoader() .getResourceAsStream("mappings/" + getBukkitVersion() + "/cb2numpkg.srg"); @@ -153,49 +147,37 @@ public class ReflectionManager { Matcher methodMatcher = methodPattern.matcher(line); if (methodMatcher.matches()) { // get by CB class name - Map[], String>> middleMap = ForgeMethodMappings.get(dir2fqn(methodMatcher.group(5))); + Map> middleMap = ForgeMethodMappings.get(dir2fqn(methodMatcher.group(5))); if (middleMap == null) { - middleMap = new HashMap[], String>>(); + middleMap = new HashMap>(); ForgeMethodMappings.put(dir2fqn(methodMatcher.group(5)), middleMap); } // get by CB method name - Map[], String> innerMap = middleMap.get(methodMatcher.group(2)); + Map innerMap = middleMap.get(methodMatcher.group(2)); if (innerMap == null) { - innerMap = new HashMap[], String>(); + innerMap = new HashMap(); middleMap.put(methodMatcher.group(2), innerMap); } - // parse the class array - Class[] argsCb = null, argsForge = null; - try { - argsCb = parseSignatureArguments(methodMatcher.group(3)); - } catch (Throwable ignored) { - } - try { - argsForge = parseSignatureArguments(methodMatcher.group(7)); - } catch (Throwable ignored) { - } - - innerMap.put(argsCb, methodMatcher.group(6)); - innerMap.put(argsForge, methodMatcher.group(6)); - System.out.println(methodMatcher.group(5) + "/" + methodMatcher.group(2) + "(" + argsForge + ") -> " + methodMatcher.group(6)); - continue; + // store the parameter strings + innerMap.put(methodMatcher.group(3), methodMatcher.group(6)); + innerMap.put(methodMatcher.group(7), methodMatcher.group(6)); } } System.out.println("[LibsDisguises] Loaded in Cauldron/Forge mode"); - System.out.println("[LibsDisguises]" + ForgeClassMappings.size() + " Cauldron class mappings loaded"); - System.out.println("[LibsDisguises]" + ForgeFieldMappings.size() + " Cauldron field mappings loaded"); - System.out.println("[LibsDisguises]" + ForgeMethodMappings.size() + " Cauldron method mappings loaded"); + System.out.println("[LibsDisguises] Loaded " + ForgeClassMappings.size() + " Cauldron class mappings"); + System.out.println("[LibsDisguises] Loaded " + ForgeFieldMappings.size() + " Cauldron field mappings"); + System.out.println("[LibsDisguises] Loaded " + ForgeMethodMappings.size() + " Cauldron method mappings"); } catch (ClassNotFoundException e) { e.printStackTrace(); - System.err.println("Warning: Running on Cauldron server, but couldn't load mappings file"); + System.err.println("Warning: Running on Cauldron server, but couldn't load mappings file. LibsDisguises will likely crash!"); } catch (IOException e) { e.printStackTrace(); - System.err.println("Warning: Running on Cauldron server, but couldn't load mappings file"); + System.err.println("Warning: Running on Cauldron server, but couldn't load mappings file. LibsDisguises will likely crash!"); } } } - private static final Class craftItemClass; + private static final Class craftItemClass; private static final Field pingField; private static final Field trackerField; private static final Field entitiesField; @@ -224,36 +206,17 @@ public class ReflectionManager { trackerField = getNmsField("WorldServer", "tracker"); entitiesField = getNmsField("EntityTracker", "trackedEntities"); ihmGet = getNmsMethod("IntHashMap", "get", int.class); + + Method m = getNmsMethod("Item", "getItemOf", getNmsClass("Block")); + System.out.println(m); + + DisguiseType.ARROW.isMisc(); } private static String dir2fqn(String s) { return s.replaceAll("/", "."); } - public static Class[] parseSignatureArguments(String args) throws ClassNotFoundException { - List> classes = new ArrayList>(); - Matcher matcher = signatureSegment.matcher(args); - while (matcher.find()) { - classes.add(parseClass(matcher.group())); - } - return classes.toArray(new Class[classes.size()]); - } - - private static Class parseClass(String str) throws ClassNotFoundException { - if (str.startsWith("[")) { - // Array - // http://stackoverflow.com/a/4901192/1210278 - return java.lang.reflect.Array.newInstance(parseClass(str.substring(1)), 0).getClass(); - } else if (str.length() == 1) { - return primitiveTypes.get(str); - } else if (str.startsWith("L")) { - // Chop off L and ; - return Class.forName(str.substring(1, str.length() - 1)); - } else { - throw new ClassNotFoundException("Malformed method signature fragment? Argument: " + str); - } - } - // === public static Object createEntityInstance(String entityName) { @@ -327,7 +290,7 @@ public class ReflectionManager { public static Entity getBukkitEntity(Object nmsEntity) { try { - return (Entity) ReflectionManager.getNmsClass("Entity").getMethod("getBukkitEntity").invoke(nmsEntity); + return (Entity) getNmsMethod("Entity", "getBukkitEntity").invoke(nmsEntity); } catch (Exception ex) { ex.printStackTrace(); } @@ -347,7 +310,7 @@ public class ReflectionManager { return bukkitVersion; } - public static Class getCraftClass(String className) { + public static Class getCraftClass(String className) { try { return Class.forName("org.bukkit.craftbukkit." + getBukkitVersion() + "." + className); } catch (Exception e) { @@ -358,8 +321,7 @@ public class ReflectionManager { public static String getCraftSound(Sound sound) { try { - Class c = getCraftClass("CraftSound"); - return (String) c.getMethod("getSound", Sound.class).invoke(null, sound); + return (String) getCraftClass("CraftSound").getMethod("getSound", Sound.class).invoke(null, sound); } catch (Exception ex) { ex.printStackTrace(); } @@ -368,8 +330,7 @@ public class ReflectionManager { public static String getEnumArt(Art art) { try { - Class craftArt = Class.forName("org.bukkit.craftbukkit." + getBukkitVersion() + ".CraftArt"); - Object enumArt = craftArt.getMethod("BukkitToNotch", Art.class).invoke(null, art); + Object enumArt = getCraftClass("CraftArt").getMethod("BukkitToNotch", Art.class).invoke(null, art); for (Field field : enumArt.getClass().getFields()) { if (field.getType() == String.class) { return (String) field.get(enumArt); @@ -416,15 +377,17 @@ public class ReflectionManager { } public static Class getNmsClass(String className) { - try { - if (isForge) { - String forgeName = ForgeClassMappings.get(className); - if (forgeName == null) { - throw new RuntimeException("Missing Forge mapping for " + className); + if (isForge) { + String forgeName = ForgeClassMappings.get(className); + if (forgeName != null) { + try { + return Class.forName(forgeName); + } catch (ClassNotFoundException ignored) { } - return Class.forName(forgeName); - } - + } else + throw new RuntimeException("Missing Forge mapping for " + className); + } + try { return Class.forName("net.minecraft.server." + getBukkitVersion() + "." + className); } catch (Exception e) { e.printStackTrace(); @@ -455,14 +418,21 @@ public class ReflectionManager { } public static Field getNmsField(Class clazz, String fieldName) { - try { - if (isForge) { - Map fieldMap = ForgeFieldMappings.get(clazz.getName()); - if (fieldMap == null) { throw new RuntimeException("No field mappings for " + clazz.getName()); } + if (isForge) { + Map fieldMap = ForgeFieldMappings.get(clazz.getName()); + if (fieldMap != null) { String forgeName = fieldMap.get(fieldName); - if (forgeName == null) { throw new RuntimeException("No field mapping for " + clazz.getName() + "." + fieldName); } - return clazz.getField(forgeName); - } + if (forgeName != null) { + try { + return clazz.getField(forgeName); + } catch (NoSuchFieldException ignored) { + } + } else + throw new RuntimeException("No field mapping for " + clazz.getName() + "." + fieldName); + } else + throw new RuntimeException("No field mappings for " + clazz.getName()); + } + try { return clazz.getField(fieldName); } catch (NoSuchFieldException e) { e.printStackTrace(); @@ -474,17 +444,40 @@ public class ReflectionManager { return getNmsMethod(getNmsClass(className), methodName, parameters); } + private static String methodSignaturePart(Class param) { + if (param.isArray()) { + return "[" + methodSignaturePart(param.getComponentType()); + } else if (param.isPrimitive()) { + return primitiveTypes.get(param); + } else { + return "L" + param.getName().replaceAll("\\.", "/") + ";"; + } + } + public static Method getNmsMethod(Class clazz, String methodName, Class... parameters) { + if (isForge) { + Map> middleMap = ForgeMethodMappings.get(clazz.getName()); + if (middleMap != null) { + Map innerMap = middleMap.get(methodName); + if (innerMap != null) { + StringBuilder sb = new StringBuilder(); + for (Class cl : parameters) { + sb.append(methodSignaturePart(cl)); + } + String trName = innerMap.get(sb.toString()); + if (trName != null) { + try { + return clazz.getMethod(trName, parameters); + } catch (NoSuchMethodException ignored) { + } + } else + throw new RuntimeException("No method mapping for " + clazz.getName() + "." + methodName + "(" + sb.toString() + ")"); + } else + throw new RuntimeException("No method mapping for " + clazz.getName() + "." + methodName); + } else + throw new RuntimeException("No method mappings for " + clazz.getName()); + } try { - if (isForge) { - Map[], String>> middleMap = ForgeMethodMappings.get(clazz.getName()); - if (middleMap == null) { throw new RuntimeException("No method mappings for " + clazz.getName()); } - Map[], String> innerMap = middleMap.get(methodName); - if (innerMap == null) { throw new RuntimeException("No method mapping for " + clazz.getName() + "." + methodName); } - String trName = innerMap.get(parameters); - if (trName == null) { throw new RuntimeException("No method mapping for " + clazz.getName() + "." + methodName + "(" + parameters + ")"); } - return clazz.getMethod(trName, parameters); - } return clazz.getMethod(methodName, parameters); } catch (NoSuchMethodException e) { e.printStackTrace(); @@ -550,7 +543,7 @@ public class ReflectionManager { public static WrappedGameProfile grabProfileAddUUID(String playername) { try { - Object minecraftServer = getNmsClass("MinecraftServer").getMethod("getServer").invoke(null); + Object minecraftServer = getNmsMethod("MinecraftServer", "getServer").invoke(null); for (Method method : getNmsClass("MinecraftServer").getMethods()) { if (method.getReturnType().getSimpleName().equals("GameProfileRepository")) { Object profileRepo = method.invoke(minecraftServer); diff --git a/test/me/libraryaddict/disguise/utilities/ReflectionManagerTests.java b/test/me/libraryaddict/disguise/utilities/ReflectionManagerTests.java deleted file mode 100644 index 8bfdedf7..00000000 --- a/test/me/libraryaddict/disguise/utilities/ReflectionManagerTests.java +++ /dev/null @@ -1,29 +0,0 @@ -package me.libraryaddict.disguise.utilities; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -public class ReflectionManagerTests { - - @Test - public void testParseSignatureArguments() throws Exception { - Class[] expect, actual; - - expect = new Class[] {boolean.class, byte.class, char.class, short.class, int.class, long.class, float.class, double.class}; - actual = ReflectionManager.parseSignatureArguments("ZBCSIJFD"); - assertEquals(expect, actual); - - expect = new Class[] {int.class, String[].class, int.class, String.class}; - actual = ReflectionManager.parseSignatureArguments("I[Ljava/lang/String;ILjava/lang/String;"); - assertEquals(expect, actual); - - expect = new Class[] {}; - actual = ReflectionManager.parseSignatureArguments(""); - assertEquals(expect, actual); - - expect = new Class[] {boolean[][][][][][].class}; - actual = ReflectionManager.parseSignatureArguments("[[[[[[Z"); - assertEquals(expect, actual); - } -}