diff options
Diffstat (limited to 'meshmc/libraries/launcher')
12 files changed, 1718 insertions, 0 deletions
diff --git a/meshmc/libraries/launcher/.gitignore b/meshmc/libraries/launcher/.gitignore new file mode 100644 index 0000000000..cc1c52bf4d --- /dev/null +++ b/meshmc/libraries/launcher/.gitignore @@ -0,0 +1,6 @@ +.idea +*.iml +out +.classpath +.idea +.project diff --git a/meshmc/libraries/launcher/CMakeLists.txt b/meshmc/libraries/launcher/CMakeLists.txt new file mode 100644 index 0000000000..860776385f --- /dev/null +++ b/meshmc/libraries/launcher/CMakeLists.txt @@ -0,0 +1,22 @@ +cmake_minimum_required(VERSION 3.25) +project(launcher Java) +find_package(Java 1.7 REQUIRED COMPONENTS Development) + +include(UseJava) +set(CMAKE_JAVA_JAR_ENTRY_POINT org.projecttick.EntryPoint) +set(CMAKE_JAVA_COMPILE_FLAGS -target 7 -source 7 -Xlint:deprecation -Xlint:unchecked) + +set(SRC + org/projecttick/EntryPoint.java + org/projecttick/MeshMC.java + org/projecttick/LegacyFrame.java + org/projecttick/NotFoundException.java + org/projecttick/ParamBucket.java + org/projecttick/ParseException.java + org/projecttick/Utils.java + org/projecttick/onesix/OneSixLauncher.java + org/projecttick/modern/ModernLauncher.java + net/minecraft/MeshMC.java +) +add_jar(NewLaunch ${SRC}) +install_jar(NewLaunch "${JARS_DEST_DIR}") diff --git a/meshmc/libraries/launcher/net/minecraft/MeshMC.java b/meshmc/libraries/launcher/net/minecraft/MeshMC.java new file mode 100644 index 0000000000..0d4da46d70 --- /dev/null +++ b/meshmc/libraries/launcher/net/minecraft/MeshMC.java @@ -0,0 +1,208 @@ +/* SPDX-FileCopyrightText: 2026 Project Tick + * SPDX-FileContributor: Project Tick + * SPDX-License-Identifier: GPL-3.0-or-later + * + * MeshMC - A Custom Launcher for Minecraft + * Copyright (C) 2026 Project Tick + * + * 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, either version 3 of the License, or + * (at your option) any later version. + * + * 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/>. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * 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 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.net.MalformedURLException; + +public class MeshMC extends Applet implements AppletStub +{ + private Applet wrappedApplet; + private URL documentBase; + private boolean active = false; + private final Map<String, String> params; + + public MeshMC(Applet applet, URL documentBase) + { + params = new TreeMap<String, String>(); + + this.setLayout(new BorderLayout()); + this.add(applet, "Center"); + this.wrappedApplet = applet; + this.documentBase = documentBase; + } + + public void setParameter(String name, String value) + { + 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) + { + String param = params.get(name); + if (param != null) + return param; + try + { + return super.getParameter(name); + } catch (Exception ignore){} + return null; + } + + @Override + public boolean isActive() + { + return active; + } + + @Override + public void appletResize(int width, int height) + { + wrappedApplet.resize(width, height); + } + + @Override + public void resize(int width, int height) + { + wrappedApplet.resize(width, height); + } + + @Override + public void resize(Dimension d) + { + wrappedApplet.resize(d); + } + + @Override + public void init() + { + if (wrappedApplet != null) + { + wrappedApplet.init(); + } + } + + @Override + public void start() + { + wrappedApplet.start(); + active = true; + } + + @Override + public void stop() + { + wrappedApplet.stop(); + active = false; + } + + public void destroy() + { + wrappedApplet.destroy(); + } + + @Override + public URL getCodeBase() { + try { + return new URL("http://www.minecraft.net/game/"); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + return null; + } + + @Override + 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); + } + return new URL("http://www.minecraft.net/game/"); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + return null; + } + + @Override + public void setVisible(boolean b) + { + super.setVisible(b); + wrappedApplet.setVisible(b); + } + public void update(Graphics paramGraphics) + { + } + public void paint(Graphics paramGraphics) + { + } +}
\ No newline at end of file diff --git a/meshmc/libraries/launcher/org/projecttick/EntryPoint.java b/meshmc/libraries/launcher/org/projecttick/EntryPoint.java new file mode 100644 index 0000000000..ca0c63f22d --- /dev/null +++ b/meshmc/libraries/launcher/org/projecttick/EntryPoint.java @@ -0,0 +1,200 @@ +/* SPDX-FileCopyrightText: 2026 Project Tick + * SPDX-FileContributor: Project Tick + * SPDX-License-Identifier: GPL-3.0-or-later + * + * MeshMC - A Custom Launcher for Minecraft + * Copyright (C) 2026 Project Tick + * + * 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, either version 3 of the License, or + * (at your option) any later version. + * + * 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/>. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * 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.projecttick; + +import org.projecttick.modern.ModernLauncher; +import org.projecttick.onesix.OneSixLauncher; + +import java.io.*; +import java.nio.charset.Charset; + +public class EntryPoint +{ + private enum Action + { + Proceed, + Launch, + Abort + } + + public static void main(String[] args) + { + EntryPoint listener = new EntryPoint(); + int retCode = listener.listen(); + if (retCode != 0) + { + System.out.println("Exiting with " + retCode); + System.exit(retCode); + } + } + + private Action parseLine(String inData) throws ParseException + { + String[] pair = inData.split(" ", 2); + + if(pair.length == 1) + { + String command = pair[0]; + if (pair[0].equals("launch")) + return Action.Launch; + + else if (pair[0].equals("abort")) + return Action.Abort; + + else throw new ParseException("Error while parsing:" + pair[0]); + } + + if(pair.length != 2) + throw new ParseException("Pair length is not 2."); + + String command = pair[0]; + String param = pair[1]; + + if(command.equals("launcher")) + { + if(param.equals("onesix")) + { + m_launcher = new OneSixLauncher(); + Utils.log("Using onesix launcher."); + Utils.log(); + return Action.Proceed; + } + else if(param.equals("modern")) + { + m_launcher = new ModernLauncher(); + Utils.log("Using modern launcher (subprocess mode)."); + Utils.log(); + return Action.Proceed; + } + else + throw new ParseException("Invalid launcher type: " + param); + } + + m_params.add(command, param); + //System.out.println(command + " : " + param); + return Action.Proceed; + } + + public int listen() + { + BufferedReader buffer; + try + { + buffer = new BufferedReader(new InputStreamReader(System.in, "UTF-8")); + } catch (UnsupportedEncodingException e) + { + System.err.println("For some reason, your java does not support UTF-8. Consider living in the current century."); + e.printStackTrace(); + return 1; + } + boolean isListening = true; + boolean isAborted = false; + // Main loop + while (isListening) + { + String inData; + try + { + // Read from the pipe one line at a time + inData = buffer.readLine(); + if (inData != null) + { + Action a = parseLine(inData); + if(a == Action.Abort) + { + isListening = false; + isAborted = true; + } + if(a == Action.Launch) + { + isListening = false; + } + } + else + { + isListening = false; + isAborted = true; + } + } + catch (IOException e) + { + System.err.println("MeshMC ABORT due to IO exception:"); + e.printStackTrace(); + return 1; + } + catch (ParseException e) + { + System.err.println("MeshMC ABORT due to PARSE exception:"); + e.printStackTrace(); + return 1; + } + } + if(isAborted) + { + System.err.println("Launch aborted by MeshMC."); + return 1; + } + if(m_launcher != null) + { + return m_launcher.launch(m_params); + } + System.err.println("No valid launcher implementation specified."); + return 1; + } + + private ParamBucket m_params = new ParamBucket(); + private org.projecttick.MeshMC m_launcher; +} diff --git a/meshmc/libraries/launcher/org/projecttick/LegacyFrame.java b/meshmc/libraries/launcher/org/projecttick/LegacyFrame.java new file mode 100644 index 0000000000..0ea9936e33 --- /dev/null +++ b/meshmc/libraries/launcher/org/projecttick/LegacyFrame.java @@ -0,0 +1,217 @@ +/* SPDX-FileCopyrightText: 2026 Project Tick + * SPDX-FileContributor: Project Tick + * SPDX-License-Identifier: GPL-3.0-or-later + * + * MeshMC - A Custom Launcher for Minecraft + * Copyright (C) 2026 Project Tick + * + * 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, either version 3 of the License, or + * (at your option) any later version. + * + * 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/>. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * 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.projecttick; + +import net.minecraft.MeshMC; + +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 MeshMC 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 MeshMC( 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 ) {} +} diff --git a/meshmc/libraries/launcher/org/projecttick/MeshMC.java b/meshmc/libraries/launcher/org/projecttick/MeshMC.java new file mode 100644 index 0000000000..dae081c70f --- /dev/null +++ b/meshmc/libraries/launcher/org/projecttick/MeshMC.java @@ -0,0 +1,61 @@ +/* SPDX-FileCopyrightText: 2026 Project Tick + * SPDX-FileContributor: Project Tick + * SPDX-License-Identifier: GPL-3.0-or-later + * + * MeshMC - A Custom Launcher for Minecraft + * Copyright (C) 2026 Project Tick + * + * 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, either version 3 of the License, or + * (at your option) any later version. + * + * 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/>. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * 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.projecttick; + +public interface MeshMC +{ + abstract int launch(ParamBucket params); +} diff --git a/meshmc/libraries/launcher/org/projecttick/NotFoundException.java b/meshmc/libraries/launcher/org/projecttick/NotFoundException.java new file mode 100644 index 0000000000..fdf94ace4c --- /dev/null +++ b/meshmc/libraries/launcher/org/projecttick/NotFoundException.java @@ -0,0 +1,60 @@ +/* SPDX-FileCopyrightText: 2026 Project Tick + * SPDX-FileContributor: Project Tick + * SPDX-License-Identifier: GPL-3.0-or-later + * + * MeshMC - A Custom Launcher for Minecraft + * Copyright (C) 2026 Project Tick + * + * 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, either version 3 of the License, or + * (at your option) any later version. + * + * 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/>. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * 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.projecttick; + +public class NotFoundException extends Exception +{ +} diff --git a/meshmc/libraries/launcher/org/projecttick/ParamBucket.java b/meshmc/libraries/launcher/org/projecttick/ParamBucket.java new file mode 100644 index 0000000000..97773c9605 --- /dev/null +++ b/meshmc/libraries/launcher/org/projecttick/ParamBucket.java @@ -0,0 +1,125 @@ +/* SPDX-FileCopyrightText: 2026 Project Tick + * SPDX-FileContributor: Project Tick + * SPDX-License-Identifier: GPL-3.0-or-later + * + * MeshMC - A Custom Launcher for Minecraft + * Copyright (C) 2026 Project Tick + * + * 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, either version 3 of the License, or + * (at your option) any later version. + * + * 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/>. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * 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.projecttick; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +public class ParamBucket +{ + public void add(String key, String value) + { + List<String> coll = null; + if(!m_params.containsKey(key)) + { + coll = new ArrayList<String>(); + m_params.put(key, coll); + } + else + { + coll = m_params.get(key); + } + coll.add(value); + } + + public List<String> all(String key) throws NotFoundException + { + if(!m_params.containsKey(key)) + throw new NotFoundException(); + return m_params.get(key); + } + + public List<String> allSafe(String key, List<String> def) + { + if(!m_params.containsKey(key) || m_params.get(key).size() < 1) + { + return def; + } + return m_params.get(key); + } + + public List<String> allSafe(String key) + { + return allSafe(key, new ArrayList<String>()); + } + + public String first(String key) throws NotFoundException + { + List<String> list = all(key); + if(list.size() < 1) + { + throw new NotFoundException(); + } + return list.get(0); + } + + public String firstSafe(String key, String def) + { + if(!m_params.containsKey(key) || m_params.get(key).size() < 1) + { + return def; + } + return m_params.get(key).get(0); + } + + public String firstSafe(String key) + { + return firstSafe(key, ""); + } + + private HashMap<String, List<String>> m_params = new HashMap<String, List<String>>(); +} diff --git a/meshmc/libraries/launcher/org/projecttick/ParseException.java b/meshmc/libraries/launcher/org/projecttick/ParseException.java new file mode 100644 index 0000000000..5e3ca0df1a --- /dev/null +++ b/meshmc/libraries/launcher/org/projecttick/ParseException.java @@ -0,0 +1,64 @@ +/* SPDX-FileCopyrightText: 2026 Project Tick + * SPDX-FileContributor: Project Tick + * SPDX-License-Identifier: GPL-3.0-or-later + * + * MeshMC - A Custom Launcher for Minecraft + * Copyright (C) 2026 Project Tick + * + * 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, either version 3 of the License, or + * (at your option) any later version. + * + * 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/>. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * 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.projecttick; + +public class ParseException extends java.lang.Exception +{ + public ParseException() { super(); } + public ParseException(String message) { + super(message); + } +} diff --git a/meshmc/libraries/launcher/org/projecttick/Utils.java b/meshmc/libraries/launcher/org/projecttick/Utils.java new file mode 100644 index 0000000000..0dab388eff --- /dev/null +++ b/meshmc/libraries/launcher/org/projecttick/Utils.java @@ -0,0 +1,158 @@ +/* SPDX-FileCopyrightText: 2026 Project Tick + * SPDX-FileContributor: Project Tick + * SPDX-License-Identifier: GPL-3.0-or-later + * + * MeshMC - A Custom Launcher for Minecraft + * Copyright (C) 2026 Project Tick + * + * 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, either version 3 of the License, or + * (at your option) any later version. + * + * 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/>. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * 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.projecttick; + +import java.io.*; +import java.io.File; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.*; +import java.util.Arrays; +import java.util.Enumeration; +import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +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; + } + + /** + * Log to MeshMC console + * + * @param message A String containing the message + * @param level A String containing the level name. See MinecraftLauncher::getLevel() + */ + public static void log(String message, String level) + { + // Kinda dirty + String tag = "!![" + level + "]!"; + System.out.println(tag + message.replace("\n", "\n" + tag)); + } + + public static void log(String message) + { + log(message, "MeshMC"); + } + + public static void log() + { + System.out.println(); + } +} + diff --git a/meshmc/libraries/launcher/org/projecttick/modern/ModernLauncher.java b/meshmc/libraries/launcher/org/projecttick/modern/ModernLauncher.java new file mode 100644 index 0000000000..41616c346b --- /dev/null +++ b/meshmc/libraries/launcher/org/projecttick/modern/ModernLauncher.java @@ -0,0 +1,309 @@ +/* SPDX-FileCopyrightText: 2026 Project Tick + * SPDX-FileContributor: Project Tick + * SPDX-License-Identifier: GPL-3.0-or-later + * + * MeshMC - A Custom Launcher for Minecraft + * Copyright (C) 2026 Project Tick + * + * 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, either version 3 of the License, or + * (at your option) any later version. + * + * 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/>. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * 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.projecttick.modern; + +import org.projecttick.MeshMC; +import org.projecttick.ParamBucket; +import org.projecttick.Utils; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * Modern launcher implementation for Minecraft 1.0 and above. + * + * Unlike OneSixLauncher which loads the game in-process via reflection, + * ModernLauncher spawns Minecraft as a separate child process using the + * Java binary specified by MeshMC. This decouples the JVM version + * running MeshMC library from the JVM version required by the game, + * allowing Minecraft versions that require Java 21+ or newer (e.g., class + * file version 69.0 / Java 25) to be launched correctly even when the + * launcher itself runs on an older JVM. + * + * Parameters consumed from ParamBucket: + * javaPath - Path to the Java binary for the game process (required) + * cp - Classpath entries, one per entry (required) + * mainClass - Main class to invoke (default: net.minecraft.client.main.Main) + * param - Game arguments, one per entry + * jvmArg - JVM arguments to forward to the game process, one per arg + * natives - Path to the native libraries directory + * serverAddress - Server address for direct-connect on launch (optional) + * serverPort - Server port for direct-connect on launch (optional) + */ +public class ModernLauncher implements MeshMC +{ + @Override + public int launch(ParamBucket params) + { + try + { + return doLaunch(params); + } + catch (Exception e) + { + Utils.log("ModernLauncher encountered a fatal error: " + e.getMessage(), "Error"); + e.printStackTrace(); + return 1; + } + } + + private int doLaunch(ParamBucket params) throws Exception + { + // --- Java binary --- + String javaPath = params.firstSafe("javaPath", "java"); + Utils.log("Java binary: " + javaPath); + + // --- Main class --- + String mainClass = params.firstSafe("mainClass", "net.minecraft.client.main.Main"); + Utils.log("Main class: " + mainClass); + + // --- Classpath --- + // "cp" = regular game libraries + // "ext" = native-classifier JARs (e.g. lwjgl-3.x-natives-linux.jar) that + // LWJGL 3's SharedLibraryLoader needs to find on the classpath. + // OneSixLauncher works without these because it runs in-process and + // MeshMC JVM already has them on its own classpath. For + // ModernLauncher we must include them explicitly. + List<String> cpEntries = params.allSafe("cp", Collections.<String>emptyList()); + List<String> extEntries = params.allSafe("ext", Collections.<String>emptyList()); + List<String> allCpEntries = new ArrayList<String>(cpEntries); + allCpEntries.addAll(extEntries); + if (allCpEntries.isEmpty()) + { + Utils.log("No classpath entries provided to ModernLauncher.", "Error"); + return 1; + } + String classpath = buildClassPath(allCpEntries); + + // --- Native library path --- + String natives = params.firstSafe("natives", ""); + + // --- JVM arguments (Xmx, Xms, GC flags, platform-specific flags, etc.) --- + List<String> jvmArgs = params.allSafe("jvmArg", Collections.<String>emptyList()); + + // --- Game arguments --- + // param entries are already pre-expanded by the C++ launcher (auth tokens, + // game directory, asset index, resolution, etc.) + List<String> gameArgs = new ArrayList<String>( + params.allSafe("param", Collections.<String>emptyList()) + ); + + // Direct-connect: server address / port are passed as separate keys and + // must be appended to game args manually (processMinecraftArgs skips them + // when a launch script is used). + String serverAddress = params.firstSafe("serverAddress", ""); + String serverPort = params.firstSafe("serverPort", ""); + if (serverAddress != null && !serverAddress.isEmpty()) + { + gameArgs.add("--server"); + gameArgs.add(serverAddress); + if (serverPort != null && !serverPort.isEmpty()) + { + gameArgs.add("--port"); + gameArgs.add(serverPort); + } + } + + // --- Build the full command --- + List<String> command = buildCommand(javaPath, jvmArgs, natives, classpath, mainClass, gameArgs); + + // Log the full command for diagnostics (visible in launcher console) + StringBuilder cmdLog = new StringBuilder("Spawning game process:\n CMD: "); + for (String s : command) + { + cmdLog.append(s).append(" "); + } + Utils.log(cmdLog.toString().trim()); + + ProcessBuilder pb = new ProcessBuilder(command); + // Let the game process inherit the working directory from us (set by LauncherPartLaunch) + pb.directory(null); + + // Set JAVA_HOME so the game and any native launchers can locate Java correctly + File javaFile = new File(javaPath); + File javaParent = javaFile.getParentFile(); + if (javaParent != null && javaParent.getParentFile() != null) + { + pb.environment().put("JAVA_HOME", javaParent.getParent()); + } + + final Process process = pb.start(); + + // Pipe stdout and stderr from the child process to our own streams so + // the C++ launcher's LoggedProcess can capture and display them. + Thread outPipe = pipeStream(process.getInputStream(), System.out, "stdout"); + Thread errPipe = pipeStream(process.getErrorStream(), System.err, "stderr"); + outPipe.start(); + errPipe.start(); + + // Shutdown hook: ensure the game process is terminated if MeshMC is + // forcefully killed (e.g., SIGKILL from within MeshMC UI). + Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() + { + @Override + public void run() + { + if (process.isAlive()) + { + process.destroyForcibly(); + } + } + }, "ModernLauncher-ShutdownHook")); + + // Block until the game process exits + int exitCode = process.waitFor(); + + outPipe.join(); + errPipe.join(); + + if (exitCode != 0) + { + Utils.log("Game process exited with code " + exitCode, "Error"); + } + + return exitCode; + } + + private String buildClassPath(List<String> entries) + { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < entries.size(); i++) + { + if (i > 0) + sb.append(File.pathSeparator); + sb.append(entries.get(i)); + } + return sb.toString(); + } + + private List<String> buildCommand( + String javaPath, + List<String> jvmArgs, + String natives, + String classpath, + String mainClass, + List<String> gameArgs) + { + List<String> cmd = new ArrayList<String>(); + + // Java executable + cmd.add(javaPath); + + // JVM arguments (memory settings, GC options, platform flags, etc.) + cmd.addAll(jvmArgs); + + // Native library path - needed for LWJGL and other native dependencies. + // Pass both the standard JVM property and the LWJGL-specific property: + // java.library.path - used by java.lang.System.loadLibrary() + // org.lwjgl.librarypath - checked first by LWJGL 3.3+ before java.library.path + if (natives != null && !natives.isEmpty()) + { + cmd.add("-Djava.library.path=" + natives); + cmd.add("-Dorg.lwjgl.librarypath=" + natives); + } + + // Classpath + if (!classpath.isEmpty()) + { + cmd.add("-cp"); + cmd.add(classpath); + } + + // Main class + cmd.add(mainClass); + + // Game arguments + cmd.addAll(gameArgs); + + return cmd; + } + + /** + * Reads bytes from {@code src} and writes them to {@code dst} on a dedicated + * daemon thread so neither stream blocks the main thread. + */ + private Thread pipeStream(final InputStream src, final PrintStream dst, final String name) + { + Thread t = new Thread(new Runnable() + { + @Override + public void run() + { + byte[] buffer = new byte[8192]; + int read; + try + { + while ((read = src.read(buffer)) != -1) + { + dst.write(buffer, 0, read); + dst.flush(); + } + } + catch (IOException e) + { + // Stream closed - expected when the child process exits + } + } + }, "ModernLauncher-" + name + "-pipe"); + t.setDaemon(true); + return t; + } +} diff --git a/meshmc/libraries/launcher/org/projecttick/onesix/OneSixLauncher.java b/meshmc/libraries/launcher/org/projecttick/onesix/OneSixLauncher.java new file mode 100644 index 0000000000..25936149f9 --- /dev/null +++ b/meshmc/libraries/launcher/org/projecttick/onesix/OneSixLauncher.java @@ -0,0 +1,288 @@ +/* SPDX-FileCopyrightText: 2026 Project Tick + * SPDX-FileContributor: Project Tick + * SPDX-License-Identifier: GPL-3.0-or-later + * + * MeshMC - A Custom Launcher for Minecraft + * Copyright (C) 2026 Project Tick + * + * 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, either version 3 of the License, or + * (at your option) any later version. + * + * 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/>. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * 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.projecttick.onesix; + +import org.projecttick.*; + +import java.applet.Applet; +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + +public class OneSixLauncher implements MeshMC +{ + // 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) + { + System.err.println("Could not find Minecraft path field."); + } + else + { + f.setAccessible(true); + f.set(null, new File(cwd)); + } + } catch (Exception e) + { + System.err.println("Could not set base folder. Failed to find/access Minecraft main class:"); + e.printStackTrace(System.err); + return -1; + } + + System.setProperty("minecraft.applet.TargetDirectory", cwd); + + if(!traits.contains("noapplet")) + { + Utils.log("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) + { + Utils.log("Applet wrapper failed:", "Error"); + e.printStackTrace(System.err); + Utils.log(); + Utils.log("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) + { + Utils.log("Failed to invoke the Minecraft main class:", "Fatal"); + e.printStackTrace(System.err); + 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) + { + System.err.println("Failed to find Minecraft main class:"); + e.printStackTrace(System.err); + return -1; + } + + // get the main method. + Method meth; + try + { + meth = mc.getMethod("main", String[].class); + } catch (NoSuchMethodException e) + { + System.err.println("Failed to acquire the main method:"); + e.printStackTrace(System.err); + return -1; + } + + // 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) + { + System.err.println("Failed to start Minecraft:"); + e.printStackTrace(System.err); + return -1; + } + return 0; + } + + @Override + public int launch(ParamBucket params) + { + // get and process the launch script params + try + { + processParams(params); + } catch (NotFoundException e) + { + System.err.println("Not enough arguments."); + e.printStackTrace(System.err); + 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(); + } + } +} |
