mirror of
https://github.com/GravitLauncher/Launcher
synced 2024-12-22 16:41:46 +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 {
|
||||
AGENT, LAUNCHER, SYSTEM_ARGS
|
||||
AGENT, LAUNCHER, MODULE, SYSTEM_ARGS
|
||||
}
|
||||
|
||||
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'
|
||||
targetCompatibility = '1.8'
|
||||
|
||||
compileJava11Java {
|
||||
sourceCompatibility = 11
|
||||
targetCompatibility = 11
|
||||
}
|
||||
|
||||
jar {
|
||||
into('META-INF/versions/11') {
|
||||
from sourceSets.java11.output
|
||||
}
|
||||
archiveClassifier.set('clean')
|
||||
manifest.attributes("Main-Class": mainClassName,
|
||||
"Premain-Class": mainAgentName,
|
||||
"Can-Redefine-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) {
|
||||
|
|
|
@ -18,6 +18,10 @@
|
|||
import pro.gravit.launcher.request.auth.RestoreRequest;
|
||||
import pro.gravit.launcher.request.update.ProfilesRequest;
|
||||
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.utils.PublicURLClassLoader;
|
||||
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'");
|
||||
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 (!ServerAgent.isAgentStarted()) {
|
||||
throw new UnsupportedOperationException("JavaAgent not found, autoloadLibraries not available");
|
||||
|
@ -165,24 +153,34 @@ public void run(String... args) throws Throwable {
|
|||
LogHelper.info("Load libraries");
|
||||
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("Minecraft Version (for profile): %s", wrapper.profile == null ? "unknown" : wrapper.profile.getVersion().name);
|
||||
LogHelper.info("Start Minecraft Server");
|
||||
LogHelper.debug("Invoke main method %s", mainClass.getName());
|
||||
if (config.args == null) {
|
||||
String[] real_args;
|
||||
if (args.length > 0) {
|
||||
real_args = new String[args.length - 1];
|
||||
System.arraycopy(args, 1, real_args, 0, args.length - 1);
|
||||
} else real_args = args;
|
||||
|
||||
mainMethod.invoke(real_args);
|
||||
} else {
|
||||
mainMethod.invoke(config.args.toArray(new String[0]));
|
||||
String[] real_args;
|
||||
if (args.length > 0) {
|
||||
real_args = new String[args.length - 1];
|
||||
System.arraycopy(args, 1, real_args, 0, args.length - 1);
|
||||
} else real_args = args;
|
||||
Launch launch;
|
||||
switch (config.classLoaderConfig) {
|
||||
case LAUNCHER:
|
||||
launch = new ClasspathLaunch();
|
||||
break;
|
||||
case MODULE:
|
||||
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() {
|
||||
|
@ -231,8 +229,15 @@ public static final class Config {
|
|||
public long oauthExpireTime;
|
||||
public Map<String, String> extendedTokens;
|
||||
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