Move legacy support classes to another jar

Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
This commit is contained in:
TheKodeToad 2023-01-06 09:21:09 +00:00
parent cb32711077
commit 17317ea308
23 changed files with 150 additions and 161 deletions

View File

@ -440,7 +440,7 @@ QStringList MinecraftInstance::javaArguments()
args << "-Duser.language=en";
if (javaVersion.isModular() && traits().contains("legacyServices") && settings()->get("OnlineFixes").toBool())
if (javaVersion.isModular() && shouldApplyOnlineFixes())
// allow reflective access to java.net - required by the skin fix
args << "--add-opens"
<< "java.base/java.net=ALL-UNNAMED";
@ -448,7 +448,8 @@ QStringList MinecraftInstance::javaArguments()
return args;
}
QString MinecraftInstance::getLauncher() {
QString MinecraftInstance::getLauncher()
{
// use legacy launcher if the traits are set
if (traits().contains("legacyLaunch") || traits().contains("alphaLaunch"))
return "legacy";
@ -456,6 +457,11 @@ QString MinecraftInstance::getLauncher() {
return "standard";
}
bool MinecraftInstance::shouldApplyOnlineFixes()
{
return traits().contains("legacyServices") && settings()->get("OnlineFixes").toBool();
}
QMap<QString, QString> MinecraftInstance::getVariables()
{
QMap<QString, QString> out;
@ -665,7 +671,7 @@ QString MinecraftInstance::createLaunchScript(AuthSessionPtr session, MinecraftS
launchScript += "traits " + trait + "\n";
}
if (profile->getTraits().contains("legacyServices") && settings()->get("OnlineFixes").toBool())
if (shouldApplyOnlineFixes())
launchScript += "onlineFixes true\n";
launchScript += "launcher " + getLauncher() + "\n";

View File

@ -132,6 +132,7 @@ public:
/// get arguments passed to java
QStringList javaArguments();
QString getLauncher();
bool shouldApplyOnlineFixes();
/// get variables for launch command variable substitution/environment
QMap<QString, QString> getVariables() override;

View File

@ -107,6 +107,19 @@ void LauncherPartLaunch::executeTask()
auto instance = m_parent->instance();
std::shared_ptr<MinecraftInstance> minecraftInstance = std::dynamic_pointer_cast<MinecraftInstance>(instance);
QString legacyJarPath;
if (minecraftInstance->getLauncher() == "legacy" || minecraftInstance->shouldApplyOnlineFixes())
{
legacyJarPath = APPLICATION->getJarPath("NewLaunchLegacy.jar");
if (legacyJarPath.isEmpty())
{
const char *reason = QT_TR_NOOP("Legacy launcher library could not be found. Please check your installation.");
emit logLine(tr(reason), MessageLevel::Fatal);
emitFailed(tr(reason));
return;
}
}
m_launchScript = minecraftInstance->createLaunchScript(m_session, m_serverToJoin);
QStringList args = minecraftInstance->javaArguments();
QString allArgs = args.join(", ");
@ -122,6 +135,9 @@ void LauncherPartLaunch::executeTask()
auto classPath = minecraftInstance->getClassPath();
classPath.prepend(jarPath);
if (!legacyJarPath.isEmpty())
classPath.prepend(legacyJarPath);
auto natPath = minecraftInstance->getNativePath();
#ifdef Q_OS_WIN
if (!fitsInLocal8bit(natPath))

View File

@ -11,25 +11,33 @@ set(SRC
org/prismlauncher/launcher/Launcher.java
org/prismlauncher/launcher/impl/AbstractLauncher.java
org/prismlauncher/launcher/impl/StandardLauncher.java
org/prismlauncher/launcher/impl/legacy/LegacyLauncher.java
org/prismlauncher/launcher/impl/legacy/LegacyFrame.java
org/prismlauncher/exception/ParameterNotFoundException.java
org/prismlauncher/exception/ParseException.java
org/prismlauncher/fix/Fixes.java
org/prismlauncher/fix/online/OnlineFixes.java
org/prismlauncher/fix/online/SkinFix.java
org/prismlauncher/fix/online/Handler.java
org/prismlauncher/utils/Base64.java
org/prismlauncher/utils/JsonParser.java
org/prismlauncher/utils/Parameters.java
org/prismlauncher/utils/ReflectionUtils.java
org/prismlauncher/utils/api/MojangApi.java
org/prismlauncher/utils/api/Texture.java
org/prismlauncher/utils/logging/Level.java
org/prismlauncher/utils/logging/Log.java
org/prismlauncher/utils/url/UrlUtils.java
org/prismlauncher/utils/url/CustomUrlConnection.java
net/minecraft/Launcher.java
org/prismlauncher/legacy/LegacyProxy.java
)
set(LEGACY_SRC
legacy/org/prismlauncher/legacy/LegacyFrame.java
legacy/org/prismlauncher/legacy/LegacyLauncher.java
legacy/org/prismlauncher/legacy/fix/online/Handler.java
legacy/org/prismlauncher/legacy/fix/online/OnlineFixes.java
legacy/org/prismlauncher/legacy/fix/online/SkinFix.java
legacy/org/prismlauncher/legacy/utils/Base64.java
legacy/org/prismlauncher/legacy/utils/JsonParseException.java
legacy/org/prismlauncher/legacy/utils/JsonParser.java
legacy/org/prismlauncher/legacy/utils/api/MojangApi.java
legacy/org/prismlauncher/legacy/utils/api/Texture.java
legacy/org/prismlauncher/legacy/utils/url/CustomUrlConnection.java
legacy/org/prismlauncher/legacy/utils/url/UrlUtils.java
legacy/net/minecraft/Launcher.java
legacy/org/prismlauncher/legacy/LegacyProxy.java
)
add_jar(NewLaunch ${SRC})
add_jar(NewLaunchLegacy ${LEGACY_SRC} INCLUDE_JARS NewLaunch)
install_jar(NewLaunch "${JARS_DEST_DIR}")
install_jar(NewLaunchLegacy "${JARS_DEST_DIR}")

View File

@ -52,7 +52,7 @@
* limitations under the License.
*/
package org.prismlauncher.launcher.impl.legacy;
package org.prismlauncher.legacy;
import java.applet.Applet;
import java.awt.Dimension;
@ -74,7 +74,7 @@ import org.prismlauncher.utils.logging.Log;
import net.minecraft.Launcher;
public final class LegacyFrame extends JFrame {
final class LegacyFrame extends JFrame {
private static final long serialVersionUID = 1L;

View File

@ -53,11 +53,15 @@
* limitations under the License.
*/
package org.prismlauncher.launcher.impl.legacy;
package org.prismlauncher.legacy;
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.lang.reflect.Modifier;
import java.util.Collections;
import java.util.List;
@ -69,7 +73,7 @@ import org.prismlauncher.utils.logging.Log;
/**
* Used to launch old versions that support applets.
*/
public final class LegacyLauncher extends AbstractLauncher {
final class LegacyLauncher extends AbstractLauncher {
private final String user, session;
private final String title;
@ -94,11 +98,9 @@ public final class LegacyLauncher extends AbstractLauncher {
@Override
public void launch() throws Throwable {
Class<?> main = ClassLoader.getSystemClassLoader().loadClass(mainClassName);
Field gameDirField = ReflectionUtils.findMinecraftGameDirField(main);
Field gameDirField = findMinecraftGameDirField(main);
if (gameDirField == null)
Log.warning("Could not find Minecraft folder field");
else {
if (gameDirField != null) {
gameDirField.setAccessible(true);
gameDirField.set(null, new File(gameDir));
}
@ -107,7 +109,7 @@ public final class LegacyLauncher extends AbstractLauncher {
System.setProperty("minecraft.applet.TargetDirectory", gameDir);
try {
LegacyFrame window = new LegacyFrame(title, ReflectionUtils.createAppletClass(appletClass));
LegacyFrame window = new LegacyFrame(title, createAppletClass(appletClass));
window.start(user, session, width, height, maximize, serverAddress, serverPort,
gameArgs.contains("--demo"));
@ -123,4 +125,37 @@ public final class LegacyLauncher extends AbstractLauncher {
method.invokeExact(gameArgs.toArray(new String[0]));
}
private static Applet createAppletClass(String clazz) throws Throwable {
Class<?> appletClass = ClassLoader.getSystemClassLoader().loadClass(clazz);
MethodHandle appletConstructor = MethodHandles.lookup().findConstructor(appletClass, MethodType.methodType(void.class));
return (Applet) appletConstructor.invoke();
}
private static Field findMinecraftGameDirField(Class<?> clazz) {
Log.debug("Resolving minecraft game directory field");
// search for private static File
for (Field field : clazz.getDeclaredFields()) {
if (field.getType() != File.class) {
continue;
}
int fieldModifiers = field.getModifiers();
if (!Modifier.isStatic(fieldModifiers))
continue;
if (!Modifier.isPrivate(fieldModifiers))
continue;
if (Modifier.isFinal(fieldModifiers))
continue;
return field;
}
return null;
}
}

View File

@ -0,0 +1,17 @@
package org.prismlauncher.legacy;
import org.prismlauncher.launcher.Launcher;
import org.prismlauncher.legacy.fix.online.OnlineFixes;
import org.prismlauncher.utils.Parameters;
public final class LegacyProxy {
public static Launcher createLauncher(Parameters params) {
return new LegacyLauncher(params);
}
public static void applyOnlineFixes(Parameters parameters) {
OnlineFixes.apply(parameters);
}
}

View File

@ -33,7 +33,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.prismlauncher.fix.online;
package org.prismlauncher.legacy.fix.online;
import java.io.IOException;
import java.net.Proxy;
@ -41,7 +41,7 @@ import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
import org.prismlauncher.utils.url.UrlUtils;
import org.prismlauncher.legacy.utils.url.UrlUtils;
final class Handler extends URLStreamHandler {

View File

@ -33,15 +33,16 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.prismlauncher.fix.online;
package org.prismlauncher.legacy.fix.online;
import java.net.URL;
import java.net.URLStreamHandler;
import java.net.URLStreamHandlerFactory;
import org.prismlauncher.utils.Base64;
import org.prismlauncher.legacy.utils.Base64;
import org.prismlauncher.legacy.utils.url.UrlUtils;
import org.prismlauncher.utils.Parameters;
import org.prismlauncher.utils.logging.Log;
import org.prismlauncher.utils.url.UrlUtils;
/**
* Fixes skins by redirecting to other URLs.
@ -51,7 +52,10 @@ import org.prismlauncher.utils.url.UrlUtils;
*/
public final class OnlineFixes implements URLStreamHandlerFactory {
public static void apply() {
public static void apply(Parameters params) {
if (!"true".equals(params.getString("onlineFixes", null)))
return;
if (!UrlUtils.isSupported() || !Base64.isSupported()) {
Log.warning("Cannot access the necessary Java internals for skin fix");
Log.warning("Turning off legacy skin fix in Settings > Miscellaneous will silence the warnings");

View File

@ -1,4 +1,4 @@
package org.prismlauncher.fix.online;
package org.prismlauncher.legacy.fix.online;
import java.awt.AlphaComposite;
import java.awt.Graphics2D;
@ -12,10 +12,8 @@ import java.net.URLConnection;
import javax.imageio.ImageIO;
import org.prismlauncher.utils.api.MojangApi;
import org.prismlauncher.utils.api.Texture;
import org.prismlauncher.utils.url.CustomUrlConnection;
import org.prismlauncher.utils.url.UrlUtils;
import org.prismlauncher.legacy.utils.api.*;
import org.prismlauncher.legacy.utils.url.*;
final class SkinFix {

View File

@ -33,7 +33,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.prismlauncher.utils;
package org.prismlauncher.legacy.utils;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;

View File

@ -33,7 +33,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.prismlauncher.exception;
package org.prismlauncher.legacy.utils;
import java.io.IOException;

View File

@ -33,7 +33,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.prismlauncher.utils;
package org.prismlauncher.legacy.utils;
import java.io.IOException;
import java.io.InputStream;
@ -46,8 +46,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.prismlauncher.exception.JsonParseException;
/**
* Single-file JSON parser to allow for usage in versions without GSON.
*/

View File

@ -33,15 +33,14 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.prismlauncher.utils.api;
package org.prismlauncher.legacy.utils.api;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Map;
import org.prismlauncher.utils.Base64;
import org.prismlauncher.utils.JsonParser;
import org.prismlauncher.legacy.utils.*;
/**
* Basic access to Mojang's Minecraft API.

View File

@ -33,7 +33,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.prismlauncher.utils.api;
package org.prismlauncher.legacy.utils.api;
import java.net.URL;

View File

@ -33,7 +33,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.prismlauncher.utils.url;
package org.prismlauncher.legacy.utils.url;
import java.io.ByteArrayInputStream;
import java.io.IOException;

View File

@ -33,7 +33,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.prismlauncher.utils.url;
package org.prismlauncher.legacy.utils.url;
import java.io.IOException;
import java.lang.invoke.MethodHandle;

View File

@ -59,10 +59,9 @@ import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import org.prismlauncher.exception.ParseException;
import org.prismlauncher.fix.Fixes;
import org.prismlauncher.launcher.Launcher;
import org.prismlauncher.launcher.impl.StandardLauncher;
import org.prismlauncher.launcher.impl.legacy.LegacyLauncher;
import org.prismlauncher.legacy.LegacyProxy;
import org.prismlauncher.utils.Parameters;
import org.prismlauncher.utils.logging.Log;
@ -108,7 +107,7 @@ public final class EntryPoint {
}
try {
Fixes.apply(params);
LegacyProxy.applyOnlineFixes(params);
Launcher launcher;
String type = params.getString("launcher");
@ -119,7 +118,7 @@ public final class EntryPoint {
break;
case "legacy":
launcher = new LegacyLauncher(params);
launcher = LegacyProxy.createLauncher(params);
break;
default:

View File

@ -1,48 +0,0 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
* Prism Launcher - Minecraft Launcher
* Copyright (C) 2022 TheKodeToad <TheKodeToad@proton.me>
*
* 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.
*
* Linking this library statically or dynamically with other modules is
* making a combined work based on this library. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* As a special exception, the copyright holders of this library give
* you permission to link this library with independent modules to
* produce an executable, regardless of the license terms of these
* independent modules, and to copy and distribute the resulting
* executable under terms of your choice, provided that you also meet,
* for each linked independent module, the terms and conditions of the
* license of that module. An independent module is a module which is
* not derived from or based on this library. If you modify this
* library, you may extend this exception to your version of the
* library, but you are not obliged to do so. If you do not wish to do
* so, delete this exception statement from your version.
*
* 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.prismlauncher.fix;
import org.prismlauncher.fix.online.OnlineFixes;
import org.prismlauncher.utils.Parameters;
public final class Fixes {
public static void apply(Parameters params) {
if ("true".equalsIgnoreCase(params.getString("onlineFixes", null)))
OnlineFixes.apply();
}
}

View File

@ -0,0 +1,17 @@
package org.prismlauncher.legacy;
import org.prismlauncher.launcher.Launcher;
import org.prismlauncher.utils.Parameters;
// used as a fallback if NewLaunchLegacy is not on the classpath
// if it is, this class will be replaced
public final class LegacyProxy {
public static Launcher createLauncher(Parameters params) {
throw new AssertionError("NewLaunchLegacy is not loaded");
}
public static void applyOnlineFixes(Parameters params) {
}
}

View File

@ -54,76 +54,15 @@
package org.prismlauncher.utils;
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.lang.reflect.Modifier;
import org.prismlauncher.utils.logging.Log;
public final class ReflectionUtils {
private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
private static final ClassLoader LOADER = ClassLoader.getSystemClassLoader();
/**
* Construct a Java applet by its class name.
*
* @param clazz The class name
* @return The applet instance
* @throws Throwable
*/
public static Applet createAppletClass(String clazz) throws Throwable {
Class<?> appletClass = LOADER.loadClass(clazz);
MethodHandle appletConstructor = LOOKUP.findConstructor(appletClass, MethodType.methodType(void.class));
return (Applet) appletConstructor.invoke();
}
/**
* Best guess of the game directory field within net.minecraft.client.Minecraft.
* Designed for legacy versions - newer versions do not use a static field.
*
* @param clazz The class
* @return The first field matching criteria
*/
public static Field findMinecraftGameDirField(Class<?> clazz) {
Log.debug("Resolving minecraft game directory field");
// search for private static File
for (Field field : clazz.getDeclaredFields()) {
if (field.getType() != File.class) {
continue;
}
int fieldModifiers = field.getModifiers();
if (!Modifier.isStatic(fieldModifiers)) {
Log.debug("Rejecting field " + field.getName() + " because it is not static");
continue;
}
if (!Modifier.isPrivate(fieldModifiers)) {
Log.debug("Rejecting field " + field.getName() + " because it is not private");
continue;
}
if (Modifier.isFinal(fieldModifiers)) {
Log.debug("Rejecting field " + field.getName() + " because it is final");
continue;
}
Log.debug("Identified field " + field.getName() + " to match conditions for game directory field");
return field;
}
return null;
}
/**
* Gets the main method within a class.
*