Upload magma

This commit is contained in:
Diamond Creeper 2024-03-04 21:16:02 +13:00
commit dfa9ee0b24
5008 changed files with 653442 additions and 0 deletions

View 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")
}
}
}

9
magmalauncher/index.html Normal file
View 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>

View 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>

View 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>

View 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>

View 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>

View file

@ -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>

View file

@ -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;
}
}

View file

@ -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>

View file

@ -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;
}
}
}

View file

@ -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();
}
}
}
}

View file

@ -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");
}
}
}

View file

@ -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>

View file

@ -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!");
}
}

View file

@ -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>

View file

@ -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));
}
}

View file

@ -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);
}
}
}
}
}

View file

@ -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) {
}
}))));
}
}

View file

@ -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>