Merge pull request #520 from icelimetea/refactor-java-launcher-v2
This commit is contained in:
commit
2646ae29f0
@ -4,17 +4,18 @@ find_package(Java 1.7 REQUIRED COMPONENTS Development)
|
||||
|
||||
include(UseJava)
|
||||
set(CMAKE_JAVA_JAR_ENTRY_POINT org.multimc.EntryPoint)
|
||||
set(CMAKE_JAVA_COMPILE_FLAGS -target 8 -source 8 -Xlint:deprecation -Xlint:unchecked)
|
||||
set(CMAKE_JAVA_COMPILE_FLAGS -target 7 -source 7 -Xlint:deprecation -Xlint:unchecked)
|
||||
|
||||
set(SRC
|
||||
org/multimc/EntryPoint.java
|
||||
org/multimc/Launcher.java
|
||||
org/multimc/LegacyFrame.java
|
||||
org/multimc/NotFoundException.java
|
||||
org/multimc/ParamBucket.java
|
||||
org/multimc/ParseException.java
|
||||
org/multimc/Utils.java
|
||||
org/multimc/onesix/OneSixLauncher.java
|
||||
org/multimc/LauncherFactory.java
|
||||
org/multimc/impl/OneSixLauncher.java
|
||||
org/multimc/applet/LegacyFrame.java
|
||||
org/multimc/exception/ParameterNotFoundException.java
|
||||
org/multimc/exception/ParseException.java
|
||||
org/multimc/utils/Parameters.java
|
||||
org/multimc/utils/Utils.java
|
||||
net/minecraft/Launcher.java
|
||||
)
|
||||
add_jar(NewLaunch ${SRC})
|
||||
|
@ -16,31 +16,28 @@
|
||||
|
||||
package net.minecraft;
|
||||
|
||||
import java.util.TreeMap;
|
||||
import java.util.Map;
|
||||
import java.net.URL;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Graphics;
|
||||
import java.applet.Applet;
|
||||
import java.applet.AppletStub;
|
||||
import java.awt.*;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
public final class Launcher extends Applet implements AppletStub {
|
||||
|
||||
private final Map<String, String> params = new TreeMap<>();
|
||||
|
||||
private final Applet wrappedApplet;
|
||||
|
||||
public class Launcher extends Applet implements AppletStub
|
||||
{
|
||||
private Applet wrappedApplet;
|
||||
private URL documentBase;
|
||||
private boolean active = false;
|
||||
private final Map<String, String> params;
|
||||
|
||||
public Launcher(Applet applet, URL documentBase)
|
||||
{
|
||||
params = new TreeMap<String, String>();
|
||||
|
||||
public Launcher(Applet applet) {
|
||||
this.setLayout(new BorderLayout());
|
||||
|
||||
this.add(applet, "Center");
|
||||
|
||||
this.wrappedApplet = applet;
|
||||
this.documentBase = documentBase;
|
||||
}
|
||||
|
||||
public void setParameter(String name, String value)
|
||||
@ -48,84 +45,61 @@ 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();
|
||||
validate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getParameter(String name)
|
||||
{
|
||||
public String getParameter(String name) {
|
||||
String param = params.get(name);
|
||||
|
||||
if (param != null)
|
||||
return param;
|
||||
try
|
||||
{
|
||||
|
||||
try {
|
||||
return super.getParameter(name);
|
||||
} catch (Exception ignore){}
|
||||
} catch (Exception ignore) {}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive()
|
||||
{
|
||||
public boolean isActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appletResize(int width, int height)
|
||||
{
|
||||
public void appletResize(int width, int height) {
|
||||
wrappedApplet.resize(width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resize(int width, int height)
|
||||
{
|
||||
public void resize(int width, int height) {
|
||||
wrappedApplet.resize(width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resize(Dimension d)
|
||||
{
|
||||
public void resize(Dimension d) {
|
||||
wrappedApplet.resize(d);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init()
|
||||
{
|
||||
public void init() {
|
||||
if (wrappedApplet != null)
|
||||
{
|
||||
wrappedApplet.init();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start()
|
||||
{
|
||||
public void start() {
|
||||
wrappedApplet.start();
|
||||
|
||||
active = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop()
|
||||
{
|
||||
public void stop() {
|
||||
wrappedApplet.stop();
|
||||
|
||||
active = false;
|
||||
}
|
||||
|
||||
public void destroy()
|
||||
{
|
||||
public void destroy() {
|
||||
wrappedApplet.destroy();
|
||||
}
|
||||
|
||||
@ -136,34 +110,34 @@ public class Launcher extends Applet implements AppletStub
|
||||
} catch (MalformedURLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL getDocumentBase()
|
||||
{
|
||||
public URL getDocumentBase() {
|
||||
try {
|
||||
// Special case only for Classic versions
|
||||
if (wrappedApplet.getClass().getCanonicalName().startsWith("com.mojang")) {
|
||||
return new URL("http", "www.minecraft.net", 80, "/game/", null);
|
||||
}
|
||||
if (wrappedApplet.getClass().getCanonicalName().startsWith("com.mojang"))
|
||||
return new URL("http", "www.minecraft.net", 80, "/game/");
|
||||
|
||||
return new URL("http://www.minecraft.net/game/");
|
||||
} catch (MalformedURLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVisible(boolean b)
|
||||
{
|
||||
public void setVisible(boolean b) {
|
||||
super.setVisible(b);
|
||||
|
||||
wrappedApplet.setVisible(b);
|
||||
}
|
||||
public void update(Graphics paramGraphics)
|
||||
{
|
||||
}
|
||||
public void paint(Graphics paramGraphics)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public void update(Graphics paramGraphics) {}
|
||||
|
||||
public void paint(Graphics paramGraphics) {}
|
||||
|
||||
}
|
||||
|
@ -1,20 +1,42 @@
|
||||
package org.multimc;/*
|
||||
* Copyright 2012-2021 MultiMC Contributors
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
/*
|
||||
* PolyMC - Minecraft Launcher
|
||||
* Copyright (C) 2022 icelimetea, <fr3shtea@outlook.com>
|
||||
*
|
||||
* 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
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* 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.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* This file incorporates work covered by the following copyright and
|
||||
* permission notice:
|
||||
*
|
||||
* Copyright 2013-2021 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.onesix.OneSixLauncher;
|
||||
package org.multimc;
|
||||
|
||||
import org.multimc.exception.ParseException;
|
||||
import org.multimc.utils.Parameters;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
@ -23,31 +45,25 @@ import java.nio.charset.StandardCharsets;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class EntryPoint
|
||||
{
|
||||
public final class EntryPoint {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger("EntryPoint");
|
||||
|
||||
private final ParamBucket params = new ParamBucket();
|
||||
private final Parameters params = new Parameters();
|
||||
|
||||
private org.multimc.Launcher launcher;
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
public static void main(String[] args) {
|
||||
EntryPoint listener = new EntryPoint();
|
||||
|
||||
int retCode = listener.listen();
|
||||
|
||||
if (retCode != 0)
|
||||
{
|
||||
if (retCode != 0) {
|
||||
LOGGER.info("Exiting with " + retCode);
|
||||
|
||||
System.exit(retCode);
|
||||
}
|
||||
}
|
||||
|
||||
private Action parseLine(String inData) throws ParseException
|
||||
{
|
||||
private Action parseLine(String inData) throws ParseException {
|
||||
String[] tokens = inData.split("\\s+", 2);
|
||||
|
||||
if (tokens.length == 0)
|
||||
@ -62,21 +78,6 @@ public class EntryPoint
|
||||
return Action.Abort;
|
||||
}
|
||||
|
||||
case "launcher": {
|
||||
if (tokens.length != 2)
|
||||
throw new ParseException("Expected 2 tokens, got " + tokens.length);
|
||||
|
||||
if (tokens[1].equals("onesix")) {
|
||||
launcher = new OneSixLauncher();
|
||||
|
||||
LOGGER.info("Using onesix launcher.");
|
||||
|
||||
return Action.Proceed;
|
||||
} else {
|
||||
throw new ParseException("Invalid launcher type: " + tokens[1]);
|
||||
}
|
||||
}
|
||||
|
||||
default: {
|
||||
if (tokens.length != 2)
|
||||
throw new ParseException("Error while parsing:" + inData);
|
||||
@ -88,8 +89,7 @@ public class EntryPoint
|
||||
}
|
||||
}
|
||||
|
||||
public int listen()
|
||||
{
|
||||
public int listen() {
|
||||
Action action = Action.Proceed;
|
||||
|
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(
|
||||
@ -112,21 +112,30 @@ public class EntryPoint
|
||||
}
|
||||
|
||||
// Main loop
|
||||
if (action == Action.Abort)
|
||||
{
|
||||
if (action == Action.Abort) {
|
||||
LOGGER.info("Launch aborted by the launcher.");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (launcher != null)
|
||||
{
|
||||
return launcher.launch(params);
|
||||
try {
|
||||
Launcher launcher =
|
||||
LauncherFactory
|
||||
.getInstance()
|
||||
.createLauncher(params);
|
||||
|
||||
launcher.launch();
|
||||
|
||||
return 0;
|
||||
} catch (IllegalArgumentException e) {
|
||||
LOGGER.log(Level.SEVERE, "Wrong argument.", e);
|
||||
|
||||
return 1;
|
||||
} catch (Exception e) {
|
||||
LOGGER.log(Level.SEVERE, "Exception caught from launcher.", e);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
LOGGER.log(Level.SEVERE, "No valid launcher implementation specified.");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
private enum Action {
|
||||
|
@ -16,7 +16,8 @@
|
||||
|
||||
package org.multimc;
|
||||
|
||||
public interface Launcher
|
||||
{
|
||||
int launch(ParamBucket params);
|
||||
public interface Launcher {
|
||||
|
||||
void launch() throws Exception;
|
||||
|
||||
}
|
||||
|
63
libraries/launcher/org/multimc/LauncherFactory.java
Normal file
63
libraries/launcher/org/multimc/LauncherFactory.java
Normal file
@ -0,0 +1,63 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
/*
|
||||
* PolyMC - Minecraft Launcher
|
||||
* Copyright (C) 2022 icelimetea, <fr3shtea@outlook.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.multimc;
|
||||
|
||||
import org.multimc.impl.OneSixLauncher;
|
||||
import org.multimc.utils.Parameters;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public final class LauncherFactory {
|
||||
|
||||
private static final LauncherFactory INSTANCE = new LauncherFactory();
|
||||
|
||||
private final Map<String, LauncherProvider> launcherRegistry = new HashMap<>();
|
||||
|
||||
private LauncherFactory() {
|
||||
launcherRegistry.put("onesix", new LauncherProvider() {
|
||||
@Override
|
||||
public Launcher provide(Parameters parameters) {
|
||||
return new OneSixLauncher(parameters);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public Launcher createLauncher(Parameters parameters) {
|
||||
String name = parameters.first("launcher");
|
||||
|
||||
LauncherProvider launcherProvider = launcherRegistry.get(name);
|
||||
|
||||
if (launcherProvider == null)
|
||||
throw new IllegalArgumentException("Invalid launcher type: " + name);
|
||||
|
||||
return launcherProvider.provide(parameters);
|
||||
}
|
||||
|
||||
public static LauncherFactory getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
public interface LauncherProvider {
|
||||
|
||||
Launcher provide(Parameters parameters);
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,176 +0,0 @@
|
||||
package org.multimc;/*
|
||||
* Copyright 2012-2021 MultiMC Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import net.minecraft.Launcher;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.applet.Applet;
|
||||
import java.awt.*;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.awt.event.WindowListener;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.Scanner;
|
||||
|
||||
public class LegacyFrame extends Frame implements WindowListener
|
||||
{
|
||||
private Launcher appletWrap = null;
|
||||
public LegacyFrame(String title)
|
||||
{
|
||||
super ( title );
|
||||
BufferedImage image;
|
||||
try {
|
||||
image = ImageIO.read ( new File ( "icon.png" ) );
|
||||
setIconImage ( image );
|
||||
} catch ( IOException e ) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
this.addWindowListener ( this );
|
||||
}
|
||||
|
||||
public void start (
|
||||
Applet mcApplet,
|
||||
String user,
|
||||
String session,
|
||||
int winSizeW,
|
||||
int winSizeH,
|
||||
boolean maximize,
|
||||
String serverAddress,
|
||||
String serverPort
|
||||
)
|
||||
{
|
||||
try {
|
||||
appletWrap = new Launcher( mcApplet, new URL ( "http://www.minecraft.net/game" ) );
|
||||
} catch ( MalformedURLException ignored ) {}
|
||||
|
||||
// Implements support for launching in to multiplayer on classic servers using a mpticket
|
||||
// file generated by an external program and stored in the instance's root folder.
|
||||
File mpticketFile = null;
|
||||
Scanner fileReader = null;
|
||||
try {
|
||||
mpticketFile = new File(System.getProperty("user.dir") + "/../mpticket").getCanonicalFile();
|
||||
fileReader = new Scanner(new FileInputStream(mpticketFile), "ascii");
|
||||
String[] mpticketParams = new String[3];
|
||||
|
||||
for(int i=0;i<3;i++) {
|
||||
if(fileReader.hasNextLine()) {
|
||||
mpticketParams[i] = fileReader.nextLine();
|
||||
} else {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
// Assumes parameters are valid and in the correct order
|
||||
appletWrap.setParameter("server", mpticketParams[0]);
|
||||
appletWrap.setParameter("port", mpticketParams[1]);
|
||||
appletWrap.setParameter("mppass", mpticketParams[2]);
|
||||
|
||||
fileReader.close();
|
||||
mpticketFile.delete();
|
||||
}
|
||||
catch (FileNotFoundException e) {}
|
||||
catch (IllegalArgumentException e) {
|
||||
|
||||
fileReader.close();
|
||||
File mpticketFileCorrupt = new File(System.getProperty("user.dir") + "/../mpticket.corrupt");
|
||||
if(mpticketFileCorrupt.exists()) {
|
||||
mpticketFileCorrupt.delete();
|
||||
}
|
||||
mpticketFile.renameTo(mpticketFileCorrupt);
|
||||
|
||||
System.err.println("Malformed mpticket file, missing argument.");
|
||||
e.printStackTrace(System.err);
|
||||
System.exit(-1);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace(System.err);
|
||||
System.exit(-1);
|
||||
}
|
||||
|
||||
if (serverAddress != null)
|
||||
{
|
||||
appletWrap.setParameter("server", serverAddress);
|
||||
appletWrap.setParameter("port", serverPort);
|
||||
}
|
||||
|
||||
appletWrap.setParameter ( "username", user );
|
||||
appletWrap.setParameter ( "sessionid", session );
|
||||
appletWrap.setParameter ( "stand-alone", "true" ); // Show the quit button.
|
||||
appletWrap.setParameter ( "haspaid", "true" ); // Some old versions need this for world saves to work.
|
||||
appletWrap.setParameter ( "demo", "false" );
|
||||
appletWrap.setParameter ( "fullscreen", "false" );
|
||||
mcApplet.setStub(appletWrap);
|
||||
this.add ( appletWrap );
|
||||
appletWrap.setPreferredSize ( new Dimension (winSizeW, winSizeH) );
|
||||
this.pack();
|
||||
this.setLocationRelativeTo ( null );
|
||||
this.setResizable ( true );
|
||||
if ( maximize ) {
|
||||
this.setExtendedState ( MAXIMIZED_BOTH );
|
||||
}
|
||||
validate();
|
||||
appletWrap.init();
|
||||
appletWrap.start();
|
||||
setVisible ( true );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowActivated ( WindowEvent e ) {}
|
||||
|
||||
@Override
|
||||
public void windowClosed ( WindowEvent e ) {}
|
||||
|
||||
@Override
|
||||
public void windowClosing ( WindowEvent e )
|
||||
{
|
||||
new Thread() {
|
||||
public void run() {
|
||||
try {
|
||||
Thread.sleep ( 30000L );
|
||||
} catch ( InterruptedException localInterruptedException ) {
|
||||
localInterruptedException.printStackTrace();
|
||||
}
|
||||
System.out.println ( "FORCING EXIT!" );
|
||||
System.exit ( 0 );
|
||||
}
|
||||
}
|
||||
.start();
|
||||
|
||||
if ( appletWrap != null ) {
|
||||
appletWrap.stop();
|
||||
appletWrap.destroy();
|
||||
}
|
||||
// old minecraft versions can hang without this >_<
|
||||
System.exit ( 0 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowDeactivated ( WindowEvent e ) {}
|
||||
|
||||
@Override
|
||||
public void windowDeiconified ( WindowEvent e ) {}
|
||||
|
||||
@Override
|
||||
public void windowIconified ( WindowEvent e ) {}
|
||||
|
||||
@Override
|
||||
public void windowOpened ( WindowEvent e ) {}
|
||||
}
|
@ -1,86 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2021 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.Modifier;
|
||||
import java.util.List;
|
||||
|
||||
public class Utils
|
||||
{
|
||||
/**
|
||||
* Combine two parts of a path.
|
||||
*
|
||||
* @param path1
|
||||
* @param path2
|
||||
* @return the paths, combined
|
||||
*/
|
||||
public static String combine(String path1, String path2)
|
||||
{
|
||||
File file1 = new File(path1);
|
||||
File file2 = new File(file1, path2);
|
||||
return file2.getPath();
|
||||
}
|
||||
|
||||
/**
|
||||
* Join a list of strings into a string using a separator!
|
||||
*
|
||||
* @param strings the string list to join
|
||||
* @param separator the glue
|
||||
* @return the result.
|
||||
*/
|
||||
public static String join(List<String> strings, String separator)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String sep = "";
|
||||
for (String s : strings)
|
||||
{
|
||||
sb.append(sep).append(s);
|
||||
sep = separator;
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
162
libraries/launcher/org/multimc/applet/LegacyFrame.java
Normal file
162
libraries/launcher/org/multimc/applet/LegacyFrame.java
Normal file
@ -0,0 +1,162 @@
|
||||
/*
|
||||
* Copyright 2012-2021 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.applet;
|
||||
|
||||
import net.minecraft.Launcher;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.applet.Applet;
|
||||
import java.awt.*;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public final class LegacyFrame extends Frame {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger("LegacyFrame");
|
||||
|
||||
private final Launcher appletWrap;
|
||||
|
||||
public LegacyFrame(String title, Applet mcApplet) {
|
||||
super(title);
|
||||
|
||||
appletWrap = new Launcher(mcApplet);
|
||||
|
||||
mcApplet.setStub(appletWrap);
|
||||
|
||||
try {
|
||||
setIconImage(ImageIO.read(new File("icon.png")));
|
||||
} catch (IOException e) {
|
||||
LOGGER.log(Level.WARNING, "Unable to read Minecraft icon!", e);
|
||||
}
|
||||
|
||||
addWindowListener(new ForceExitHandler());
|
||||
}
|
||||
|
||||
public void start (
|
||||
String user,
|
||||
String session,
|
||||
int winSizeW,
|
||||
int winSizeH,
|
||||
boolean maximize,
|
||||
String serverAddress,
|
||||
String serverPort
|
||||
) {
|
||||
// Implements support for launching in to multiplayer on classic servers using a mpticket
|
||||
// file generated by an external program and stored in the instance's root folder.
|
||||
|
||||
Path mpticketFile =
|
||||
Paths.get(System.getProperty("user.dir"), "..", "mpticket");
|
||||
|
||||
Path mpticketFileCorrupt =
|
||||
Paths.get(System.getProperty("user.dir"), "..", "mpticket.corrupt");
|
||||
|
||||
if (Files.exists(mpticketFile)) {
|
||||
try {
|
||||
List<String> lines = Files.readAllLines(mpticketFile, StandardCharsets.UTF_8);
|
||||
|
||||
if (lines.size() < 3) {
|
||||
Files.move(
|
||||
mpticketFile,
|
||||
mpticketFileCorrupt,
|
||||
StandardCopyOption.REPLACE_EXISTING
|
||||
);
|
||||
|
||||
LOGGER.warning("Mpticket file is corrupted!");
|
||||
} else {
|
||||
// Assumes parameters are valid and in the correct order
|
||||
appletWrap.setParameter("server", lines.get(0));
|
||||
appletWrap.setParameter("port", lines.get(1));
|
||||
appletWrap.setParameter("mppass", lines.get(2));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
LOGGER.log(Level.WARNING, "Unable to read mpticket file!", e);
|
||||
}
|
||||
}
|
||||
|
||||
if (serverAddress != null) {
|
||||
appletWrap.setParameter("server", serverAddress);
|
||||
appletWrap.setParameter("port", serverPort);
|
||||
}
|
||||
|
||||
appletWrap.setParameter("username", user);
|
||||
appletWrap.setParameter("sessionid", session);
|
||||
appletWrap.setParameter("stand-alone", "true"); // Show the quit button.
|
||||
appletWrap.setParameter("haspaid", "true"); // Some old versions need this for world saves to work.
|
||||
appletWrap.setParameter("demo", "false");
|
||||
appletWrap.setParameter("fullscreen", "false");
|
||||
|
||||
add(appletWrap);
|
||||
|
||||
appletWrap.setPreferredSize(new Dimension(winSizeW, winSizeH));
|
||||
|
||||
pack();
|
||||
|
||||
setLocationRelativeTo(null);
|
||||
setResizable(true);
|
||||
|
||||
if (maximize)
|
||||
this.setExtendedState(MAXIMIZED_BOTH);
|
||||
|
||||
validate();
|
||||
|
||||
appletWrap.init();
|
||||
appletWrap.start();
|
||||
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
private final class ForceExitHandler extends WindowAdapter {
|
||||
|
||||
@Override
|
||||
public void windowClosing(WindowEvent e) {
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Thread.sleep(30000L);
|
||||
} catch (InterruptedException localInterruptedException) {
|
||||
localInterruptedException.printStackTrace();
|
||||
}
|
||||
|
||||
LOGGER.info("Forcing exit!");
|
||||
|
||||
System.exit(0);
|
||||
}
|
||||
}).start();
|
||||
|
||||
if (appletWrap != null) {
|
||||
appletWrap.stop();
|
||||
appletWrap.destroy();
|
||||
}
|
||||
|
||||
// old minecraft versions can hang without this >_<
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -14,8 +14,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.multimc;
|
||||
package org.multimc.exception;
|
||||
|
||||
public final class ParameterNotFoundException extends IllegalArgumentException {
|
||||
|
||||
public ParameterNotFoundException(String key) {
|
||||
super("Unknown parameter name: " + key);
|
||||
}
|
||||
|
||||
public class NotFoundException extends Exception
|
||||
{
|
||||
}
|
@ -14,12 +14,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.multimc;
|
||||
package org.multimc.exception;
|
||||
|
||||
public final class ParseException extends IllegalArgumentException {
|
||||
|
||||
public class ParseException extends java.lang.Exception
|
||||
{
|
||||
public ParseException() { super(); }
|
||||
public ParseException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
189
libraries/launcher/org/multimc/impl/OneSixLauncher.java
Normal file
189
libraries/launcher/org/multimc/impl/OneSixLauncher.java
Normal file
@ -0,0 +1,189 @@
|
||||
/* Copyright 2012-2021 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.impl;
|
||||
|
||||
import org.multimc.Launcher;
|
||||
import org.multimc.applet.LegacyFrame;
|
||||
import org.multimc.utils.Parameters;
|
||||
import org.multimc.utils.Utils;
|
||||
|
||||
import java.applet.Applet;
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public final class OneSixLauncher implements Launcher {
|
||||
|
||||
private static final int DEFAULT_WINDOW_WIDTH = 854;
|
||||
private static final int DEFAULT_WINDOW_HEIGHT = 480;
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger("OneSixLauncher");
|
||||
|
||||
// parameters, separated from ParamBucket
|
||||
private final List<String> mcParams;
|
||||
private final List<String> traits;
|
||||
private final String appletClass;
|
||||
private final String mainClass;
|
||||
private final String userName, sessionId;
|
||||
private final String windowTitle;
|
||||
|
||||
// secondary parameters
|
||||
private final int winSizeW;
|
||||
private final int winSizeH;
|
||||
private final boolean maximize;
|
||||
private final String cwd;
|
||||
|
||||
private final String serverAddress;
|
||||
private final String serverPort;
|
||||
|
||||
private final ClassLoader classLoader;
|
||||
|
||||
public OneSixLauncher(Parameters params) {
|
||||
classLoader = ClassLoader.getSystemClassLoader();
|
||||
|
||||
mcParams = params.allSafe("param", Collections.<String>emptyList());
|
||||
mainClass = params.firstSafe("mainClass", "net.minecraft.client.Minecraft");
|
||||
appletClass = params.firstSafe("appletClass", "net.minecraft.client.MinecraftApplet");
|
||||
traits = params.allSafe("traits", Collections.<String>emptyList());
|
||||
|
||||
userName = params.first("userName");
|
||||
sessionId = params.first("sessionId");
|
||||
windowTitle = params.firstSafe("windowTitle", "Minecraft");
|
||||
|
||||
serverAddress = params.firstSafe("serverAddress", null);
|
||||
serverPort = params.firstSafe("serverPort", null);
|
||||
|
||||
cwd = System.getProperty("user.dir");
|
||||
|
||||
String windowParams = params.firstSafe("windowParams", null);
|
||||
|
||||
if (windowParams != null) {
|
||||
String[] dimStrings = windowParams.split("x");
|
||||
|
||||
if (windowParams.equalsIgnoreCase("max")) {
|
||||
maximize = true;
|
||||
|
||||
winSizeW = DEFAULT_WINDOW_WIDTH;
|
||||
winSizeH = DEFAULT_WINDOW_HEIGHT;
|
||||
} else if (dimStrings.length == 2) {
|
||||
maximize = false;
|
||||
|
||||
winSizeW = Integer.parseInt(dimStrings[0]);
|
||||
winSizeH = Integer.parseInt(dimStrings[1]);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unexpected window size parameter value: " + windowParams);
|
||||
}
|
||||
} else {
|
||||
maximize = false;
|
||||
|
||||
winSizeW = DEFAULT_WINDOW_WIDTH;
|
||||
winSizeH = DEFAULT_WINDOW_HEIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
private void invokeMain(Class<?> mainClass) throws Exception {
|
||||
Method method = mainClass.getMethod("main", String[].class);
|
||||
|
||||
method.invoke(null, (Object) mcParams.toArray(new String[0]));
|
||||
}
|
||||
|
||||
private void legacyLaunch() throws Exception {
|
||||
// Get the Minecraft Class and set the base folder
|
||||
Class<?> minecraftClass = classLoader.loadClass(mainClass);
|
||||
|
||||
Field baseDirField = Utils.getMinecraftBaseDirField(minecraftClass);
|
||||
|
||||
if (baseDirField == null) {
|
||||
LOGGER.warning("Could not find Minecraft path field.");
|
||||
} else {
|
||||
baseDirField.setAccessible(true);
|
||||
|
||||
baseDirField.set(null, new File(cwd));
|
||||
}
|
||||
|
||||
System.setProperty("minecraft.applet.TargetDirectory", cwd);
|
||||
|
||||
if (!traits.contains("noapplet")) {
|
||||
LOGGER.info("Launching with applet wrapper...");
|
||||
|
||||
try {
|
||||
Class<?> mcAppletClass = classLoader.loadClass(appletClass);
|
||||
|
||||
Applet mcApplet = (Applet) mcAppletClass.getConstructor().newInstance();
|
||||
|
||||
LegacyFrame mcWindow = new LegacyFrame(windowTitle, mcApplet);
|
||||
|
||||
mcWindow.start(
|
||||
userName,
|
||||
sessionId,
|
||||
winSizeW,
|
||||
winSizeH,
|
||||
maximize,
|
||||
serverAddress,
|
||||
serverPort
|
||||
);
|
||||
|
||||
return;
|
||||
} catch (Exception e) {
|
||||
LOGGER.log(Level.SEVERE, "Applet wrapper failed: ", e);
|
||||
|
||||
LOGGER.warning("Falling back to using main class.");
|
||||
}
|
||||
}
|
||||
|
||||
invokeMain(minecraftClass);
|
||||
}
|
||||
|
||||
private void launchWithMainClass() throws Exception {
|
||||
// window size, title and state, onesix
|
||||
|
||||
// FIXME: there is no good way to maximize the minecraft window in onesix.
|
||||
// the following often breaks linux screen setups
|
||||
// mcparams.add("--fullscreen");
|
||||
|
||||
if (!maximize) {
|
||||
mcParams.add("--width");
|
||||
mcParams.add(Integer.toString(winSizeW));
|
||||
mcParams.add("--height");
|
||||
mcParams.add(Integer.toString(winSizeH));
|
||||
}
|
||||
|
||||
if (serverAddress != null) {
|
||||
mcParams.add("--server");
|
||||
mcParams.add(serverAddress);
|
||||
mcParams.add("--port");
|
||||
mcParams.add(serverPort);
|
||||
}
|
||||
|
||||
invokeMain(classLoader.loadClass(mainClass));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void launch() throws Exception {
|
||||
if (traits.contains("legacyLaunch") || traits.contains("alphaLaunch")) {
|
||||
// legacy launch uses the applet wrapper
|
||||
legacyLaunch();
|
||||
} else {
|
||||
// normal launch just calls main()
|
||||
launchWithMainClass();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,256 +0,0 @@
|
||||
/* Copyright 2012-2021 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.applet.Applet;
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class OneSixLauncher implements Launcher
|
||||
{
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger("OneSixLauncher");
|
||||
|
||||
// parameters, separated from ParamBucket
|
||||
private List<String> libraries;
|
||||
private List<String> mcparams;
|
||||
private List<String> mods;
|
||||
private List<String> jarmods;
|
||||
private List<String> coremods;
|
||||
private List<String> traits;
|
||||
private String appletClass;
|
||||
private String mainClass;
|
||||
private String nativePath;
|
||||
private String userName, sessionId;
|
||||
private String windowTitle;
|
||||
private String windowParams;
|
||||
|
||||
// secondary parameters
|
||||
private int winSizeW;
|
||||
private int winSizeH;
|
||||
private boolean maximize;
|
||||
private String cwd;
|
||||
|
||||
private String serverAddress;
|
||||
private String serverPort;
|
||||
|
||||
// the much abused system classloader, for convenience (for further abuse)
|
||||
private ClassLoader cl;
|
||||
|
||||
private void processParams(ParamBucket params) throws NotFoundException
|
||||
{
|
||||
libraries = params.all("cp");
|
||||
mcparams = params.allSafe("param", new ArrayList<String>() );
|
||||
mainClass = params.firstSafe("mainClass", "net.minecraft.client.Minecraft");
|
||||
appletClass = params.firstSafe("appletClass", "net.minecraft.client.MinecraftApplet");
|
||||
traits = params.allSafe("traits", new ArrayList<String>());
|
||||
nativePath = params.first("natives");
|
||||
|
||||
userName = params.first("userName");
|
||||
sessionId = params.first("sessionId");
|
||||
windowTitle = params.firstSafe("windowTitle", "Minecraft");
|
||||
windowParams = params.firstSafe("windowParams", "854x480");
|
||||
|
||||
serverAddress = params.firstSafe("serverAddress", null);
|
||||
serverPort = params.firstSafe("serverPort", null);
|
||||
|
||||
cwd = System.getProperty("user.dir");
|
||||
|
||||
winSizeW = 854;
|
||||
winSizeH = 480;
|
||||
maximize = false;
|
||||
|
||||
String[] dimStrings = windowParams.split("x");
|
||||
|
||||
if (windowParams.equalsIgnoreCase("max"))
|
||||
{
|
||||
maximize = true;
|
||||
}
|
||||
else if (dimStrings.length == 2)
|
||||
{
|
||||
try
|
||||
{
|
||||
winSizeW = Integer.parseInt(dimStrings[0]);
|
||||
winSizeH = Integer.parseInt(dimStrings[1]);
|
||||
} catch (NumberFormatException ignored) {}
|
||||
}
|
||||
}
|
||||
|
||||
int legacyLaunch()
|
||||
{
|
||||
// Get the Minecraft Class and set the base folder
|
||||
Class<?> mc;
|
||||
try
|
||||
{
|
||||
mc = cl.loadClass(mainClass);
|
||||
|
||||
Field f = Utils.getMCPathField(mc);
|
||||
|
||||
if (f == null)
|
||||
{
|
||||
LOGGER.warning("Could not find Minecraft path field.");
|
||||
}
|
||||
else
|
||||
{
|
||||
f.setAccessible(true);
|
||||
f.set(null, new File(cwd));
|
||||
}
|
||||
} catch (Exception e)
|
||||
{
|
||||
LOGGER.log(
|
||||
Level.SEVERE,
|
||||
"Could not set base folder. Failed to find/access Minecraft main class:",
|
||||
e
|
||||
);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
System.setProperty("minecraft.applet.TargetDirectory", cwd);
|
||||
|
||||
if(!traits.contains("noapplet"))
|
||||
{
|
||||
LOGGER.info("Launching with applet wrapper...");
|
||||
try
|
||||
{
|
||||
Class<?> MCAppletClass = cl.loadClass(appletClass);
|
||||
Applet mcappl = (Applet) MCAppletClass.newInstance();
|
||||
LegacyFrame mcWindow = new LegacyFrame(windowTitle);
|
||||
mcWindow.start(mcappl, userName, sessionId, winSizeW, winSizeH, maximize, serverAddress, serverPort);
|
||||
return 0;
|
||||
} catch (Exception e)
|
||||
{
|
||||
LOGGER.log(Level.SEVERE, "Applet wrapper failed:", e);
|
||||
|
||||
LOGGER.warning("Falling back to using main class.");
|
||||
}
|
||||
}
|
||||
|
||||
// init params for the main method to chomp on.
|
||||
String[] paramsArray = mcparams.toArray(new String[mcparams.size()]);
|
||||
try
|
||||
{
|
||||
mc.getMethod("main", String[].class).invoke(null, (Object) paramsArray);
|
||||
return 0;
|
||||
} catch (Exception e)
|
||||
{
|
||||
LOGGER.log(Level.SEVERE, "Failed to invoke the Minecraft main class:", e);
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int launchWithMainClass()
|
||||
{
|
||||
// window size, title and state, onesix
|
||||
if (maximize)
|
||||
{
|
||||
// FIXME: there is no good way to maximize the minecraft window in onesix.
|
||||
// the following often breaks linux screen setups
|
||||
// mcparams.add("--fullscreen");
|
||||
}
|
||||
else
|
||||
{
|
||||
mcparams.add("--width");
|
||||
mcparams.add(Integer.toString(winSizeW));
|
||||
mcparams.add("--height");
|
||||
mcparams.add(Integer.toString(winSizeH));
|
||||
}
|
||||
|
||||
if (serverAddress != null)
|
||||
{
|
||||
mcparams.add("--server");
|
||||
mcparams.add(serverAddress);
|
||||
mcparams.add("--port");
|
||||
mcparams.add(serverPort);
|
||||
}
|
||||
|
||||
// Get the Minecraft Class.
|
||||
Class<?> mc;
|
||||
try
|
||||
{
|
||||
mc = cl.loadClass(mainClass);
|
||||
} catch (ClassNotFoundException e)
|
||||
{
|
||||
LOGGER.log(Level.SEVERE, "Failed to find Minecraft main class:", e);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// get the main method.
|
||||
Method meth;
|
||||
try
|
||||
{
|
||||
meth = mc.getMethod("main", String[].class);
|
||||
} catch (NoSuchMethodException e)
|
||||
{
|
||||
LOGGER.log(Level.SEVERE, "Failed to acquire the main method:", e);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// init params for the main method to chomp on.
|
||||
String[] paramsArray = mcparams.toArray(new String[mcparams.size()]);
|
||||
try
|
||||
{
|
||||
// static method doesn't have an instance
|
||||
meth.invoke(null, (Object) paramsArray);
|
||||
} catch (Exception e)
|
||||
{
|
||||
LOGGER.log(Level.SEVERE, "Failed to start Minecraft:", e);
|
||||
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int launch(ParamBucket params)
|
||||
{
|
||||
// get and process the launch script params
|
||||
try
|
||||
{
|
||||
processParams(params);
|
||||
} catch (NotFoundException e)
|
||||
{
|
||||
LOGGER.log(Level.SEVERE, "Not enough arguments!");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// grab the system classloader and ...
|
||||
cl = ClassLoader.getSystemClassLoader();
|
||||
|
||||
if (traits.contains("legacyLaunch") || traits.contains("alphaLaunch") )
|
||||
{
|
||||
// legacy launch uses the applet wrapper
|
||||
return legacyLaunch();
|
||||
}
|
||||
else
|
||||
{
|
||||
// normal launch just calls main()
|
||||
return launchWithMainClass();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -14,36 +14,41 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.multimc;
|
||||
package org.multimc.utils;
|
||||
|
||||
import org.multimc.exception.ParameterNotFoundException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ParamBucket
|
||||
{
|
||||
public final class Parameters {
|
||||
|
||||
private final Map<String, List<String>> paramsMap = new HashMap<>();
|
||||
|
||||
public void add(String key, String value)
|
||||
{
|
||||
paramsMap.computeIfAbsent(key, k -> new ArrayList<>())
|
||||
.add(value);
|
||||
public void add(String key, String value) {
|
||||
List<String> params = paramsMap.get(key);
|
||||
|
||||
if (params == null) {
|
||||
params = new ArrayList<>();
|
||||
|
||||
paramsMap.put(key, params);
|
||||
}
|
||||
|
||||
params.add(value);
|
||||
}
|
||||
|
||||
public List<String> all(String key) throws NotFoundException
|
||||
{
|
||||
public List<String> all(String key) throws ParameterNotFoundException {
|
||||
List<String> params = paramsMap.get(key);
|
||||
|
||||
if (params == null)
|
||||
throw new NotFoundException();
|
||||
throw new ParameterNotFoundException(key);
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
public List<String> allSafe(String key, List<String> def)
|
||||
{
|
||||
public List<String> allSafe(String key, List<String> def) {
|
||||
List<String> params = paramsMap.get(key);
|
||||
|
||||
if (params == null || params.isEmpty())
|
||||
@ -52,23 +57,16 @@ public class ParamBucket
|
||||
return params;
|
||||
}
|
||||
|
||||
public List<String> allSafe(String key)
|
||||
{
|
||||
return allSafe(key, new ArrayList<>());
|
||||
}
|
||||
|
||||
public String first(String key) throws NotFoundException
|
||||
{
|
||||
public String first(String key) throws ParameterNotFoundException {
|
||||
List<String> list = all(key);
|
||||
|
||||
if (list.isEmpty())
|
||||
throw new NotFoundException();
|
||||
throw new ParameterNotFoundException(key);
|
||||
|
||||
return list.get(0);
|
||||
}
|
||||
|
||||
public String firstSafe(String key, String def)
|
||||
{
|
||||
public String firstSafe(String key, String def) {
|
||||
List<String> params = paramsMap.get(key);
|
||||
|
||||
if (params == null || params.isEmpty())
|
||||
@ -77,9 +75,4 @@ public class ParamBucket
|
||||
return params.get(0);
|
||||
}
|
||||
|
||||
public String firstSafe(String key)
|
||||
{
|
||||
return firstSafe(key, "");
|
||||
}
|
||||
|
||||
}
|
49
libraries/launcher/org/multimc/utils/Utils.java
Normal file
49
libraries/launcher/org/multimc/utils/Utils.java
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2012-2021 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.utils;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
public final class Utils {
|
||||
|
||||
private Utils() {}
|
||||
|
||||
/**
|
||||
* Finds a field that looks like a Minecraft base folder in a supplied class
|
||||
*
|
||||
* @param clazz the class to scan
|
||||
*/
|
||||
public static Field getMinecraftBaseDirField(Class<?> clazz) {
|
||||
for (Field f : clazz.getDeclaredFields()) {
|
||||
// Has to be File
|
||||
if (f.getType() != File.class)
|
||||
continue;
|
||||
|
||||
// And Private Static.
|
||||
if (!Modifier.isStatic(f.getModifiers()) || !Modifier.isPrivate(f.getModifiers()))
|
||||
continue;
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user