Last active
August 29, 2015 14:02
-
-
Save riking/2f330f831c30e2276df7 to your computer and use it in GitHub Desktop.
MIT-licensed Cauldron compatibility helpers
This file contains 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
MIT License | |
Copyright (c) 2014, Kane York | |
Permission is hereby granted, free of charge, to any person obtaining a copy | |
of this software and associated documentation files (the "Software"), to deal | |
in the Software without restriction, including without limitation the rights | |
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
copies of the Software, and to permit persons to whom the Software is | |
furnished to do so, subject to the following conditions: | |
The above copyright notice and this permission notice shall be included in | |
all copies or substantial portions of the Software. | |
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
THE SOFTWARE. |
This file contains 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
// Method not shown: getBukkitVersion() | |
// Returns "1_6_R3", "1_7_R1" etc | |
/** | |
* Map of mc-dev simple class name to fully qualified Forge class name. | |
*/ | |
private static Map<String, String> ForgeClassMappings; | |
/** | |
* Map of Forge fully qualified class names to a map from mc-dev field names to Forge field names. | |
*/ | |
private static Map<String, Map<String, String>> ForgeFieldMappings; | |
/** | |
* 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, Map<String, Map<String, String>>> ForgeMethodMappings; | |
private static final boolean isForge = Bukkit.getServer().getName().contains("Cauldron") || Bukkit.getServer().getName().contains("MCPC-Plus"); | |
static { | |
final String nameseg_class = "a-zA-Z0-9$_"; | |
final String fqn_class = nameseg_class + "/"; | |
primitiveTypes = ImmutableMap.<Class<?>, 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<String, String>(); | |
ForgeFieldMappings = new HashMap<String, Map<String, String>>(); | |
ForgeMethodMappings = new HashMap<String, Map<String, Map<String, String>>>(); | |
try { | |
InputStream stream = Class.forName("net.minecraftforge.common.MinecraftForge").getClassLoader() | |
.getResourceAsStream("mappings/" + getBukkitVersion() + "/cb2numpkg.srg"); | |
BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); | |
// 1: cb-simpleName | |
// 2: forge-fullName (Needs dir2fqn()) | |
Pattern classPattern = Pattern.compile("^CL: net/minecraft/server/([" + nameseg_class + "]+) ([" + fqn_class | |
+ "]+)$"); | |
// 1: cb-simpleName | |
// 2: cb-fieldName | |
// 3: forge-fullName (Needs dir2fqn()) | |
// 4: forge-fieldName | |
Pattern fieldPattern = Pattern.compile("^FD: net/minecraft/server/([" + nameseg_class + "]+)/([" + nameseg_class | |
+ "]+) ([" + fqn_class + "]+)/([" + nameseg_class + "]+)$"); | |
// 1: cb-simpleName | |
// 2: cb-methodName | |
// 3: cb-signature-args | |
// 4: cb-signature-ret | |
// 5: forge-fullName (Needs dir2fqn()) | |
// 6: forge-methodName | |
// 7: forge-signature-args | |
// 8: forge-signature-ret | |
Pattern methodPattern = Pattern.compile("^MD: net/minecraft/server/([" + fqn_class + "]+)/([" + nameseg_class | |
+ "]+) \\(([;\\[" + fqn_class + "]*)\\)([;\\[" + fqn_class + "]+) " + "([" + fqn_class + "]+)/([" | |
+ nameseg_class + "]+) \\(([;\\[" + fqn_class + "]*)\\)([;\\[" + fqn_class + "]+)$"); | |
String line; | |
while ((line = reader.readLine()) != null) { | |
Matcher classMatcher = classPattern.matcher(line); | |
if (classMatcher.matches()) { | |
// by CB class name | |
ForgeClassMappings.put(classMatcher.group(1), dir2fqn(classMatcher.group(2))); | |
continue; | |
} | |
Matcher fieldMatcher = fieldPattern.matcher(line); | |
if (fieldMatcher.matches()) { | |
// by CB class name | |
Map<String, String> innerMap = ForgeFieldMappings.get(dir2fqn(fieldMatcher.group(3))); | |
if (innerMap == null) { | |
innerMap = new HashMap<String, String>(); | |
ForgeFieldMappings.put(dir2fqn(fieldMatcher.group(3)), innerMap); | |
} | |
// by CB field name to Forge field name | |
innerMap.put(fieldMatcher.group(2), fieldMatcher.group(4)); | |
continue; | |
} | |
Matcher methodMatcher = methodPattern.matcher(line); | |
if (methodMatcher.matches()) { | |
// get by CB class name | |
Map<String, Map<String, String>> middleMap = ForgeMethodMappings.get(dir2fqn(methodMatcher.group(5))); | |
if (middleMap == null) { | |
middleMap = new HashMap<String, Map<String, String>>(); | |
ForgeMethodMappings.put(dir2fqn(methodMatcher.group(5)), middleMap); | |
} | |
// get by CB method name | |
Map<String, String> innerMap = middleMap.get(methodMatcher.group(2)); | |
if (innerMap == null) { | |
innerMap = new HashMap<String, String>(); | |
middleMap.put(methodMatcher.group(2), innerMap); | |
} | |
// 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] 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. LibsDisguises will likely crash!"); | |
} catch (IOException e) { | |
e.printStackTrace(); | |
System.err | |
.println("Warning: Running on Cauldron server, but couldn't load mappings file. LibsDisguises will likely crash!"); | |
} | |
} | |
} | |
private static String dir2fqn(String s) { | |
return s.replaceAll("/", "."); | |
} | |
public static Class getNmsClass(String className) { | |
if (isForge) { | |
String forgeName = ForgeClassMappings.get(className); | |
if (forgeName != null) { | |
try { | |
return Class.forName(forgeName); | |
} catch (ClassNotFoundException ignored) { | |
} | |
} else { | |
// Throw, because the default cannot possibly work | |
throw new RuntimeException("Missing Forge mapping for " + className); | |
} | |
} | |
try { | |
return Class.forName("net.minecraft.server." + getBukkitVersion() + "." + className); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
return null; | |
} | |
public static Field getNmsField(String className, String fieldName) { | |
return getNmsField(getNmsClass(className), fieldName); | |
} | |
public static Field getNmsField(Class clazz, String fieldName) { | |
if (isForge) { | |
try { | |
return clazz.getField(ForgeFieldMappings.get(clazz.getName()).get(fieldName)); | |
} catch (NoSuchFieldException ex) { | |
ex.printStackTrace(); | |
} catch (NullPointerException ignored) { | |
} | |
} | |
try { | |
return clazz.getField(fieldName); | |
} catch (NoSuchFieldException e) { | |
e.printStackTrace(); | |
} | |
return null; | |
} | |
public static Method getNmsMethod(String className, String methodName, Class<?>... parameters) { | |
return getNmsMethod(getNmsClass(className), methodName, parameters); | |
} | |
public static Method getNmsMethod(Class<?> clazz, String methodName, Class<?>... parameters) { | |
if (isForge) { | |
try { | |
Map<String, String> innerMap = ForgeMethodMappings.get(clazz.getName()).get(methodName); | |
StringBuilder sb = new StringBuilder(); | |
for (Class<?> cl : parameters) { | |
sb.append(methodSignaturePart(cl)); | |
} | |
return clazz.getMethod(innerMap.get(sb.toString()), parameters); | |
} catch (NoSuchMethodException e) { | |
e.printStackTrace(); | |
} catch (NullPointerException ignored) { | |
} | |
} | |
try { | |
return clazz.getMethod(methodName, parameters); | |
} catch (NoSuchMethodException e) { | |
e.printStackTrace(); | |
} | |
return null; | |
} | |
public static boolean isForge() { | |
return isForge; | |
} | |
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("\\.", "/") + ";"; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment