Upload magma
This commit is contained in:
commit
dfa9ee0b24
5008 changed files with 653442 additions and 0 deletions
38
magmalauncher/build.gradle
Normal file
38
magmalauncher/build.gradle
Normal file
|
@ -0,0 +1,38 @@
|
|||
plugins {
|
||||
id 'com.github.ben-manes.versions'
|
||||
id 'org.javamodularity.moduleplugin' version '1.8.3' apply false
|
||||
}
|
||||
apply plugin: 'java-library'
|
||||
apply plugin: 'jacoco'
|
||||
apply plugin: 'org.javamodularity.moduleplugin'
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven { url 'https://repo1.maven.org/maven2' }
|
||||
}
|
||||
|
||||
dependencyUpdates.rejectVersionIf { isNonStable(it.candidate.version) }
|
||||
|
||||
dependencies {
|
||||
implementation project(':fmlcore')
|
||||
implementation 'org.yaml:snakeyaml:2.0'
|
||||
implementation "cpw.mods:securejarhandler:2.1.6"
|
||||
implementation 'com.google.guava:guava:31.1-jre'
|
||||
implementation "com.google.code.gson:gson:2.10"
|
||||
implementation 'dev.vankka:dependencydownload-runtime:1.3.0'
|
||||
implementation 'dev.vankka:dependencydownload-common:1.3.0'
|
||||
implementation 'me.tongfei:progressbar:0.9.3'
|
||||
}
|
||||
|
||||
license {
|
||||
header = rootProject.file('LICENSE-header.txt')
|
||||
|
||||
include 'org/magmafoundation/magma/'
|
||||
exclude 'net/minecraftforge/'
|
||||
|
||||
tasks {
|
||||
main {
|
||||
files.from files("$rootDir/magmalauncher/src/main/java")
|
||||
}
|
||||
}
|
||||
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
9
magmalauncher/index.html
Normal file
9
magmalauncher/index.html
Normal file
|
@ -0,0 +1,9 @@
|
|||
<html>
|
||||
<head><title>Index of /mirror/src/Magma-1-20-x/magmalauncher/</title></head>
|
||||
<body>
|
||||
<h1>Index of /mirror/src/Magma-1-20-x/magmalauncher/</h1><hr><pre><a href="../">../</a>
|
||||
<a href="src/">src/</a> 07-Oct-2023 14:12 -
|
||||
<a href="build.gradle">build.gradle</a> 07-Oct-2023 14:12 1109
|
||||
</pre><hr><script defer src="https://static.cloudflareinsights.com/beacon.min.js/v84a3a4012de94ce1a686ba8c167c359c1696973893317" integrity="sha512-euoFGowhlaLqXsPWQ48qSkBSCFs3DPRyiwVu3FjR96cMPx+Fr+gpWRhIafcHwqwCqWS42RZhIudOvEI+Ckf6MA==" nonce="725661fb53b0d3f75308f4728d709371" data-cf-beacon='{"rayId":"85f014f2fef050c2","version":"2024.2.4","r":1,"token":"583109dda43e47a593fd006526a81120","b":1}' crossorigin="anonymous"></script>
|
||||
</body>
|
||||
</html>
|
8
magmalauncher/src/index.html
Normal file
8
magmalauncher/src/index.html
Normal file
|
@ -0,0 +1,8 @@
|
|||
<html>
|
||||
<head><title>Index of /mirror/src/Magma-1-20-x/magmalauncher/src/</title></head>
|
||||
<body>
|
||||
<h1>Index of /mirror/src/Magma-1-20-x/magmalauncher/src/</h1><hr><pre><a href="../">../</a>
|
||||
<a href="main/">main/</a> 07-Oct-2023 14:12 -
|
||||
</pre><hr><script defer src="https://static.cloudflareinsights.com/beacon.min.js/v84a3a4012de94ce1a686ba8c167c359c1696973893317" integrity="sha512-euoFGowhlaLqXsPWQ48qSkBSCFs3DPRyiwVu3FjR96cMPx+Fr+gpWRhIafcHwqwCqWS42RZhIudOvEI+Ckf6MA==" nonce="fb786c5fa61d9966edb73efb5beaba4d" data-cf-beacon='{"rayId":"85f0153e6fb650c2","version":"2024.2.4","r":1,"token":"583109dda43e47a593fd006526a81120","b":1}' crossorigin="anonymous"></script>
|
||||
</body>
|
||||
</html>
|
8
magmalauncher/src/main/index.html
Normal file
8
magmalauncher/src/main/index.html
Normal file
|
@ -0,0 +1,8 @@
|
|||
<html>
|
||||
<head><title>Index of /mirror/src/Magma-1-20-x/magmalauncher/src/main/</title></head>
|
||||
<body>
|
||||
<h1>Index of /mirror/src/Magma-1-20-x/magmalauncher/src/main/</h1><hr><pre><a href="../">../</a>
|
||||
<a href="java/">java/</a> 07-Oct-2023 14:12 -
|
||||
</pre><hr><script defer src="https://static.cloudflareinsights.com/beacon.min.js/v84a3a4012de94ce1a686ba8c167c359c1696973893317" integrity="sha512-euoFGowhlaLqXsPWQ48qSkBSCFs3DPRyiwVu3FjR96cMPx+Fr+gpWRhIafcHwqwCqWS42RZhIudOvEI+Ckf6MA==" nonce="4c6adc53afd7908e651b8bd70198f46f" data-cf-beacon='{"rayId":"85f0157dabce50c2","version":"2024.2.4","r":1,"token":"583109dda43e47a593fd006526a81120","b":1}' crossorigin="anonymous"></script>
|
||||
</body>
|
||||
</html>
|
8
magmalauncher/src/main/java/index.html
Normal file
8
magmalauncher/src/main/java/index.html
Normal file
|
@ -0,0 +1,8 @@
|
|||
<html>
|
||||
<head><title>Index of /mirror/src/Magma-1-20-x/magmalauncher/src/main/java/</title></head>
|
||||
<body>
|
||||
<h1>Index of /mirror/src/Magma-1-20-x/magmalauncher/src/main/java/</h1><hr><pre><a href="../">../</a>
|
||||
<a href="org/">org/</a> 07-Oct-2023 14:12 -
|
||||
</pre><hr><script defer src="https://static.cloudflareinsights.com/beacon.min.js/v84a3a4012de94ce1a686ba8c167c359c1696973893317" integrity="sha512-euoFGowhlaLqXsPWQ48qSkBSCFs3DPRyiwVu3FjR96cMPx+Fr+gpWRhIafcHwqwCqWS42RZhIudOvEI+Ckf6MA==" nonce="afb21cb89ccc77168260926697c94fc1" data-cf-beacon='{"rayId":"85f015b2183e50c2","version":"2024.2.4","r":1,"token":"583109dda43e47a593fd006526a81120","b":1}' crossorigin="anonymous"></script>
|
||||
</body>
|
||||
</html>
|
8
magmalauncher/src/main/java/org/index.html
Normal file
8
magmalauncher/src/main/java/org/index.html
Normal file
|
@ -0,0 +1,8 @@
|
|||
<html>
|
||||
<head><title>Index of /mirror/src/Magma-1-20-x/magmalauncher/src/main/java/org/</title></head>
|
||||
<body>
|
||||
<h1>Index of /mirror/src/Magma-1-20-x/magmalauncher/src/main/java/org/</h1><hr><pre><a href="../">../</a>
|
||||
<a href="magmafoundation/">magmafoundation/</a> 07-Oct-2023 14:12 -
|
||||
</pre><hr><script defer src="https://static.cloudflareinsights.com/beacon.min.js/v84a3a4012de94ce1a686ba8c167c359c1696973893317" integrity="sha512-euoFGowhlaLqXsPWQ48qSkBSCFs3DPRyiwVu3FjR96cMPx+Fr+gpWRhIafcHwqwCqWS42RZhIudOvEI+Ckf6MA==" nonce="742f70ee28f0fab4aadf7da28b994a7b" data-cf-beacon='{"rayId":"85f0162e8cfa50c2","version":"2024.2.4","r":1,"token":"583109dda43e47a593fd006526a81120","b":1}' crossorigin="anonymous"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,8 @@
|
|||
<html>
|
||||
<head><title>Index of /mirror/src/Magma-1-20-x/magmalauncher/src/main/java/org/magmafoundation/</title></head>
|
||||
<body>
|
||||
<h1>Index of /mirror/src/Magma-1-20-x/magmalauncher/src/main/java/org/magmafoundation/</h1><hr><pre><a href="../">../</a>
|
||||
<a href="magma/">magma/</a> 07-Oct-2023 14:12 -
|
||||
</pre><hr><script defer src="https://static.cloudflareinsights.com/beacon.min.js/v84a3a4012de94ce1a686ba8c167c359c1696973893317" integrity="sha512-euoFGowhlaLqXsPWQ48qSkBSCFs3DPRyiwVu3FjR96cMPx+Fr+gpWRhIafcHwqwCqWS42RZhIudOvEI+Ckf6MA==" nonce="a261b50d9eee933037df2a7746d87505" data-cf-beacon='{"rayId":"85f016e36a5950c2","version":"2024.2.4","r":1,"token":"583109dda43e47a593fd006526a81120","b":1}' crossorigin="anonymous"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,138 @@
|
|||
/*
|
||||
* Magma Server
|
||||
* Copyright (C) 2019-${year}.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.magmafoundation.magma;/*
|
||||
* Magma Server
|
||||
* Copyright (C) 2019-2022.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import org.magmafoundation.magma.common.betterui.BetterUI;
|
||||
import org.magmafoundation.magma.common.utils.JarTool;
|
||||
import org.magmafoundation.magma.common.utils.SystemType;
|
||||
import org.magmafoundation.magma.installer.MagmaInstaller;
|
||||
import org.magmafoundation.magma.updater.MagmaUpdater;
|
||||
import org.magmafoundation.magma.utils.BootstrapLauncher;
|
||||
import org.magmafoundation.magma.utils.ServerInitHelper;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Array;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.magmafoundation.magma.common.MagmaConstants.*;
|
||||
|
||||
|
||||
/**
|
||||
* Project: Magma
|
||||
*
|
||||
* @author Malcolm (M1lc0lm) / Hexeption
|
||||
* @date 03.07.2022 - 17:19
|
||||
*/
|
||||
public class MagmaStart {
|
||||
|
||||
private static String[] args;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
MagmaStart.args = args;
|
||||
|
||||
if (containsArg("-noui"))
|
||||
BetterUI.setEnabled(false);
|
||||
|
||||
if (containsArg("-nologo"))
|
||||
BetterUI.setEnableBigLogo(false);
|
||||
|
||||
Path eula = Paths.get("eula.txt");
|
||||
if (containsArg("-accepteula"))
|
||||
BetterUI.forceAcceptEULA(eula);
|
||||
|
||||
boolean enableUpdate = !containsArg("-dau");
|
||||
|
||||
containsArg("-nojline"); //For some reason when passing -nojline to the console the whole thing crashes, remove this
|
||||
|
||||
BetterUI.printTitle(NAME, BRAND, System.getProperty("java.version") + " (" + System.getProperty("java.vendor") + ")", VERSION, BUKKIT_VERSION, FORGE_VERSION);
|
||||
System.out.println("If the server crashes while installing, try removing the libraries folder and launching the server again.");
|
||||
|
||||
if(!BetterUI.checkEula(eula)) System.exit(0);
|
||||
|
||||
List<String> launchArgs = JarTool.readFileLinesFromJar("data/" + (SystemType.getOS().equals(SystemType.OS.WINDOWS) ? "win" : "unix") + "_args.txt");
|
||||
List<String> forgeArgs = new ArrayList<>();
|
||||
launchArgs.stream().filter(s -> s.startsWith("--launchTarget") || s.startsWith("--fml.forgeVersion") || s.startsWith("--fml.mcVersion") || s.startsWith("--fml.forgeGroup") || s.startsWith("--fml.mcpVersion")).toList().forEach(arg -> {
|
||||
forgeArgs.add(arg.split(" ")[0]);
|
||||
forgeArgs.add(arg.split(" ")[1]);
|
||||
});
|
||||
|
||||
MagmaInstaller.run();
|
||||
|
||||
ServerInitHelper.init(launchArgs);
|
||||
|
||||
ServerInitHelper.addToPath(new File("libraries/com/google/code/gson/gson/2.10/gson-2.10.jar").toPath());
|
||||
ServerInitHelper.addToPath(new File("libraries/org/yaml/snakeyaml/1.33/snakeyaml-1.33.jar").toPath());
|
||||
if (enableUpdate)
|
||||
MagmaUpdater.checkForUpdates();
|
||||
|
||||
String[] invokeArgs = Stream.concat(forgeArgs.stream(), Stream.of(MagmaStart.args)).toArray(String[]::new);
|
||||
BootstrapLauncher.startServer(invokeArgs);
|
||||
}
|
||||
|
||||
private static boolean containsArg(String arg) {
|
||||
if (Arrays.stream(MagmaStart.args).anyMatch(s -> s.equalsIgnoreCase(arg))) {
|
||||
MagmaStart.args = remove(MagmaStart.args, arg);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static String[] remove(String[] array, String element) {
|
||||
if (array.length > 0) {
|
||||
int index = -1;
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
if (array[i].equalsIgnoreCase(element)) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (index >= 0) {
|
||||
String[] copy = (String[]) Array.newInstance(array.getClass()
|
||||
.getComponentType(), array.length - 1);
|
||||
if (copy.length > 0) {
|
||||
System.arraycopy(array, 0, copy, 0, index);
|
||||
System.arraycopy(array, index + 1, copy, index, copy.length - index);
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
}
|
||||
return array;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
<html>
|
||||
<head><title>Index of /mirror/src/Magma-1-20-x/magmalauncher/src/main/java/org/magmafoundation/magma/</title></head>
|
||||
<body>
|
||||
<h1>Index of /mirror/src/Magma-1-20-x/magmalauncher/src/main/java/org/magmafoundation/magma/</h1><hr><pre><a href="../">../</a>
|
||||
<a href="installer/">installer/</a> 28-Oct-2023 12:00 -
|
||||
<a href="updater/">updater/</a> 07-Oct-2023 14:12 -
|
||||
<a href="utils/">utils/</a> 07-Oct-2023 14:12 -
|
||||
<a href="MagmaStart.java">MagmaStart.java</a> 07-Oct-2023 14:12 5367
|
||||
</pre><hr><script defer src="https://static.cloudflareinsights.com/beacon.min.js/v84a3a4012de94ce1a686ba8c167c359c1696973893317" integrity="sha512-euoFGowhlaLqXsPWQ48qSkBSCFs3DPRyiwVu3FjR96cMPx+Fr+gpWRhIafcHwqwCqWS42RZhIudOvEI+Ckf6MA==" nonce="2770d752e020511a6056b54aff81f185" data-cf-beacon='{"rayId":"85f019b83f6d50c2","version":"2024.2.4","r":1,"token":"583109dda43e47a593fd006526a81120","b":1}' crossorigin="anonymous"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,181 @@
|
|||
/*
|
||||
* Magma Server
|
||||
* Copyright (C) 2019-${year}.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.magmafoundation.magma.installer;
|
||||
|
||||
import org.magmafoundation.magma.MagmaStart;
|
||||
import org.magmafoundation.magma.common.MagmaConstants;
|
||||
import org.magmafoundation.magma.common.utils.JarTool;
|
||||
import org.magmafoundation.magma.common.utils.MD5;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
/**
|
||||
* Project: Magma
|
||||
*
|
||||
* @author Malcolm (M1lc0lm)
|
||||
* @date 03.07.2022 - 17:19
|
||||
*
|
||||
* Inspired by Shawiiz_z (https://github.com/Shawiizz)
|
||||
*/
|
||||
public abstract class AbstractMagmaInstaller {
|
||||
|
||||
public static final String LIB_PATH = new File(JarTool.getJarDir(), MagmaConstants.INSTALLER_LIBRARIES_FOLDER).getAbsolutePath() + "/";
|
||||
public static final File INSTALL_DIR = new File(LIB_PATH + "org/magma/install/");
|
||||
public static final File INSTALL_INFO = new File(INSTALL_DIR.getAbsolutePath() + "/installInfo");
|
||||
|
||||
private PrintStream origin = System.out;
|
||||
public String forgeVer;
|
||||
public String mcpVer;
|
||||
public String mcVer;
|
||||
|
||||
public String forgeStart;
|
||||
public File universalJar;
|
||||
public File serverJar;
|
||||
|
||||
public File lzma;
|
||||
|
||||
public String otherStart;
|
||||
public File extra;
|
||||
public File slim;
|
||||
public File srg;
|
||||
|
||||
public String mcpStart;
|
||||
public File mcpZip;
|
||||
public File mcpTxt;
|
||||
|
||||
public File minecraft_server;
|
||||
|
||||
private PrintStream installerLog;
|
||||
|
||||
protected AbstractMagmaInstaller() throws IOException {
|
||||
this.forgeVer = MagmaConstants.FORGE_VERSION_FULL.split("-")[1];
|
||||
this.mcpVer = MagmaConstants.FORGE_VERSION_FULL.split("-")[3];
|
||||
this.mcVer = MagmaConstants.FORGE_VERSION_FULL.split("-")[0];
|
||||
|
||||
this.forgeStart = LIB_PATH + "net/minecraftforge/forge/" + mcVer + "-" + forgeVer + "/forge-" + mcVer + "-" + forgeVer;
|
||||
this.universalJar = new File(forgeStart + "-universal.jar");
|
||||
this.serverJar = new File(forgeStart + "-server.jar");
|
||||
|
||||
this.lzma = new File(LIB_PATH + "org/magma/install/data/server.lzma");
|
||||
|
||||
this.otherStart = LIB_PATH + "net/minecraft/server/" + mcVer + "-" + mcpVer + "/server-" + mcVer + "-" + mcpVer;
|
||||
|
||||
this.extra = new File(otherStart + "-extra.jar");
|
||||
this.slim = new File(otherStart + "-slim.jar");
|
||||
this.srg = new File(otherStart + "-srg.jar");
|
||||
|
||||
this.mcpStart = LIB_PATH + "de/oceanlabs/mcp/mcp_config/" + mcVer + "-" + mcpVer + "/mcp_config-" + mcVer + "-" + mcpVer;
|
||||
this.mcpZip = new File(mcpStart + ".zip");
|
||||
this.mcpTxt = new File(mcpStart + "-mappings.txt");
|
||||
|
||||
this.minecraft_server = new File(LIB_PATH + "minecraft_server." + mcVer + ".jar");
|
||||
|
||||
File out = new File("logs/installer.log");
|
||||
if(!out.exists()) {
|
||||
out.getParentFile().mkdirs();
|
||||
out.createNewFile();
|
||||
} else {
|
||||
out.delete();
|
||||
out.createNewFile();
|
||||
}
|
||||
|
||||
this.installerLog = new PrintStream(new BufferedOutputStream(new FileOutputStream(out)));
|
||||
}
|
||||
|
||||
protected void launchService(String mainClass, List<String> args, List<URL> classPath) throws Exception {
|
||||
try {
|
||||
Class.forName(mainClass);
|
||||
} catch (ClassNotFoundException e) {
|
||||
System.out.println("Class not found: " + e.getMessage());
|
||||
}
|
||||
URLClassLoader loader = URLClassLoader.newInstance(classPath.toArray(new URL[0]));
|
||||
Class.forName(mainClass, true, loader).getDeclaredMethod("main", String[].class).invoke(null, (Object) args.toArray(new String[0]));
|
||||
loader.clearAssertionStatus();
|
||||
loader.close();
|
||||
}
|
||||
|
||||
protected List<URL> stringToUrl(List<String> strs) throws Exception {
|
||||
List<URL> temp = new ArrayList<>();
|
||||
for (String t : strs) {
|
||||
temp.add(new File(t).toURI().toURL());
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
/*
|
||||
THIS IS TO NOT SPAM CONSOLE WHEN IT WILL PRINT A LOT OF THINGS
|
||||
*/
|
||||
protected void mute() {
|
||||
System.setOut(installerLog);
|
||||
}
|
||||
|
||||
protected void unmute() {
|
||||
System.setOut(origin);
|
||||
}
|
||||
|
||||
protected void copyFileFromJar(File file, String pathInJar) throws Exception {
|
||||
InputStream is = MagmaStart.class.getClassLoader().getResourceAsStream(pathInJar);
|
||||
if(!file.exists() || !MD5.getMd5(file).equals(MD5.getMd5(is)) || file.length() <= 1) {
|
||||
file.getParentFile().mkdirs();
|
||||
file.createNewFile();
|
||||
if(is != null) Files.copy(is, file.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
||||
else {
|
||||
System.out.println("The file " + file.getName() + " was not found in the jar.");
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void deleteIfExists(File file) throws IOException {
|
||||
Files.deleteIfExists(file.toPath());
|
||||
File dir = file.getParentFile();
|
||||
if (dir.isDirectory() && dir.list().length == 0)
|
||||
Files.delete(dir.toPath());
|
||||
}
|
||||
|
||||
protected static void deleteFolder(File folder) {
|
||||
File[] files = folder.listFiles();
|
||||
if (files != null) { //some JVMs return null for empty dirs
|
||||
for(File f : files) {
|
||||
if (f.isDirectory())
|
||||
deleteFolder(f);
|
||||
else
|
||||
f.delete();
|
||||
}
|
||||
}
|
||||
folder.delete();
|
||||
}
|
||||
|
||||
protected boolean isCorrupted(File f) {
|
||||
try {
|
||||
JarFile j = new JarFile(f);
|
||||
j.close();
|
||||
return false;
|
||||
} catch (IOException e) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,445 @@
|
|||
/*
|
||||
* Magma Server
|
||||
* Copyright (C) 2019-${year}.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.magmafoundation.magma.installer;
|
||||
|
||||
import dev.vankka.dependencydownload.DependencyManager;
|
||||
import dev.vankka.dependencydownload.dependency.Dependency;
|
||||
import dev.vankka.dependencydownload.path.CleanupPathProvider;
|
||||
import dev.vankka.dependencydownload.path.DependencyPathProvider;
|
||||
import dev.vankka.dependencydownload.repository.Repository;
|
||||
import dev.vankka.dependencydownload.repository.StandardRepository;
|
||||
import me.tongfei.progressbar.ProgressBar;
|
||||
import me.tongfei.progressbar.ProgressBarBuilder;
|
||||
import me.tongfei.progressbar.ProgressBarStyle;
|
||||
import org.magmafoundation.magma.common.MagmaConstants;
|
||||
import org.magmafoundation.magma.common.utils.JarTool;
|
||||
import org.magmafoundation.magma.common.utils.MD5;
|
||||
import org.magmafoundation.magma.utils.LibHelper;
|
||||
import org.magmafoundation.magma.utils.ServerInitHelper;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.spi.FileSystemProvider;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Project: Magma
|
||||
*
|
||||
* @author Malcolm (M1lc0lm)
|
||||
* @date 03.07.2022 - 17:19
|
||||
*
|
||||
* Inspired by Shawiiz_z (https://github.com/Shawiizz)
|
||||
*/
|
||||
public class MagmaInstaller extends AbstractMagmaInstaller {
|
||||
|
||||
private static final List<String> loadedLibsPaths = new ArrayList<>();
|
||||
|
||||
private final String magmaVersion = MagmaConstants.VERSION;
|
||||
|
||||
public final File fmlloader = new File(LIB_PATH + "net/minecraftforge/fmlloader/" + mcVer + "-" + forgeVer + "/fmlloader-" + mcVer + "-" + forgeVer + ".jar");
|
||||
public final File fmlcore = new File(LIB_PATH + "net/minecraftforge/fmlcore/" + mcVer + "-" + forgeVer + "/fmlcore-" + mcVer + "-" + forgeVer + ".jar");
|
||||
public final File javafmllanguage = new File(LIB_PATH + "net/minecraftforge/javafmllanguage/" + mcVer + "-" + forgeVer + "/javafmllanguage-" + mcVer + "-" + forgeVer + ".jar");
|
||||
public final File mclanguage = new File(LIB_PATH + "net/minecraftforge/mclanguage/" + mcVer + "-" + forgeVer + "/mclanguage-" + mcVer + "-" + forgeVer + ".jar");
|
||||
public final File lowcodelanguage = new File(LIB_PATH + "net/minecraftforge/lowcodelanguage/" + mcVer + "-" + forgeVer + "/lowcodelanguage-" + mcVer + "-" + forgeVer + ".jar");
|
||||
|
||||
public final File mojmap = new File(otherStart + "-mappings.txt");
|
||||
public final File mc_unpacked = new File(otherStart + "-unpacked.jar");
|
||||
|
||||
public final File mergedMapping = new File(mcpStart + "-mappings-merged.txt");
|
||||
|
||||
public MagmaInstaller() throws Exception {
|
||||
new Dependencies(mcVer, mcpVer, minecraft_server);
|
||||
install();
|
||||
unmute(); //just to be sure ;)
|
||||
}
|
||||
|
||||
//Inspired by the Mohist 1.19 installer
|
||||
private void install() throws Exception {
|
||||
ProgressBarBuilder builder = new ProgressBarBuilder()
|
||||
.setTaskName("Patching server...")
|
||||
.setStyle(ProgressBarStyle.ASCII)
|
||||
.setUpdateIntervalMillis(100)
|
||||
.setInitialMax(8);
|
||||
|
||||
try (ProgressBar pb = builder.build()) {
|
||||
copyFileFromJar(lzma, "data/server.lzma");
|
||||
copyFileFromJar(universalJar, "data/forge-" + mcVer + "-" + forgeVer + "-universal.jar");
|
||||
copyFileFromJar(fmlloader, "data/fmlloader-" + mcVer + "-" + forgeVer + ".jar");
|
||||
copyFileFromJar(fmlcore, "data/fmlcore-" + mcVer + "-" + forgeVer + ".jar");
|
||||
copyFileFromJar(javafmllanguage, "data/javafmllanguage-" + mcVer + "-" + forgeVer + ".jar");
|
||||
copyFileFromJar(mclanguage, "data/mclanguage-" + mcVer + "-" + forgeVer + ".jar");
|
||||
copyFileFromJar(lowcodelanguage, "data/lowcodelanguage-" + mcVer + "-" + forgeVer + ".jar");
|
||||
|
||||
if (magmaVersion == null || mcpVer == null) {
|
||||
System.out.println("The server has an invalid version and cannot proceed. Please report this to the developer.");
|
||||
System.exit(-1);
|
||||
}
|
||||
|
||||
if (minecraft_server.exists()) {
|
||||
mute();
|
||||
System.out.println("[STEP ONE] Extracting bundled resources...");
|
||||
launchService("net.minecraftforge.installertools.ConsoleTool",
|
||||
new ArrayList<>(Arrays.asList("--task", "BUNDLER_EXTRACT", "--input", minecraft_server.getAbsolutePath(), "--output", LIB_PATH, "--libraries")),
|
||||
stringToUrl(loadedLibsPaths));
|
||||
|
||||
//Delete brigadier, we have our own implementation
|
||||
deleteLib("com/mojang/brigadier");
|
||||
//Delete datafixers, we have our own implementation
|
||||
deleteLib("com/mojang/datafixerupper");
|
||||
System.out.println();
|
||||
unmute();
|
||||
pb.step();
|
||||
if (!mc_unpacked.exists()) {
|
||||
mute();
|
||||
System.out.println("[STEP TWO] Extracting jars...");
|
||||
launchService("net.minecraftforge.installertools.ConsoleTool",
|
||||
new ArrayList<>(Arrays.asList("--task", "BUNDLER_EXTRACT", "--input", minecraft_server.getAbsolutePath(), "--output", mc_unpacked.getAbsolutePath(), "--jar-only")),
|
||||
stringToUrl(loadedLibsPaths));
|
||||
System.out.println();
|
||||
unmute();
|
||||
}
|
||||
pb.step();
|
||||
} else {
|
||||
System.err.println("The server is missing essential files to install properly, delete your libraries folder and try again.");
|
||||
System.exit(-1);
|
||||
}
|
||||
|
||||
if (mcpZip.exists()) {
|
||||
if (!mcpTxt.exists()) {
|
||||
mute();
|
||||
System.out.println("[STEP THREE] Getting mappings...");
|
||||
launchService("net.minecraftforge.installertools.ConsoleTool",
|
||||
new ArrayList<>(Arrays.asList("--task", "MCP_DATA", "--input", mcpZip.getAbsolutePath(), "--output", mcpTxt.getAbsolutePath(), "--key", "mappings")),
|
||||
stringToUrl(loadedLibsPaths));
|
||||
System.out.println();
|
||||
unmute();
|
||||
}
|
||||
} else {
|
||||
System.err.println("The server is missing essential files to install properly, delete your libraries folder and try again.");
|
||||
System.exit(-1);
|
||||
}
|
||||
pb.step();
|
||||
|
||||
if (isCorrupted(extra)) extra.delete();
|
||||
if (isCorrupted(slim)) slim.delete();
|
||||
if (isCorrupted(srg)) srg.delete();
|
||||
|
||||
if (!mojmap.exists()) {
|
||||
mute();
|
||||
System.out.println("[STEP FOUR] Downloading mojang mappings...");
|
||||
launchService("net.minecraftforge.installertools.ConsoleTool",
|
||||
new ArrayList<>(Arrays.asList("--task", "DOWNLOAD_MOJMAPS", "--version", mcVer, "--side", "server", "--output", mojmap.getAbsolutePath())),
|
||||
stringToUrl(loadedLibsPaths));
|
||||
System.out.println();
|
||||
unmute();
|
||||
}
|
||||
pb.step();
|
||||
|
||||
if (!mergedMapping.exists()) {
|
||||
mute();
|
||||
System.out.println("[STEP FIVE] Merging mappings...");
|
||||
launchService("net.minecraftforge.installertools.ConsoleTool",
|
||||
new ArrayList<>(Arrays.asList("--task", "MERGE_MAPPING", "--left", mcpTxt.getAbsolutePath(), "--right", mojmap.getAbsolutePath(), "--output", mergedMapping.getAbsolutePath(), "--classes", "--reverse-right")),
|
||||
stringToUrl(loadedLibsPaths));
|
||||
System.out.println();
|
||||
unmute();
|
||||
}
|
||||
pb.step();
|
||||
|
||||
if (!slim.exists() || !extra.exists()) {
|
||||
mute();
|
||||
System.out.println("[STEP SIX] Splitting server jar...");
|
||||
launchService("net.minecraftforge.jarsplitter.ConsoleTool",
|
||||
new ArrayList<>(Arrays.asList("--input", minecraft_server.getAbsolutePath(), "--slim", slim.getAbsolutePath(), "--extra", extra.getAbsolutePath(), "--srg", mergedMapping.getAbsolutePath())),
|
||||
stringToUrl(loadedLibsPaths));
|
||||
launchService("net.minecraftforge.jarsplitter.ConsoleTool",
|
||||
new ArrayList<>(Arrays.asList("--input", mc_unpacked.getAbsolutePath(), "--slim", slim.getAbsolutePath(), "--extra", extra.getAbsolutePath(), "--srg", mergedMapping.getAbsolutePath())),
|
||||
stringToUrl(loadedLibsPaths));
|
||||
System.out.println();
|
||||
unmute();
|
||||
}
|
||||
pb.step();
|
||||
|
||||
if (!srg.exists()) {
|
||||
mute();
|
||||
System.out.println("[STEP SEVEN] Creating srg jar file...");
|
||||
launchService("net.minecraftforge.fart.Main",
|
||||
new ArrayList<>(Arrays.asList("--input", slim.getAbsolutePath(), "--output", srg.getAbsolutePath(), "--names", mergedMapping.getAbsolutePath(), "--ann-fix", "--ids-fix", "--src-fix", "--record-fix")),
|
||||
stringToUrl(loadedLibsPaths));
|
||||
System.out.println();
|
||||
unmute();
|
||||
}
|
||||
pb.step();
|
||||
|
||||
String storedServerMD5 = null;
|
||||
String storedMagmaMD5 = null;
|
||||
String serverMD5 = MD5.getMd5(serverJar);
|
||||
String magmaMD5 = MD5.getMd5(JarTool.getFile());
|
||||
|
||||
if (INSTALL_INFO.exists()) {
|
||||
List<String> infoLines = Files.readAllLines(INSTALL_INFO.toPath());
|
||||
if (infoLines.size() > 0)
|
||||
storedServerMD5 = infoLines.get(0);
|
||||
if (infoLines.size() > 1)
|
||||
storedMagmaMD5 = infoLines.get(1);
|
||||
}
|
||||
|
||||
if (!serverJar.exists()
|
||||
|| storedServerMD5 == null
|
||||
|| storedMagmaMD5 == null
|
||||
|| !storedServerMD5.equals(serverMD5)
|
||||
|| !storedMagmaMD5.equals(magmaMD5)) {
|
||||
mute();
|
||||
System.out.println("[STEP EIGHT] Patching forge jar...");
|
||||
launchService("net.minecraftforge.binarypatcher.ConsoleTool",
|
||||
new ArrayList<>(Arrays.asList("--clean", srg.getAbsolutePath(), "--output", serverJar.getAbsolutePath(), "--apply", lzma.getAbsolutePath())),
|
||||
stringToUrl(new ArrayList<>(Arrays.asList(
|
||||
LIB_PATH + "net/minecraftforge/binarypatcher/1.1.1/binarypatcher-1.1.1.jar",
|
||||
LIB_PATH + "commons-io/commons-io/2.11.0/commons-io-2.11.0.jar",
|
||||
LIB_PATH + "com/google/guava/guava/31.1-jre/guava-31.1-jre.jar",
|
||||
LIB_PATH + "net/sf/jopt-simple/jopt-simple/5.0.4/jopt-simple-5.0.4.jar",
|
||||
LIB_PATH + "com/github/jponge/lzma-java/1.3/lzma-java-1.3.jar",
|
||||
LIB_PATH + "com/nothome/javaxdelta/2.0.1/javaxdelta-2.0.1.jar",
|
||||
LIB_PATH + "com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.jar",
|
||||
LIB_PATH + "org/checkerframework/checker-qual/2.0.0/checker-qual-2.0.0.jar",
|
||||
LIB_PATH + "com/google/errorprone/error_prone_annotations/2.1.3/error_prone_annotations-2.1.3.jar",
|
||||
LIB_PATH + "com/google/j2objc/j2objc-annotations/1.1/j2objc-annotations-1.1.jar",
|
||||
LIB_PATH + "org/codehaus/mojo/animal-sniffer-annotations/1.14/animal-sniffer-annotations-1.14.jar",
|
||||
LIB_PATH + "trove/trove/1.0.2/trove-1.0.2.jar"
|
||||
))));
|
||||
unmute();
|
||||
serverMD5 = MD5.getMd5(serverJar);
|
||||
}
|
||||
pb.step();
|
||||
|
||||
FileWriter fw = new FileWriter(INSTALL_INFO);
|
||||
fw.write(serverMD5 + "\n");
|
||||
fw.write(magmaMD5);
|
||||
fw.close();
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteLib(String path) throws IOException {
|
||||
File libDir = new File(LIB_PATH + path);
|
||||
if (libDir.exists()) {
|
||||
Files.walk(libDir.toPath())
|
||||
.map(Path::toFile)
|
||||
.forEach(File::delete);
|
||||
libDir.delete();
|
||||
}
|
||||
}
|
||||
|
||||
public static void run() {
|
||||
try {
|
||||
if (!checkDependencies())
|
||||
return;
|
||||
|
||||
var urls = loadInternalDependencies();
|
||||
urls.add(MagmaInstaller.class.getProtectionDomain().getCodeSource().getLocation().toURI().toURL());
|
||||
var installerClassLoader = new URLClassLoader(urls.toArray(URL[]::new), null);
|
||||
var installerClass = Class.forName(MagmaInstaller.class.getName(), false, installerClassLoader);
|
||||
installerClass.getConstructor().newInstance();
|
||||
installerClassLoader.close();
|
||||
|
||||
// Who needs file systems anyway
|
||||
ServerInitHelper.addOpens("java.base", "java.nio.file.spi", "ALL-UNNAMED");
|
||||
var loadingProvidersField = FileSystemProvider.class.getDeclaredField("loadingProviders");
|
||||
loadingProvidersField.setAccessible(true);
|
||||
loadingProvidersField.set(null, false);
|
||||
var installedProvidersField = FileSystemProvider.class.getDeclaredField("installedProviders");
|
||||
installedProvidersField.setAccessible(true);
|
||||
installedProvidersField.set(null, null);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean checkDependencies() throws IOException {
|
||||
if (INSTALL_INFO.exists()) {
|
||||
String magmaMD5 = MD5.getMd5(JarTool.getFile());
|
||||
List<String> lines = Files.readAllLines(INSTALL_INFO.toPath());
|
||||
if (lines.size() >= 2 && magmaMD5.equals(lines.get(1))) //Latest patch is installed
|
||||
return false;
|
||||
else {
|
||||
System.out.println("Update found! Magma will now update itself...");
|
||||
//extracted libs
|
||||
deleteFolder(new File(LIB_PATH + "net/minecraftforge/"));
|
||||
deleteFolder(new File(LIB_PATH + "net/minecraft/server/"));
|
||||
|
||||
//install info
|
||||
deleteFolder(INSTALL_DIR);
|
||||
|
||||
//mcp
|
||||
deleteFolder(new File(LIB_PATH + "de/oceanlabs/mcp/"));
|
||||
|
||||
//libraries in path
|
||||
deleteFolder(new File(LIB_PATH + "cpw/mods"));
|
||||
deleteFolder(new File(LIB_PATH + "org/ow2/asm/"));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static List<URL> loadInternalDependencies() throws Exception {
|
||||
var dependencies = new InternalDependency[] {
|
||||
new InternalDependency(LIB_PATH + "dev/vankka/dependencydownload-common/1.3.0/dependencydownload-common-1.3.0.jar", "b6d32a6d0c4d4407f54e601cfa3f0a5a", "https://repo1.maven.org/maven2/dev/vankka/dependencydownload-common/1.3.0/dependencydownload-common-1.3.0.jar"),
|
||||
new InternalDependency(LIB_PATH + "dev/vankka/dependencydownload-runtime/1.3.0/dependencydownload-runtime-1.3.0.jar", "ec35cf4906c6151111d9eabe4f4ea949", "https://repo1.maven.org/maven2/dev/vankka/dependencydownload-runtime/1.3.0/dependencydownload-runtime-1.3.0.jar"),
|
||||
new InternalDependency(LIB_PATH + "org/jline/jline/3.21.0/jline-3.21.0.jar", "859778f9cdd3bd42bbaaf0f6f7fe5e6a", "https://repo1.maven.org/maven2/org/jline/jline/3.21.0/jline-3.21.0.jar"),
|
||||
new InternalDependency(LIB_PATH + "me/tongfei/progressbar/0.9.3/progressbar-0.9.3.jar", "25d3101d2ca7f0847a804208d5411d78", "https://repo1.maven.org/maven2/me/tongfei/progressbar/0.9.3/progressbar-0.9.3.jar")
|
||||
};
|
||||
var urls = new ArrayList<URL>();
|
||||
for (var dependency : dependencies) {
|
||||
if (!dependency.file().exists() || !dependency.signature().equals(MD5.getMd5(dependency.file()))) {
|
||||
dependency.file().getParentFile().mkdirs();
|
||||
dependency.download();
|
||||
}
|
||||
urls.add(dependency.url());
|
||||
}
|
||||
return urls;
|
||||
}
|
||||
|
||||
private record InternalDependency(File file, String signature, String link) {
|
||||
private InternalDependency(String path, String signature, String link) {
|
||||
this(new File(path), signature, link);
|
||||
}
|
||||
|
||||
private void download() throws Exception {
|
||||
NetworkUtils.downloadFile(this.link(), this.file(), this.signature());
|
||||
}
|
||||
|
||||
private URL url() {
|
||||
try {
|
||||
return file.toURI().toURL();
|
||||
} catch (MalformedURLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected class Dependencies {
|
||||
|
||||
private String mcVersion;
|
||||
private String mcpVersion;
|
||||
private File minecraft_server;
|
||||
|
||||
public Dependencies(String mcVersion, String mcpVersion, File minecraft_server) throws Exception {
|
||||
this.mcVersion = mcVersion;
|
||||
this.mcpVersion = mcpVersion;
|
||||
this.minecraft_server = minecraft_server;
|
||||
|
||||
downloadLibraries();
|
||||
}
|
||||
|
||||
public void downloadLibraries() throws Exception {
|
||||
DependencyPathProvider dependencyPathProvider = new CleanupPathProvider() {
|
||||
|
||||
public final Path baseDirPath = JarTool.getJarDir().toPath();
|
||||
|
||||
@Override
|
||||
public Path getCleanupPath() {
|
||||
return baseDirPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getDependencyPath(Dependency dependency, boolean relocated) {
|
||||
return baseDirPath.resolve("libraries")
|
||||
.resolve(dependency.getGroupId().replace(".", "/"))
|
||||
.resolve(dependency.getArtifactId())
|
||||
.resolve(dependency.getVersion())
|
||||
.resolve(dependency.getFileName());
|
||||
}
|
||||
};
|
||||
|
||||
DependencyManager manager = new DependencyManager(dependencyPathProvider);
|
||||
manager.loadFromResource(new URL("jar:file:" + JarTool.getJarPath() + "!/data/magma_libraries.txt"));
|
||||
|
||||
List<Repository> standardRepositories = new ArrayList<>();
|
||||
standardRepositories.add(new StandardRepository("https://nexus.c0d3m4513r.com/repository/Magma/"));
|
||||
standardRepositories.add(new StandardRepository("https://maven.minecraftforge.net"));
|
||||
standardRepositories.add(new StandardRepository("https://repo1.maven.org/maven2"));
|
||||
standardRepositories.add(new StandardRepository("https://git.magmafoundation.org/magmafoundation/magma-maven-repo/-/raw/repository/"));
|
||||
standardRepositories.add(new StandardRepository("https://maven.izzel.io/releases"));
|
||||
|
||||
List<Dependency> dependencies = manager.getDependencies();
|
||||
|
||||
ProgressBarBuilder builder = new ProgressBarBuilder()
|
||||
.setTaskName("Loading libraries...")
|
||||
.setStyle(ProgressBarStyle.ASCII)
|
||||
.setUpdateIntervalMillis(100)
|
||||
.setInitialMax(dependencies.size());
|
||||
|
||||
mute();
|
||||
System.out.println("[INITIAL SETUP] Loading libraries...");
|
||||
unmute();
|
||||
|
||||
//AtomicReference<Throwable> error = new AtomicReference<>(null);
|
||||
ProgressBar.wrap(dependencies.stream(), builder).forEach(dep -> {
|
||||
try {
|
||||
mute();
|
||||
System.out.println("Considering library " + dep.getFileName() + "...");
|
||||
LibHelper.downloadDependency(manager, dep, standardRepositories);
|
||||
LibHelper.loadDependency(manager, dep, path -> loadedLibsPaths.add(path.toFile().getAbsolutePath()));
|
||||
System.out.println("Library " + dep.getFileName() + " loaded!");
|
||||
unmute();
|
||||
} catch (Exception e) {
|
||||
unmute();
|
||||
throw new RuntimeException("Something went wrong while trying to load dependencies", e);
|
||||
}
|
||||
});
|
||||
|
||||
downloadMcp(mcVersion, mcpVersion);
|
||||
downloadMinecraftServer(minecraft_server);
|
||||
}
|
||||
|
||||
public void downloadMcp(String mc_version, String mcp_version) {
|
||||
File mcp_config = new File(LIB_PATH + "de/oceanlabs/mcp/mcp_config/" + mc_version + "-" + mcp_version + "/mcp_config-" + mc_version + "-" + mcp_version + ".zip");
|
||||
if (Files.exists(mcp_config.toPath()))
|
||||
return;
|
||||
mcp_config.getParentFile().mkdirs();
|
||||
try {
|
||||
NetworkUtils.downloadFile("https://maven.minecraftforge.net/de/oceanlabs/mcp/mcp_config/"+ mc_version + "-"+ mcp_version + "/mcp_config-"+ mc_version + "-"+ mcp_version +".zip",
|
||||
mcp_config);
|
||||
} catch (Exception e) {
|
||||
System.out.println("Can't find mcp_config");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void downloadMinecraftServer(File minecraft_server) throws IOException {
|
||||
if (Files.exists(minecraft_server.toPath()))
|
||||
return;
|
||||
minecraft_server.getParentFile().mkdirs();
|
||||
try {
|
||||
NetworkUtils.downloadFile("https://piston-data.mojang.com/v1/objects/84194a2f286ef7c14ed7ce0090dba59902951553/server.jar", minecraft_server);
|
||||
} catch (Exception e) {
|
||||
System.out.println("Can't download minecraft_server");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Magma Server
|
||||
* Copyright (C) 2019-${year}.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.magmafoundation.magma.installer;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.nio.channels.Channels;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.channels.ReadableByteChannel;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
|
||||
/**
|
||||
* Project: Magma
|
||||
*
|
||||
* @author Malcolm (M1lc0lm)
|
||||
* @date 03.07.2022 - 17:19
|
||||
*
|
||||
* Inspired by MohistMC (https://github.com/MohistMC)
|
||||
*/
|
||||
public class NetworkUtils {
|
||||
|
||||
public static URLConnection getConnection(String URL) {
|
||||
URLConnection conn = null;
|
||||
try {
|
||||
conn = new URL(URL).openConnection();
|
||||
conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:31.0) Gecko/20100101 Firefox/31.0");
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return conn;
|
||||
}
|
||||
|
||||
public static void downloadFile(String URL, File f) throws Exception {
|
||||
downloadFile(URL, f, null);
|
||||
}
|
||||
|
||||
public static void downloadFile(String URL, File f, String md5) throws Exception {
|
||||
URLConnection conn = getConnection(URL);
|
||||
ReadableByteChannel rbc = Channels.newChannel(conn.getInputStream());
|
||||
FileChannel fc = FileChannel.open(f.toPath(), StandardOpenOption.CREATE, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING);
|
||||
int fS = conn.getContentLength();
|
||||
fc.transferFrom(rbc, 0, Long.MAX_VALUE);
|
||||
fc.close();
|
||||
rbc.close();
|
||||
String MD5 = org.magmafoundation.magma.common.utils.MD5.getMd5(f);
|
||||
if(md5 != null && MD5 != null && !MD5.equals(md5.toLowerCase())) {
|
||||
f.delete();
|
||||
throw new Exception("md5");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
<html>
|
||||
<head><title>Index of /mirror/src/Magma-1-20-x/magmalauncher/src/main/java/org/magmafoundation/magma/installer/</title></head>
|
||||
<body>
|
||||
<h1>Index of /mirror/src/Magma-1-20-x/magmalauncher/src/main/java/org/magmafoundation/magma/installer/</h1><hr><pre><a href="../">../</a>
|
||||
<a href="AbstractMagmaInstaller.java">AbstractMagmaInstaller.java</a> 07-Oct-2023 14:12 6304
|
||||
<a href="MagmaInstaller.java">MagmaInstaller.java</a> 28-Oct-2023 12:00 22K
|
||||
<a href="NetworkUtils.java">NetworkUtils.java</a> 07-Oct-2023 14:12 2419
|
||||
</pre><hr><script defer src="https://static.cloudflareinsights.com/beacon.min.js/v84a3a4012de94ce1a686ba8c167c359c1696973893317" integrity="sha512-euoFGowhlaLqXsPWQ48qSkBSCFs3DPRyiwVu3FjR96cMPx+Fr+gpWRhIafcHwqwCqWS42RZhIudOvEI+Ckf6MA==" nonce="7996d7b608e8948d785455492ce91722" data-cf-beacon='{"rayId":"85f02715ce001c5c","version":"2024.2.4","r":1,"token":"583109dda43e47a593fd006526a81120","b":1}' crossorigin="anonymous"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* Magma Server
|
||||
* Copyright (C) 2019-${year}.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.magmafoundation.magma.updater;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonObject;
|
||||
import org.magmafoundation.magma.common.MagmaConstants;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.nio.channels.Channels;
|
||||
import java.nio.channels.ReadableByteChannel;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.Instant;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Project: Magma
|
||||
*
|
||||
* @author Malcolm (M1lc0lm)
|
||||
* @date 03.07.2022 - 17:19
|
||||
*/
|
||||
public class MagmaUpdater {
|
||||
|
||||
private static Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||
private String newSha;
|
||||
private String currentSha;
|
||||
|
||||
private String latestVersionURL = "https://api.magmafoundation.org/api/v2/1.20/latest/";
|
||||
|
||||
public boolean versionChecker() {
|
||||
try {
|
||||
URL url = new URL(latestVersionURL);
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setRequestMethod("GET");
|
||||
connection.addRequestProperty("User-Agent", "Magma");
|
||||
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
||||
JsonObject root = gson.fromJson(reader, JsonObject.class);
|
||||
|
||||
Date created_at = Date.from(Instant.parse(root.get("created_at").getAsString()));
|
||||
String date = new SimpleDateFormat("dd-MM-yyyy").format(created_at);
|
||||
String time = new SimpleDateFormat("H:mm a").format(created_at);
|
||||
|
||||
newSha = root.get("tag_name").getAsString();
|
||||
currentSha = MagmaConstants.VERSION.split("-")[1];
|
||||
|
||||
if(currentSha.equals(newSha)) {
|
||||
System.out.printf("[Magma] No update found, latest version: (%s) current version: (%s)%n", currentSha, newSha);
|
||||
return false;
|
||||
} else {
|
||||
System.out.printf("[Magma] The latest Magma version is (%s) but you have (%s). The latest version was built on %s at %s.%n", newSha, currentSha, date, time);
|
||||
return true;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.out.println("[Magma] Failed to check for updates.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void downloadJar() {
|
||||
String url = latestVersionURL + newSha + "/download";
|
||||
try {
|
||||
Path path = Paths.get(MagmaUpdater.class.getProtectionDomain().getCodeSource().getLocation().toURI());
|
||||
System.out.println("[Magma] Updating Magma Jar ...");
|
||||
System.out.println("[Magma] Downloading " + url + " ...");
|
||||
URL website = new URL(url);
|
||||
HttpURLConnection connection = (HttpURLConnection) website.openConnection();
|
||||
connection.setRequestMethod("GET");
|
||||
connection.addRequestProperty("User-Agent", "Magma");
|
||||
ReadableByteChannel rbc = Channels.newChannel(connection.getInputStream());
|
||||
FileOutputStream fos = new FileOutputStream(path.toFile());
|
||||
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
|
||||
} catch (IOException | URISyntaxException e) {
|
||||
System.out.println("[Magma] Failed to download update! Starting old version.");
|
||||
return;
|
||||
}
|
||||
System.out.println("[Magma] Download Complete! Please restart the server.");
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
public static void checkForUpdates() throws IOException {
|
||||
// Path path = Paths.get("magma.yml");
|
||||
// if(Files.exists(path)) {
|
||||
// try (InputStream stream = Files.newInputStream(path)) {
|
||||
// Yaml yaml = new Yaml();
|
||||
// Map<String, Object> data = yaml.load(stream);
|
||||
// Map<String, Object> forge = (Map<String, Object>) data.get("magma");
|
||||
// if (!forge.get("auto-update").equals(true) || MagmaConstants.VERSION.equals("dev-env"))
|
||||
// return;
|
||||
//
|
||||
// MagmaUpdater updater = new MagmaUpdater();
|
||||
// System.out.println("Checking for updates...");
|
||||
// if(updater.versionChecker())
|
||||
// updater.downloadJar();
|
||||
// }
|
||||
// }
|
||||
System.out.println("[Magma] Auto Updater is currently disabled!");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
<html>
|
||||
<head><title>Index of /mirror/src/Magma-1-20-x/magmalauncher/src/main/java/org/magmafoundation/magma/updater/</title></head>
|
||||
<body>
|
||||
<h1>Index of /mirror/src/Magma-1-20-x/magmalauncher/src/main/java/org/magmafoundation/magma/updater/</h1><hr><pre><a href="../">../</a>
|
||||
<a href="MagmaUpdater.java">MagmaUpdater.java</a> 07-Oct-2023 14:12 5107
|
||||
</pre><hr><script defer src="https://static.cloudflareinsights.com/beacon.min.js/v84a3a4012de94ce1a686ba8c167c359c1696973893317" integrity="sha512-euoFGowhlaLqXsPWQ48qSkBSCFs3DPRyiwVu3FjR96cMPx+Fr+gpWRhIafcHwqwCqWS42RZhIudOvEI+Ckf6MA==" nonce="a1ef11f0d3ab1079cebb68872c768af3" data-cf-beacon='{"rayId":"85f027196c941c5c","version":"2024.2.4","r":1,"token":"583109dda43e47a593fd006526a81120","b":1}' crossorigin="anonymous"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
* Magma Server
|
||||
* Copyright (C) 2019-${year}.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.magmafoundation.magma.utils;
|
||||
|
||||
import cpw.mods.cl.JarModuleFinder;
|
||||
import cpw.mods.cl.ModuleClassLoader;
|
||||
import cpw.mods.jarhandling.SecureJar;
|
||||
import org.magmafoundation.magma.common.MagmaConstants;
|
||||
import org.magmafoundation.magma.common.utils.JarTool;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.module.ModuleFinder;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.*;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class BootstrapLauncher {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void startServer(String[] args) {
|
||||
var legacyClasspath = loadLegacyClassPath();
|
||||
legacyClasspath.replaceAll(s -> s.startsWith("libraries/") ? s.replace("libraries/", JarTool.getJarDir() + File.separator + MagmaConstants.INSTALLER_LIBRARIES_FOLDER + File.separator) : s);
|
||||
|
||||
System.setProperty("legacyClassPath", String.join(File.pathSeparator, legacyClasspath));
|
||||
|
||||
var ignoreList = System.getProperty("ignoreList", "asm,securejarhandler");
|
||||
var ignores = ignoreList.split(",");
|
||||
|
||||
var previousPackages = new HashSet<String>();
|
||||
var jars = new ArrayList<SecureJar>();
|
||||
var filenameMap = getMergeFilenameMap();
|
||||
var mergeMap = new HashMap<Integer, List<Path>>();
|
||||
|
||||
outer:
|
||||
for (var legacy : legacyClasspath) {
|
||||
var path = Paths.get(legacy);
|
||||
var filename = path.getFileName().toString();
|
||||
|
||||
for (var filter : ignores) {
|
||||
if(filename.startsWith(filter)) {
|
||||
continue outer;
|
||||
}
|
||||
}
|
||||
|
||||
if(filenameMap.containsKey(filename)) {
|
||||
mergeMap.computeIfAbsent(filenameMap.get(filename), k -> new ArrayList<>()).add(path);
|
||||
continue;
|
||||
}
|
||||
|
||||
var jar = SecureJar.from(new PackageTracker(Set.copyOf(previousPackages), path), path);
|
||||
var packages = jar.getPackages();
|
||||
|
||||
previousPackages.addAll(packages);
|
||||
jars.add(jar);
|
||||
}
|
||||
|
||||
mergeMap.forEach((idx, paths) -> {
|
||||
var pathsArray = paths.toArray(Path[]::new);
|
||||
var jar = SecureJar.from(new PackageTracker(Set.copyOf(previousPackages), pathsArray), pathsArray);
|
||||
var packages = jar.getPackages();
|
||||
|
||||
previousPackages.addAll(packages);
|
||||
jars.add(jar);
|
||||
});
|
||||
var secureJarsArray = jars.toArray(SecureJar[]::new);
|
||||
|
||||
var allTargets = Arrays.stream(secureJarsArray).map(SecureJar::name).toList();
|
||||
var jarModuleFinder = JarModuleFinder.of(secureJarsArray);
|
||||
var bootModuleConfiguration = ModuleLayer.boot().configuration();
|
||||
var bootstrapConfiguration = bootModuleConfiguration.resolveAndBind(jarModuleFinder, ModuleFinder.ofSystem(), allTargets);
|
||||
var moduleClassLoader = new ModuleClassLoader("MC-BOOTSTRAP", bootstrapConfiguration, List.of(ModuleLayer.boot()));
|
||||
var layer = ModuleLayer.defineModules(bootstrapConfiguration, List.of(ModuleLayer.boot()), m -> moduleClassLoader);
|
||||
Thread.currentThread().setContextClassLoader(moduleClassLoader);
|
||||
|
||||
final var loader = ServiceLoader.load(layer.layer(), Consumer.class);
|
||||
((Consumer<String[]>) loader.stream().findFirst().orElseThrow().get()).accept(args);
|
||||
}
|
||||
|
||||
private static Map<String, Integer> getMergeFilenameMap() {
|
||||
var mergeModules = System.getProperty("mergeModules");
|
||||
if(mergeModules == null) return Map.of();
|
||||
// `mergeModules` is a semicolon-separated set of comma-separated set of paths, where each (comma) set of paths is
|
||||
// combined into a single modules
|
||||
// example: filename1.jar,filename2.jar;filename2.jar,filename3.jar
|
||||
|
||||
Map<String, Integer> filenameMap = new HashMap<>();
|
||||
int i = 0;
|
||||
for (var merge : mergeModules.split(";")) {
|
||||
var targets = merge.split(",");
|
||||
for (String target : targets) {
|
||||
filenameMap.put(target, i);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
return filenameMap;
|
||||
}
|
||||
|
||||
private record PackageTracker(Set<String> packages, Path... paths) implements BiPredicate<String, String> {
|
||||
@Override
|
||||
public boolean test(final String path, final String basePath) {
|
||||
// This method returns true if the given path is allowed within the JAR (filters out 'bad' paths)
|
||||
|
||||
if(packages.isEmpty() || // This is the first jar, nothing is claimed yet, so allow everything
|
||||
path.startsWith("META-INF/")) // Every module can have their own META-INF
|
||||
return true;
|
||||
|
||||
int idx = path.lastIndexOf('/');
|
||||
return idx < 0 || // Resources at the root are allowed to co-exist
|
||||
idx == path.length() - 1 || // All directories can have a potential to exist without conflict, we only care about real files.
|
||||
!packages.contains(path.substring(0, idx).replace('/', '.')); // If the package hasn't been used by a previous JAR
|
||||
}
|
||||
}
|
||||
|
||||
private static List<String> loadLegacyClassPath() {
|
||||
var legacyCpPath = System.getProperty("legacyClassPath.file");
|
||||
|
||||
if(legacyCpPath != null) {
|
||||
var legacyCPFileCandidatePath = Paths.get(legacyCpPath);
|
||||
if(Files.exists(legacyCPFileCandidatePath) && Files.isRegularFile(legacyCPFileCandidatePath)) {
|
||||
try {
|
||||
return Files.readAllLines(legacyCPFileCandidatePath);
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException("Failed to load the legacy class path from the specified file: " + legacyCpPath, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var legacyClasspath = System.getProperty("legacyClassPath", System.getProperty("java.class.path"));
|
||||
Objects.requireNonNull(legacyClasspath, "Missing legacyClassPath, cannot bootstrap");
|
||||
return Arrays.asList(legacyClasspath.split(File.pathSeparator));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* Magma Server
|
||||
* Copyright (C) 2019-${year}.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.magmafoundation.magma.utils;
|
||||
|
||||
import dev.vankka.dependencydownload.DependencyManager;
|
||||
import dev.vankka.dependencydownload.classpath.ClasspathAppender;
|
||||
import dev.vankka.dependencydownload.dependency.Dependency;
|
||||
import dev.vankka.dependencydownload.repository.Repository;
|
||||
import org.magmafoundation.magma.common.utils.Hash;
|
||||
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.List;
|
||||
|
||||
// Code copied from package dev.vankka.dependencydownload, all credit goes to the author
|
||||
// Check them out: https://github.com/Vankka/DependencyDownload
|
||||
public class LibHelper {
|
||||
|
||||
public static void downloadDependency(DependencyManager manager, Dependency dependency, List<Repository> repositories) throws IOException, NoSuchAlgorithmException {
|
||||
Path dependencyPath = manager.getPathForDependency(dependency, false);
|
||||
|
||||
if (!Files.exists(dependencyPath.getParent())) {
|
||||
Files.createDirectories(dependencyPath.getParent());
|
||||
}
|
||||
|
||||
if (Files.exists(dependencyPath)) {
|
||||
String fileHash = Hash.getHash(dependencyPath.toFile(), dependency.getHashingAlgorithm());
|
||||
if (!fileHash.equals(dependency.getHash()))
|
||||
Files.delete(dependencyPath);
|
||||
else return;
|
||||
}
|
||||
Files.createFile(dependencyPath);
|
||||
|
||||
RuntimeException failure = new RuntimeException("All provided repositories failed to download dependency");
|
||||
for (Repository repository : repositories) {
|
||||
try {
|
||||
MessageDigest digest = MessageDigest.getInstance(dependency.getHashingAlgorithm());
|
||||
downloadFromRepository(dependency, repository, dependencyPath, digest);
|
||||
|
||||
String hash = Hash.getHash(digest);
|
||||
String dependencyHash = dependency.getHash();
|
||||
if (!hash.equals(dependencyHash)) {
|
||||
throw new RuntimeException("Failed to verify file hash: " + hash + " should've been: " + dependencyHash);
|
||||
}
|
||||
|
||||
// Success
|
||||
return;
|
||||
} catch (Throwable e) {
|
||||
Files.deleteIfExists(dependencyPath);
|
||||
failure.addSuppressed(e);
|
||||
}
|
||||
}
|
||||
throw failure;
|
||||
}
|
||||
|
||||
public static void loadDependency(DependencyManager manager, Dependency dependency, ClasspathAppender classpathAppender) throws MalformedURLException {
|
||||
classpathAppender.appendFileToClasspath(manager.getPathForDependency(dependency, false));
|
||||
}
|
||||
|
||||
private static void downloadFromRepository(Dependency dependency, Repository repository, Path dependencyPath, MessageDigest digest) throws Throwable {
|
||||
HttpsURLConnection connection = repository.openConnection(dependency);
|
||||
|
||||
byte[] buffer = new byte[4096];
|
||||
try (BufferedInputStream inputStream = new BufferedInputStream(connection.getInputStream())) {
|
||||
try (BufferedOutputStream outputStream = new BufferedOutputStream(Files.newOutputStream(dependencyPath))) {
|
||||
int total;
|
||||
while ((total = inputStream.read(buffer)) != -1) {
|
||||
outputStream.write(buffer, 0, total);
|
||||
digest.update(buffer, 0, total);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,312 @@
|
|||
/*
|
||||
* Magma Server
|
||||
* Copyright (C) 2019-${year}.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.magmafoundation.magma.utils;
|
||||
|
||||
import io.izzel.arclight.api.Unsafe;
|
||||
import org.magmafoundation.magma.common.MagmaConstants;
|
||||
import org.magmafoundation.magma.common.utils.JarTool;
|
||||
import org.magmafoundation.magma.common.utils.SystemType;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.instrument.Instrumentation;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.module.*;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.security.AccessControlContext;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Project: Magma
|
||||
*
|
||||
* @author Malcolm (M1lc0lm)
|
||||
* @date 03.07.2022 - 17:19
|
||||
* <p>
|
||||
* Inspired and made with Shawiiz_z and Arclight (Izzel)
|
||||
*/
|
||||
public class ServerInitHelper {
|
||||
|
||||
private static final MethodHandles.Lookup IMPL_LOOKUP = Unsafe.lookup();
|
||||
private static final List<String> OPENS = new ArrayList<>();
|
||||
private static final List<String> EXPORTS = new ArrayList<>();
|
||||
private static String MODULE_PATH = null;
|
||||
|
||||
public static void init(List<String> args) {
|
||||
EXPORTS.add("cpw.mods.securejarhandler/cpw.mods.niofs.union=ALL-UNNAMED");
|
||||
EXPORTS.add("cpw.mods.securejarhandler/cpw.mods.jarhandling=ALL-UNNAMED");
|
||||
|
||||
String libsPath = JarTool.getJarDir() + File.separator + MagmaConstants.INSTALLER_LIBRARIES_FOLDER + File.separator;
|
||||
StringBuilder modulePath = new StringBuilder();
|
||||
|
||||
args.parallelStream().forEach(arg -> {
|
||||
if(arg.startsWith("-p ")) {
|
||||
MODULE_PATH = arg.substring(2).trim();
|
||||
String[] split = MODULE_PATH.split(File.pathSeparator);
|
||||
|
||||
for(String s : split) {
|
||||
if (s.startsWith("libraries/")) {
|
||||
modulePath.append(libsPath).append(s.substring("libraries/".length() - 1)).append(File.pathSeparator);
|
||||
}
|
||||
}
|
||||
} else if(arg.startsWith("--add-opens ")) {
|
||||
OPENS.add(arg.substring("--add-opens ".length()).trim());
|
||||
} else if(arg.startsWith("--add-exports ")) {
|
||||
EXPORTS.add(arg.substring("--add-exports ".length()).trim());
|
||||
} else if(arg.startsWith("-D")) {
|
||||
String[] params = arg.substring(2).split("=", 2);
|
||||
|
||||
if (params[0].equals("legacyClassPath")) {
|
||||
String[] split = params[1].split(File.pathSeparator);
|
||||
|
||||
StringBuilder tmp = new StringBuilder();
|
||||
|
||||
for (String s : split) {
|
||||
if (s.startsWith("libraries/com/mojang/brigadier"))
|
||||
continue;
|
||||
if (s.startsWith("libraries/com/mojang/datafixerupper"))
|
||||
continue;
|
||||
|
||||
if (s.startsWith("libraries/")) {
|
||||
tmp.append(libsPath).append(s.substring("libraries/".length() - 1)).append(File.pathSeparator);
|
||||
}
|
||||
}
|
||||
|
||||
System.setProperty(params[0], tmp.toString());
|
||||
} else if (params[0].equals("libraryDirectory")) {
|
||||
System.setProperty(params[0], libsPath);
|
||||
} else System.setProperty(params[0], params[1]);
|
||||
}
|
||||
});
|
||||
|
||||
MODULE_PATH = modulePath.toString();
|
||||
|
||||
try {
|
||||
loadModules(MODULE_PATH);
|
||||
Thread.sleep(500);
|
||||
addOpens(OPENS);
|
||||
addExports(EXPORTS);
|
||||
Thread.sleep(500);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
//Code snipped from (https://github.com/IzzelAliz/Arclight/blob/f98046185ebfc183a242ac5497619dc35d741042/forge-installer/src/main/java/io/izzel/arclight/forgeinstaller/ForgeInstaller.java)
|
||||
|
||||
public static void addToPath(Path path) {
|
||||
ClassLoader loader = Thread.currentThread().getContextClassLoader();
|
||||
try {
|
||||
Field ucpField;
|
||||
try {
|
||||
ucpField = loader.getClass().getDeclaredField("ucp");
|
||||
} catch (NoSuchFieldException e) {
|
||||
ucpField = loader.getClass().getSuperclass().getDeclaredField("ucp");
|
||||
}
|
||||
long offset = Unsafe.objectFieldOffset(ucpField);
|
||||
Object ucp = Unsafe.getObject(loader, offset);
|
||||
if(ucp == null) {
|
||||
var cl = Class.forName("jdk.internal.loader.URLClassPath");
|
||||
var handle = Unsafe.lookup().findConstructor(cl, MethodType.methodType(void.class, URL[].class, AccessControlContext.class));
|
||||
ucp = handle.invoke(new URL[]{}, (AccessControlContext) null);
|
||||
Unsafe.putObjectVolatile(loader, offset, ucp);
|
||||
}
|
||||
Method method = ucp.getClass().getDeclaredMethod("addURL", URL.class);
|
||||
Unsafe.lookup().unreflect(method).invoke(ucp, path.toUri().toURL());
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void agentmain(final String a, final Instrumentation inst) {
|
||||
}
|
||||
|
||||
public static void premain(String agentArgs, Instrumentation inst) {
|
||||
}
|
||||
|
||||
public static void addExports(String module, String pkg, String target) {
|
||||
if(target == null) target = "ALL-UNNAMED";
|
||||
|
||||
try {
|
||||
addExports(List.of(module + "/" + pkg + "=" + target));
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static void addExports(List<String> exports) throws Throwable {
|
||||
MethodHandle implAddExportsMH = IMPL_LOOKUP.findVirtual(Module.class, "implAddExports", MethodType.methodType(void.class, String.class, Module.class));
|
||||
MethodHandle implAddExportsToAllUnnamedMH = IMPL_LOOKUP.findVirtual(Module.class, "implAddExportsToAllUnnamed", MethodType.methodType(void.class, String.class));
|
||||
|
||||
addExtra(exports, implAddExportsMH, implAddExportsToAllUnnamedMH);
|
||||
}
|
||||
|
||||
public static void addOpens(String module, String pkg, String target) {
|
||||
if(target == null) target = "ALL-UNNAMED";
|
||||
|
||||
try {
|
||||
addOpens(List.of(module + "/" + pkg + "=" + target));
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static void addOpens(List<String> opens) throws Throwable {
|
||||
MethodHandle implAddOpensMH = IMPL_LOOKUP.findVirtual(Module.class, "implAddOpens", MethodType.methodType(void.class, String.class, Module.class));
|
||||
MethodHandle implAddOpensToAllUnnamedMH = IMPL_LOOKUP.findVirtual(Module.class, "implAddOpensToAllUnnamed", MethodType.methodType(void.class, String.class));
|
||||
|
||||
addExtra(opens, implAddOpensMH, implAddOpensToAllUnnamedMH);
|
||||
}
|
||||
|
||||
private static ParserData parseModuleExtra(String extra) {
|
||||
String[] all = extra.split("=", 2);
|
||||
if(all.length < 2) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String[] source = all[0].split("/", 2);
|
||||
if(source.length < 2) {
|
||||
return null;
|
||||
}
|
||||
return new ParserData(source[0], source[1], all[1]);
|
||||
}
|
||||
|
||||
private record ParserData(String module, String packages, String target) {
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if(obj == this) return true;
|
||||
if(obj == null || obj.getClass() != this.getClass()) return false;
|
||||
var that = (ParserData) obj;
|
||||
return Objects.equals(this.module, that.module) && Objects.equals(this.packages, that.packages) && Objects.equals(this.target, that.target);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ParserData[" + "module=" + module + ", " + "packages=" + packages + ", " + "target=" + target + ']';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static void addExtra(List<String> extras, MethodHandle implAddExtraMH, MethodHandle implAddExtraToAllUnnamedMH) {
|
||||
extras.parallelStream().parallel().forEach(extra -> {
|
||||
ParserData data = parseModuleExtra(extra);
|
||||
if(data != null) {
|
||||
ModuleLayer.boot().findModule(data.module).ifPresent(m -> {
|
||||
try {
|
||||
if("ALL-UNNAMED".equals(data.target)) {
|
||||
implAddExtraToAllUnnamedMH.invokeWithArguments(m, data.packages);
|
||||
//System.out.println("Added extra to all unnamed modules: " + data);
|
||||
} else {
|
||||
ModuleLayer.boot().findModule(data.target).ifPresent(tm -> {
|
||||
try {
|
||||
implAddExtraMH.invokeWithArguments(m, data.packages, tm);
|
||||
//System.out.println("Added extra: " + data);
|
||||
} catch (Throwable t) {
|
||||
throw new RuntimeException(t);
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
throw new RuntimeException(t);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void loadModules(String modulePath) throws Throwable {
|
||||
// Find all extra modules
|
||||
ModuleFinder finder = ModuleFinder.of(Arrays.stream(modulePath.split(SystemType.getOS() == SystemType.OS.WINDOWS ? ";" : ":")).map(Paths::get).peek(ServerInitHelper::addToPath).toArray(Path[]::new));
|
||||
MethodHandle loadModuleMH = IMPL_LOOKUP.findVirtual(Class.forName("jdk.internal.loader.BuiltinClassLoader"), "loadModule", MethodType.methodType(void.class, ModuleReference.class));
|
||||
|
||||
// Resolve modules to a new config
|
||||
Configuration config = Configuration.resolveAndBind(finder, List.of(ModuleLayer.boot().configuration()), finder, finder.findAll().stream().peek(mref -> {
|
||||
try {
|
||||
// Load all extra modules in system class loader (unnamed modules for now)
|
||||
loadModuleMH.invokeWithArguments(Thread.currentThread().getContextClassLoader(), mref);
|
||||
} catch (Throwable e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}).map(ModuleReference::descriptor).map(ModuleDescriptor::name).collect(Collectors.toList()));
|
||||
|
||||
// Copy the new config graph to boot module layer config
|
||||
MethodHandle graphGetter = IMPL_LOOKUP.findGetter(Configuration.class, "graph", Map.class);
|
||||
HashMap<ResolvedModule, Set<ResolvedModule>> graphMap = new HashMap<>((Map<ResolvedModule, Set<ResolvedModule>>) graphGetter.invokeWithArguments(config));
|
||||
MethodHandle cfSetter = IMPL_LOOKUP.findSetter(ResolvedModule.class, "cf", Configuration.class);
|
||||
// Reset all extra resolved modules config to boot module layer config
|
||||
graphMap.forEach((k, v) -> {
|
||||
try {
|
||||
cfSetter.invokeWithArguments(k, ModuleLayer.boot().configuration());
|
||||
v.forEach(m -> {
|
||||
try {
|
||||
cfSetter.invokeWithArguments(m, ModuleLayer.boot().configuration());
|
||||
} catch (Throwable e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
} catch (Throwable e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
graphMap.putAll((Map<ResolvedModule, Set<ResolvedModule>>) graphGetter.invokeWithArguments(ModuleLayer.boot().configuration()));
|
||||
IMPL_LOOKUP.findSetter(Configuration.class, "graph", Map.class).invokeWithArguments(ModuleLayer.boot().configuration(), new HashMap<>(graphMap));
|
||||
|
||||
// Reset boot module layer resolved modules as new config resolved modules to prepare define modules
|
||||
Set<ResolvedModule> oldBootModules = ModuleLayer.boot().configuration().modules();
|
||||
MethodHandle modulesSetter = IMPL_LOOKUP.findSetter(Configuration.class, "modules", Set.class);
|
||||
HashSet<ResolvedModule> modulesSet = new HashSet<>(config.modules());
|
||||
modulesSetter.invokeWithArguments(ModuleLayer.boot().configuration(), new HashSet<>(modulesSet));
|
||||
|
||||
// Prepare to add all of the new config "nameToModule" to boot module layer config
|
||||
MethodHandle nameToModuleGetter = IMPL_LOOKUP.findGetter(Configuration.class, "nameToModule", Map.class);
|
||||
HashMap<String, ResolvedModule> nameToModuleMap = new HashMap<>((Map<String, ResolvedModule>) nameToModuleGetter.invokeWithArguments(ModuleLayer.boot().configuration()));
|
||||
nameToModuleMap.putAll((Map<String, ResolvedModule>) nameToModuleGetter.invokeWithArguments(config));
|
||||
IMPL_LOOKUP.findSetter(Configuration.class, "nameToModule", Map.class).invokeWithArguments(ModuleLayer.boot().configuration(), new HashMap<>(nameToModuleMap));
|
||||
|
||||
// Define all extra modules and add all of the new config "nameToModule" to boot module layer config
|
||||
((Map<String, Module>) IMPL_LOOKUP.findGetter(ModuleLayer.class, "nameToModule", Map.class).invokeWithArguments(ModuleLayer.boot())).putAll((Map<String, Module>) IMPL_LOOKUP.findStatic(Module.class, "defineModules", MethodType.methodType(Map.class, Configuration.class, Function.class, ModuleLayer.class)).invokeWithArguments(ModuleLayer.boot().configuration(), (Function<String, ClassLoader>) name -> Thread.currentThread().getContextClassLoader(), ModuleLayer.boot()));
|
||||
|
||||
// Add all of resolved modules
|
||||
modulesSet.addAll(oldBootModules);
|
||||
modulesSetter.invokeWithArguments(ModuleLayer.boot().configuration(), new HashSet<>(modulesSet));
|
||||
|
||||
// Reset cache of boot module layer
|
||||
IMPL_LOOKUP.findSetter(ModuleLayer.class, "modules", Set.class).invokeWithArguments(ModuleLayer.boot(), null);
|
||||
IMPL_LOOKUP.findSetter(ModuleLayer.class, "servicesCatalog", Class.forName("jdk.internal.module.ServicesCatalog")).invokeWithArguments(ModuleLayer.boot(), null);
|
||||
|
||||
// Add reads from extra modules to jdk modules
|
||||
MethodHandle implAddReadsMH = IMPL_LOOKUP.findVirtual(Module.class, "implAddReads", MethodType.methodType(void.class, Module.class));
|
||||
config.modules().forEach(rm -> ModuleLayer.boot().findModule(rm.name()).ifPresent(m -> oldBootModules.forEach(brm -> ModuleLayer.boot().findModule(brm.name()).ifPresent(bm -> {
|
||||
try {
|
||||
implAddReadsMH.invokeWithArguments(m, bm);
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
}))));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<html>
|
||||
<head><title>Index of /mirror/src/Magma-1-20-x/magmalauncher/src/main/java/org/magmafoundation/magma/utils/</title></head>
|
||||
<body>
|
||||
<h1>Index of /mirror/src/Magma-1-20-x/magmalauncher/src/main/java/org/magmafoundation/magma/utils/</h1><hr><pre><a href="../">../</a>
|
||||
<a href="BootstrapLauncher.java">BootstrapLauncher.java</a> 07-Oct-2023 14:12 6730
|
||||
<a href="LibHelper.java">LibHelper.java</a> 07-Oct-2023 14:12 4212
|
||||
<a href="ServerInitHelper.java">ServerInitHelper.java</a> 07-Oct-2023 14:12 15K
|
||||
</pre><hr><script defer src="https://static.cloudflareinsights.com/beacon.min.js/v84a3a4012de94ce1a686ba8c167c359c1696973893317" integrity="sha512-euoFGowhlaLqXsPWQ48qSkBSCFs3DPRyiwVu3FjR96cMPx+Fr+gpWRhIafcHwqwCqWS42RZhIudOvEI+Ckf6MA==" nonce="edcd55dcee79221aa931f861b2d1082f" data-cf-beacon='{"rayId":"85f0271c1a3d1c5c","version":"2024.2.4","r":1,"token":"583109dda43e47a593fd006526a81120","b":1}' crossorigin="anonymous"></script>
|
||||
</body>
|
||||
</html>
|
Loading…
Add table
Add a link
Reference in a new issue