From 35d200356fdeb2d54c0ad0537c9c3b4cd9a8eb4d Mon Sep 17 00:00:00 2001 From: TheKodeToad Date: Sat, 29 Oct 2022 15:31:41 +0100 Subject: Create launcher.impl.legacy Signed-off-by: TheKodeToad --- .../org/prismlauncher/applet/LegacyFrame.java | 203 --------------------- .../prismlauncher/launcher/LauncherFactory.java | 2 +- .../launcher/impl/LegacyLauncher.java | 169 ----------------- .../launcher/impl/legacy/LegacyFrame.java | 203 +++++++++++++++++++++ .../launcher/impl/legacy/LegacyLauncher.java | 169 +++++++++++++++++ 5 files changed, 373 insertions(+), 373 deletions(-) delete mode 100644 libraries/launcher/org/prismlauncher/applet/LegacyFrame.java delete mode 100644 libraries/launcher/org/prismlauncher/launcher/impl/LegacyLauncher.java create mode 100644 libraries/launcher/org/prismlauncher/launcher/impl/legacy/LegacyFrame.java create mode 100644 libraries/launcher/org/prismlauncher/launcher/impl/legacy/LegacyLauncher.java (limited to 'libraries/launcher/org') diff --git a/libraries/launcher/org/prismlauncher/applet/LegacyFrame.java b/libraries/launcher/org/prismlauncher/applet/LegacyFrame.java deleted file mode 100644 index 58125160..00000000 --- a/libraries/launcher/org/prismlauncher/applet/LegacyFrame.java +++ /dev/null @@ -1,203 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-only -/* - * PolyMC - Minecraft Launcher - * Copyright (C) 2022 icelimetea - * Copyright (C) 2022 Sefa Eyeoglu - * Copyright (C) 2022 flow - * Copyright (C) 2022 Samisafool - * Copyright (C) 2022 TheKodeToad - * - * 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 . - * - * 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. - */ - -package org.prismlauncher.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 launcher; - - public LegacyFrame(String title, Applet applet) { - super(title); - - launcher = new Launcher(applet); - - applet.setStub(launcher); - - 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 width, - int height, - boolean maximize, - String serverAddress, - String serverPort, - boolean isDemo - ) { - // 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 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 - launcher.setParameter("server", lines.get(0)); - launcher.setParameter("port", lines.get(1)); - launcher.setParameter("mppass", lines.get(2)); - } - } catch (IOException e) { - LOGGER.log(Level.WARNING, "Unable to read mpticket file!", e); - } - } - - if (serverAddress != null) { - launcher.setParameter("server", serverAddress); - launcher.setParameter("port", serverPort); - } - - launcher.setParameter("username", user); - launcher.setParameter("sessionid", session); - launcher.setParameter("stand-alone", "true"); // Show the quit button. TODO: why won't this work? - launcher.setParameter("haspaid", "true"); // Some old versions need this for world saves to work. - launcher.setParameter("demo", isDemo ? "true" : "false"); - launcher.setParameter("fullscreen", "false"); - - add(launcher); - - launcher.setPreferredSize(new Dimension(width, height)); - - pack(); - - setLocationRelativeTo(null); - setResizable(true); - - if (maximize) - this.setExtendedState(MAXIMIZED_BOTH); - - validate(); - - launcher.init(); - launcher.start(); - - setVisible(true); - } - - private final class ForceExitHandler extends WindowAdapter { - - @Override - public void windowClosing(WindowEvent event) { - new Thread(new Runnable() { - @Override - public void run() { - try { - Thread.sleep(30000L); - } catch (InterruptedException e) { - e.printStackTrace(); - } - - LOGGER.info("Forcing exit!"); - - System.exit(0); - } - }).start(); - - if (launcher != null) { - launcher.stop(); - launcher.destroy(); - } - - // old minecraft versions can hang without this >_< - System.exit(0); - } - - } - -} diff --git a/libraries/launcher/org/prismlauncher/launcher/LauncherFactory.java b/libraries/launcher/org/prismlauncher/launcher/LauncherFactory.java index e6de35fa..22e92632 100644 --- a/libraries/launcher/org/prismlauncher/launcher/LauncherFactory.java +++ b/libraries/launcher/org/prismlauncher/launcher/LauncherFactory.java @@ -56,8 +56,8 @@ package org.prismlauncher.launcher; -import org.prismlauncher.launcher.impl.LegacyLauncher; import org.prismlauncher.launcher.impl.StandardLauncher; +import org.prismlauncher.launcher.impl.legacy.LegacyLauncher; import org.prismlauncher.utils.Parameters; import java.util.HashMap; diff --git a/libraries/launcher/org/prismlauncher/launcher/impl/LegacyLauncher.java b/libraries/launcher/org/prismlauncher/launcher/impl/LegacyLauncher.java deleted file mode 100644 index c249c714..00000000 --- a/libraries/launcher/org/prismlauncher/launcher/impl/LegacyLauncher.java +++ /dev/null @@ -1,169 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-only -/* - * PolyMC - Minecraft Launcher - * Copyright (C) 2022 icelimetea - * Copyright (C) 2022 flow - * Copyright (C) 2022 TheKodeToad - * Copyright (C) 2022 solonovamax - * - * 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 . - * - * 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. - */ - -package org.prismlauncher.launcher.impl; - -import org.prismlauncher.applet.LegacyFrame; -import org.prismlauncher.utils.Parameters; - -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; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Used to launch old versions that support applets. - */ -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.getString("userName"); - session = params.getString("sessionId"); - title = params.getString("windowTitle", "Minecraft"); - appletClass = params.getString("appletClass", "net.minecraft.client.MinecraftApplet"); - - List traits = params.getList("traits", Collections.emptyList()); - noApplet = traits.contains("noapplet"); - - cwd = System.getProperty("user.dir"); - } - - @Override - public void launch() throws Throwable { - Class main = loadMain(); - Field gameDirField = 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); - } - - /** - * Finds a field that looks like a Minecraft base folder in a supplied class - * @param clazz the class to scan - * @return The found field. - */ - private static Field getMinecraftGameDirField(Class clazz) { - // Field we're looking for is always - // private static File obfuscatedName = null; - for (Field field : clazz.getDeclaredFields()) { - // Has to be File - if (field.getType() != File.class) - continue; - - // And Private Static. - if (!Modifier.isStatic(field.getModifiers()) || !Modifier.isPrivate(field.getModifiers())) - continue; - - return field; - } - - return null; - } - -} diff --git a/libraries/launcher/org/prismlauncher/launcher/impl/legacy/LegacyFrame.java b/libraries/launcher/org/prismlauncher/launcher/impl/legacy/LegacyFrame.java new file mode 100644 index 00000000..12196fd4 --- /dev/null +++ b/libraries/launcher/org/prismlauncher/launcher/impl/legacy/LegacyFrame.java @@ -0,0 +1,203 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * PolyMC - Minecraft Launcher + * Copyright (C) 2022 icelimetea + * Copyright (C) 2022 Sefa Eyeoglu + * Copyright (C) 2022 flow + * Copyright (C) 2022 Samisafool + * Copyright (C) 2022 TheKodeToad + * + * 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 . + * + * 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. + */ + +package org.prismlauncher.launcher.impl.legacy; + +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 launcher; + + public LegacyFrame(String title, Applet applet) { + super(title); + + launcher = new Launcher(applet); + + applet.setStub(launcher); + + 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 width, + int height, + boolean maximize, + String serverAddress, + String serverPort, + boolean isDemo + ) { + // 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 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 + launcher.setParameter("server", lines.get(0)); + launcher.setParameter("port", lines.get(1)); + launcher.setParameter("mppass", lines.get(2)); + } + } catch (IOException e) { + LOGGER.log(Level.WARNING, "Unable to read mpticket file!", e); + } + } + + if (serverAddress != null) { + launcher.setParameter("server", serverAddress); + launcher.setParameter("port", serverPort); + } + + launcher.setParameter("username", user); + launcher.setParameter("sessionid", session); + launcher.setParameter("stand-alone", "true"); // Show the quit button. TODO: why won't this work? + launcher.setParameter("haspaid", "true"); // Some old versions need this for world saves to work. + launcher.setParameter("demo", isDemo ? "true" : "false"); + launcher.setParameter("fullscreen", "false"); + + add(launcher); + + launcher.setPreferredSize(new Dimension(width, height)); + + pack(); + + setLocationRelativeTo(null); + setResizable(true); + + if (maximize) + this.setExtendedState(MAXIMIZED_BOTH); + + validate(); + + launcher.init(); + launcher.start(); + + setVisible(true); + } + + private final class ForceExitHandler extends WindowAdapter { + + @Override + public void windowClosing(WindowEvent event) { + new Thread(new Runnable() { + @Override + public void run() { + try { + Thread.sleep(30000L); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + LOGGER.info("Forcing exit!"); + + System.exit(0); + } + }).start(); + + if (launcher != null) { + launcher.stop(); + launcher.destroy(); + } + + // old minecraft versions can hang without this >_< + System.exit(0); + } + + } + +} diff --git a/libraries/launcher/org/prismlauncher/launcher/impl/legacy/LegacyLauncher.java b/libraries/launcher/org/prismlauncher/launcher/impl/legacy/LegacyLauncher.java new file mode 100644 index 00000000..d7a98352 --- /dev/null +++ b/libraries/launcher/org/prismlauncher/launcher/impl/legacy/LegacyLauncher.java @@ -0,0 +1,169 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * PolyMC - Minecraft Launcher + * Copyright (C) 2022 icelimetea + * Copyright (C) 2022 flow + * Copyright (C) 2022 TheKodeToad + * Copyright (C) 2022 solonovamax + * + * 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 . + * + * 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. + */ + +package org.prismlauncher.launcher.impl.legacy; + +import org.prismlauncher.launcher.impl.AbstractLauncher; +import org.prismlauncher.utils.Parameters; + +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; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Used to launch old versions that support applets. + */ +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.getString("userName"); + session = params.getString("sessionId"); + title = params.getString("windowTitle", "Minecraft"); + appletClass = params.getString("appletClass", "net.minecraft.client.MinecraftApplet"); + + List traits = params.getList("traits", Collections.emptyList()); + noApplet = traits.contains("noapplet"); + + cwd = System.getProperty("user.dir"); + } + + @Override + public void launch() throws Throwable { + Class main = loadMain(); + Field gameDirField = 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); + } + + /** + * Finds a field that looks like a Minecraft base folder in a supplied class + * @param clazz the class to scan + * @return The found field. + */ + private static Field getMinecraftGameDirField(Class clazz) { + // Field we're looking for is always + // private static File obfuscatedName = null; + for (Field field : clazz.getDeclaredFields()) { + // Has to be File + if (field.getType() != File.class) + continue; + + // And Private Static. + if (!Modifier.isStatic(field.getModifiers()) || !Modifier.isPrivate(field.getModifiers())) + continue; + + return field; + } + + return null; + } + +} -- cgit