Various tweaks to the Java component of the launcher
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
This commit is contained in:
parent
e4e0c27e1c
commit
e68dcea6bc
@ -3,6 +3,7 @@
|
|||||||
* PolyMC - Minecraft Launcher
|
* PolyMC - Minecraft Launcher
|
||||||
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||||
* Copyright (C) 2022 Jamie Mansfield <jmansfield@cadixdev.org>
|
* Copyright (C) 2022 Jamie Mansfield <jmansfield@cadixdev.org>
|
||||||
|
* Copyright (C) 2022 TheKodeToad <TheKodeToad@proton.me>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -647,7 +648,17 @@ QString MinecraftInstance::createLaunchScript(AuthSessionPtr session, MinecraftS
|
|||||||
{
|
{
|
||||||
launchScript += "traits " + trait + "\n";
|
launchScript += "traits " + trait + "\n";
|
||||||
}
|
}
|
||||||
launchScript += "launcher onesix\n";
|
|
||||||
|
launchScript += "launcher ";
|
||||||
|
|
||||||
|
// use legacy launcher if the traits are set
|
||||||
|
if (profile->getTraits().contains("legacyLaunch") || profile->getTraits().contains("alphaLaunch"))
|
||||||
|
launchScript += "legacy";
|
||||||
|
else
|
||||||
|
launchScript += "standard";
|
||||||
|
|
||||||
|
launchScript += "\n";
|
||||||
|
|
||||||
// qDebug() << "Generated launch script:" << launchScript;
|
// qDebug() << "Generated launch script:" << launchScript;
|
||||||
return launchScript;
|
return launchScript;
|
||||||
}
|
}
|
||||||
|
@ -51,10 +51,10 @@ It:
|
|||||||
|
|
||||||
This means the process is essentially idle until the final command is sent. You can, for example, attach a profiler before you send it.
|
This means the process is essentially idle until the final command is sent. You can, for example, attach a profiler before you send it.
|
||||||
|
|
||||||
A `legacy` and `onesix` launchers are available.
|
A `legacy` and `standard` launchers are available.
|
||||||
|
|
||||||
- `legacy` is intended for use with Minecraft versions < 1.6 and is deprecated.
|
- `legacy` is intended for use with Minecraft versions < 1.6 and is deprecated.
|
||||||
- `onesix` can handle launching any Minecraft version, at the cost of some extra features `legacy` enables (custom window icon and title).
|
- `standard` can handle launching any Minecraft version, at the cost of some extra features `legacy` enables (custom window icon and title).
|
||||||
|
|
||||||
Example (some parts have been censored):
|
Example (some parts have been censored):
|
||||||
|
|
||||||
@ -132,7 +132,7 @@ ext /home/peterix/minecraft/FTB/libraries/org/lwjgl/lwjgl/lwjgl-platform/2.9.1/l
|
|||||||
ext /home/peterix/minecraft/FTB/libraries/net/java/jinput/jinput-platform/2.0.5/jinput-platform-2.0.5-natives-linux.jar
|
ext /home/peterix/minecraft/FTB/libraries/net/java/jinput/jinput-platform/2.0.5/jinput-platform-2.0.5-natives-linux.jar
|
||||||
natives /home/peterix/minecraft/FTB/17ForgeTest/natives
|
natives /home/peterix/minecraft/FTB/17ForgeTest/natives
|
||||||
cp /home/peterix/minecraft/FTB/versions/1.7.10/1.7.10.jar
|
cp /home/peterix/minecraft/FTB/versions/1.7.10/1.7.10.jar
|
||||||
launcher onesix
|
launcher standard
|
||||||
```
|
```
|
||||||
|
|
||||||
Available under `GPL-3.0-only` (with classpath exception), sublicensed from its original `Apache-2.0` codebase
|
Available under `GPL-3.0-only` (with classpath exception), sublicensed from its original `Apache-2.0` codebase
|
||||||
|
@ -10,7 +10,9 @@ set(SRC
|
|||||||
org/prismlauncher/EntryPoint.java
|
org/prismlauncher/EntryPoint.java
|
||||||
org/prismlauncher/Launcher.java
|
org/prismlauncher/Launcher.java
|
||||||
org/prismlauncher/LauncherFactory.java
|
org/prismlauncher/LauncherFactory.java
|
||||||
org/prismlauncher/impl/OneSixLauncher.java
|
org/prismlauncher/impl/AbstractLauncher.java
|
||||||
|
org/prismlauncher/impl/LegacyLauncher.java
|
||||||
|
org/prismlauncher/impl/StandardLauncher.java
|
||||||
org/prismlauncher/applet/LegacyFrame.java
|
org/prismlauncher/applet/LegacyFrame.java
|
||||||
org/prismlauncher/exception/ParameterNotFoundException.java
|
org/prismlauncher/exception/ParameterNotFoundException.java
|
||||||
org/prismlauncher/exception/ParseException.java
|
org/prismlauncher/exception/ParseException.java
|
||||||
|
@ -81,33 +81,35 @@ public final class EntryPoint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Action parseLine(String inData) throws ParseException {
|
private Action parseLine(String inData) throws ParseException {
|
||||||
String[] tokens = inData.split("\\s+", 2);
|
if (inData.length() == 0)
|
||||||
|
|
||||||
if (tokens.length == 0)
|
|
||||||
throw new ParseException("Unexpected empty string!");
|
throw new ParseException("Unexpected empty string!");
|
||||||
|
|
||||||
switch (tokens[0]) {
|
String first = inData;
|
||||||
case "launch": {
|
String second = null;
|
||||||
return Action.Launch;
|
int splitPoint = inData.indexOf(' ');
|
||||||
|
|
||||||
|
if (splitPoint != -1) {
|
||||||
|
first = first.substring(0, splitPoint);
|
||||||
|
second = inData.substring(splitPoint + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
case "abort": {
|
switch (first) {
|
||||||
return Action.Abort;
|
case "launch":
|
||||||
}
|
return Action.LAUNCH;
|
||||||
|
case "abort":
|
||||||
default: {
|
return Action.ABORT;
|
||||||
if (tokens.length != 2)
|
default:
|
||||||
|
if (second == null || second.isEmpty())
|
||||||
throw new ParseException("Error while parsing:" + inData);
|
throw new ParseException("Error while parsing:" + inData);
|
||||||
|
|
||||||
params.add(tokens[0], tokens[1]);
|
params.add(first, second);
|
||||||
|
|
||||||
return Action.Proceed;
|
return Action.PROCEED;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int listen() {
|
public int listen() {
|
||||||
Action action = Action.Proceed;
|
Action action = Action.PROCEED;
|
||||||
|
|
||||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(
|
try (BufferedReader reader = new BufferedReader(new InputStreamReader(
|
||||||
System.in,
|
System.in,
|
||||||
@ -115,21 +117,21 @@ public final class EntryPoint {
|
|||||||
))) {
|
))) {
|
||||||
String line;
|
String line;
|
||||||
|
|
||||||
while (action == Action.Proceed) {
|
while (action == Action.PROCEED) {
|
||||||
if ((line = reader.readLine()) != null) {
|
if ((line = reader.readLine()) != null) {
|
||||||
action = parseLine(line);
|
action = parseLine(line);
|
||||||
} else {
|
} else {
|
||||||
action = Action.Abort;
|
action = Action.ABORT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException | ParseException e) {
|
} catch (IOException | ParseException e) {
|
||||||
LOGGER.log(Level.SEVERE, "Launcher ABORT due to exception:", e);
|
LOGGER.log(Level.SEVERE, "Launcher abort due to exception:", e);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Main loop
|
// Main loop
|
||||||
if (action == Action.Abort) {
|
if (action == Action.ABORT) {
|
||||||
LOGGER.info("Launch aborted by the launcher.");
|
LOGGER.info("Launch aborted by the launcher.");
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@ -138,7 +140,7 @@ public final class EntryPoint {
|
|||||||
try {
|
try {
|
||||||
Launcher launcher =
|
Launcher launcher =
|
||||||
LauncherFactory
|
LauncherFactory
|
||||||
.getInstance()
|
.INSTANCE
|
||||||
.createLauncher(params);
|
.createLauncher(params);
|
||||||
|
|
||||||
launcher.launch();
|
launcher.launch();
|
||||||
@ -148,7 +150,7 @@ public final class EntryPoint {
|
|||||||
LOGGER.log(Level.SEVERE, "Wrong argument.", e);
|
LOGGER.log(Level.SEVERE, "Wrong argument.", e);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
} catch (Exception e) {
|
} catch (Throwable e) {
|
||||||
LOGGER.log(Level.SEVERE, "Exception caught from launcher.", e);
|
LOGGER.log(Level.SEVERE, "Exception caught from launcher.", e);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@ -156,9 +158,9 @@ public final class EntryPoint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private enum Action {
|
private enum Action {
|
||||||
Proceed,
|
PROCEED,
|
||||||
Launch,
|
LAUNCH,
|
||||||
Abort
|
ABORT
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,6 @@ package org.prismlauncher;
|
|||||||
|
|
||||||
public interface Launcher {
|
public interface Launcher {
|
||||||
|
|
||||||
void launch() throws Exception;
|
void launch() throws Throwable;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,8 @@
|
|||||||
|
|
||||||
package org.prismlauncher;
|
package org.prismlauncher;
|
||||||
|
|
||||||
import org.prismlauncher.impl.OneSixLauncher;
|
import org.prismlauncher.impl.LegacyLauncher;
|
||||||
|
import org.prismlauncher.impl.StandardLauncher;
|
||||||
import org.prismlauncher.utils.Parameters;
|
import org.prismlauncher.utils.Parameters;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -43,15 +44,21 @@ import java.util.Map;
|
|||||||
|
|
||||||
public final class LauncherFactory {
|
public final class LauncherFactory {
|
||||||
|
|
||||||
private static final LauncherFactory INSTANCE = new LauncherFactory();
|
public static final LauncherFactory INSTANCE = new LauncherFactory();
|
||||||
|
|
||||||
private final Map<String, LauncherProvider> launcherRegistry = new HashMap<>();
|
private final Map<String, LauncherProvider> launcherRegistry = new HashMap<>();
|
||||||
|
|
||||||
private LauncherFactory() {
|
private LauncherFactory() {
|
||||||
launcherRegistry.put("onesix", new LauncherProvider() {
|
launcherRegistry.put("standard", new LauncherProvider() {
|
||||||
@Override
|
@Override
|
||||||
public Launcher provide(Parameters parameters) {
|
public Launcher provide(Parameters parameters) {
|
||||||
return new OneSixLauncher(parameters);
|
return new StandardLauncher(parameters);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
launcherRegistry.put("legacy", new LauncherProvider() {
|
||||||
|
@Override
|
||||||
|
public Launcher provide(Parameters parameters) {
|
||||||
|
return new LegacyLauncher(parameters);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -67,10 +74,6 @@ public final class LauncherFactory {
|
|||||||
return launcherProvider.provide(parameters);
|
return launcherProvider.provide(parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static LauncherFactory getInstance() {
|
|
||||||
return INSTANCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface LauncherProvider {
|
public interface LauncherProvider {
|
||||||
|
|
||||||
Launcher provide(Parameters parameters);
|
Launcher provide(Parameters parameters);
|
||||||
|
@ -34,6 +34,7 @@ import java.util.List;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
@SuppressWarnings("removal")
|
||||||
public final class LegacyFrame extends Frame {
|
public final class LegacyFrame extends Frame {
|
||||||
|
|
||||||
private static final Logger LOGGER = Logger.getLogger("LegacyFrame");
|
private static final Logger LOGGER = Logger.getLogger("LegacyFrame");
|
||||||
@ -105,7 +106,7 @@ public final class LegacyFrame extends Frame {
|
|||||||
|
|
||||||
appletWrap.setParameter("username", user);
|
appletWrap.setParameter("username", user);
|
||||||
appletWrap.setParameter("sessionid", session);
|
appletWrap.setParameter("sessionid", session);
|
||||||
appletWrap.setParameter("stand-alone", "true"); // Show the quit button.
|
appletWrap.setParameter("stand-alone", "true"); // Show the quit button. TODO: why won't this work?
|
||||||
appletWrap.setParameter("haspaid", "true"); // Some old versions need this for world saves to work.
|
appletWrap.setParameter("haspaid", "true"); // Some old versions need this for world saves to work.
|
||||||
appletWrap.setParameter("demo", isDemo ? "true" : "false");
|
appletWrap.setParameter("demo", isDemo ? "true" : "false");
|
||||||
appletWrap.setParameter("fullscreen", "false");
|
appletWrap.setParameter("fullscreen", "false");
|
||||||
|
@ -0,0 +1,95 @@
|
|||||||
|
/* 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.prismlauncher.impl;
|
||||||
|
|
||||||
|
import java.lang.invoke.MethodHandle;
|
||||||
|
import java.lang.invoke.MethodHandles;
|
||||||
|
import java.lang.invoke.MethodType;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.prismlauncher.Launcher;
|
||||||
|
import org.prismlauncher.exception.ParseException;
|
||||||
|
import org.prismlauncher.utils.Parameters;
|
||||||
|
|
||||||
|
public abstract class AbstractLauncher implements Launcher {
|
||||||
|
|
||||||
|
private static final int DEFAULT_WINDOW_WIDTH = 854;
|
||||||
|
private static final int DEFAULT_WINDOW_HEIGHT = 480;
|
||||||
|
|
||||||
|
// parameters, separated from ParamBucket
|
||||||
|
protected final List<String> mcParams;
|
||||||
|
private final String mainClass;
|
||||||
|
|
||||||
|
// secondary parameters
|
||||||
|
protected final int width;
|
||||||
|
protected final int height;
|
||||||
|
protected final boolean maximize;
|
||||||
|
|
||||||
|
protected final String serverAddress, serverPort;
|
||||||
|
|
||||||
|
protected final ClassLoader classLoader;
|
||||||
|
|
||||||
|
public AbstractLauncher(Parameters params) {
|
||||||
|
classLoader = ClassLoader.getSystemClassLoader();
|
||||||
|
|
||||||
|
mcParams = params.allSafe("param", new ArrayList<String>());
|
||||||
|
mainClass = params.firstSafe("mainClass", "net.minecraft.client.Minecraft");
|
||||||
|
|
||||||
|
serverAddress = params.firstSafe("serverAddress", null);
|
||||||
|
serverPort = params.firstSafe("serverPort", null);
|
||||||
|
|
||||||
|
String windowParams = params.firstSafe("windowParams", null);
|
||||||
|
|
||||||
|
if ("max".equals(windowParams) || windowParams == null) {
|
||||||
|
maximize = windowParams != null;
|
||||||
|
|
||||||
|
width = DEFAULT_WINDOW_WIDTH;
|
||||||
|
height = DEFAULT_WINDOW_HEIGHT;
|
||||||
|
} else {
|
||||||
|
maximize = false;
|
||||||
|
|
||||||
|
int byIndex = windowParams.indexOf('x');
|
||||||
|
|
||||||
|
if (byIndex != -1) {
|
||||||
|
try {
|
||||||
|
width = Integer.parseInt(windowParams.substring(0, byIndex));
|
||||||
|
height = Integer.parseInt(windowParams.substring(byIndex + 1));
|
||||||
|
return;
|
||||||
|
} catch(NumberFormatException pass) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new ParseException("Invalid window size parameter value: " + windowParams);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Class<?> loadMain() throws ClassNotFoundException {
|
||||||
|
return classLoader.loadClass(mainClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void loadAndInvokeMain() throws Throwable, ClassNotFoundException {
|
||||||
|
invokeMain(loadMain());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void invokeMain(Class<?> mainClass) throws Throwable {
|
||||||
|
MethodHandle method = MethodHandles.lookup().findStatic(mainClass, "main", MethodType.methodType(void.class, String[].class));
|
||||||
|
|
||||||
|
method.invokeExact(mcParams.toArray(new String[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
104
libraries/launcher/org/prismlauncher/impl/LegacyLauncher.java
Normal file
104
libraries/launcher/org/prismlauncher/impl/LegacyLauncher.java
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
/* 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.prismlauncher.impl;
|
||||||
|
|
||||||
|
import java.applet.Applet;
|
||||||
|
import java.io.File;
|
||||||
|
import java.lang.invoke.MethodHandle;
|
||||||
|
import java.lang.invoke.MethodHandles;
|
||||||
|
import java.lang.invoke.MethodType;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import org.prismlauncher.applet.LegacyFrame;
|
||||||
|
import org.prismlauncher.utils.Parameters;
|
||||||
|
import org.prismlauncher.utils.Utils;
|
||||||
|
|
||||||
|
@SuppressWarnings("removal")
|
||||||
|
public final class LegacyLauncher extends AbstractLauncher {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = Logger.getLogger("LegacyLauncher");
|
||||||
|
|
||||||
|
private final String user, session;
|
||||||
|
private final String title;
|
||||||
|
private final String appletClass;
|
||||||
|
|
||||||
|
private final boolean noApplet;
|
||||||
|
private final String cwd;
|
||||||
|
|
||||||
|
public LegacyLauncher(Parameters params) {
|
||||||
|
super(params);
|
||||||
|
|
||||||
|
user = params.first("userName");
|
||||||
|
session = params.first("sessionId");
|
||||||
|
title = params.firstSafe("windowTitle", "Minecraft");
|
||||||
|
appletClass = params.firstSafe("appletClass", "net.minecraft.client.MinecraftApplet");
|
||||||
|
|
||||||
|
List<String> traits = params.allSafe("traits", Collections.<String>emptyList());
|
||||||
|
noApplet = traits.contains("noapplet");
|
||||||
|
|
||||||
|
cwd = System.getProperty("user.dir");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void launch() throws Throwable {
|
||||||
|
Class<?> main = loadMain();
|
||||||
|
Field gameDirField = Utils.getMinecraftGameDirField(main);
|
||||||
|
|
||||||
|
if (gameDirField == null) {
|
||||||
|
LOGGER.warning("Could not find Mineraft path field.");
|
||||||
|
} else {
|
||||||
|
gameDirField.setAccessible(true);
|
||||||
|
gameDirField.set(null, new File(cwd));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!noApplet) {
|
||||||
|
LOGGER.info("Launching with applet wrapper...");
|
||||||
|
|
||||||
|
try {
|
||||||
|
Class<?> appletClass = classLoader.loadClass(this.appletClass);
|
||||||
|
|
||||||
|
MethodHandle constructor = MethodHandles.lookup().findConstructor(appletClass, MethodType.methodType(void.class));
|
||||||
|
Applet applet = (Applet) constructor.invoke();
|
||||||
|
|
||||||
|
LegacyFrame window = new LegacyFrame(title, applet);
|
||||||
|
|
||||||
|
window.start(
|
||||||
|
user,
|
||||||
|
session,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
maximize,
|
||||||
|
serverAddress,
|
||||||
|
serverPort,
|
||||||
|
mcParams.contains("--demo")
|
||||||
|
);
|
||||||
|
|
||||||
|
return;
|
||||||
|
} catch (Throwable e) {
|
||||||
|
LOGGER.log(Level.SEVERE, "Applet wrapper failed:", e);
|
||||||
|
|
||||||
|
LOGGER.warning("Falling back to using main class.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
invokeMain(main);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,190 +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.prismlauncher.impl;
|
|
||||||
|
|
||||||
import org.prismlauncher.Launcher;
|
|
||||||
import org.prismlauncher.applet.LegacyFrame;
|
|
||||||
import org.prismlauncher.utils.Parameters;
|
|
||||||
import org.prismlauncher.utils.Utils;
|
|
||||||
|
|
||||||
import java.applet.Applet;
|
|
||||||
import java.io.File;
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
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", 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>());
|
|
||||||
|
|
||||||
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,
|
|
||||||
mcParams.contains("--demo")
|
|
||||||
);
|
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -0,0 +1,51 @@
|
|||||||
|
/* 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.prismlauncher.impl;
|
||||||
|
|
||||||
|
import org.prismlauncher.utils.Parameters;
|
||||||
|
|
||||||
|
public final class StandardLauncher extends AbstractLauncher {
|
||||||
|
|
||||||
|
public StandardLauncher(Parameters params) {
|
||||||
|
super(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void launch() throws Throwable {
|
||||||
|
// window size, title and state
|
||||||
|
|
||||||
|
// FIXME: there is no good way to maximize the minecraft window from here.
|
||||||
|
// the following often breaks linux screen setups
|
||||||
|
// mcparams.add("--fullscreen");
|
||||||
|
|
||||||
|
if (!maximize) {
|
||||||
|
mcParams.add("--width");
|
||||||
|
mcParams.add(Integer.toString(width));
|
||||||
|
mcParams.add("--height");
|
||||||
|
mcParams.add(Integer.toString(height));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (serverAddress != null) {
|
||||||
|
mcParams.add("--server");
|
||||||
|
mcParams.add(serverAddress);
|
||||||
|
mcParams.add("--port");
|
||||||
|
mcParams.add(serverPort);
|
||||||
|
}
|
||||||
|
|
||||||
|
loadAndInvokeMain();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -25,22 +25,22 @@ import java.util.Map;
|
|||||||
|
|
||||||
public final class Parameters {
|
public final class Parameters {
|
||||||
|
|
||||||
private final Map<String, List<String>> paramsMap = new HashMap<>();
|
private final Map<String, List<String>> map = new HashMap<>();
|
||||||
|
|
||||||
public void add(String key, String value) {
|
public void add(String key, String value) {
|
||||||
List<String> params = paramsMap.get(key);
|
List<String> params = map.get(key);
|
||||||
|
|
||||||
if (params == null) {
|
if (params == null) {
|
||||||
params = new ArrayList<>();
|
params = new ArrayList<>();
|
||||||
|
|
||||||
paramsMap.put(key, params);
|
map.put(key, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
params.add(value);
|
params.add(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> all(String key) throws ParameterNotFoundException {
|
public List<String> all(String key) throws ParameterNotFoundException {
|
||||||
List<String> params = paramsMap.get(key);
|
List<String> params = map.get(key);
|
||||||
|
|
||||||
if (params == null)
|
if (params == null)
|
||||||
throw new ParameterNotFoundException(key);
|
throw new ParameterNotFoundException(key);
|
||||||
@ -49,7 +49,7 @@ public final class Parameters {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public List<String> allSafe(String key, List<String> def) {
|
public List<String> allSafe(String key, List<String> def) {
|
||||||
List<String> params = paramsMap.get(key);
|
List<String> params = map.get(key);
|
||||||
|
|
||||||
if (params == null || params.isEmpty())
|
if (params == null || params.isEmpty())
|
||||||
return def;
|
return def;
|
||||||
@ -67,7 +67,7 @@ public final class Parameters {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String firstSafe(String key, String def) {
|
public String firstSafe(String key, String def) {
|
||||||
List<String> params = paramsMap.get(key);
|
List<String> params = map.get(key);
|
||||||
|
|
||||||
if (params == null || params.isEmpty())
|
if (params == null || params.isEmpty())
|
||||||
return def;
|
return def;
|
||||||
|
@ -29,7 +29,7 @@ public final class Utils {
|
|||||||
*
|
*
|
||||||
* @param clazz the class to scan
|
* @param clazz the class to scan
|
||||||
*/
|
*/
|
||||||
public static Field getMinecraftBaseDirField(Class<?> clazz) {
|
public static Field getMinecraftGameDirField(Class<?> clazz) {
|
||||||
for (Field f : clazz.getDeclaredFields()) {
|
for (Field f : clazz.getDeclaredFields()) {
|
||||||
// Has to be File
|
// Has to be File
|
||||||
if (f.getType() != File.class)
|
if (f.getType() != File.class)
|
||||||
|
Loading…
Reference in New Issue
Block a user