Replace old launcher part with a shiny new one. No more garbage on the command line.
This commit is contained in:
parent
c51a993ff7
commit
fca4441229
6
depends/javacheck/.gitignore
vendored
Normal file
6
depends/javacheck/.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
.idea
|
||||
*.iml
|
||||
out
|
||||
.classpath
|
||||
.idea
|
||||
.project
|
6
depends/launcher/.gitignore
vendored
Normal file
6
depends/launcher/.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
.idea
|
||||
*.iml
|
||||
out
|
||||
.classpath
|
||||
.idea
|
||||
.project
|
@ -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
|
||||
|
||||
# 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})
|
||||
|
||||
add_jar(MultiMCLauncher ${SRC})
|
||||
|
||||
INSTALL_JAR(MultiMCLauncher "${BINARY_DEST_DIR}/jars")
|
||||
INSTALL_JAR(NewLaunch "${BINARY_DEST_DIR}/jars")
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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();
|
||||
|
135
depends/launcher/org/multimc/EntryPoint.java
Normal file
135
depends/launcher/org/multimc/EntryPoint.java
Normal file
@ -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;
|
||||
}
|
132
depends/launcher/org/multimc/IconLoader.java
Normal file
132
depends/launcher/org/multimc/IconLoader.java
Normal file
@ -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);
|
||||
}
|
||||
}
|
22
depends/launcher/org/multimc/Launcher.java
Normal file
22
depends/launcher/org/multimc/Launcher.java
Normal file
@ -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);
|
||||
}
|
21
depends/launcher/org/multimc/NotFoundException.java
Normal file
21
depends/launcher/org/multimc/NotFoundException.java
Normal file
@ -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
|
||||
{
|
||||
}
|
86
depends/launcher/org/multimc/ParamBucket.java
Normal file
86
depends/launcher/org/multimc/ParamBucket.java
Normal file
@ -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>>();
|
||||
}
|
22
depends/launcher/org/multimc/ParseException.java
Normal file
22
depends/launcher/org/multimc/ParseException.java
Normal file
@ -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
|
||||
{
|
||||
|
||||
}
|
125
depends/launcher/org/multimc/Utils.java
Normal file
125
depends/launcher/org/multimc/Utils.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
@ -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();
|
178
depends/launcher/org/multimc/legacy/LegacyLauncher.java
Normal file
178
depends/launcher/org/multimc/legacy/LegacyLauncher.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
196
depends/launcher/org/multimc/onesix/OneSixLauncher.java
Normal file
196
depends/launcher/org/multimc/onesix/OneSixLauncher.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;">
|
||||
</style></head><body style=" font-family:'Bitstream Vera Sans'; font-size:11pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:10pt; font-weight:600;">MultiMC</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:10pt;">Andrew Okin &lt;</span><a href="mailto:forkk@forkk.net"><span style=" font-family:'MS Shell Dlg 2'; font-size:10pt; text-decoration: underline; color:#0000ff;">forkk@forkk.net</span></a><span style=" font-family:'MS Shell Dlg 2'; font-size:10pt;">&gt;</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:10pt;">Petr Mrázek &lt;</span><a href="mailto:peterix@gmail.com"><span style=" font-family:'MS Shell Dlg 2'; font-size:10pt; text-decoration: underline; color:#0000ff;">peterix@gmail.com</span></a><span style=" font-family:'MS Shell Dlg 2'; font-size:10pt;">&gt;</span></p>
|
||||
@ -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><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'DejaVu Sans Mono'; font-size:9pt; font-weight:400; font-style:normal;">
|
||||
</style></head><body style=" font-family:'DejaVu Sans Mono'; font-size:11pt; font-weight:400; font-style:normal;">
|
||||
<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Bitstream Vera Sans'; font-size:18pt; font-weight:600;">MultiMC</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Copyright 2012-2014 MultiMC Contributors</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);</span></p>
|
||||
@ -430,7 +430,36 @@ p, li { white-space: pre-wrap; }
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> *</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> * This file has been put into the public domain.</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> * You can do whatever you want with this file.</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> */</span></p></body></html></string>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> */</span></p>
|
||||
<p style="-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;"><br /></p>
|
||||
<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Bitstream Vera Sans'; font-size:18pt; font-weight:600;">Java IconLoader class</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Copyright (c) 2011, Chris Molini</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">All rights reserved.</span></p>
|
||||
<p style="-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;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Redistribution and use in source and binary forms, with or without</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">modification, are permitted provided that the following conditions are met:</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> * Redistributions of source code must retain the above copyright</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> notice, this list of conditions and the following disclaimer.</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> * Redistributions in binary form must reproduce the above copyright</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> notice, this list of conditions and the following disclaimer in the</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> documentation and/or other materials provided with the distribution.</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> * Neither the name of the &lt;organization&gt; nor the</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> names of its contributors may be used to endorse or promote products</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> derived from this software without specific prior written permission.</span></p>
|
||||
<p style="-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;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &quot;AS IS&quot; AND</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">DISCLAIMED. IN NO EVENT SHALL &lt;COPYRIGHT HOLDER&gt; BE LIABLE FOR ANY</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</span></p>
|
||||
<p style="-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;"><br /></p>
|
||||
<p style="-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;"><br /></p></body></html></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><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Bitstream Vera Sans'; font-size:11pt;">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.</span></p>
|
||||
<p style="-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;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Bitstream Vera Sans'; font-size:11pt;">Part of the reason for using the Apache license is we don't want people using the &quot;MultiMC&quot; name when redistributing the project. This means people must take the time to go through the source code and remove all references to &quot;MultiMC&quot;, including but not limited to the project icon and the title of windows, (no *MultiMC-fork* in the title).</span></p>
|
||||
<p style="-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;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Bitstream Vera Sans'; font-size:11pt;">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 </span><span style=" font-family:'Bitstream Vera Sans'; font-size:11pt; font-weight:600;">without</span><span style=" font-family:'Bitstream Vera Sans'; font-size:11pt;"> implying that you have our blessing.</span></p></body></html></string>
|
||||
</style></head><body style=" font-family:'Bitstream Vera Sans'; font-size:11pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">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.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Part of the reason for using the Apache license is we don't want people using the &quot;MultiMC&quot; name when redistributing the project. This means people must take the time to go through the source code and remove all references to &quot;MultiMC&quot;, including but not limited to the project icon and the title of windows, (no *MultiMC-fork* in the title).</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">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 <span style=" font-weight:600;">without</span> implying that you have our blessing.</p></body></html></string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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());
|
||||
|
@ -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);
|
||||
@ -189,13 +184,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
|
||||
@ -204,11 +229,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;
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user