diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index aec14a00..b9cd5e3f 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -35,10 +35,12 @@ jobs: run: | mkdir -p artifacts/modules cd LaunchServer/build/libs + mv proguard proguard-libraries zip -r -9 ../../../artifacts/libraries.zip * -x "LaunchServer.jar" -x "LaunchServer-clean.jar" cp LaunchServer.jar ../../../artifacts/LaunchServer.jar cd ../../.. cp ServerWrapper/build/libs/ServerWrapper.jar artifacts/ServerWrapper.jar + cp ServerWrapper/build/libs/ServerWrapper-inline.jar artifacts/ServerWrapperInline.jar cp LauncherAuthlib/build/libs/LauncherAuthlib.jar artifacts/LauncherAuthlib.jar || true cp modules/*_module/build/libs/*.jar artifacts/modules || true cp modules/*_lmodule/build/libs/*.jar artifacts/modules || true diff --git a/Launcher/src/main/java/pro/gravit/launcher/runtime/debug/DebugMain.java b/Launcher/src/main/java/pro/gravit/launcher/runtime/debug/DebugMain.java index 1d3ee6c3..cecb2f28 100644 --- a/Launcher/src/main/java/pro/gravit/launcher/runtime/debug/DebugMain.java +++ b/Launcher/src/main/java/pro/gravit/launcher/runtime/debug/DebugMain.java @@ -28,6 +28,7 @@ public class DebugMain { public static String webSocketURL = System.getProperty("launcherdebug.websocket", "ws://localhost:9274/api"); public static String projectName = System.getProperty("launcherdebug.projectname", "Minecraft"); public static String unlockSecret = System.getProperty("launcherdebug.unlocksecret", ""); + public static boolean disableConsole = Boolean.getBoolean("launcherdebug.disableConsole"); public static boolean offlineMode = Boolean.getBoolean("launcherdebug.offlinemode"); public static boolean disableAutoRefresh = Boolean.getBoolean("launcherdebug.disableautorefresh"); public static String[] moduleClasses = System.getProperty("launcherdebug.modules", "").split(","); @@ -37,6 +38,14 @@ public class DebugMain { public static void main(String[] args) throws Throwable { LogHelper.printVersion("Launcher"); LogHelper.printLicense("Launcher"); + initialize(); + LogHelper.debug("Initialization LauncherEngine"); + LauncherEngine instance = LauncherEngine.newInstance(false, ClientRuntimeProvider.class); + instance.start(args); + LauncherEngine.exitLauncher(0); + } + + public static void initialize() throws Exception { IS_DEBUG.set(true); LogHelper.info("Launcher start in DEBUG mode (Only for developers)"); LogHelper.debug("Initialization LauncherConfig"); @@ -56,7 +65,9 @@ public static void main(String[] args) throws Throwable { } LauncherEngine.modulesManager.initModules(null); LauncherEngine.initGson(LauncherEngine.modulesManager); - ConsoleManager.initConsole(); + if(!disableConsole) { + ConsoleManager.initConsole(); + } LauncherEngine.modulesManager.invokeEvent(new PreConfigPhase()); RequestService service; if (offlineMode) { @@ -72,10 +83,6 @@ public static void main(String[] args) throws Throwable { if(!disableAutoRefresh) { Request.startAutoRefresh(); } - LogHelper.debug("Initialization LauncherEngine"); - LauncherEngine instance = LauncherEngine.newInstance(false, ClientRuntimeProvider.class); - instance.start(args); - LauncherEngine.exitLauncher(0); } @SuppressWarnings("unchecked") diff --git a/Launcher/src/main/java/pro/gravit/launcher/runtime/debug/DebugMainInlineInitializer.java b/Launcher/src/main/java/pro/gravit/launcher/runtime/debug/DebugMainInlineInitializer.java new file mode 100644 index 00000000..2686344f --- /dev/null +++ b/Launcher/src/main/java/pro/gravit/launcher/runtime/debug/DebugMainInlineInitializer.java @@ -0,0 +1,7 @@ +package pro.gravit.launcher.runtime.debug; + +public class DebugMainInlineInitializer { + public static void run() throws Exception { + DebugMain.initialize(); + } +} diff --git a/LauncherClient/src/main/java/pro/gravit/launcher/client/ClientLauncherEntryPoint.java b/LauncherClient/src/main/java/pro/gravit/launcher/client/ClientLauncherEntryPoint.java index 65dcb764..d38100b3 100644 --- a/LauncherClient/src/main/java/pro/gravit/launcher/client/ClientLauncherEntryPoint.java +++ b/LauncherClient/src/main/java/pro/gravit/launcher/client/ClientLauncherEntryPoint.java @@ -116,15 +116,6 @@ private static void realMain(String[] args) throws Throwable { // Verify ClientLauncher sign and classpath LogHelper.debug("Verifying ClientLauncher sign and classpath"); - Set ignoredPath = new HashSet<>(); - List classpath = resolveClassPath(ignoredPath, clientDir, params.actions, params.profile) - .collect(Collectors.toCollection(ArrayList::new)); - if(LogHelper.isDevEnabled()) { - for(var e : classpath) { - LogHelper.dev("Classpath entry %s", e); - } - } - List classpathURLs = classpath.stream().map(IOHelper::toURL).toList(); // Start client with WatchService monitoring RequestService service; if (params.offlineMode) { @@ -158,6 +149,18 @@ private static void realMain(String[] args) throws Throwable { System.load(Paths.get(params.nativesDir).resolve(ClientService.findLibrary(e)).toAbsolutePath().toString()); } } + Set ignoredPath = new HashSet<>(); + if(options.moduleConf != null && options.moduleConf.modulePath != null) { + List resolvedModulePath = resolveClassPath(ignoredPath, clientDir, null, params.profile).toList(); + } + List classpath = resolveClassPath(ignoredPath, clientDir, params.actions, params.profile) + .collect(Collectors.toCollection(ArrayList::new)); + if(LogHelper.isDevEnabled()) { + for(var e : classpath) { + LogHelper.dev("Classpath entry %s", e); + } + } + List classpathURLs = classpath.stream().map(IOHelper::toURL).toList(); if (classLoaderConfig == ClientProfile.ClassLoaderConfig.LAUNCHER || classLoaderConfig == ClientProfile.ClassLoaderConfig.MODULE) { if(JVMHelper.JVM_VERSION <= 11) { launch = new LegacyLaunch(); @@ -274,9 +277,11 @@ private static Stream resolveClassPathStream(Set ignorePaths, Path c public static Stream resolveClassPath(Set ignorePaths, Path clientDir, Set actions, ClientProfile profile) throws IOException { Stream result = resolveClassPathStream(ignorePaths, clientDir, profile.getClassPath()); - for (OptionalAction a : actions) { - if (a instanceof OptionalActionClassPath) - result = Stream.concat(result, resolveClassPathStream(ignorePaths, clientDir, ((OptionalActionClassPath) a).args)); + if(actions != null) { + for (OptionalAction a : actions) { + if (a instanceof OptionalActionClassPath) + result = Stream.concat(result, resolveClassPathStream(ignorePaths, clientDir, ((OptionalActionClassPath) a).args)); + } } return result; } diff --git a/LauncherCore/src/main/java/pro/gravit/utils/Version.java b/LauncherCore/src/main/java/pro/gravit/utils/Version.java index c8301391..dd3bcf83 100644 --- a/LauncherCore/src/main/java/pro/gravit/utils/Version.java +++ b/LauncherCore/src/main/java/pro/gravit/utils/Version.java @@ -6,7 +6,7 @@ public final class Version implements Comparable { public static final int MAJOR = 5; public static final int MINOR = 6; - public static final int PATCH = 14; + public static final int PATCH = 15; public static final int BUILD = 1; public static final Version.Type RELEASE = Type.STABLE; public final int major; diff --git a/ServerWrapper/build.gradle b/ServerWrapper/build.gradle index 68a4f2bc..a84b4353 100644 --- a/ServerWrapper/build.gradle +++ b/ServerWrapper/build.gradle @@ -48,6 +48,21 @@ pack project(':LauncherAPI') exclude 'module-info.class' } +tasks.register('inlinejar', Jar) { + dependsOn configurations.runtimeClasspath + from { + configurations.runtimeClasspath.filter {! (it.name =~ /gson.*\.jar/ || it.name =~ /error_prone_annotations.*\.jar/)}.collect { it.isDirectory() ? it : zipTree(it) } + } + from { + sourceSets.main.output + } + archiveClassifier.set('inline') + manifest.attributes("Main-Class": mainClassName, + "Automatic-Module-Name": "ServerWrapper" + ) + duplicatesStrategy = DuplicatesStrategy.EXCLUDE +} + publishing { publications { serverwrapperapi(MavenPublication) { @@ -94,4 +109,4 @@ pack project(':LauncherAPI') sign publishing.publications.serverwrapperapi } -assemble.dependsOn tasks.shadowJar +assemble.dependsOn tasks.shadowJar, tasks.inlinejar diff --git a/ServerWrapper/src/main/java/pro/gravit/launcher/server/ServerWrapper.java b/ServerWrapper/src/main/java/pro/gravit/launcher/server/ServerWrapper.java index aaa393e0..b97787a3 100644 --- a/ServerWrapper/src/main/java/pro/gravit/launcher/server/ServerWrapper.java +++ b/ServerWrapper/src/main/java/pro/gravit/launcher/server/ServerWrapper.java @@ -25,15 +25,18 @@ import pro.gravit.utils.launch.*; import java.io.File; +import java.io.IOException; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.lang.reflect.Type; +import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; +import java.util.stream.Stream; public class ServerWrapper extends JsonConfigurable { public static final Path configFile = Paths.get(System.getProperty("serverwrapper.configFile", "ServerWrapperConfig.json")); @@ -100,31 +103,20 @@ public void getProfiles() throws Exception { } } - public void run(String... args) throws Throwable { + + public void initialize() throws Exception { initGson(); AuthRequest.registerProviders(); GetAvailabilityAuthRequest.registerProviders(); OptionalAction.registerProviders(); OptionalTrigger.registerProviders(); - if (args.length > 0 && args[0].equalsIgnoreCase("setup") && !disableSetup) { - LogHelper.debug("Read ServerWrapperConfig.json"); - loadConfig(); - ServerWrapperSetup setup = new ServerWrapperSetup(); - setup.run(); - System.exit(0); - } - if (args.length > 1 && args[0].equalsIgnoreCase("installAuthlib") && !disableSetup) { - LogHelper.debug("Read ServerWrapperConfig.json"); - loadConfig(); - InstallAuthlib command = new InstallAuthlib(); - command. run(args[1]); - System.exit(0); - } LogHelper.debug("Read ServerWrapperConfig.json"); loadConfig(); + } + + public void connect() throws Exception { config.applyEnv(); updateLauncherConfig(); - Launcher.applyLauncherEnv(Objects.requireNonNullElse(config.env, LauncherConfig.LauncherEnvironment.STD)); StdWebSocketService service = StdWebSocketService.initWebSockets(config.address).get(); service.reconnectCallback = () -> { @@ -136,11 +128,6 @@ public void run(String... args) throws Throwable { LogHelper.error(e); } }; - if(config.properties != null) { - for(Map.Entry e : config.properties.entrySet()) { - System.setProperty(e.getKey(), e.getValue()); - } - } Request.setRequestService(service); if (config.logFile != null) LogHelper.addOutput(IOHelper.newWriter(Paths.get(config.logFile), true)); { @@ -153,6 +140,47 @@ public void run(String... args) throws Throwable { if(config.encodedServerEcPublicKey != null) { KeyService.serverEcPublicKey = SecurityHelper.toPublicECDSAKey(config.encodedServerEcPublicKey); } + ClientService.nativePath = config.nativesDir; + ConfigService.serverName = config.serverName; + if(config.configServiceSettings != null) { + config.configServiceSettings.apply(); + } + } + + public void runCompatClasses() throws Throwable { + if(config.compatClasses != null) { + for (String e : config.compatClasses) { + Class clazz = classLoaderControl == null ? Class.forName(e) : classLoaderControl.getClass(e); + MethodHandle runMethod = MethodHandles.lookup().findStatic(clazz, "run", MethodType.methodType(void.class, ClassLoaderControl.class)); + runMethod.invoke(classLoaderControl); + } + } + } + + public void run(String... args) throws Throwable { + initialize(); + if (args.length > 0 && args[0].equalsIgnoreCase("setup") && !disableSetup) { + ServerWrapperSetup setup = new ServerWrapperSetup(); + setup.run(); + System.exit(0); + } + if (args.length > 1 && args[0].equalsIgnoreCase("installAuthlib") && !disableSetup) { + InstallAuthlib command = new InstallAuthlib(); + command. run(args[1]); + System.exit(0); + } + connect(); + if(config.properties != null) { + for(Map.Entry e : config.properties.entrySet()) { + System.setProperty(e.getKey(), e.getValue()); + } + } + if(config.encodedServerRsaPublicKey != null) { + KeyService.serverRsaPublicKey = SecurityHelper.toPublicRSAKey(config.encodedServerRsaPublicKey); + } + if(config.encodedServerEcPublicKey != null) { + KeyService.serverEcPublicKey = SecurityHelper.toPublicECDSAKey(config.encodedServerEcPublicKey); + } String classname = (config.mainclass == null || config.mainclass.isEmpty()) ? args[0] : config.mainclass; if (classname.isEmpty()) { LogHelper.error("MainClass not found. Please set MainClass for ServerWrapper.json or first commandline argument"); @@ -182,8 +210,6 @@ public void run(String... args) throws Throwable { System.arraycopy(args, 1, real_args, 0, args.length - 1); } else real_args = args; Launch launch; - ClientService.nativePath = config.nativesDir; - ConfigService.serverName = config.serverName; if(config.loadNatives != null) { for(String e : config.loadNatives) { System.load(Paths.get(config.nativesDir).resolve(ClientService.findLibrary(e)).toAbsolutePath().toString()); @@ -209,24 +235,27 @@ public void run(String... args) throws Throwable { LaunchOptions options = new LaunchOptions(); options.enableHacks = config.enableHacks; options.moduleConf = config.moduleConf; - classLoaderControl = launch.init(config.classpath.stream().map(Paths::get).collect(Collectors.toCollection(ArrayList::new)), config.nativesDir, options); + classLoaderControl = launch.init(config.classpath.stream() + .map(Paths::get) + .flatMap(p -> { + if(!Files.isDirectory(p)) { + return Stream.of(p); + } + try { + return Files.walk(p).filter(e -> e.getFileName().toString().endsWith(".jar")); + } catch (IOException e) { + throw new RuntimeException(e); + } + }) + .collect(Collectors.toCollection(ArrayList::new)), config.nativesDir, options); if(ServerAgent.isAgentStarted()) { ClientService.instrumentation = ServerAgent.inst; } ClientService.classLoaderControl = classLoaderControl; ClientService.baseURLs = classLoaderControl.getURLs(); - if(config.configServiceSettings != null) { - config.configServiceSettings.apply(); - } LogHelper.info("Start Minecraft Server"); try { - if(config.compatClasses != null) { - for (String e : config.compatClasses) { - Class clazz = classLoaderControl.getClass(e); - MethodHandle runMethod = MethodHandles.lookup().findStatic(clazz, "run", MethodType.methodType(void.class, ClassLoaderControl.class)); - runMethod.invoke(classLoaderControl); - } - } + runCompatClasses(); LogHelper.debug("Invoke main method %s with %s", classname, launch.getClass().getName()); launch.launch(config.mainclass, config.mainmodule, Arrays.asList(real_args)); } catch (Throwable e) { @@ -253,12 +282,12 @@ public void setConfig(Config config) { @Override public Config getDefaultConfig() { Config newConfig = new Config(); - newConfig.serverName = "your server name"; + newConfig.serverName = ""; newConfig.mainclass = ""; newConfig.extendedTokens = new HashMap<>(); newConfig.args = new ArrayList<>(); newConfig.classpath = new ArrayList<>(); - newConfig.address = "ws://localhost:9274/api"; + newConfig.address = ""; newConfig.classLoaderConfig = ClientProfile.ClassLoaderConfig.SYSTEM_ARGS; newConfig.env = LauncherConfig.LauncherEnvironment.STD; newConfig.properties = new HashMap<>(); diff --git a/ServerWrapper/src/main/java/pro/gravit/launcher/server/ServerWrapperInlineInitializer.java b/ServerWrapper/src/main/java/pro/gravit/launcher/server/ServerWrapperInlineInitializer.java new file mode 100644 index 00000000..121f7a2f --- /dev/null +++ b/ServerWrapper/src/main/java/pro/gravit/launcher/server/ServerWrapperInlineInitializer.java @@ -0,0 +1,10 @@ +package pro.gravit.launcher.server; + +public class ServerWrapperInlineInitializer { + public static void run() throws Throwable { + ServerWrapper.wrapper = new ServerWrapper(ServerWrapper.Config.class, ServerWrapper.configFile); + ServerWrapper.wrapper.initialize(); + ServerWrapper.wrapper.connect(); + ServerWrapper.wrapper.runCompatClasses(); + } +} diff --git a/build.gradle b/build.gradle index a2f55153..2cb7fbc8 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ id 'org.openjfx.javafxplugin' version '0.1.0' apply false } group = 'pro.gravit.launcher' -version = '5.6.14' +version = '5.6.15' apply from: 'props.gradle'