mirror of
https://github.com/GravitLauncher/Launcher
synced 2025-03-30 21:18:17 +03:00
[FEATURE][EXPERIMENTAL] ServerWrapper launch methods
This commit is contained in:
parent
7cedaef90a
commit
be565e2218
9 changed files with 188 additions and 35 deletions
|
@ -516,7 +516,7 @@ public enum SecurityManagerConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum ClassLoaderConfig {
|
public enum ClassLoaderConfig {
|
||||||
AGENT, LAUNCHER, SYSTEM_ARGS
|
AGENT, LAUNCHER, MODULE, SYSTEM_ARGS
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum SignedClientConfig {
|
public enum SignedClientConfig {
|
||||||
|
|
|
@ -14,16 +14,37 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
java11 {
|
||||||
|
java {
|
||||||
|
srcDirs = ['src/main/java11']
|
||||||
|
}
|
||||||
|
dependencies {
|
||||||
|
java11Implementation project(':LauncherAPI')
|
||||||
|
java11Implementation files(sourceSets.main.output.classesDirs) { builtBy compileJava }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sourceCompatibility = '1.8'
|
sourceCompatibility = '1.8'
|
||||||
targetCompatibility = '1.8'
|
targetCompatibility = '1.8'
|
||||||
|
|
||||||
|
compileJava11Java {
|
||||||
|
sourceCompatibility = 11
|
||||||
|
targetCompatibility = 11
|
||||||
|
}
|
||||||
|
|
||||||
jar {
|
jar {
|
||||||
|
into('META-INF/versions/11') {
|
||||||
|
from sourceSets.java11.output
|
||||||
|
}
|
||||||
archiveClassifier.set('clean')
|
archiveClassifier.set('clean')
|
||||||
manifest.attributes("Main-Class": mainClassName,
|
manifest.attributes("Main-Class": mainClassName,
|
||||||
"Premain-Class": mainAgentName,
|
"Premain-Class": mainAgentName,
|
||||||
"Can-Redefine-Classes": "true",
|
"Can-Redefine-Classes": "true",
|
||||||
"Can-Retransform-Classes": "true",
|
"Can-Retransform-Classes": "true",
|
||||||
"Can-Set-Native-Method-Prefix": "true")
|
"Can-Set-Native-Method-Prefix": "true",
|
||||||
|
"Multi-Release": "true")
|
||||||
}
|
}
|
||||||
|
|
||||||
task sourcesJar(type: Jar) {
|
task sourcesJar(type: Jar) {
|
||||||
|
|
|
@ -18,6 +18,10 @@
|
||||||
import pro.gravit.launcher.request.auth.RestoreRequest;
|
import pro.gravit.launcher.request.auth.RestoreRequest;
|
||||||
import pro.gravit.launcher.request.update.ProfilesRequest;
|
import pro.gravit.launcher.request.update.ProfilesRequest;
|
||||||
import pro.gravit.launcher.request.websockets.StdWebSocketService;
|
import pro.gravit.launcher.request.websockets.StdWebSocketService;
|
||||||
|
import pro.gravit.launcher.server.launch.ClasspathLaunch;
|
||||||
|
import pro.gravit.launcher.server.launch.Launch;
|
||||||
|
import pro.gravit.launcher.server.launch.ModuleLaunch;
|
||||||
|
import pro.gravit.launcher.server.launch.SimpleLaunch;
|
||||||
import pro.gravit.launcher.server.setup.ServerWrapperSetup;
|
import pro.gravit.launcher.server.setup.ServerWrapperSetup;
|
||||||
import pro.gravit.utils.PublicURLClassLoader;
|
import pro.gravit.utils.PublicURLClassLoader;
|
||||||
import pro.gravit.utils.helper.IOHelper;
|
import pro.gravit.utils.helper.IOHelper;
|
||||||
|
@ -139,22 +143,6 @@ public void run(String... args) throws Throwable {
|
||||||
LogHelper.error("Auth not configured. Please use 'java -jar ServerWrapper.jar setup'");
|
LogHelper.error("Auth not configured. Please use 'java -jar ServerWrapper.jar setup'");
|
||||||
System.exit(-1);
|
System.exit(-1);
|
||||||
}
|
}
|
||||||
Class<?> mainClass;
|
|
||||||
if (config.classpath != null && !config.classpath.isEmpty()) {
|
|
||||||
if(config.classLoaderConfig == ClientProfile.ClassLoaderConfig.LAUNCHER) {
|
|
||||||
URL[] urls = config.classpath.stream().map(Paths::get).map(IOHelper::toURL).toArray(URL[]::new);
|
|
||||||
ucp = new PublicURLClassLoader(urls);
|
|
||||||
Thread.currentThread().setContextClassLoader(ucp);
|
|
||||||
loader = ucp;
|
|
||||||
} else if(config.classLoaderConfig == ClientProfile.ClassLoaderConfig.AGENT) {
|
|
||||||
if (!ServerAgent.isAgentStarted()) {
|
|
||||||
LogHelper.error("JavaAgent not found");
|
|
||||||
System.exit(-1);
|
|
||||||
}
|
|
||||||
for (String c : config.classpath)
|
|
||||||
ServerAgent.addJVMClassPath(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (config.autoloadLibraries) {
|
if (config.autoloadLibraries) {
|
||||||
if (!ServerAgent.isAgentStarted()) {
|
if (!ServerAgent.isAgentStarted()) {
|
||||||
throw new UnsupportedOperationException("JavaAgent not found, autoloadLibraries not available");
|
throw new UnsupportedOperationException("JavaAgent not found, autoloadLibraries not available");
|
||||||
|
@ -165,24 +153,34 @@ public void run(String... args) throws Throwable {
|
||||||
LogHelper.info("Load libraries");
|
LogHelper.info("Load libraries");
|
||||||
ServerAgent.loadLibraries(librariesDir);
|
ServerAgent.loadLibraries(librariesDir);
|
||||||
}
|
}
|
||||||
if (loader != null) mainClass = Class.forName(classname, true, loader);
|
|
||||||
else mainClass = Class.forName(classname);
|
|
||||||
MethodHandle mainMethod = MethodHandles.lookup().findStatic(mainClass, "main", MethodType.methodType(void.class, String[].class));
|
|
||||||
LogHelper.info("ServerWrapper: LaunchServer address: %s. Title: %s", config.address, Launcher.profile != null ? Launcher.profile.getTitle() : "unknown");
|
LogHelper.info("ServerWrapper: LaunchServer address: %s. Title: %s", config.address, Launcher.profile != null ? Launcher.profile.getTitle() : "unknown");
|
||||||
LogHelper.info("Minecraft Version (for profile): %s", wrapper.profile == null ? "unknown" : wrapper.profile.getVersion().name);
|
LogHelper.info("Minecraft Version (for profile): %s", wrapper.profile == null ? "unknown" : wrapper.profile.getVersion().name);
|
||||||
LogHelper.info("Start Minecraft Server");
|
String[] real_args;
|
||||||
LogHelper.debug("Invoke main method %s", mainClass.getName());
|
if (args.length > 0) {
|
||||||
if (config.args == null) {
|
real_args = new String[args.length - 1];
|
||||||
String[] real_args;
|
System.arraycopy(args, 1, real_args, 0, args.length - 1);
|
||||||
if (args.length > 0) {
|
} else real_args = args;
|
||||||
real_args = new String[args.length - 1];
|
Launch launch;
|
||||||
System.arraycopy(args, 1, real_args, 0, args.length - 1);
|
switch (config.classLoaderConfig) {
|
||||||
} else real_args = args;
|
case LAUNCHER:
|
||||||
|
launch = new ClasspathLaunch();
|
||||||
mainMethod.invoke(real_args);
|
break;
|
||||||
} else {
|
case MODULE:
|
||||||
mainMethod.invoke(config.args.toArray(new String[0]));
|
launch = new ModuleLaunch();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
launch = new SimpleLaunch();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
LogHelper.info("Start Minecraft Server");
|
||||||
|
LogHelper.debug("Invoke main method %s with %s", config.mainclass, launch.getClass().getName());
|
||||||
|
try {
|
||||||
|
launch.run(config, real_args);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
LogHelper.error(e);
|
||||||
|
System.exit(-1);
|
||||||
|
}
|
||||||
|
System.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateLauncherConfig() {
|
public void updateLauncherConfig() {
|
||||||
|
@ -231,8 +229,15 @@ public static final class Config {
|
||||||
public long oauthExpireTime;
|
public long oauthExpireTime;
|
||||||
public Map<String, String> extendedTokens;
|
public Map<String, String> extendedTokens;
|
||||||
public LauncherConfig.LauncherEnvironment env;
|
public LauncherConfig.LauncherEnvironment env;
|
||||||
|
public ModuleConf moduleConf = new ModuleConf();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class WebSocketConf {
|
public static final class ModuleConf {
|
||||||
|
public List<String> modules = new ArrayList<>();
|
||||||
|
public List<String> modulePath = new ArrayList<>();
|
||||||
|
public String mainModule = "";
|
||||||
|
public Map<String, String> exports = new HashMap<>();
|
||||||
|
public Map<String, String> opens = new HashMap<>();
|
||||||
|
public Map<String, String> reads = new HashMap<>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
package pro.gravit.launcher.server.launch;
|
||||||
|
|
||||||
|
import pro.gravit.launcher.server.ServerWrapper;
|
||||||
|
import pro.gravit.utils.PublicURLClassLoader;
|
||||||
|
import pro.gravit.utils.helper.IOHelper;
|
||||||
|
|
||||||
|
import java.lang.invoke.MethodHandle;
|
||||||
|
import java.lang.invoke.MethodHandles;
|
||||||
|
import java.lang.invoke.MethodType;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
|
||||||
|
public class ClasspathLaunch implements Launch {
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("ConfusingArgumentToVarargsMethod")
|
||||||
|
public void run(ServerWrapper.Config config, String[] args) throws Throwable {
|
||||||
|
URL[] urls = config.classpath.stream().map(Paths::get).map(IOHelper::toURL).toArray(URL[]::new);
|
||||||
|
ClassLoader ucl = new PublicURLClassLoader(urls);
|
||||||
|
Class<?> mainClass = Class.forName(config.mainclass, true, ucl);
|
||||||
|
MethodHandle mainMethod = MethodHandles.lookup().findStatic(mainClass, "main", MethodType.methodType(void.class, String[].class));
|
||||||
|
mainMethod.invoke(args);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package pro.gravit.launcher.server.launch;
|
||||||
|
|
||||||
|
import pro.gravit.launcher.server.ServerWrapper;
|
||||||
|
|
||||||
|
public interface Launch {
|
||||||
|
void run(ServerWrapper.Config config, String[] args) throws Throwable;
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package pro.gravit.launcher.server.launch;
|
||||||
|
|
||||||
|
import pro.gravit.launcher.server.ServerWrapper;
|
||||||
|
|
||||||
|
public class ModuleLaunch implements Launch {
|
||||||
|
@Override
|
||||||
|
public void run(ServerWrapper.Config config, String[] args) throws Throwable {
|
||||||
|
throw new UnsupportedOperationException("Module system not supported");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
package pro.gravit.launcher.server.launch;
|
||||||
|
|
||||||
|
import pro.gravit.launcher.server.ServerWrapper;
|
||||||
|
|
||||||
|
import java.lang.invoke.MethodHandle;
|
||||||
|
import java.lang.invoke.MethodHandles;
|
||||||
|
import java.lang.invoke.MethodType;
|
||||||
|
|
||||||
|
public class SimpleLaunch implements Launch {
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("ConfusingArgumentToVarargsMethod")
|
||||||
|
public void run(ServerWrapper.Config config, String[] args) throws Throwable {
|
||||||
|
Class<?> mainClass = Class.forName(config.mainclass);
|
||||||
|
MethodHandle mainMethod = MethodHandles.lookup().findStatic(mainClass, "main", MethodType.methodType(void.class, String[].class));
|
||||||
|
mainMethod.invoke(args);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
package pro.gravit.launcher.server.launch;
|
||||||
|
|
||||||
|
import pro.gravit.launcher.server.ServerWrapper;
|
||||||
|
import pro.gravit.utils.PublicURLClassLoader;
|
||||||
|
import pro.gravit.utils.helper.IOHelper;
|
||||||
|
|
||||||
|
import java.lang.invoke.MethodHandle;
|
||||||
|
import java.lang.invoke.MethodHandles;
|
||||||
|
import java.lang.invoke.MethodType;
|
||||||
|
import java.lang.module.Configuration;
|
||||||
|
import java.lang.module.ModuleFinder;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class ModuleLaunch implements Launch {
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("ConfusingArgumentToVarargsMethod")
|
||||||
|
public void run(ServerWrapper.Config config, String[] args) throws Throwable {
|
||||||
|
URL[] urls = config.classpath.stream().map(Paths::get).map(IOHelper::toURL).toArray(URL[]::new);
|
||||||
|
ClassLoader ucl = new PublicURLClassLoader(urls);
|
||||||
|
// Create Module Layer
|
||||||
|
ModuleFinder finder = ModuleFinder.of(config.moduleConf.modulePath.stream().map(Paths::get).toArray(Path[]::new));
|
||||||
|
ModuleLayer bootLayer = ModuleLayer.boot();
|
||||||
|
Configuration configuration = bootLayer.configuration()
|
||||||
|
.resolveAndBind(ModuleFinder.of(), finder, config.moduleConf.modules);
|
||||||
|
ModuleLayer.Controller controller = ModuleLayer.defineModulesWithOneLoader(configuration, List.of(bootLayer), ucl);
|
||||||
|
ModuleLayer layer = controller.layer();
|
||||||
|
// Configure exports / opens
|
||||||
|
for(var e : config.moduleConf.exports.entrySet()) {
|
||||||
|
String[] split = e.getKey().split("\\\\");
|
||||||
|
Module source = layer.findModule(split[0]).orElseThrow();
|
||||||
|
String pkg = split[1];
|
||||||
|
Module target = layer.findModule(e.getValue()).orElseThrow();
|
||||||
|
controller.addExports(source, pkg, target);
|
||||||
|
}
|
||||||
|
for(var e : config.moduleConf.opens.entrySet()) {
|
||||||
|
String[] split = e.getKey().split("\\\\");
|
||||||
|
Module source = layer.findModule(split[0]).orElseThrow();
|
||||||
|
String pkg = split[1];
|
||||||
|
Module target = layer.findModule(e.getValue()).orElseThrow();
|
||||||
|
controller.addOpens(source, pkg, target);
|
||||||
|
}
|
||||||
|
for(var e : config.moduleConf.reads.entrySet()) {
|
||||||
|
Module source = layer.findModule(e.getKey()).orElseThrow();
|
||||||
|
Module target = layer.findModule(e.getValue()).orElseThrow();
|
||||||
|
controller.addReads(source, target);
|
||||||
|
}
|
||||||
|
Module mainModule = layer.findModule(config.moduleConf.mainModule).orElseThrow();
|
||||||
|
Module unnamed = ModuleLaunch.class.getClassLoader().getUnnamedModule();
|
||||||
|
if(unnamed != null) {
|
||||||
|
controller.addOpens(mainModule, getPackageFromClass(config.mainclass), unnamed);
|
||||||
|
}
|
||||||
|
// Start main class
|
||||||
|
ClassLoader loader = mainModule.getClassLoader();
|
||||||
|
Class<?> mainClass = Class.forName(config.mainclass, true, loader);
|
||||||
|
MethodHandle mainMethod = MethodHandles.lookup().findStatic(mainClass, "main", MethodType.methodType(void.class, String[].class));
|
||||||
|
mainMethod.invoke(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getPackageFromClass(String clazz) {
|
||||||
|
int index = clazz.indexOf(".");
|
||||||
|
if(index >= 0) {
|
||||||
|
return clazz.substring(0, index);
|
||||||
|
}
|
||||||
|
return clazz;
|
||||||
|
}
|
||||||
|
}
|
2
modules
2
modules
|
@ -1 +1 @@
|
||||||
Subproject commit a1318b09c1f5657ad60eaee362746cd493d38c8a
|
Subproject commit 2d9466cd82b1a6c916f045851021585e6e831bd5
|
Loading…
Reference in a new issue