diff --git a/src/main/java/net/minecraft/launchwrapper/Launch.java b/src/main/java/net/minecraft/launchwrapper/Launch.java index bb3766f..f60317e 100644 --- a/src/main/java/net/minecraft/launchwrapper/Launch.java +++ b/src/main/java/net/minecraft/launchwrapper/Launch.java @@ -7,13 +7,20 @@ import joptsimple.OptionSpec; import java.io.File; import java.lang.reflect.Method; import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; import java.util.logging.Level; public class Launch { private static final String DEFAULT_TWEAK = "net.minecraft.launchwrapper.VanillaTweaker"; public static File minecraftHome; public static File assetsDir; - + public static Map blackboard; + public static void main(String[] args) { new Launch().launch(args); } @@ -23,6 +30,7 @@ public class Launch { private Launch() { final URLClassLoader ucl = (URLClassLoader) getClass().getClassLoader(); classLoader = new LaunchClassLoader(ucl.getURLs()); + blackboard = new HashMap(); } private void launch(String[] args) { @@ -32,29 +40,60 @@ public class Launch { final OptionSpec profileOption = parser.accepts("version", "The version we launched with").withRequiredArg(); final OptionSpec gameDirOption = parser.accepts("gameDir", "Alternative game directory").withRequiredArg().ofType(File.class); final OptionSpec assetsDirOption = parser.accepts("assetsDir", "Assets directory").withRequiredArg().ofType(File.class); - final OptionSpec tweakClassOption = parser.accepts("tweakClass", "Tweak class to load").withRequiredArg().defaultsTo(DEFAULT_TWEAK); + final OptionSpec tweakClassOption = parser.accepts("tweakClass", "Tweak class(es) to load").withRequiredArg().defaultsTo(DEFAULT_TWEAK); final OptionSpec nonOption = parser.nonOptions(); final OptionSet options = parser.parse(args); minecraftHome = options.valueOf(gameDirOption); assetsDir = options.valueOf(assetsDirOption); final String profileName = options.valueOf(profileOption); - final String tweakClassName = options.valueOf(tweakClassOption); + final List tweakClassNames = new ArrayList(options.valuesOf(tweakClassOption)); + final List argumentList = new ArrayList(); + + blackboard.put("TweakClasses", tweakClassNames); + blackboard.put("ArgumentList", argumentList); + + final List allTweakers = new ArrayList(); try { - LogWrapper.log(Level.INFO, "Using tweak class name %s", tweakClassName); + final List tweakers = new ArrayList(tweakClassNames.size() + 1); + blackboard.put("Tweaks", tweakers); + ITweaker primaryTweaker = null; + do { + for (final Iterator it = tweakClassNames.iterator(); it.hasNext(); ) { + final String tweakName = it.next(); + LogWrapper.log(Level.INFO, "Loading tweak class name %s", tweakName); + + // Ensure we allow the tweak class to load with the parent classloader + classLoader.addClassLoaderExclusion(tweakName.substring(0,tweakName.lastIndexOf('.'))); + final ITweaker tweaker = (ITweaker) Class.forName(tweakName, true, classLoader).newInstance(); + tweakers.add(tweaker); + it.remove(); + if (primaryTweaker == null) { + LogWrapper.log(Level.INFO, "Using primary tweak class name %s", tweakName); + primaryTweaker = tweaker; + } + } + for (final Iterator it = tweakers.iterator(); it.hasNext(); ) { + final ITweaker tweaker = it.next(); + LogWrapper.log(Level.INFO, "Calling tweak class %s", tweaker.getClass().getName()); + tweaker.acceptOptions(options.valuesOf(nonOption), minecraftHome, assetsDir, profileName); + tweaker.injectIntoClassLoader(classLoader); + allTweakers.add(tweaker); + it.remove(); + } + } while (!tweakClassNames.isEmpty()); - // Ensure we allow the tweak class to load with the parent classloader - classLoader.addClassLoaderExclusion(tweakClassName.substring(0,tweakClassName.lastIndexOf('.'))); - final ITweaker tweaker = (ITweaker) Class.forName(tweakClassName, true, classLoader).newInstance(); - tweaker.acceptOptions(options.valuesOf(nonOption), minecraftHome, assetsDir, profileName); - tweaker.injectIntoClassLoader(classLoader); - - final Class clazz = Class.forName(tweaker.getLaunchTarget(), false, classLoader); + for (final ITweaker tweaker : allTweakers) { + argumentList.addAll(Arrays.asList(tweaker.getLaunchArguments())); + } + + final String launchTarget = primaryTweaker.getLaunchTarget(); + final Class clazz = Class.forName(launchTarget, false, classLoader); final Method mainMethod = clazz.getMethod("main", new Class[]{String[].class}); - LogWrapper.info("Launching wrapped minecraft"); - mainMethod.invoke(null, (Object) tweaker.getLaunchArguments()); + LogWrapper.info("Launching wrapped minecraft {%s}", launchTarget); + mainMethod.invoke(null, (Object) argumentList.toArray(new String[argumentList.size()])); } catch (Exception e) { LogWrapper.log(Level.SEVERE, e, "Unable to launch"); }