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. --- depends/launcher/CMakeLists.txt | 2 +- depends/launcher/org/multimc/LegacyFrame.java | 112 ++++++++ .../launcher/org/multimc/legacy/LegacyFrame.java | 112 -------- .../org/multimc/legacy/LegacyLauncher.java | 5 +- .../org/multimc/onesix/OneSixLauncher.java | 318 +++++++++++++++------ 5 files changed, 337 insertions(+), 212 deletions(-) create mode 100644 depends/launcher/org/multimc/LegacyFrame.java delete mode 100644 depends/launcher/org/multimc/legacy/LegacyFrame.java (limited to 'depends') diff --git a/depends/launcher/CMakeLists.txt b/depends/launcher/CMakeLists.txt index ad06fa7b..42c77a89 100644 --- a/depends/launcher/CMakeLists.txt +++ b/depends/launcher/CMakeLists.txt @@ -18,7 +18,7 @@ set(SRC # The launcher has to be there for silly FML/Forge relauncher. net/minecraft/Launcher.java org/multimc/legacy/LegacyLauncher.java - org/multimc/legacy/LegacyFrame.java + org/multimc/LegacyFrame.java # onesix launcher org/multimc/onesix/OneSixLauncher.java diff --git a/depends/launcher/org/multimc/LegacyFrame.java b/depends/launcher/org/multimc/LegacyFrame.java new file mode 100644 index 00000000..a081f3ae --- /dev/null +++ b/depends/launcher/org/multimc/LegacyFrame.java @@ -0,0 +1,112 @@ +package org.multimc;/* + * Copyright 2012-2014 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import net.minecraft.Launcher; + +import javax.imageio.ImageIO; +import java.applet.Applet; +import java.awt.*; +import java.awt.event.WindowEvent; +import java.awt.event.WindowListener; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; + +public class LegacyFrame extends Frame implements WindowListener +{ + private Launcher appletWrap = null; + public LegacyFrame(String title) + { + super ( title ); + BufferedImage image; + try { + image = ImageIO.read ( new File ( "icon.png" ) ); + setIconImage ( image ); + } catch ( IOException e ) { + e.printStackTrace(); + } + this.addWindowListener ( this ); + } + + public void start ( Applet mcApplet, String user, String session, Dimension winSize, boolean maximize ) + { + try { + appletWrap = new Launcher( mcApplet, new URL ( "http://www.minecraft.net/game" ) ); + } catch ( MalformedURLException ignored ) {} + appletWrap.setParameter ( "username", user ); + appletWrap.setParameter ( "sessionid", session ); + appletWrap.setParameter ( "stand-alone", "true" ); // Show the quit button. + appletWrap.setParameter ( "demo", "false" ); + appletWrap.setParameter("fullscreen", "false"); + mcApplet.setStub(appletWrap); + this.add ( appletWrap ); + appletWrap.setPreferredSize ( winSize ); + this.pack(); + this.setLocationRelativeTo ( null ); + this.setResizable ( true ); + if ( maximize ) { + this.setExtendedState ( MAXIMIZED_BOTH ); + } + validate(); + appletWrap.init(); + appletWrap.start(); + setVisible ( true ); + } + + @Override + public void windowActivated ( WindowEvent e ) {} + + @Override + public void windowClosed ( WindowEvent e ) {} + + @Override + public void windowClosing ( WindowEvent e ) + { + new Thread() { + public void run() { + try { + Thread.sleep ( 30000L ); + } catch ( InterruptedException localInterruptedException ) { + localInterruptedException.printStackTrace(); + } + System.out.println ( "FORCING EXIT!" ); + System.exit ( 0 ); + } + } + .start(); + + if ( appletWrap != null ) { + appletWrap.stop(); + appletWrap.destroy(); + } + // old minecraft versions can hang without this >_< + System.exit ( 0 ); + } + + @Override + public void windowDeactivated ( WindowEvent e ) {} + + @Override + public void windowDeiconified ( WindowEvent e ) {} + + @Override + public void windowIconified ( WindowEvent e ) {} + + @Override + public void windowOpened ( WindowEvent e ) {} +} diff --git a/depends/launcher/org/multimc/legacy/LegacyFrame.java b/depends/launcher/org/multimc/legacy/LegacyFrame.java deleted file mode 100644 index c3c0cafc..00000000 --- a/depends/launcher/org/multimc/legacy/LegacyFrame.java +++ /dev/null @@ -1,112 +0,0 @@ -package org.multimc.legacy;/* - * Copyright 2012-2014 MultiMC Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import net.minecraft.Launcher; - -import javax.imageio.ImageIO; -import java.applet.Applet; -import java.awt.*; -import java.awt.event.WindowEvent; -import java.awt.event.WindowListener; -import java.awt.image.BufferedImage; -import java.io.File; -import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URL; - -public class LegacyFrame extends Frame implements WindowListener -{ - private Launcher appletWrap = null; - public LegacyFrame(String title) - { - super ( title ); - BufferedImage image; - try { - image = ImageIO.read ( new File ( "icon.png" ) ); - setIconImage ( image ); - } catch ( IOException e ) { - e.printStackTrace(); - } - this.addWindowListener ( this ); - } - - public void start ( Applet mcApplet, String user, String session, Dimension winSize, boolean maximize ) - { - try { - appletWrap = new Launcher( mcApplet, new URL ( "http://www.minecraft.net/game" ) ); - } catch ( MalformedURLException ignored ) {} - appletWrap.setParameter ( "username", user ); - appletWrap.setParameter ( "sessionid", session ); - appletWrap.setParameter ( "stand-alone", "true" ); // Show the quit button. - appletWrap.setParameter ( "demo", "false" ); - appletWrap.setParameter("fullscreen", "false"); - mcApplet.setStub(appletWrap); - this.add ( appletWrap ); - appletWrap.setPreferredSize ( winSize ); - this.pack(); - this.setLocationRelativeTo ( null ); - this.setResizable ( true ); - if ( maximize ) { - this.setExtendedState ( MAXIMIZED_BOTH ); - } - validate(); - appletWrap.init(); - appletWrap.start(); - setVisible ( true ); - } - - @Override - public void windowActivated ( WindowEvent e ) {} - - @Override - public void windowClosed ( WindowEvent e ) {} - - @Override - public void windowClosing ( WindowEvent e ) - { - new Thread() { - public void run() { - try { - Thread.sleep ( 30000L ); - } catch ( InterruptedException localInterruptedException ) { - localInterruptedException.printStackTrace(); - } - System.out.println ( "FORCING EXIT!" ); - System.exit ( 0 ); - } - } - .start(); - - if ( appletWrap != null ) { - appletWrap.stop(); - appletWrap.destroy(); - } - // old minecraft versions can hang without this >_< - System.exit ( 0 ); - } - - @Override - public void windowDeactivated ( WindowEvent e ) {} - - @Override - public void windowDeiconified ( WindowEvent e ) {} - - @Override - public void windowIconified ( WindowEvent e ) {} - - @Override - public void windowOpened ( WindowEvent e ) {} -} diff --git a/depends/launcher/org/multimc/legacy/LegacyLauncher.java b/depends/launcher/org/multimc/legacy/LegacyLauncher.java index 1ca37c4a..347bb1a2 100644 --- a/depends/launcher/org/multimc/legacy/LegacyLauncher.java +++ b/depends/launcher/org/multimc/legacy/LegacyLauncher.java @@ -14,10 +14,7 @@ package org.multimc.legacy;/* * limitations under the License. */ -import org.multimc.Launcher; -import org.multimc.NotFoundException; -import org.multimc.ParamBucket; -import org.multimc.Utils; +import org.multimc.*; import java.applet.Applet; import java.awt.*; 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