From 2590c6be15ab549256f0a39028aefb887ac5131a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Tue, 6 May 2014 22:38:28 +0200 Subject: Fix launcher part for legacy in onesix. --- .../org/multimc/onesix/OneSixLauncher.java | 318 +++++++++++++++------ 1 file changed, 223 insertions(+), 95 deletions(-) (limited to 'depends/launcher/org/multimc/onesix/OneSixLauncher.java') diff --git a/depends/launcher/org/multimc/onesix/OneSixLauncher.java b/depends/launcher/org/multimc/onesix/OneSixLauncher.java index a908f6f3..0bd5c7ce 100644 --- a/depends/launcher/org/multimc/onesix/OneSixLauncher.java +++ b/depends/launcher/org/multimc/onesix/OneSixLauncher.java @@ -17,7 +17,9 @@ package org.multimc.onesix; import org.multimc.*; +import java.applet.Applet; import java.io.File; +import java.awt.*; import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; @@ -30,81 +32,225 @@ import java.util.List; public class OneSixLauncher implements Launcher { - @Override - public int launch(ParamBucket params) + // parameters, separated from ParamBucket + private List libraries; + private List extlibs; + private List mcparams; + private List mods; + private List traits; + private String mainClass; + private String natives; + private String userName, sessionId; + private String windowTitle; + private String windowParams; + + // secondary parameters + private Dimension winSize; + private boolean maximize; + private String cwd; + + // the much abused system classloader, for convenience (for further abuse) + private ClassLoader cl; + + private void processParams(ParamBucket params) throws NotFoundException { - // get and process the launch script params - List libraries; - List extlibs; - List mcparams; - List mods; - List traits; - String mainClass; - String natives; - final String windowTitle; - String windowParams; - try - { - libraries = params.all("cp"); - extlibs = params.all("ext"); - mcparams = params.all("param"); - mainClass = params.first("mainClass"); - mods = params.allSafe("mods", new ArrayList()); - traits = params.allSafe("traits", new ArrayList()); - natives = params.first("natives"); + libraries = params.all("cp"); + extlibs = params.all("ext"); + mcparams = params.all("param"); + mainClass = params.first("mainClass"); + mods = params.allSafe("mods", new ArrayList()); + traits = params.allSafe("traits", new ArrayList()); + natives = params.first("natives"); - windowTitle = params.first("windowTitle"); - // windowParams = params.first("windowParams"); - } catch (NotFoundException e) + userName = params.first("userName"); + sessionId = params.first("sessionId"); + windowTitle = params.firstSafe("windowTitle", "Minecraft"); + windowParams = params.firstSafe("windowParams", "854x480"); + + cwd = System.getProperty("user.dir"); + winSize = new Dimension(854, 480); + maximize = false; + + String[] dimStrings = windowParams.split("x"); + + if (windowParams.equalsIgnoreCase("max")) { - System.err.println("Not enough arguments."); - e.printStackTrace(System.err); - return -1; + maximize = true; } + else if (dimStrings.length == 2) + { + try + { + winSize = new Dimension(Integer.parseInt(dimStrings[0]), Integer.parseInt(dimStrings[1])); + } catch (NumberFormatException ignored) {} + } + } + + private void printStats() + { + Utils.log("Main Class:"); + Utils.log(" " + mainClass); + Utils.log(); - List allJars = new ArrayList(); - allJars.addAll(mods); - allJars.addAll(libraries); + Utils.log("Native path:"); + Utils.log(" " + natives); + Utils.log(); + + Utils.log("Traits:"); + Utils.log(" " + traits); + Utils.log(); - if(!Utils.addToClassPath(allJars)) + Utils.log("Libraries:"); + for (String s : libraries) { - System.err.println("Halting launch due to previous errors."); - return -1; + Utils.log(" " + s); } + Utils.log(); - // print the pretty things + if(mods.size() > 0) { - Utils.log("Main Class:"); - Utils.log(" " + mainClass); - Utils.log(); - - Utils.log("Native path:"); - Utils.log(" " + natives); - Utils.log(); - - Utils.log("Libraries:"); - for (String s : libraries) + Utils.log("Class Path Mods:"); + for (String s : mods) { Utils.log(" " + s); } Utils.log(); + } + + Utils.log("Params:"); + Utils.log(" " + mcparams.toString()); + Utils.log(); + } + + int legacyLaunch() + { + // Get the Minecraft Class and set the base folder + Class mc; + try + { + mc = cl.loadClass(mainClass); - if(mods.size() > 0) + Field f = Utils.getMCPathField(mc); + + if (f == null) { - Utils.log("Class Path Mods:"); - for (String s : mods) - { - Utils.log(" " + s); - } - Utils.log(); + System.err.println("Could not find Minecraft path field. Launch failed."); + return -1; } - Utils.log("Params:"); - Utils.log(" " + mcparams.toString()); + f.setAccessible(true); + f.set(null, new File(cwd)); + } catch (Exception e) + { + System.err.println("Could not set base folder. Failed to find/access Minecraft main class:"); + e.printStackTrace(System.err); + return -1; + } + + System.setProperty("minecraft.applet.TargetDirectory", cwd); + + String[] mcArgs = new String[2]; + mcArgs[0] = userName; + mcArgs[1] = sessionId; + + Utils.log("Launching with applet wrapper..."); + try + { + Class MCAppletClass = cl.loadClass("net.minecraft.client.MinecraftApplet"); + Applet mcappl = (Applet) MCAppletClass.newInstance(); + LegacyFrame mcWindow = new LegacyFrame(windowTitle); + mcWindow.start(mcappl, userName, sessionId, winSize, maximize); + } catch (Exception e) + { + Utils.log("Applet wrapper failed:", "Error"); + e.printStackTrace(System.err); Utils.log(); + Utils.log("Falling back to compatibility mode."); + try + { + mc.getMethod("main", String[].class).invoke(null, (Object) mcArgs); + } catch (Exception e1) + { + Utils.log("Failed to invoke the Minecraft main class:", "Fatal"); + e1.printStackTrace(System.err); + return -1; + } + } + return 0; + } + + int launchWithMainClass() + { + // Get the Minecraft Class. + Class mc; + try + { + mc = cl.loadClass(mainClass); + } catch (ClassNotFoundException e) + { + System.err.println("Failed to find Minecraft main class:"); + e.printStackTrace(System.err); + return -1; + } + + // get the main method. + Method meth; + try + { + meth = mc.getMethod("main", String[].class); + } catch (NoSuchMethodException e) + { + System.err.println("Failed to acquire the main method:"); + e.printStackTrace(System.err); + return -1; + } + + // init params for the main method to chomp on. + String[] paramsArray = mcparams.toArray(new String[mcparams.size()]); + try + { + // static method doesn't have an instance + meth.invoke(null, (Object) paramsArray); + } catch (Exception e) + { + System.err.println("Failed to start Minecraft:"); + e.printStackTrace(System.err); + return -1; + } + return 0; + } + + @Override + public int launch(ParamBucket params) + { + // get and process the launch script params + try + { + processParams(params); + } catch (NotFoundException e) + { + System.err.println("Not enough arguments."); + e.printStackTrace(System.err); + return -1; + } + + // do some horrible black magic with the classpath + { + List allJars = new ArrayList(); + allJars.addAll(mods); + allJars.addAll(libraries); + + if(!Utils.addToClassPath(allJars)) + { + System.err.println("Halting launch due to previous errors."); + return -1; + } } - // set up the natives path(s). + // print the pretty things + printStats(); + + // extract native libs (depending on platform here... java!) Utils.log("Preparing native libraries..."); String property = System.getProperty("os.arch"); boolean is_64 = property.equalsIgnoreCase("x86_64") || property.equalsIgnoreCase("amd64"); @@ -124,12 +270,16 @@ public class OneSixLauncher implements Launcher } } Utils.log(); - - System.setProperty("java.library.path", natives); - Field fieldSysPath; + + // set the native libs path... the brute force way try { - fieldSysPath = ClassLoader.class.getDeclaredField("sys_paths"); + System.setProperty("java.library.path", natives); + System.setProperty("org.lwjgl.librarypath", natives); + System.setProperty("net.java.games.input.librarypath", natives); + // by the power of reflection, initialize native libs again. DIRTY! + // this is SO BAD. imagine doing that to ld + Field fieldSysPath = ClassLoader.class.getDeclaredField("sys_paths"); fieldSysPath.setAccessible( true ); fieldSysPath.set( null, null ); } catch (Exception e) @@ -138,33 +288,25 @@ public class OneSixLauncher implements Launcher e.printStackTrace(System.err); return -1; } - - // Get the Minecraft Class. - final ClassLoader cl = ClassLoader.getSystemClassLoader(); - Class mc; - try + + // grab the system classloader and ... + cl = ClassLoader.getSystemClassLoader(); + + if (traits.contains("legacyLaunch")) { - mc = cl.loadClass(mainClass); - } catch (ClassNotFoundException e) - { - System.err.println("Failed to find Minecraft main class:"); - e.printStackTrace(System.err); - return -1; + // legacy launch uses the applet wrapper + return legacyLaunch(); } - - // get the main method. - Method meth; - try - { - meth = mc.getMethod("main", String[].class); - } catch (NoSuchMethodException e) + else { - System.err.println("Failed to acquire the main method:"); - e.printStackTrace(System.err); - return -1; + // normal launch just calls main() + return launchWithMainClass(); } + } +} + - // FIXME: works only on linux, we need a better solution +// FIXME: works only on linux, we need a better solution /* final java.nio.ByteBuffer[] icons = IconLoader.load("icon.png"); new Thread() { @@ -208,18 +350,4 @@ public class OneSixLauncher implements Launcher } } .start(); -*/ - // start Minecraft - String[] paramsArray = mcparams.toArray(new String[mcparams.size()]); // init params accordingly - try - { - meth.invoke(null, (Object) paramsArray); // static method doesn't have an instance - } catch (Exception e) - { - System.err.println("Failed to start Minecraft:"); - e.printStackTrace(System.err); - return -1; - } - return 0; - } -} +*/ \ No newline at end of file -- cgit v1.2.3