diff --git a/fml/build.xml b/fml/build.xml
index 587bb5a053..eff40159e7 100644
--- a/fml/build.xml
+++ b/fml/build.xml
@@ -266,14 +266,17 @@
Moving old patched sources at ${mcp.home}/src-work out of the way
-
+
-
+
+
+
+
-
+
diff --git a/fml/client/cpw/mods/fml/client/FMLClientHandler.java b/fml/client/cpw/mods/fml/client/FMLClientHandler.java
index 4ce22755bb..eea61f0d4c 100644
--- a/fml/client/cpw/mods/fml/client/FMLClientHandler.java
+++ b/fml/client/cpw/mods/fml/client/FMLClientHandler.java
@@ -88,13 +88,13 @@ import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.ModContainer;
import cpw.mods.fml.common.ModMetadata;
import cpw.mods.fml.common.ProxyInjector;
-import cpw.mods.fml.common.ReflectionHelper;
import cpw.mods.fml.common.Side;
import cpw.mods.fml.common.TickType;
import cpw.mods.fml.common.modloader.ModLoaderHelper;
import cpw.mods.fml.common.modloader.ModLoaderModContainer;
import cpw.mods.fml.common.modloader.ModProperty;
import cpw.mods.fml.common.registry.FMLRegistry;
+import cpw.mods.fml.common.ReflectionHelper;
/**
diff --git a/fml/client/net/minecraft/src/ModLoader.java b/fml/client/net/minecraft/src/ModLoader.java
index 91be235c7d..502caebd03 100644
--- a/fml/client/net/minecraft/src/ModLoader.java
+++ b/fml/client/net/minecraft/src/ModLoader.java
@@ -26,10 +26,10 @@ import cpw.mods.fml.client.FMLClientHandler;
import cpw.mods.fml.client.SpriteHelper;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.Loader;
-import cpw.mods.fml.common.ReflectionHelper;
import cpw.mods.fml.common.modloader.ModLoaderHelper;
import cpw.mods.fml.common.modloader.ModLoaderModContainer;
import cpw.mods.fml.common.registry.FMLRegistry;
+import cpw.mods.fml.common.ReflectionHelper;
public class ModLoader
{
@@ -733,7 +733,7 @@ public class ModLoader
*/
public static void setPrivateValue(Class super T> instanceclass, T instance, int fieldindex, E value)
{
- ReflectionHelper.setPrivateValue(instanceclass, instance, fieldindex, value);
+ ReflectionHelper.setPrivateValue(instanceclass, instance, value, fieldindex);
}
/**
@@ -747,7 +747,7 @@ public class ModLoader
*/
public static void setPrivateValue(Class super T> instanceclass, T instance, String field, E value)
{
- ReflectionHelper.setPrivateValue(instanceclass, instance, field, value);
+ ReflectionHelper.setPrivateValue(instanceclass, instance, value, field);
}
/**
diff --git a/fml/common/cpw/mods/fml/common/ReflectionHelper.java b/fml/common/cpw/mods/fml/common/ReflectionHelper.java
index 30bc523448..251da11835 100644
--- a/fml/common/cpw/mods/fml/common/ReflectionHelper.java
+++ b/fml/common/cpw/mods/fml/common/ReflectionHelper.java
@@ -14,9 +14,15 @@ package cpw.mods.fml.common;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.logging.Level;
+
+import cpw.mods.fml.common.FMLCommonHandler;
+import cpw.mods.fml.relauncher.ReflectionHelper.UnableToAccessFieldException;
+import cpw.mods.fml.relauncher.ReflectionHelper.UnableToFindFieldException;
/**
* Some reflection helper code.
- *
+ *
* @author cpw
*
*/
@@ -29,73 +35,79 @@ public class ReflectionHelper
{
try
{
- Field f = classToAccess.getDeclaredFields()[fieldIndex];
- f.setAccessible(true);
- return (T) f.get(instance);
+ return cpw.mods.fml.relauncher.ReflectionHelper.getPrivateValue(classToAccess, instance, fieldIndex);
}
- catch (Exception e)
+ catch (UnableToAccessFieldException e)
{
- FMLCommonHandler.instance().getFMLLogger().severe(String.format("There was a problem getting field %d from %s", fieldIndex, classToAccess.getName()));
- FMLCommonHandler.instance().getFMLLogger().throwing("ReflectionHelper", "getPrivateValue", e);
- throw new RuntimeException(e);
+ FMLCommonHandler.instance().getFMLLogger().log(Level.SEVERE, String.format("There was a problem getting field index %d from %s", fieldIndex, classToAccess.getName()), e);
+ throw e;
}
}
@SuppressWarnings("unchecked")
- public static T getPrivateValue(Class super E > classToAccess, E instance, String fieldName)
+ public static T getPrivateValue(Class super E > classToAccess, E instance, String... fieldNames)
{
try
{
- Field f = classToAccess.getDeclaredField(fieldName);
- f.setAccessible(true);
- return (T) f.get(instance);
+ return cpw.mods.fml.relauncher.ReflectionHelper.getPrivateValue(classToAccess, instance, fieldNames);
}
- catch (Exception e)
+ catch (UnableToFindFieldException e)
{
- if ((fieldName.length() > 3 && !obfuscation) || (fieldName.length() <= 3 && obfuscation)) {
- FMLCommonHandler.instance().getFMLLogger().severe(String.format("There was a problem getting field %s from %s", fieldName, classToAccess.getName()));
- FMLCommonHandler.instance().getFMLLogger().throwing("ReflectionHelper", "getPrivateValue", e);
- }
- throw new RuntimeException(e);
+ FMLCommonHandler.instance().getFMLLogger().log(Level.SEVERE, String.format("Unable to locate any field %s on type %s", Arrays.toString(fieldNames), classToAccess.getName()), e);
+ throw e;
+ }
+ catch (UnableToAccessFieldException e)
+ {
+ FMLCommonHandler.instance().getFMLLogger().log(Level.SEVERE, String.format("Unable to access any field %s on type %s", Arrays.toString(fieldNames), classToAccess.getName()), e);
+ throw e;
}
}
+ @Deprecated
public static void setPrivateValue(Class super T > classToAccess, T instance, int fieldIndex, E value)
{
- try
- {
- Field f = classToAccess.getDeclaredFields()[fieldIndex];
- f.setAccessible(true);
- f.set(instance, value);
- }
- catch (Exception e)
- {
- FMLCommonHandler.instance().getFMLLogger().severe(String.format("There was a problem setting field %d from %s", fieldIndex, classToAccess.getName()));
- FMLCommonHandler.instance().getFMLLogger().throwing("ReflectionHelper", "getPrivateValue", e);
- throw new RuntimeException(e);
- }
+ setPrivateValue(classToAccess, instance, value, fieldIndex);
}
- public static void setPrivateValue(Class super T > classToAccess, T instance, String fieldName, E value)
+ public static void setPrivateValue(Class super T > classToAccess, T instance, E value, int fieldIndex)
{
try
{
- Field f = classToAccess.getDeclaredField(fieldName);
- f.setAccessible(true);
- f.set(instance, value);
+ cpw.mods.fml.relauncher.ReflectionHelper.setPrivateValue(classToAccess, instance, value, fieldIndex);
}
- catch (Exception e)
+ catch (UnableToAccessFieldException e)
{
- if ((fieldName.length() > 3 && !obfuscation) || (fieldName.length() <= 3 && obfuscation)) {
- FMLCommonHandler.instance().getFMLLogger().severe(String.format("There was a problem setting field %s from %s", fieldName, classToAccess.getName()));
- FMLCommonHandler.instance().getFMLLogger().throwing("ReflectionHelper", "getPrivateValue", e);
- }
- throw new RuntimeException(e);
+ FMLCommonHandler.instance().getFMLLogger().log(Level.SEVERE, String.format("There was a problem setting field index %d on type %s", fieldIndex, classToAccess.getName()));
+ throw e;
+ }
+ }
+
+ @Deprecated
+ public static void setPrivateValue(Class super T > classToAccess, T instance, String fieldName, E value)
+ {
+ setPrivateValue(classToAccess, instance, value, fieldName);
+ }
+
+ public static void setPrivateValue(Class super T > classToAccess, T instance, E value, String... fieldNames)
+ {
+ try
+ {
+ cpw.mods.fml.relauncher.ReflectionHelper.setPrivateValue(classToAccess, instance, value, fieldNames);
+ }
+ catch (UnableToFindFieldException e)
+ {
+ FMLCommonHandler.instance().getFMLLogger().log(Level.SEVERE, String.format("Unable to locate any field %s on type %s", Arrays.toString(fieldNames), classToAccess.getName()), e);
+ throw e;
+ }
+ catch (UnableToAccessFieldException e)
+ {
+ FMLCommonHandler.instance().getFMLLogger().log(Level.SEVERE, String.format("Unable to set any field %s on type %s", Arrays.toString(fieldNames), classToAccess.getName()), e);
+ throw e;
}
}
/**
- *
+ *
*/
public static void detectObfuscation(Class> clazz)
{
diff --git a/fml/common/cpw/mods/fml/relauncher/FMLEmbeddingRelauncher.java b/fml/common/cpw/mods/fml/relauncher/FMLEmbeddingRelauncher.java
index d924f816f0..f905984268 100644
--- a/fml/common/cpw/mods/fml/relauncher/FMLEmbeddingRelauncher.java
+++ b/fml/common/cpw/mods/fml/relauncher/FMLEmbeddingRelauncher.java
@@ -1,17 +1,18 @@
package cpw.mods.fml.relauncher;
+import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
import java.net.URLClassLoader;
+import java.util.Arrays;
-import net.minecraft.client.Minecraft;
import net.minecraft.src.WorldSettings;
public class FMLEmbeddingRelauncher
{
private static FMLEmbeddingRelauncher INSTANCE;
private RelaunchClassLoader clientLoader;
- private RelaunchClassLoader serverLoader;
public static void relaunch(ArgsWrapper wrap)
{
@@ -24,25 +25,36 @@ public class FMLEmbeddingRelauncher
URLClassLoader ucl = (URLClassLoader)getClass().getClassLoader();
clientLoader = new RelaunchClassLoader(ucl.getURLs());
- serverLoader = new RelaunchClassLoader(ucl.getURLs());
}
private void relaunchClient(ArgsWrapper wrap)
{
+ Class super Object> mcMaster = ReflectionHelper.getClass(getClass().getClassLoader(), "net.minecraft.client.Minecraft");
+ // We force minecraft to setup it's homedir very early on so we can inject stuff into it
+ Method setupHome = ReflectionHelper.findMethod(mcMaster, null, new String[] { "func_6240_b", "getMinecraftDir", "b"} );
try
{
- Class> original = Class.forName("net.minecraft.client.Minecraft", false, getClass().getClassLoader());
- Field origDir = original.getDeclaredField("field_6275_Z");
- origDir.setAccessible(true);
- Class client = Class.forName("net.minecraft.client.Minecraft", false, clientLoader);
- Field homeDir = client.getDeclaredField("field_6275_Z");
- homeDir.setAccessible(true);
- homeDir.set(null, origDir.get(null));
- client.getMethod("fmlReentry", ArgsWrapper.class).invoke(null, wrap);
+ setupHome.invoke(null);
}
catch (Exception e)
{
- e.printStackTrace();
+ // Hmmm
+ }
+ File minecraftHome = ReflectionHelper.getPrivateValue(mcMaster, null, "field_6275_Z", "ap", "minecraftDir");
+
+ RelaunchLibraryManager.handleLaunch(minecraftHome, clientLoader);
+
+ // Now we re-inject the home into the "new" minecraft under our control
+ Class super Object> client = ReflectionHelper.getClass(clientLoader, "net.minecraft.client.Minecraft");
+ ReflectionHelper.setPrivateValue(client, null, minecraftHome, "field_6275_Z", "ap", "minecraftDir");
+
+ try
+ {
+ ReflectionHelper.findMethod(client, null, new String[] { "fmlReentry" }, ArgsWrapper.class).invoke(null, wrap);
+ }
+ catch (Exception e)
+ {
+ // Hmmm
}
}
}
diff --git a/fml/common/cpw/mods/fml/relauncher/ReflectionHelper.java b/fml/common/cpw/mods/fml/relauncher/ReflectionHelper.java
new file mode 100644
index 0000000000..f441197feb
--- /dev/null
+++ b/fml/common/cpw/mods/fml/relauncher/ReflectionHelper.java
@@ -0,0 +1,183 @@
+/*
+ * The FML Forge Mod Loader suite. Copyright (C) 2012 cpw
+ *
+ * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 2.1 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+package cpw.mods.fml.relauncher;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+import cpw.mods.fml.common.FMLCommonHandler;
+/**
+ * Some reflection helper code.
+ *
+ * @author cpw
+ *
+ */
+public class ReflectionHelper
+{
+ public static class UnableToFindMethodException extends RuntimeException
+ {
+ private String[] methodNames;
+
+ public UnableToFindMethodException(String[] methodNames, Exception failed)
+ {
+ super(failed);
+ this.methodNames = methodNames;
+ }
+
+ }
+
+ public static class UnableToFindClassException extends RuntimeException
+ {
+ private String[] classNames;
+
+ public UnableToFindClassException(String[] classNames, Exception err)
+ {
+ super(err);
+ this.classNames = classNames;
+ }
+
+ }
+
+ public static class UnableToAccessFieldException extends RuntimeException
+ {
+
+ private String[] fieldNameList;
+
+ public UnableToAccessFieldException(String[] fieldNames, Exception e)
+ {
+ super(e);
+ this.fieldNameList = fieldNames;
+ }
+ }
+
+ public static class UnableToFindFieldException extends RuntimeException
+ {
+ private String[] fieldNameList;
+ public UnableToFindFieldException(String[] fieldNameList, Exception e)
+ {
+ super(e);
+ this.fieldNameList = fieldNameList;
+ }
+ }
+
+ public static Field findField(Class> clazz, String... fieldNames)
+ {
+ Exception failed = null;
+ for (String fieldName : fieldNames)
+ {
+ try
+ {
+ Field f = clazz.getDeclaredField(fieldName);
+ f.setAccessible(true);
+ return f;
+ }
+ catch (Exception e)
+ {
+ failed = e;
+ }
+ }
+ throw new UnableToFindFieldException(fieldNames, failed);
+ }
+
+ @SuppressWarnings("unchecked")
+ public static T getPrivateValue(Class super E > classToAccess, E instance, int fieldIndex)
+ {
+ try
+ {
+ Field f = classToAccess.getDeclaredFields()[fieldIndex];
+ f.setAccessible(true);
+ return (T) f.get(instance);
+ }
+ catch (Exception e)
+ {
+ throw new UnableToAccessFieldException(new String[0], e);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public static T getPrivateValue(Class super E > classToAccess, E instance, String... fieldNames)
+ {
+ try
+ {
+ return (T) findField(classToAccess, fieldNames).get(instance);
+ }
+ catch (Exception e)
+ {
+ throw new UnableToAccessFieldException(fieldNames, e);
+ }
+ }
+
+ public static void setPrivateValue(Class super T > classToAccess, T instance, E value, int fieldIndex)
+ {
+ try
+ {
+ Field f = classToAccess.getDeclaredFields()[fieldIndex];
+ f.setAccessible(true);
+ f.set(instance, value);
+ }
+ catch (Exception e)
+ {
+ throw new UnableToAccessFieldException(new String[0] , e);
+ }
+ }
+
+ public static void setPrivateValue(Class super T > classToAccess, T instance, E value, String... fieldNames)
+ {
+ try
+ {
+ findField(classToAccess, fieldNames).set(instance, value);
+ }
+ catch (Exception e)
+ {
+ throw new UnableToAccessFieldException(fieldNames, e);
+ }
+ }
+
+ public static Class super Object> getClass(ClassLoader loader, String... classNames)
+ {
+ Exception err = null;
+ for (String className : classNames)
+ {
+ try
+ {
+ return (Class super Object>) Class.forName(className, false, loader);
+ }
+ catch (Exception e)
+ {
+ err = e;
+ }
+ }
+
+ throw new UnableToFindClassException(classNames, err);
+ }
+
+
+ public static Method findMethod(Class super E> clazz, E instance, String[] methodNames, Class>... methodTypes)
+ {
+ Exception failed = null;
+ for (String methodName : methodNames)
+ {
+ try
+ {
+ Method m = clazz.getDeclaredMethod(methodName, methodTypes);
+ m.setAccessible(true);
+ return m;
+ }
+ catch (Exception e)
+ {
+ failed = e;
+ }
+ }
+ throw new UnableToFindMethodException(methodNames, failed);
+ }
+}
diff --git a/fml/common/cpw/mods/fml/relauncher/RelaunchClassLoader.java b/fml/common/cpw/mods/fml/relauncher/RelaunchClassLoader.java
index 5a4e720349..78546e91cc 100644
--- a/fml/common/cpw/mods/fml/relauncher/RelaunchClassLoader.java
+++ b/fml/common/cpw/mods/fml/relauncher/RelaunchClassLoader.java
@@ -28,4 +28,11 @@ public class RelaunchClassLoader extends URLClassLoader
return super.loadClass(name);
}
}
+
+ @Override
+ protected void addURL(URL url)
+ {
+ super.addURL(url);
+ System.out.println(Arrays.toString(getURLs()));
+ }
}
diff --git a/fml/common/cpw/mods/fml/relauncher/RelaunchLibraryManager.java b/fml/common/cpw/mods/fml/relauncher/RelaunchLibraryManager.java
new file mode 100644
index 0000000000..383e3682c9
--- /dev/null
+++ b/fml/common/cpw/mods/fml/relauncher/RelaunchLibraryManager.java
@@ -0,0 +1,137 @@
+package cpw.mods.fml.relauncher;
+
+import java.awt.HeadlessException;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigInteger;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+import java.net.URLConnection;
+import java.nio.MappedByteBuffer;
+import java.nio.channels.Channels;
+import java.nio.channels.FileChannel;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.FileChannel.MapMode;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+import javax.swing.JOptionPane;
+
+public class RelaunchLibraryManager
+{
+ private static String[] libraries = { "argo-2.25.jar","guava-12.0.jar","asm-all-4.0.jar" };
+ private static String[] checksums = { "bb672829fde76cb163004752b86b0484bd0a7f4b", "5bc66dd95b79db1e437eb08adba124a3e4088dc0", "98308890597acb64047f7e896638e0d98753ae82" };
+ private static final String HEXES = "0123456789abcdef";
+ public static void handleLaunch(File mcDir, RelaunchClassLoader actualClassLoader)
+ {
+ File libDir = new File(mcDir,"lib");
+ try
+ {
+ libDir = libDir.getCanonicalFile();
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException(String.format("Unable to canonicalize the lib dir at %s", mcDir.getName()),e);
+ }
+ if (!libDir.exists())
+ {
+ libDir.mkdir();
+ }
+ else if (libDir.exists() && !libDir.isDirectory())
+ {
+ throw new RuntimeException(String.format("Found a lib file in %s that's not a directory", mcDir.getName()));
+ }
+
+ for (int i=0; i> 4))
+ .append(HEXES.charAt((b & 0x0F)));
+ }
+ return hex.toString();
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+ private static void downloadFile(File libFile)
+ {
+ // try
+// {
+// JOptionPane.showMessageDialog(null, String.format("Downloading required FML library %s from github.com",libName));
+// }
+// catch (HeadlessException he)
+// {
+// // Ignore
+// }
+ try
+ {
+ URL libDownload = new URL(String.format("http://cloud.github.com/downloads/cpw/FML/%s",libFile.getName()));
+ System.out.printf("Downloading %s..", libDownload.toString());
+ InputStream urlConn = libDownload.openStream();
+ ReadableByteChannel urlChannel = Channels.newChannel(urlConn);
+ FileOutputStream libFileStream = new FileOutputStream(libFile);
+ FileChannel libFileChannel = libFileStream.getChannel();
+ libFileChannel.transferFrom(urlChannel, 0, 1<<24);
+ libFileChannel.close();
+ libFileStream.close();
+ urlChannel.close();
+ urlConn.close();
+ System.out.println("download successful");
+ }
+ catch (Exception e)
+ {
+
+ }
+ }
+}
diff --git a/fml/eclipse/Clean-Client/.classpath b/fml/eclipse/Clean-Client/.classpath
index 6bf817e741..2660e24ec7 100644
--- a/fml/eclipse/Clean-Client/.classpath
+++ b/fml/eclipse/Clean-Client/.classpath
@@ -18,5 +18,6 @@
+
diff --git a/fml/eclipse/FML-Client/.classpath b/fml/eclipse/FML-Client/.classpath
index d750167506..ea960b8032 100644
--- a/fml/eclipse/FML-Client/.classpath
+++ b/fml/eclipse/FML-Client/.classpath
@@ -1,7 +1,7 @@
-
+