package amidst.minecraft; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.HashMap; import amidst.logging.Log; public class MinecraftMethod { private MinecraftClass parent; private Minecraft minecraft; private Class<?>[] paramClasses; private String[] paramNames; private boolean hasParameters; private Method method; private String name, internalName; private MinecraftClass returnType; private boolean isMinecraftClass = false; private boolean loadFailed = false; private static HashMap<String, Class<?>> primitives; static { primitives = new HashMap<String, Class<?>>(); primitives.put("byte", byte.class); primitives.put("int", int.class); primitives.put("float", float.class); primitives.put("short", short.class); primitives.put("long", long.class); primitives.put("double", double.class); primitives.put("boolean", boolean.class); primitives.put("char", char.class); primitives.put("String", String.class); } public MinecraftMethod(MinecraftClass parent, String name, String methodName) { this.parent = parent; hasParameters = false; this.name = name; internalName = methodName; paramClasses = new Class<?>[] {}; } public MinecraftMethod(MinecraftClass parent, String name, String methodName, String... args) { this.parent = parent; paramNames = args; paramClasses = new Class<?>[paramNames.length]; hasParameters = true; this.name = name; internalName = methodName; } public void load(Minecraft mc, MinecraftClass mcClass) { minecraft = mc; Class<?> clazz = mcClass.getClazz(); int i = 0; try { if (hasParameters) { for (; i < paramNames.length; i++) { paramClasses[i] = primitives.get(paramNames[i]); if (paramClasses[i] == null) paramClasses[i] = mc.getClassLoader().loadClass(paramNames[i]); // TODO: Does this cause duplicate loads? } } method = clazz.getDeclaredMethod(internalName, paramClasses); method.setAccessible(true); String methodType = method.getReturnType().getName(); if (methodType.contains(".")) { String[] typeSplit = methodType.split("\\."); methodType = typeSplit[typeSplit.length-1]; } returnType = minecraft.getClassByType(methodType); if (returnType == null) isMinecraftClass = false; } catch (ClassNotFoundException e) { loadFailed = true; Log.w(e, "Unabled to find class for parameter. (" + paramNames[i] + ") on (" + mcClass.getName() + " / " + mcClass.getClassName() + ")"); e.printStackTrace(); } catch (SecurityException e) { loadFailed = true; Log.w(e, "SecurityException on (" + mcClass.getName() + " / " + mcClass.getClassName() + ") method (" + name + " / " + internalName +")"); e.printStackTrace(); } catch (NoSuchMethodException e) { loadFailed = true; Log.w(e, "Unable to find class method (" + mcClass.getName() + " / " + mcClass.getClassName() + ") (" + name + " / " + internalName +")"); e.printStackTrace(); } } public Object callStatic(Object... param) { Object value = call((Object)null, param); if (isMinecraftClass) { return new MinecraftObject(returnType, value); } return value; } public Object call(MinecraftObject obj, Object... param) { Object value = call(obj.get(), param); if (isMinecraftClass) return new MinecraftObject(returnType, value); return value; } private Object call(Object obj, Object... param) { try { return method.invoke(obj, param); } catch (IllegalArgumentException e) { // TODO : Add error text e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } return null; } public Object getParentName() { return parent.getName(); } public String getInternalName() { return internalName; } public String getName() { return name; } public boolean exists() { return !loadFailed; } }