summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--depends/javacheck/.gitignore6
-rw-r--r--depends/launcher/.gitignore6
-rw-r--r--depends/launcher/CMakeLists.txt25
-rw-r--r--depends/launcher/MultiMCLauncher.java331
-rw-r--r--depends/launcher/net/minecraft/Launcher.java44
-rw-r--r--depends/launcher/org/multimc/EntryPoint.java135
-rw-r--r--depends/launcher/org/multimc/IconLoader.java132
-rw-r--r--depends/launcher/org/multimc/Launcher.java22
-rw-r--r--depends/launcher/org/multimc/NotFoundException.java21
-rw-r--r--depends/launcher/org/multimc/ParamBucket.java86
-rw-r--r--depends/launcher/org/multimc/ParseException.java22
-rw-r--r--depends/launcher/org/multimc/Utils.java125
-rw-r--r--depends/launcher/org/multimc/legacy/LegacyFrame.java (renamed from depends/launcher/MCFrame.java)58
-rw-r--r--depends/launcher/org/multimc/legacy/LegacyLauncher.java178
-rw-r--r--depends/launcher/org/multimc/onesix/OneSixLauncher.java196
-rw-r--r--gui/ConsoleWindow.cpp4
-rw-r--r--gui/dialogs/AboutDialog.ui55
-rw-r--r--logic/BaseInstance.cpp7
-rw-r--r--logic/BaseInstance.h2
-rw-r--r--logic/LegacyInstance.cpp57
-rw-r--r--logic/MinecraftProcess.cpp51
-rw-r--r--logic/MinecraftProcess.h15
-rw-r--r--logic/OneSixInstance.cpp88
23 files changed, 1157 insertions, 509 deletions
diff --git a/depends/javacheck/.gitignore b/depends/javacheck/.gitignore
new file mode 100644
index 00000000..cc1c52bf
--- /dev/null
+++ b/depends/javacheck/.gitignore
@@ -0,0 +1,6 @@
+.idea
+*.iml
+out
+.classpath
+.idea
+.project
diff --git a/depends/launcher/.gitignore b/depends/launcher/.gitignore
new file mode 100644
index 00000000..cc1c52bf
--- /dev/null
+++ b/depends/launcher/.gitignore
@@ -0,0 +1,6 @@
+.idea
+*.iml
+out
+.classpath
+.idea
+.project
diff --git a/depends/launcher/CMakeLists.txt b/depends/launcher/CMakeLists.txt
index 729ebb67..6af5f738 100644
--- a/depends/launcher/CMakeLists.txt
+++ b/depends/launcher/CMakeLists.txt
@@ -3,20 +3,33 @@ project(launcher Java)
find_package(Java 1.6 REQUIRED COMPONENTS Development)
include(UseJava)
-set(CMAKE_JAVA_JAR_ENTRY_POINT MultiMCLauncher)
+set(CMAKE_JAVA_JAR_ENTRY_POINT org.multimc.EntryPoint)
set(CMAKE_JAVA_COMPILE_FLAGS -target 1.6 -source 1.6 -Xlint:deprecation -Xlint:unchecked)
set(SRC
- MultiMCLauncher.java
+ # OSX things
org/simplericity/macify/eawt/Application.java
org/simplericity/macify/eawt/ApplicationAdapter.java
org/simplericity/macify/eawt/ApplicationEvent.java
org/simplericity/macify/eawt/ApplicationListener.java
org/simplericity/macify/eawt/DefaultApplication.java
+
+ # legacy applet wrapper thing.
+ # The launcher has to be there for silly FML/Forge relauncher.
net/minecraft/Launcher.java
- MCFrame.java
-)
+ org/multimc/legacy/LegacyLauncher.java
+ org/multimc/legacy/LegacyFrame.java
-add_jar(MultiMCLauncher ${SRC})
+ # onesix launcher
+ org/multimc/onesix/OneSixLauncher.java
+
+ # generic launcher
+ org/multimc/EntryPoint.java
+ org/multimc/Launcher.java
+ org/multimc/ParseException.java
+ org/multimc/Utils.java
+ org/multimc/IconLoader.java
+)
+add_jar(NewLaunch ${SRC})
-INSTALL_JAR(MultiMCLauncher "${BINARY_DEST_DIR}/jars")
+INSTALL_JAR(NewLaunch "${BINARY_DEST_DIR}/jars")
diff --git a/depends/launcher/MultiMCLauncher.java b/depends/launcher/MultiMCLauncher.java
deleted file mode 100644
index 09a019ce..00000000
--- a/depends/launcher/MultiMCLauncher.java
+++ /dev/null
@@ -1,331 +0,0 @@
-//
-// Copyright 2012 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 java.applet.Applet;
-import java.awt.Dimension;
-
-import java.io.File;
-import java.io.IOException;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Modifier;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipException;
-import java.util.zip.ZipFile;
-
-import javax.imageio.ImageIO;
-import java.awt.image.BufferedImage;
-import org.simplericity.macify.eawt.Application;
-import org.simplericity.macify.eawt.DefaultApplication;
-
-public class MultiMCLauncher
-{
- /**
- * @param args
- * The arguments you want to launch Minecraft with. New path,
- * Username, Session ID.
- */
- public static void main(String[] args)
- {
- if (args.length < 3)
- {
- System.out.println("Not enough arguments.");
- System.exit(-1);
- }
-
- // Set the OSX application icon first, if we are on OSX.
- Application application = new DefaultApplication();
- if(application.isMac())
- {
- try
- {
- BufferedImage image = ImageIO.read(new File("icon.png"));
- application.setApplicationIconImage(image);
- }
- catch (IOException e)
- {
- e.printStackTrace();
- }
- }
-
- String userName = args[0];
- String sessionId = args[1];
- String windowtitle = args[2];
- String windowParams = args[3];
- String lwjgl = args[4];
- String cwd = System.getProperty("user.dir");
-
- Dimension winSize = new Dimension(854, 480);
- boolean maximize = false;
- boolean compatMode = false;
-
-
- String[] dimStrings = windowParams.split("x");
-
- if (windowParams.equalsIgnoreCase("compatmode"))
- {
- compatMode = true;
- }
- else if (windowParams.equalsIgnoreCase("max"))
- {
- maximize = true;
- }
- else if (dimStrings.length == 2)
- {
- try
- {
- winSize = new Dimension(Integer.parseInt(dimStrings[0]),
- Integer.parseInt(dimStrings[1]));
- }
- catch (NumberFormatException e)
- {
- System.out.println("Invalid Window size argument, " +
- "using default.");
- }
- }
- else
- {
- System.out.println("Invalid Window size argument, " +
- "using default.");
- }
-
- try
- {
- File binDir = new File(cwd, "bin");
- File lwjglDir;
- if(lwjgl.equalsIgnoreCase("Mojang"))
- lwjglDir = binDir;
- else
- lwjglDir = new File(lwjgl);
-
- System.out.println("Loading jars...");
- String[] lwjglJars = new String[] {
- "lwjgl.jar", "lwjgl_util.jar", "jinput.jar"
- };
-
- URL[] urls = new URL[4];
- try
- {
- File f = new File(binDir, "minecraft.jar");
- urls[0] = f.toURI().toURL();
- System.out.println("Loading URL: " + urls[0].toString());
-
- for (int i = 1; i < urls.length; i++)
- {
- File jar = new File(lwjglDir, lwjglJars[i-1]);
- urls[i] = jar.toURI().toURL();
- System.out.println("Loading URL: " + urls[i].toString());
- }
- }
- catch (MalformedURLException e)
- {
- System.err.println("MalformedURLException, " + e.toString());
- System.exit(5);
- }
-
- System.out.println("Loading natives...");
- String nativesDir = new File(lwjglDir, "natives").toString();
-
- System.setProperty("org.lwjgl.librarypath", nativesDir);
- System.setProperty("net.java.games.input.librarypath", nativesDir);
-
- URLClassLoader cl =
- new URLClassLoader(urls, MultiMCLauncher.class.getClassLoader());
-
- // Get the Minecraft Class.
- Class<?> mc = null;
- try
- {
- mc = cl.loadClass("net.minecraft.client.Minecraft");
-
- Field f = getMCPathField(mc);
-
- if (f == null)
- {
- System.err.println("Could not find Minecraft path field. Launch failed.");
- System.exit(-1);
- }
-
- f.setAccessible(true);
- f.set(null, new File(cwd));
- // And set it.
- System.out.println("Fixed Minecraft Path: Field was " + f.toString());
- }
- catch (ClassNotFoundException e)
- {
- System.err.println("Can't find main class. Searching...");
-
- // Look for any class that looks like the main class.
- File mcJar = new File(new File(cwd, "bin"), "minecraft.jar");
- ZipFile zip = null;
- try
- {
- zip = new ZipFile(mcJar);
- } catch (ZipException e1)
- {
- e1.printStackTrace();
- System.err.println("Search failed.");
- System.exit(-1);
- } catch (IOException e1)
- {
- e1.printStackTrace();
- System.err.println("Search failed.");
- System.exit(-1);
- }
-
- Enumeration<? extends ZipEntry> entries = zip.entries();
- ArrayList<String> classes = new ArrayList<String>();
-
- while (entries.hasMoreElements())
- {
- ZipEntry entry = entries.nextElement();
- if (entry.getName().endsWith(".class"))
- {
- String entryName = entry.getName().substring(0, entry.getName().lastIndexOf('.'));
- entryName = entryName.replace('/', '.');
- System.out.println("Found class: " + entryName);
- classes.add(entryName);
- }
- }
-
- for (String clsName : classes)
- {
- try
- {
- Class<?> cls = cl.loadClass(clsName);
- if (!Runnable.class.isAssignableFrom(cls))
- {
- continue;
- }
- else
- {
- System.out.println("Found class implementing runnable: " +
- cls.getName());
- }
-
- if (getMCPathField(cls) == null)
- {
- continue;
- }
- else
- {
- System.out.println("Found class implementing runnable " +
- "with mcpath field: " + cls.getName());
- }
-
- mc = cls;
- break;
- }
- catch (ClassNotFoundException e1)
- {
- // Ignore
- continue;
- }
- }
-
- if (mc == null)
- {
- System.err.println("Failed to find Minecraft main class.");
- System.exit(-1);
- }
- else
- {
- System.out.println("Found main class: " + mc.getName());
- }
- }
-
- System.setProperty("minecraft.applet.TargetDirectory", cwd);
-
- String[] mcArgs = new String[2];
- mcArgs[0] = userName;
- mcArgs[1] = sessionId;
-
- if (compatMode)
- {
- System.out.println("Launching in compatibility mode...");
- mc.getMethod("main", String[].class).invoke(null, (Object) mcArgs);
- }
- else
- {
- System.out.println("Launching with applet wrapper...");
- try
- {
- Class<?> MCAppletClass = cl.loadClass(
- "net.minecraft.client.MinecraftApplet");
- Applet mcappl = (Applet) MCAppletClass.newInstance();
- MCFrame mcWindow = new MCFrame(windowtitle);
- mcWindow.start(mcappl, userName, sessionId, winSize, maximize);
- } catch (InstantiationException e)
- {
- System.out.println("Applet wrapper failed! Falling back " +
- "to compatibility mode.");
- mc.getMethod("main", String[].class).invoke(null, (Object) mcArgs);
- }
- }
- } catch (ClassNotFoundException e)
- {
- e.printStackTrace();
- System.exit(1);
- } catch (IllegalArgumentException e)
- {
- e.printStackTrace();
- System.exit(2);
- } catch (IllegalAccessException e)
- {
- e.printStackTrace();
- System.exit(2);
- } catch (InvocationTargetException e)
- {
- e.printStackTrace();
- System.exit(3);
- } catch (NoSuchMethodException e)
- {
- e.printStackTrace();
- System.exit(3);
- } catch (SecurityException e)
- {
- e.printStackTrace();
- System.exit(4);
- }
- }
-
- public static Field getMCPathField(Class<?> mc)
- {
- Field[] fields = mc.getDeclaredFields();
-
- for (int i = 0; i < fields.length; i++)
- {
- Field f = fields[i];
- if (f.getType() != File.class)
- {
- // Has to be File
- continue;
- }
- if (f.getModifiers() != (Modifier.PRIVATE + Modifier.STATIC))
- {
- // And Private Static.
- continue;
- }
- return f;
- }
- return null;
- }
-}
diff --git a/depends/launcher/net/minecraft/Launcher.java b/depends/launcher/net/minecraft/Launcher.java
index 8cef35ad..c9b137e1 100644
--- a/depends/launcher/net/minecraft/Launcher.java
+++ b/depends/launcher/net/minecraft/Launcher.java
@@ -1,18 +1,18 @@
-//
-// Copyright 2012 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.
-//
+/*
+ * 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.
+ */
package net.minecraft;
@@ -38,7 +38,7 @@ public class Launcher extends Applet implements AppletStub
this.setLayout(new BorderLayout());
this.add(applet, "Center");
- this.wrappedApplet = applet;
+ this.wrappedApplet = applet;
this.documentBase = documentBase;
}
@@ -46,17 +46,17 @@ public class Launcher extends Applet implements AppletStub
{
params.put(name, value);
}
-
+
public void replace(Applet applet)
{
this.wrappedApplet = applet;
-
+
applet.setStub(this);
applet.setSize(getWidth(), getHeight());
-
+
this.setLayout(new BorderLayout());
this.add(applet, "Center");
-
+
applet.init();
active = true;
applet.start();
@@ -99,7 +99,7 @@ public class Launcher extends Applet implements AppletStub
{
wrappedApplet.resize(d);
}
-
+
@Override
public void init()
{
@@ -127,7 +127,7 @@ public class Launcher extends Applet implements AppletStub
{
wrappedApplet.destroy();
}
-
+
@Override
public URL getCodeBase() {
return wrappedApplet.getCodeBase();
diff --git a/depends/launcher/org/multimc/EntryPoint.java b/depends/launcher/org/multimc/EntryPoint.java
new file mode 100644
index 00000000..c42e34e7
--- /dev/null
+++ b/depends/launcher/org/multimc/EntryPoint.java
@@ -0,0 +1,135 @@
+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 org.multimc.legacy.LegacyLauncher;
+import org.multimc.onesix.OneSixLauncher;
+import org.simplericity.macify.eawt.Application;
+import org.simplericity.macify.eawt.DefaultApplication;
+
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.io.*;
+
+public class EntryPoint
+{
+ private enum Action
+ {
+ Proceed,
+ Launch
+ }
+
+ public static void main(String[] args)
+ {
+ // Set the OSX application icon first, if we are on OSX.
+ Application application = new DefaultApplication();
+ if(application.isMac())
+ {
+ try
+ {
+ BufferedImage image = ImageIO.read(new File("icon.png"));
+ application.setApplicationIconImage(image);
+ }
+ catch (IOException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ EntryPoint listener = new EntryPoint();
+ int retCode = listener.listen();
+ if (retCode != 0)
+ {
+ System.out.println("Exiting with " + retCode);
+ System.exit(retCode);
+ }
+ }
+
+ private Action parseLine(String inData) throws ParseException
+ {
+ String[] pair = inData.split(" ", 2);
+ if(pair.length != 2)
+ throw new ParseException();
+
+ String command = pair[0];
+ String param = pair[1];
+
+ if(command.equals("launch"))
+ {
+ if(param.equals("legacy"))
+ {
+ m_launcher = new LegacyLauncher();
+ System.out.println("Using legacy launcher.");
+ System.out.println();
+ return Action.Launch;
+ }
+ if(param.equals("onesix"))
+ {
+ m_launcher = new OneSixLauncher();
+ System.out.println("Using onesix launcher.");
+ System.out.println();
+ return Action.Launch;
+ }
+ else
+ throw new ParseException();
+ }
+
+ m_params.add(command, param);
+ //System.out.println(command + " : " + param);
+ return Action.Proceed;
+ }
+
+ public int listen()
+ {
+ BufferedReader buffer = new BufferedReader(new InputStreamReader(System.in));
+ boolean isListening = true;
+ // Main loop
+ while (isListening)
+ {
+ String inData="";
+ try
+ {
+ // Read from the pipe one line at a time
+ inData = buffer.readLine();
+ if (inData != null)
+ {
+ if(parseLine(inData) == Action.Launch)
+ {
+ isListening = false;
+ }
+ }
+ }
+ catch (IOException e)
+ {
+ e.printStackTrace();
+ return 1;
+ }
+ catch (ParseException e)
+ {
+ e.printStackTrace();
+ return 1;
+ }
+ }
+ if(m_launcher != null)
+ {
+ return m_launcher.launch(m_params);
+ }
+ System.err.println("No valid launcher implementation specified.");
+ return 1;
+ }
+
+ private ParamBucket m_params = new ParamBucket();
+ private org.multimc.Launcher m_launcher;
+}
diff --git a/depends/launcher/org/multimc/IconLoader.java b/depends/launcher/org/multimc/IconLoader.java
new file mode 100644
index 00000000..f1638f3a
--- /dev/null
+++ b/depends/launcher/org/multimc/IconLoader.java
@@ -0,0 +1,132 @@
+package org.multimc;
+
+import javax.imageio.ImageIO;
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+/*****************************************************************************
+ * A convenience class for loading icons from images.
+ *
+ * Icons loaded from this class are formatted to fit within the required
+ * dimension (16x16, 32x32, or 128x128). If the source image is larger than the
+ * target dimension, it is shrunk down to the minimum size that will fit. If it
+ * is smaller, then it is only scaled up if the new scale can be a per-pixel
+ * linear scale (i.e., x2, x3, x4, etc). In both cases, the image's width/height
+ * ratio is kept the same as the source image.
+ *
+ * @author Chris Molini
+ *****************************************************************************/
+public class IconLoader
+{
+ /*************************************************************************
+ * Loads an icon in ByteBuffer form.
+ *
+ * @param filepath
+ * The location of the Image to use as an icon.
+ *
+ * @return An array of ByteBuffers containing the pixel data for the icon in
+ * various sizes (as recommended by the OS).
+ *************************************************************************/
+ public static ByteBuffer[] load(String filepath)
+ {
+ BufferedImage image;
+ try {
+ image = ImageIO.read ( new File( filepath ) );
+ } catch ( IOException e ) {
+ e.printStackTrace();
+ return new ByteBuffer[0];
+ }
+ ByteBuffer[] buffers;
+ buffers = new ByteBuffer[1];
+ buffers[0] = loadInstance(image, 128);
+ return buffers;
+ }
+
+ /*************************************************************************
+ * Copies the supplied image into a square icon at the indicated size.
+ *
+ * @param image
+ * The image to place onto the icon.
+ * @param dimension
+ * The desired size of the icon.
+ *
+ * @return A ByteBuffer of pixel data at the indicated size.
+ *************************************************************************/
+ private static ByteBuffer loadInstance(BufferedImage image, int dimension)
+ {
+ BufferedImage scaledIcon = new BufferedImage(dimension, dimension,
+ BufferedImage.TYPE_INT_ARGB_PRE);
+ Graphics2D g = scaledIcon.createGraphics();
+ double ratio = getIconRatio(image, scaledIcon);
+ double width = image.getWidth() * ratio;
+ double height = image.getHeight() * ratio;
+ g.drawImage(image, (int) ((scaledIcon.getWidth() - width) / 2),
+ (int) ((scaledIcon.getHeight() - height) / 2), (int) (width),
+ (int) (height), null);
+ g.dispose();
+
+ return convertToByteBuffer(scaledIcon);
+ }
+
+ /*************************************************************************
+ * Gets the width/height ratio of the icon. This is meant to simplify
+ * scaling the icon to a new dimension.
+ *
+ * @param src
+ * The base image that will be placed onto the icon.
+ * @param icon
+ * The icon that will have the image placed on it.
+ *
+ * @return The amount to scale the source image to fit it onto the icon
+ * appropriately.
+ *************************************************************************/
+ private static double getIconRatio(BufferedImage src, BufferedImage icon)
+ {
+ double ratio = 1;
+ if (src.getWidth() > icon.getWidth())
+ ratio = (double) (icon.getWidth()) / src.getWidth();
+ else
+ ratio = (int) (icon.getWidth() / src.getWidth());
+ if (src.getHeight() > icon.getHeight())
+ {
+ double r2 = (double) (icon.getHeight()) / src.getHeight();
+ if (r2 < ratio)
+ ratio = r2;
+ }
+ else
+ {
+ double r2 = (int) (icon.getHeight() / src.getHeight());
+ if (r2 < ratio)
+ ratio = r2;
+ }
+ return ratio;
+ }
+
+ /*************************************************************************
+ * Converts a BufferedImage into a ByteBuffer of pixel data.
+ *
+ * @param image
+ * The image to convert.
+ *
+ * @return A ByteBuffer that contains the pixel data of the supplied image.
+ *************************************************************************/
+ public static ByteBuffer convertToByteBuffer(BufferedImage image)
+ {
+ byte[] buffer = new byte[image.getWidth() * image.getHeight() * 4];
+ int counter = 0;
+ for (int i = 0; i < image.getHeight(); i++)
+ for (int j = 0; j < image.getWidth(); j++)
+ {
+ int colorSpace = image.getRGB(j, i);
+ buffer[counter + 0] = (byte) ((colorSpace << 8) >> 24);
+ buffer[counter + 1] = (byte) ((colorSpace << 16) >> 24);
+ buffer[counter + 2] = (byte) ((colorSpace << 24) >> 24);
+ buffer[counter + 3] = (byte) (colorSpace >> 24);
+ counter += 4;
+ }
+ return ByteBuffer.wrap(buffer);
+ }
+} \ No newline at end of file
diff --git a/depends/launcher/org/multimc/Launcher.java b/depends/launcher/org/multimc/Launcher.java
new file mode 100644
index 00000000..1aa2b21f
--- /dev/null
+++ b/depends/launcher/org/multimc/Launcher.java
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+package org.multimc;
+
+public interface Launcher
+{
+ abstract int launch(ParamBucket params);
+}
diff --git a/depends/launcher/org/multimc/NotFoundException.java b/depends/launcher/org/multimc/NotFoundException.java
new file mode 100644
index 00000000..fe154a2f
--- /dev/null
+++ b/depends/launcher/org/multimc/NotFoundException.java
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+package org.multimc;
+
+public class NotFoundException extends Exception
+{
+}
diff --git a/depends/launcher/org/multimc/ParamBucket.java b/depends/launcher/org/multimc/ParamBucket.java
new file mode 100644
index 00000000..2e197d9f
--- /dev/null
+++ b/depends/launcher/org/multimc/ParamBucket.java
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ */
+
+package org.multimc;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+public class ParamBucket
+{
+ public void add(String key, String value)
+ {
+ List<String> coll = null;
+ if(!m_params.containsKey(key))
+ {
+ coll = new ArrayList<String>();
+ m_params.put(key, coll);
+ }
+ else
+ {
+ coll = m_params.get(key);
+ }
+ coll.add(value);
+ }
+
+ public List<String> all(String key) throws NotFoundException
+ {
+ if(!m_params.containsKey(key))
+ throw new NotFoundException();
+ return m_params.get(key);
+ }
+
+ public List<String> allSafe(String key, List<String> def)
+ {
+ if(!m_params.containsKey(key) || m_params.get(key).size() < 1)
+ {
+ return def;
+ }
+ return m_params.get(key);
+ }
+
+ public List<String> allSafe(String key)
+ {
+ return allSafe(key, new ArrayList<String>());
+ }
+
+ public String first(String key) throws NotFoundException
+ {
+ List<String> list = all(key);
+ if(list.size() < 1)
+ {
+ throw new NotFoundException();
+ }
+ return list.get(0);
+ }
+
+ public String firstSafe(String key, String def)
+ {
+ if(!m_params.containsKey(key) || m_params.get(key).size() < 1)
+ {
+ return def;
+ }
+ return m_params.get(key).get(0);
+ }
+
+ public String firstSafe(String key)
+ {
+ return firstSafe(key, "");
+ }
+
+ private HashMap<String, List<String>> m_params = new HashMap<String, List<String>>();
+}
diff --git a/depends/launcher/org/multimc/ParseException.java b/depends/launcher/org/multimc/ParseException.java
new file mode 100644
index 00000000..d9e8e53e
--- /dev/null
+++ b/depends/launcher/org/multimc/ParseException.java
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+package org.multimc;
+
+public class ParseException extends java.lang.Exception
+{
+
+}
diff --git a/depends/launcher/org/multimc/Utils.java b/depends/launcher/org/multimc/Utils.java
new file mode 100644
index 00000000..ba90c07f
--- /dev/null
+++ b/depends/launcher/org/multimc/Utils.java
@@ -0,0 +1,125 @@
+/*
+ * 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.
+ */
+
+package org.multimc;
+
+import java.io.File;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.Arrays;
+import java.util.List;
+
+public class Utils
+{
+ /**
+ * Adds the specified library to the classpath
+ *
+ * @param s the path to add
+ * @throws Exception
+ */
+ public static void addToClassPath(String s) throws Exception
+ {
+ File f = new File(s);
+ URL u = f.toURI().toURL();
+ URLClassLoader urlClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
+ Class urlClass = URLClassLoader.class;
+ Method method = urlClass.getDeclaredMethod("addURL", new Class[]{URL.class});
+ method.setAccessible(true);
+ method.invoke(urlClassLoader, new Object[]{u});
+ }
+
+ /**
+ * Adds many libraries to the classpath
+ *
+ * @param jars the paths to add
+ */
+ public static boolean addToClassPath(List<String> jars)
+ {
+ boolean pure = true;
+ // initialize the class path
+ for (String jar : jars)
+ {
+ try
+ {
+ Utils.addToClassPath(jar);
+ } catch (Exception e)
+ {
+ System.err.println("Unable to load: " + jar);
+ e.printStackTrace(System.err);
+ pure = false;
+ }
+ }
+ return pure;
+ }
+
+ /**
+ * Adds the specified path to the java library path
+ *
+ * @param pathToAdd the path to add
+ * @throws Exception
+ */
+ @Deprecated public static void addLibraryPath(String pathToAdd) throws Exception
+ {
+ final Field usrPathsField = ClassLoader.class.getDeclaredField("usr_paths");
+ usrPathsField.setAccessible(true);
+
+ //get array of paths
+ final String[] paths = (String[]) usrPathsField.get(null);
+
+ //check if the path to add is already present
+ for (String path : paths)
+ {
+ if (path.equals(pathToAdd))
+ {
+ return;
+ }
+ }
+
+ //add the new path
+ final String[] newPaths = Arrays.copyOf(paths, paths.length + 1);
+ newPaths[newPaths.length - 1] = pathToAdd;
+ usrPathsField.set(null, newPaths);
+ }
+
+ /**
+ * Finds a field that looks like a Minecraft base folder in a supplied class
+ *
+ * @param mc the class to scan
+ */
+ public static Field getMCPathField(Class<?> mc)
+ {
+ Field[] fields = mc.getDeclaredFields();
+
+ for (Field f : fields)
+ {
+ if (f.getType() != File.class)
+ {
+ // Has to be File
+ continue;
+ }
+ if (f.getModifiers() != (Modifier.PRIVATE + Modifier.STATIC))
+ {
+ // And Private Static.
+ continue;
+ }
+ return f;
+ }
+ return null;
+ }
+}
diff --git a/depends/launcher/MCFrame.java b/depends/launcher/org/multimc/legacy/LegacyFrame.java
index ce4564c9..c3c0cafc 100644
--- a/depends/launcher/MCFrame.java
+++ b/depends/launcher/org/multimc/legacy/LegacyFrame.java
@@ -1,40 +1,39 @@
-//
-// Copyright 2012 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.
-//
+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.Dimension;
-import java.awt.Frame;
-import java.awt.Toolkit;
+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;
-import java.io.IOException;
-import java.io.File;
-import javax.imageio.ImageIO;
-import java.awt.image.BufferedImage;
-public class MCFrame extends Frame implements WindowListener
+public class LegacyFrame extends Frame implements WindowListener
{
private Launcher appletWrap = null;
- public MCFrame ( String title )
+ public LegacyFrame(String title)
{
super ( title );
- BufferedImage image = null;
+ BufferedImage image;
try {
image = ImageIO.read ( new File ( "icon.png" ) );
setIconImage ( image );
@@ -47,14 +46,14 @@ public class MCFrame extends Frame implements WindowListener
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" ) );
+ 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.
- mcApplet.setStub ( appletWrap );
-
+ appletWrap.setParameter ( "demo", "false" );
+ appletWrap.setParameter("fullscreen", "false");
+ mcApplet.setStub(appletWrap);
this.add ( appletWrap );
appletWrap.setPreferredSize ( winSize );
this.pack();
@@ -63,7 +62,6 @@ public class MCFrame extends Frame implements WindowListener
if ( maximize ) {
this.setExtendedState ( MAXIMIZED_BOTH );
}
-
validate();
appletWrap.init();
appletWrap.start();
diff --git a/depends/launcher/org/multimc/legacy/LegacyLauncher.java b/depends/launcher/org/multimc/legacy/LegacyLauncher.java
new file mode 100644
index 00000000..6a0a3014
--- /dev/null
+++ b/depends/launcher/org/multimc/legacy/LegacyLauncher.java
@@ -0,0 +1,178 @@
+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 org.multimc.Launcher;
+import org.multimc.NotFoundException;
+import org.multimc.ParamBucket;
+import org.multimc.Utils;
+
+import java.applet.Applet;
+import java.awt.*;
+import java.io.File;
+import java.lang.reflect.Field;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+
+public class LegacyLauncher implements Launcher
+{
+ @Override
+ public int launch(ParamBucket params)
+ {
+ String userName, sessionId, windowTitle, windowParams, lwjgl;
+ String mainClass = "net.minecraft.client.Minecraft";
+ try
+ {
+ userName = params.first("userName");
+ sessionId = params.first("sessionId");
+ windowTitle = params.first("windowTitle");
+ windowParams = params.first("windowParams");
+ lwjgl = params.first("lwjgl");
+ } catch (NotFoundException e)
+ {
+ System.err.println("Not enough arguments.");
+ return -1;
+ }
+
+ String cwd = System.getProperty("user.dir");
+ Dimension winSize = new Dimension(854, 480);
+ boolean maximize = false;
+
+ String[] dimStrings = windowParams.split("x");
+
+ if (windowParams.equalsIgnoreCase("max"))
+ {
+ maximize = true;
+ }
+ else if (dimStrings.length == 2)
+ {
+ try
+ {
+ winSize = new Dimension(Integer.parseInt(dimStrings[0]), Integer.parseInt(dimStrings[1]));
+ } catch (NumberFormatException ignored) {}
+ }
+
+ File binDir = new File(cwd, "bin");
+ File lwjglDir;
+ if (lwjgl.equalsIgnoreCase("Mojang"))
+ {
+ lwjglDir = binDir;
+ }
+ else
+ {
+ lwjglDir = new File(lwjgl);
+ }
+
+ URL[] classpath;
+ {
+ try
+ {
+ classpath = new URL[]
+ {
+ new File(binDir, "minecraft.jar").toURI().toURL(),
+ new File(lwjglDir, "lwjgl.jar").toURI().toURL(),
+ new File(lwjglDir, "lwjgl_util.jar").toURI().toURL(),
+ new File(lwjglDir, "jinput.jar").toURI().toURL(),
+ };
+ } catch (MalformedURLException e)
+ {
+ System.err.println("Class path entry is badly formed:");
+ e.printStackTrace(System.err);
+ return -1;
+ }
+ }
+
+ String nativesDir = new File(lwjglDir, "natives").toString();
+
+ System.setProperty("org.lwjgl.librarypath", nativesDir);
+ System.setProperty("net.java.games.input.librarypath", nativesDir);
+
+ // print the pretty things
+ {
+ System.out.println("Main Class:");
+ System.out.println(mainClass);
+ System.out.println();
+
+ System.out.println("Class Path:");
+ for (URL s : classpath)
+ {
+ System.out.println(s);
+ }
+ System.out.println();
+
+ System.out.println("Native Path:");
+ System.out.println(nativesDir);
+ System.out.println();
+ }
+
+ URLClassLoader cl = new URLClassLoader(classpath, LegacyLauncher.class.getClassLoader());
+
+ // Get the Minecraft Class and set the base folder
+ Class<?> mc;
+ try
+ {
+ mc = cl.loadClass(mainClass);
+
+ Field f = Utils.getMCPathField(mc);
+
+ if (f == null)
+ {
+ System.err.println("Could not find Minecraft path field. Launch failed.");
+ return -1;
+ }
+
+ 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;
+
+ System.out.println("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)
+ {
+ System.err.println("Applet wrapper failed:");
+ e.printStackTrace(System.err);
+ System.err.println();
+ System.out.println("Falling back to compatibility mode.");
+ try
+ {
+ mc.getMethod("main", String[].class).invoke(null, (Object) mcArgs);
+ } catch (Exception e1)
+ {
+ System.err.println("Failed to invoke the Minecraft main class:");
+ e1.printStackTrace(System.err);
+ return -1;
+ }
+ }
+
+ return 0;
+ }
+}
diff --git a/depends/launcher/org/multimc/onesix/OneSixLauncher.java b/depends/launcher/org/multimc/onesix/OneSixLauncher.java
new file mode 100644
index 00000000..2232eeba
--- /dev/null
+++ b/depends/launcher/org/multimc/onesix/OneSixLauncher.java
@@ -0,0 +1,196 @@
+/* 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.
+ */
+
+package org.multimc.onesix;
+
+import org.multimc.*;
+
+import java.io.File;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.List;
+
+public class OneSixLauncher implements Launcher
+{
+ @Override
+ public int launch(ParamBucket params)
+ {
+ // get and process the launch script params
+ List<String> libraries;
+ List<String> mcparams;
+ List<String> mods;
+ String mainClass;
+ String natives;
+ final String windowTitle;
+ String windowParams;
+ try
+ {
+ libraries = params.all("cp");
+ mcparams = params.all("param");
+ mainClass = params.first("mainClass");
+ mods = params.allSafe("mods", new ArrayList<String>());
+ natives = params.first("natives");
+ windowTitle = params.first("windowTitle");
+ // windowParams = params.first("windowParams");
+ } catch (NotFoundException e)
+ {
+ System.err.println("Not enough arguments.");
+ e.printStackTrace(System.err);
+ return -1;
+ }
+
+ List<String> allJars = new ArrayList<String>();
+ allJars.addAll(mods);
+ allJars.addAll(libraries);
+
+ if(!Utils.addToClassPath(allJars))
+ {
+ System.err.println("Halting launch due to previous errors.");
+ return -1;
+ }
+
+ final ClassLoader cl = ClassLoader.getSystemClassLoader();
+
+ // print the pretty things
+ {
+ System.out.println("Main Class:");
+ System.out.println(mainClass);
+ System.out.println();
+
+ System.out.println("Libraries:");
+ for (String s : libraries)
+ {
+ System.out.println(s);
+ }
+ System.out.println();
+
+ if(mods.size() > 0)
+ {
+ System.out.println("Class Path Mods:");
+ for (String s : mods)
+ {
+ System.out.println(s);
+ }
+ System.out.println();
+ }
+
+ System.out.println("Params:");
+ System.out.println(mcparams.toString());
+ System.out.println();
+ }
+
+ // set up the natives path(s).
+ System.setProperty("java.library.path", natives );
+ Field fieldSysPath;
+ try
+ {
+ fieldSysPath = ClassLoader.class.getDeclaredField("sys_paths");
+ fieldSysPath.setAccessible( true );
+ fieldSysPath.set( null, null );
+ } catch (Exception e)
+ {
+ System.err.println("Failed to set the native library path:");
+ e.printStackTrace(System.err);
+ return -1;
+ }
+
+ // 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;
+ }
+
+ // FIXME: works only on linux, we need a better solution
+/*
+ final java.nio.ByteBuffer[] icons = IconLoader.load("icon.png");
+ new Thread() {
+ public void run() {
+ ClassLoader cl = ClassLoader.getSystemClassLoader();
+ try
+ {
+ Class<?> Display;
+ Method isCreated;
+ Method setTitle;
+ Method setIcon;
+
+ Display = cl.loadClass("org.lwjgl.opengl.Display");
+ isCreated = Display.getMethod("isCreated");
+ setTitle = Display.getMethod("setTitle", String.class);
+ setIcon = Display.getMethod("setIcon", java.nio.ByteBuffer[].class);
+
+ // set the window title? Maybe?
+ while(!(Boolean) isCreated.invoke(null))
+ {
+ try
+ {
+ Thread.sleep(150);
+ } catch (InterruptedException ignored) {}
+ }
+ // Give it a bit more time ;)
+ Thread.sleep(150);
+ // set the title
+ setTitle.invoke(null,windowTitle);
+ // only set icon when there's actually something to set...
+ if(icons.length > 0)
+ {
+ setIcon.invoke(null,(Object)icons);
+ }
+ }
+ catch (Exception e)
+ {
+ System.err.println("Couldn't set window icon or title.");
+ e.printStackTrace(System.err);
+ }
+ }
+ }
+ .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;
+ }
+}
diff --git a/gui/ConsoleWindow.cpp b/gui/ConsoleWindow.cpp
index 84a141ce..54a74bde 100644
--- a/gui/ConsoleWindow.cpp
+++ b/gui/ConsoleWindow.cpp
@@ -166,6 +166,10 @@ void ConsoleWindow::on_closeButton_clicked()
void ConsoleWindow::setMayClose(bool mayclose)
{
+ if(mayclose)
+ ui->closeButton->setText(tr("Close"));
+ else
+ ui->closeButton->setText(tr("Hide"));
m_mayclose = mayclose;
}
diff --git a/gui/dialogs/AboutDialog.ui b/gui/dialogs/AboutDialog.ui
index b0dafb06..64a355d3 100644
--- a/gui/dialogs/AboutDialog.ui
+++ b/gui/dialogs/AboutDialog.ui
@@ -104,7 +104,7 @@
<x>0</x>
<y>0</y>
<width>689</width>
- <height>331</height>
+ <height>311</height>
</rect>
</property>
<attribute name="label">
@@ -229,7 +229,7 @@
<x>0</x>
<y>0</y>
<width>689</width>
- <height>331</height>
+ <height>311</height>
</rect>
</property>
<attribute name="label">
@@ -245,7 +245,7 @@
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
-&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Bitstream Vera Sans'; font-size:11pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:600;&quot;&gt;MultiMC&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;Andrew Okin &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:forkk@forkk.net&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;forkk@forkk.net&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;Petr Mrázek &amp;lt;&lt;/span&gt;&lt;a href=&quot;mailto:peterix@gmail.com&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;peterix@gmail.com&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:10pt;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;
@@ -282,7 +282,7 @@ p, li { white-space: pre-wrap; }
<x>0</x>
<y>0</y>
<width>689</width>
- <height>331</height>
+ <height>311</height>
</rect>
</property>
<attribute name="label">
@@ -309,7 +309,7 @@ p, li { white-space: pre-wrap; }
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
-&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'DejaVu Sans Mono'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'DejaVu Sans Mono'; font-size:11pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p align=&quot;center&quot; style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Bitstream Vera Sans'; font-size:18pt; font-weight:600;&quot;&gt;MultiMC&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Copyright 2012-2014 MultiMC Contributors&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Licensed under the Apache License, Version 2.0 (the &amp;quot;License&amp;quot;);&lt;/span&gt;&lt;/p&gt;
@@ -430,7 +430,36 @@ p, li { white-space: pre-wrap; }
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; *&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; * This file has been put into the public domain.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; * You can do whatever you want with this file.&lt;/span&gt;&lt;/p&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; */&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; */&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p align=&quot;center&quot; style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Bitstream Vera Sans'; font-size:18pt; font-weight:600;&quot;&gt;Java IconLoader class&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;Copyright (c) 2011, Chris Molini&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;All rights reserved.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;Redistribution and use in source and binary forms, with or without&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;modification, are permitted provided that the following conditions are met:&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; * Redistributions of source code must retain the above copyright&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; notice, this list of conditions and the following disclaimer.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; * Redistributions in binary form must reproduce the above copyright&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; notice, this list of conditions and the following disclaimer in the&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; documentation and/or other materials provided with the distribution.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; * Neither the name of the &amp;lt;organization&amp;gt; nor the&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; names of its contributors may be used to endorse or promote products&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; derived from this software without specific prior written permission.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &amp;quot;AS IS&amp;quot; AND&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;DISCLAIMED. IN NO EVENT SHALL &amp;lt;COPYRIGHT HOLDER&amp;gt; BE LIABLE FOR ANY&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
@@ -442,7 +471,7 @@ p, li { white-space: pre-wrap; }
<x>0</x>
<y>0</y>
<width>689</width>
- <height>331</height>
+ <height>311</height>
</rect>
</property>
<attribute name="label">
@@ -455,12 +484,12 @@ p, li { white-space: pre-wrap; }
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
-&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Bitstream Vera Sans'; font-size:11pt;&quot;&gt;We keep MultiMC open source because we think it's important to be able to see the source code for a project like this, and we do so using the Apache license.&lt;/span&gt;&lt;/p&gt;
-&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Bitstream Vera Sans'; font-size:11pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Bitstream Vera Sans'; font-size:11pt;&quot;&gt;Part of the reason for using the Apache license is we don't want people using the &amp;quot;MultiMC&amp;quot; name when redistributing the project. This means people must take the time to go through the source code and remove all references to &amp;quot;MultiMC&amp;quot;, including but not limited to the project icon and the title of windows, (no *MultiMC-fork* in the title).&lt;/span&gt;&lt;/p&gt;
-&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Bitstream Vera Sans'; font-size:11pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Bitstream Vera Sans'; font-size:11pt;&quot;&gt;The Apache license covers reasonable use for the name - a mention of the project's origins in the About dialog and the license is acceptable. However, it should be abundantly clear that the project is a fork &lt;/span&gt;&lt;span style=&quot; font-family:'Bitstream Vera Sans'; font-size:11pt; font-weight:600;&quot;&gt;without&lt;/span&gt;&lt;span style=&quot; font-family:'Bitstream Vera Sans'; font-size:11pt;&quot;&gt; implying that you have our blessing.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Bitstream Vera Sans'; font-size:11pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;We keep MultiMC open source because we think it's important to be able to see the source code for a project like this, and we do so using the Apache license.&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Part of the reason for using the Apache license is we don't want people using the &amp;quot;MultiMC&amp;quot; name when redistributing the project. This means people must take the time to go through the source code and remove all references to &amp;quot;MultiMC&amp;quot;, including but not limited to the project icon and the title of windows, (no *MultiMC-fork* in the title).&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;The Apache license covers reasonable use for the name - a mention of the project's origins in the About dialog and the license is acceptable. However, it should be abundantly clear that the project is a fork &lt;span style=&quot; font-weight:600;&quot;&gt;without&lt;/span&gt; implying that you have our blessing.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
diff --git a/logic/BaseInstance.cpp b/logic/BaseInstance.cpp
index ac66a8d5..4fc6b9dc 100644
--- a/logic/BaseInstance.cpp
+++ b/logic/BaseInstance.cpp
@@ -26,6 +26,7 @@
#include "overridesetting.h"
#include "pathutils.h"
+#include <cmdutils.h>
#include "lists/MinecraftVersionList.h"
#include "logic/icons/IconList.h"
@@ -248,8 +249,14 @@ void BaseInstance::setName(QString val)
d->m_settings->set("name", val);
emit propertiesChanged(this);
}
+
QString BaseInstance::name() const
{
I_D(BaseInstance);
return d->m_settings->get("name").toString();
}
+
+QStringList BaseInstance::extraArguments() const
+{
+ return Util::Commandline::splitArgs(settings().get("JvmArgs").toString());
+}
diff --git a/logic/BaseInstance.h b/logic/BaseInstance.h
index 01d6dc7d..c059d058 100644
--- a/logic/BaseInstance.h
+++ b/logic/BaseInstance.h
@@ -81,6 +81,8 @@ public:
void setGroupInitial(QString val);
void setGroupPost(QString val);
+ QStringList extraArguments() const;
+
virtual QString intendedVersionId() const = 0;
virtual bool setIntendedVersionId(QString version) = 0;
diff --git a/logic/LegacyInstance.cpp b/logic/LegacyInstance.cpp
index 5ab19fc9..4b650e37 100644
--- a/logic/LegacyInstance.cpp
+++ b/logic/LegacyInstance.cpp
@@ -47,7 +47,7 @@ std::shared_ptr<Task> LegacyInstance::doUpdate(bool only_prepare)
// make sure the jar mods list is initialized by asking for it.
auto list = jarModList();
// create an update task
- return std::shared_ptr<Task> (new LegacyUpdate(this, only_prepare , this));
+ return std::shared_ptr<Task>(new LegacyUpdate(this, only_prepare, this));
}
MinecraftProcess *LegacyInstance::prepareForLaunch(MojangAccountPtr account)
@@ -58,58 +58,27 @@ MinecraftProcess *LegacyInstance::prepareForLaunch(MojangAccountPtr account)
auto pixmap = icon.pixmap(128, 128);
pixmap.save(PathCombine(minecraftRoot(), "icon.png"), "PNG");
- // extract the legacy launcher
- QString launcherJar = PathCombine(MMC->bin(), "jars", "MultiMCLauncher.jar");
-
- // set the process arguments
+ // create the launch script
+ QString launchScript;
{
- QStringList args;
-
// window size
- QString windowSize;
+ QString windowParams;
if (settings().get("LaunchMaximized").toBool())
- windowSize = "max";
+ windowParams = "max";
else
- windowSize = QString("%1x%2").arg(settings().get("MinecraftWinWidth").toInt()).arg(
+ windowParams = QString("%1x%2").arg(settings().get("MinecraftWinWidth").toInt()).arg(
settings().get("MinecraftWinHeight").toInt());
- // window title
- QString windowTitle;
- windowTitle.append("MultiMC: ").append(name());
-
- // Java arguments
- args.append(Util::Commandline::splitArgs(settings().get("JvmArgs").toString()));
-
-#ifdef OSX
- // OSX dock icon and name
- args << "-Xdock:icon=icon.png";
- args << QString("-Xdock:name=\"%1\"").arg(windowTitle);
-#endif
-
QString lwjgl = QDir(MMC->settings()->get("LWJGLDir").toString() + "/" + lwjglVersion())
.absolutePath();
-
- // launcher arguments
- args << QString("-Xms%1m").arg(settings().get("MinMemAlloc").toInt());
- args << QString("-Xmx%1m").arg(settings().get("MaxMemAlloc").toInt());
- args << QString("-XX:PermSize=%1m").arg(settings().get("PermGen").toInt());
-/**
-* HACK: Stupid hack for Intel drivers.
-* See: https://mojang.atlassian.net/browse/MCL-767
-*/
-#ifdef Q_OS_WIN32
- args << QString("-XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_"
- "minecraft.exe.heapdump");
-#endif
-
- args << "-jar" << launcherJar;
- args << account->currentProfile()->name;
- args << account->sessionId();
- args << windowTitle;
- args << windowSize;
- args << lwjgl;
- proc->setArguments(args);
+ launchScript += "userName " + account->currentProfile()->name + "\n";
+ launchScript += "sessionId " + account->sessionId() + "\n";
+ launchScript += "windowTitle MultiMC: " + name() + "\n";
+ launchScript += "windowParams " + windowParams + "\n";
+ launchScript += "lwjgl " + lwjgl + "\n";
+ launchScript += "launch legacy\n";
}
+ proc->setLaunchScript(launchScript);
// set the process work path
proc->setWorkdir(minecraftRoot());
diff --git a/logic/MinecraftProcess.cpp b/logic/MinecraftProcess.cpp
index b3959db9..9c69f1a7 100644
--- a/logic/MinecraftProcess.cpp
+++ b/logic/MinecraftProcess.cpp
@@ -14,13 +14,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#include "MultiMC.h"
#include "MinecraftProcess.h"
#include <QDataStream>
#include <QFile>
#include <QDir>
-//#include <QImage>
#include <QProcessEnvironment>
#include "BaseInstance.h"
@@ -59,11 +59,6 @@ MinecraftProcess::MinecraftProcess(BaseInstance *inst) : m_instance(inst)
connect(this, SIGNAL(readyReadStandardOutput()), SLOT(on_stdOut()));
}
-void MinecraftProcess::setArguments(QStringList args)
-{
- m_args = args;
-}
-
void MinecraftProcess::setWorkdir(QString path)
{
QDir mcDir(path);
@@ -197,13 +192,43 @@ void MinecraftProcess::launch()
}
m_instance->setLastLaunch();
+ auto &settings = m_instance->settings();
+
+ //////////// java arguments ////////////
+ QStringList args;
+ {
+ // custom args go first. we want to override them if we have our own here.
+ args.append(m_instance->extraArguments());
+
+ // OSX dock icon and name
+ #ifdef OSX
+ args << "-Xdock:icon=icon.png";
+ args << QString("-Xdock:name=\"%1\"").arg(windowTitle);
+ #endif
+
+ // HACK: Stupid hack for Intel drivers. See: https://mojang.atlassian.net/browse/MCL-767
+ #ifdef Q_OS_WIN32
+ args << QString("-XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_"
+ "minecraft.exe.heapdump");
+ #endif
+
+ args << QString("-Xms%1m").arg(settings.get("MinMemAlloc").toInt());
+ args << QString("-Xmx%1m").arg(settings.get("MaxMemAlloc").toInt());
+ args << QString("-XX:PermSize=%1m").arg(settings.get("PermGen").toInt());
+ if(!m_nativeFolder.isEmpty())
+ args << QString("-Djava.library.path=%1").arg(m_nativeFolder);
+ args << "-jar" << PathCombine(MMC->bin(), "jars", "NewLaunch.jar");
+ }
- emit log(QString("Minecraft folder is: '%1'").arg(workingDirectory()));
QString JavaPath = m_instance->settings().get("JavaPath").toString();
- emit log(QString("Java path: '%1'").arg(JavaPath));
- QString allArgs = m_args.join("' '");
- emit log(QString("Arguments: '%1'").arg(censorPrivateInfo(allArgs)));
- start(JavaPath, m_args);
+ emit log("MultiMC version: " + MMC->version().toString() + "\n\n");
+ emit log("Minecraft folder is:\n" + workingDirectory() + "\n\n");
+ emit log("Java path is:\n" + JavaPath + "\n\n");
+ QString allArgs = args.join(", ");
+ emit log("Java Arguments:\n[" + censorPrivateInfo(allArgs) + "]\n\n");
+
+ // instantiate the launcher part
+ start(JavaPath, args);
if (!waitForStarted())
{
//: Error message displayed if instace can't start
@@ -212,11 +237,13 @@ void MinecraftProcess::launch()
emit launch_failed(m_instance);
return;
}
+ // send the launch script to the launcher part
+ QByteArray bytes = launchScript.toUtf8();
+ writeData(bytes.constData(), bytes.length());
}
MessageLevel::Enum MinecraftProcess::getLevel(const QString &line, MessageLevel::Enum level)
{
-
if (line.contains("[INFO]") || line.contains("[CONFIG]") || line.contains("[FINE]") ||
line.contains("[FINER]") || line.contains("[FINEST]"))
level = MessageLevel::Message;
diff --git a/logic/MinecraftProcess.h b/logic/MinecraftProcess.h
index bd0151cc..5d1a2b71 100644
--- a/logic/MinecraftProcess.h
+++ b/logic/MinecraftProcess.h
@@ -18,7 +18,7 @@
#pragma once
#include <QProcess>
-
+#include <QString>
#include "BaseInstance.h"
/**
@@ -65,7 +65,15 @@ public:
void setWorkdir(QString path);
- void setArguments(QStringList args);
+ void setLaunchScript(QString script)
+ {
+ launchScript = script;
+ }
+
+ void setNativeFolder(QString natives)
+ {
+ m_nativeFolder = natives;
+ }
void killMinecraft();
@@ -104,12 +112,13 @@ signals:
protected:
BaseInstance *m_instance = nullptr;
- QStringList m_args;
QString m_err_leftover;
QString m_out_leftover;
QProcess m_prepostlaunchprocess;
bool killed = false;
MojangAccountPtr m_account;
+ QString launchScript;
+ QString m_nativeFolder;
protected
slots:
diff --git a/logic/OneSixInstance.cpp b/logic/OneSixInstance.cpp
index 2392c683..a12cf047 100644
--- a/logic/OneSixInstance.cpp
+++ b/logic/OneSixInstance.cpp
@@ -13,12 +13,14 @@
* limitations under the License.
*/
+#include "MultiMC.h"
#include "OneSixInstance.h"
#include "OneSixInstance_p.h"
#include "OneSixUpdate.h"
#include "MinecraftProcess.h"
#include "OneSixVersion.h"
#include "JavaChecker.h"
+#include "logic/icons/IconList.h"
#include <setting.h>
#include <pathutils.h>
@@ -27,6 +29,7 @@
#include "gui/dialogs/OneSixModEditDialog.h"
#include "logger/QsLog.h"
#include "logic/assets/AssetsUtils.h"
+#include <QIcon>
OneSixInstance::OneSixInstance(const QString &rootDir, SettingsObject *setting_obj,
QObject *parent)
@@ -40,7 +43,7 @@ OneSixInstance::OneSixInstance(const QString &rootDir, SettingsObject *setting_o
std::shared_ptr<Task> OneSixInstance::doUpdate(bool only_prepare)
{
- return std::shared_ptr<Task> (new OneSixUpdate(this, only_prepare));
+ return std::shared_ptr<Task>(new OneSixUpdate(this, only_prepare));
}
QString replaceTokensIn(QString text, QMap<QString, QString> with)
@@ -78,24 +81,25 @@ QDir OneSixInstance::reconstructAssets(std::shared_ptr<OneSixVersion> version)
QFile indexFile(indexPath);
QDir virtualRoot(PathCombine(virtualDir.path(), version->assets));
- if(!indexFile.exists())
+ if (!indexFile.exists())
{
QLOG_ERROR() << "No assets index file" << indexPath << "; can't reconstruct assets";
return virtualRoot;
}
- QLOG_DEBUG() << "reconstructAssets" << assetsDir.path() << indexDir.path() << objectDir.path() << virtualDir.path() << virtualRoot.path();
+ QLOG_DEBUG() << "reconstructAssets" << assetsDir.path() << indexDir.path()
+ << objectDir.path() << virtualDir.path() << virtualRoot.path();
AssetsIndex index;
bool loadAssetsIndex = AssetsUtils::loadAssetsIndexJson(indexPath, &index);
- if(loadAssetsIndex)
+ if (loadAssetsIndex)
{
- if(index.isVirtual)
+ if (index.isVirtual)
{
QLOG_INFO() << "Reconstructing virtual assets folder at" << virtualRoot.path();
- for(QString map : index.objects.keys())
+ for (QString map : index.objects.keys())
{
AssetObject asset_object = index.objects.value(map);
QString target_path = PathCombine(virtualRoot.path(), map);
@@ -103,17 +107,20 @@ QDir OneSixInstance::reconstructAssets(std::shared_ptr<OneSixVersion> version)
QString tlk = asset_object.hash.left(2);
- QString original_path = PathCombine(PathCombine(objectDir.path(), tlk), asset_object.hash);
+ QString original_path =
+ PathCombine(PathCombine(objectDir.path(), tlk), asset_object.hash);
QFile original(original_path);
- if(!target.exists())
+ if (!target.exists())
{
QFileInfo info(target_path);
QDir target_dir = info.dir();
- //QLOG_DEBUG() << target_dir;
- if(!target_dir.exists()) QDir("").mkpath(target_dir.path());
+ // QLOG_DEBUG() << target_dir;
+ if (!target_dir.exists())
+ QDir("").mkpath(target_dir.path());
bool couldCopy = original.copy(target_path);
- QLOG_DEBUG() << " Copying" << original_path << "to" << target_path << QString::number(couldCopy);// << original.errorString();
+ QLOG_DEBUG() << " Copying" << original_path << "to" << target_path
+ << QString::number(couldCopy); // << original.errorString();
}
}
@@ -155,7 +162,7 @@ QStringList OneSixInstance::processMinecraftArgs(MojangAccountPtr account)
auto user = account->user();
QJsonObject userAttrs;
- for(auto key: user.properties.keys())
+ for (auto key : user.properties.keys())
{
auto array = QJsonArray::fromStringList(user.properties.values(key));
userAttrs.insert(key, array);
@@ -180,71 +187,56 @@ MinecraftProcess *OneSixInstance::prepareForLaunch(MojangAccountPtr account)
{
I_D(OneSixInstance);
- QString natives_dir_raw = PathCombine(instanceRoot(), "natives/");
+ QIcon icon = MMC->icons()->getIcon(iconKey());
+ auto pixmap = icon.pixmap(128, 128);
+ pixmap.save(PathCombine(minecraftRoot(), "icon.png"), "PNG");
auto version = d->version;
if (!version)
return nullptr;
-
- QStringList args;
- args.append(Util::Commandline::splitArgs(settings().get("JvmArgs").toString()));
- args << QString("-Xms%1m").arg(settings().get("MinMemAlloc").toInt());
- args << QString("-Xmx%1m").arg(settings().get("MaxMemAlloc").toInt());
- args << QString("-XX:PermSize=%1m").arg(settings().get("PermGen").toInt());
-
-/**
- * HACK: Stupid hack for Intel drivers.
- * See: https://mojang.atlassian.net/browse/MCL-767
- */
-#ifdef Q_OS_WIN32
- args << QString("-XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_"
- "minecraft.exe.heapdump");
-#endif
-
- QDir natives_dir(natives_dir_raw);
- args << QString("-Djava.library.path=%1").arg(natives_dir.absolutePath());
- QString classPath;
+ QString launchScript;
{
auto libs = version->getActiveNormalLibs();
for (auto lib : libs)
{
QFileInfo fi(QString("libraries/") + lib->storagePath());
- classPath.append(fi.absoluteFilePath());
-#ifdef Q_OS_WIN32
- classPath.append(';');
-#else
- classPath.append(':');
-#endif
+ launchScript += "cp " + fi.absoluteFilePath() + "\n";
}
QString targetstr = "versions/" + version->id + "/" + version->id + ".jar";
QFileInfo fi(targetstr);
- classPath.append(fi.absoluteFilePath());
+ launchScript += "cp " + fi.absoluteFilePath() + "\n";
}
- if (classPath.size())
+ launchScript += "mainClass " + version->mainClass + "\n";
+
+ for (auto param : processMinecraftArgs(account))
{
- args << "-cp";
- args << classPath;
+ launchScript += "param " + param + "\n";
}
- args << version->mainClass;
- args.append(processMinecraftArgs(account));
// Set the width and height for 1.6 instances
bool maximize = settings().get("LaunchMaximized").toBool();
if (maximize)
{
// this is probably a BAD idea
- // args << QString("--fullscreen");
+ // launchScript += "param --fullscreen\n";
}
else
{
- args << QString("--width") << settings().get("MinecraftWinWidth").toString();
- args << QString("--height") << settings().get("MinecraftWinHeight").toString();
+ launchScript +=
+ "param --width\nparam " + settings().get("MinecraftWinWidth").toString() + "\n";
+ launchScript +=
+ "param --height\nparam " + settings().get("MinecraftWinHeight").toString() + "\n";
}
+ QDir natives_dir(PathCombine(instanceRoot(), "natives/"));
+ launchScript += "windowTitle MultiMC: " + name() + "\n";
+ launchScript += "natives " + natives_dir.absolutePath() + "\n";
+ launchScript += "launch onesix\n";
// create the process and set its parameters
MinecraftProcess *proc = new MinecraftProcess(this);
- proc->setArguments(args);
proc->setWorkdir(minecraftRoot());
+ proc->setLaunchScript(launchScript);
+ // proc->setNativeFolder(natives_dir.absolutePath());
return proc;
}