diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServerStarter.java b/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServerStarter.java index ee8307a7..487d5f84 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServerStarter.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServerStarter.java @@ -7,6 +7,7 @@ import pro.gravit.launcher.LauncherTrustManager; import pro.gravit.launcher.modules.events.PreConfigPhase; import pro.gravit.launcher.profiles.optional.actions.OptionalAction; +import pro.gravit.launcher.profiles.optional.triggers.OptionalTrigger; import pro.gravit.launcher.request.auth.AuthRequest; import pro.gravit.launcher.request.auth.GetAvailabilityAuthRequest; import pro.gravit.launchserver.auth.core.AuthCoreProvider; @@ -211,6 +212,7 @@ public static void registerAll() { GetAvailabilityAuthRequest.registerProviders(); HWIDProvider.registerProviders(); OptionalAction.registerProviders(); + OptionalTrigger.registerProviders(); SessionStorage.registerProviders(); } diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/command/hash/SaveProfilesCommand.java b/LaunchServer/src/main/java/pro/gravit/launchserver/command/hash/SaveProfilesCommand.java index 40f75987..7245703c 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/command/hash/SaveProfilesCommand.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/command/hash/SaveProfilesCommand.java @@ -8,9 +8,11 @@ import pro.gravit.launcher.profiles.optional.OptionalFile; import pro.gravit.launcher.profiles.optional.OptionalTrigger; import pro.gravit.launcher.profiles.optional.actions.*; +import pro.gravit.launcher.profiles.optional.triggers.OSTrigger; import pro.gravit.launchserver.LaunchServer; import pro.gravit.launchserver.command.Command; import pro.gravit.utils.helper.IOHelper; +import pro.gravit.utils.helper.JVMHelper; import java.io.IOException; import java.io.Reader; @@ -61,7 +63,7 @@ public static ClientProfile makeProfile(ClientProfile.Version version, String ti optionalMacOs.visible = false; optionalMacOs.actions = new ArrayList<>(1); optionalMacOs.actions.add(new OptionalActionJvmArgs(List.of("-XstartOnFirstThread"))); - optionalMacOs.triggers = new OptionalTrigger[]{new OptionalTrigger(OptionalTrigger.TriggerType.OS_TYPE, 2)}; + optionalMacOs.triggersList = List.of(new OSTrigger(JVMHelper.OS.MACOSX)); optionals.add(optionalMacOs); } if (optionContains(options, MakeProfileOption.LWJGLMAC)) { @@ -77,7 +79,7 @@ public static ClientProfile makeProfile(ClientProfile.Version version, String ti "libraries/libraries/org/lwjgl/lwjgl-opengl/3.2.1", "", "libraries/libraries/org/lwjgl/lwjgl-jemalloc/3.2.1", "" ))); - optionalMac.triggers = new OptionalTrigger[]{new OptionalTrigger(OptionalTrigger.TriggerType.OS_TYPE, true, 2, 0)}; + optionalMac.triggersList = List.of(new OSTrigger(JVMHelper.OS.MACOSX)); optionals.add(optionalMac); OptionalFile optionalOther = new OptionalFile(); optionalOther.name = "NonMacLwjgl"; @@ -91,7 +93,9 @@ public static ClientProfile makeProfile(ClientProfile.Version version, String ti "libraries/libraries/org/lwjgl/lwjgl-opengl/3.2.2", "", "libraries/libraries/org/lwjgl/lwjgl-jemalloc/3.2.2", "" ))); - optionalOther.triggers = new OptionalTrigger[]{new OptionalTrigger(OptionalTrigger.TriggerType.OS_TYPE, true, 2, 0)}; + OSTrigger nonMacTrigger = new OSTrigger(JVMHelper.OS.MACOSX); + nonMacTrigger.inverted = true; + optionalOther.triggersList = List.of(nonMacTrigger); optionals.add(optionalOther); } if (version.compareTo(ClientProfile.Version.MC117) >= 0) { @@ -192,6 +196,14 @@ public static void saveProfile(ClientProfile profile, Path path) throws IOExcept } file.actions.add(action); } + if (file.triggers != null) { + file.triggersList = new ArrayList<>(file.triggers.length); + for (OptionalTrigger trigger : file.triggers) { + pro.gravit.launcher.profiles.optional.triggers.OptionalTrigger newTrigger = trigger.toTrigger(); + if (newTrigger != null) file.triggersList.add(newTrigger); + } + file.triggers = null; + } } try (Writer w = IOHelper.newWriter(path)) { Launcher.gsonManager.configGson.toJson(profile, w); diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/manangers/LaunchServerGsonManager.java b/LaunchServer/src/main/java/pro/gravit/launchserver/manangers/LaunchServerGsonManager.java index ca0532b2..cb05d890 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/manangers/LaunchServerGsonManager.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/manangers/LaunchServerGsonManager.java @@ -5,6 +5,7 @@ import pro.gravit.launcher.managers.GsonManager; import pro.gravit.launcher.modules.events.PreGsonPhase; import pro.gravit.launcher.profiles.optional.actions.OptionalAction; +import pro.gravit.launcher.profiles.optional.triggers.OptionalTrigger; import pro.gravit.launcher.request.JsonResultSerializeAdapter; import pro.gravit.launcher.request.WebSocketEvent; import pro.gravit.launcher.request.auth.AuthRequest; @@ -50,6 +51,7 @@ public void registerAdapters(GsonBuilder builder) { builder.registerTypeAdapter(GetAvailabilityAuthRequestEvent.AuthAvailabilityDetails.class, new UniversalJsonAdapter<>(GetAvailabilityAuthRequest.providers)); builder.registerTypeAdapter(HWIDProvider.class, new UniversalJsonAdapter<>(HWIDProvider.providers)); builder.registerTypeAdapter(OptionalAction.class, new UniversalJsonAdapter<>(OptionalAction.providers)); + builder.registerTypeAdapter(OptionalTrigger.class, new UniversalJsonAdapter<>(OptionalTrigger.providers)); builder.registerTypeAdapter(SessionStorage.class, new UniversalJsonAdapter<>(SessionStorage.providers)); modulesManager.invokeEvent(new PreGsonPhase(builder)); //ClientWebSocketService.appendTypeAdapters(builder); diff --git a/Launcher/src/main/java/pro/gravit/launcher/ClientLauncherWrapper.java b/Launcher/src/main/java/pro/gravit/launcher/ClientLauncherWrapper.java index 61e87a96..8ca990e0 100644 --- a/Launcher/src/main/java/pro/gravit/launcher/ClientLauncherWrapper.java +++ b/Launcher/src/main/java/pro/gravit/launcher/ClientLauncherWrapper.java @@ -3,17 +3,14 @@ import pro.gravit.launcher.client.ClientModuleManager; import pro.gravit.launcher.client.DirBridge; import pro.gravit.launcher.utils.DirWatcher; -import pro.gravit.utils.helper.EnvHelper; -import pro.gravit.utils.helper.IOHelper; -import pro.gravit.utils.helper.JVMHelper; -import pro.gravit.utils.helper.LogHelper; +import pro.gravit.utils.helper.*; -import java.io.File; import java.io.IOException; -import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; public class ClientLauncherWrapper { public static final String MAGIC_ARG = "-Djdk.attach.allowAttachSelf"; @@ -56,8 +53,8 @@ public static void main(String[] arguments) throws IOException, InterruptedExcep context.javaVersion = null; try { if (!noJavaCheck) { - List javaVersions = findJava(); - for (JavaVersion version : javaVersions) { + List javaVersions = JavaHelper.findJava(); + for (JavaHelper.JavaVersion version : javaVersions) { LogHelper.debug("Found Java %d b%d in %s javafx %s", version.version, version.build, version.jvmDir.toString(), version.enabledJavaFX ? "supported" : "not supported"); if (context.javaVersion == null) { context.javaVersion = version; @@ -80,7 +77,7 @@ public static void main(String[] arguments) throws IOException, InterruptedExcep LogHelper.error(e); } if (context.javaVersion == null) { - context.javaVersion = JavaVersion.getCurrentJavaVersion(); + context.javaVersion = JavaHelper.JavaVersion.getCurrentJavaVersion(); } context.executePath = IOHelper.resolveJavaBin(context.javaVersion.jvmDir); @@ -116,14 +113,14 @@ public static void main(String[] arguments) throws IOException, InterruptedExcep if (context.javaVersion.version >= 9) { context.javaFXPaths.add(context.javaVersion.jvmDir); context.javaFXPaths.add(context.javaVersion.jvmDir.resolve("jre")); - Path openjfxPath = tryGetOpenJFXPath(context.javaVersion.jvmDir); + Path openjfxPath = JavaHelper.tryGetOpenJFXPath(context.javaVersion.jvmDir); if (openjfxPath != null) { context.javaFXPaths.add(openjfxPath); } StringBuilder modulesPath = new StringBuilder(); StringBuilder modulesAdd = new StringBuilder(); for (String moduleName : context.jvmModules) { - boolean success = tryAddModule(context.javaFXPaths, moduleName, modulesPath); + boolean success = JavaHelper.tryAddModule(context.javaFXPaths, moduleName, modulesPath); if (success) { if (modulesAdd.length() > 0) modulesAdd.append(","); modulesAdd.append(moduleName); @@ -164,213 +161,9 @@ public static void main(String[] arguments) throws IOException, InterruptedExcep } } - public static Path tryGetOpenJFXPath(Path jvmDir) { - String dirName = jvmDir.getFileName().toString(); - Path parent = jvmDir.getParent(); - if (parent == null) return null; - Path archJFXPath = parent.resolve(dirName.replace("openjdk", "openjfx")); - if (Files.isDirectory(archJFXPath)) { - return archJFXPath; - } - Path arch2JFXPath = parent.resolve(dirName.replace("jdk", "openjfx")); - if (Files.isDirectory(arch2JFXPath)) { - return arch2JFXPath; - } - if (JVMHelper.OS_TYPE == JVMHelper.OS.LINUX) { - Path debianJfxPath = Paths.get("/usr/share/openjfx"); - if (Files.isDirectory(debianJfxPath)) { - return debianJfxPath; - } - } - return null; - } - - public static Path tryFindModule(Path path, String moduleName) { - Path result = path.resolve(moduleName.concat(".jar")); - if (!IOHelper.isFile(result)) - result = path.resolve("lib").resolve(moduleName.concat(".jar")); - else return result; - if (!IOHelper.isFile(result)) - return null; - else return result; - } - - public static boolean tryAddModule(List paths, String moduleName, StringBuilder args) { - for (Path path : paths) { - if (path == null) continue; - Path result = tryFindModule(path, moduleName); - if (result != null) { - if (args.length() != 0) args.append(File.pathSeparatorChar); - args.append(result.toAbsolutePath().toString()); - return true; - } - } - return false; - } - - public static List findJava() { - List javaPaths = new ArrayList<>(4); - List result = new ArrayList<>(4); - try { - tryAddJava(javaPaths, result, ClientLauncherWrapper.JavaVersion.getCurrentJavaVersion()); - } catch (IOException e) { - LogHelper.error(e); - } - String[] path = System.getenv("PATH").split(JVMHelper.OS_TYPE == JVMHelper.OS.MUSTDIE ? ";" : ":"); - for (String p : path) { - try { - Path p1 = Paths.get(p); - Path javaExecPath = JVMHelper.OS_TYPE == JVMHelper.OS.MUSTDIE ? p1.resolve("java.exe") : p1.resolve("java"); - if (Files.exists(javaExecPath)) { - if (Files.isSymbolicLink(javaExecPath)) { - javaExecPath = javaExecPath.toRealPath(); - } - p1 = javaExecPath.getParent().getParent(); - tryAddJava(javaPaths, result, ClientLauncherWrapper.JavaVersion.getByPath(p1)); - trySearchJava(javaPaths, result, p1.getParent()); - } - } catch (IOException e) { - LogHelper.error(e); - } - } - if (JVMHelper.OS_TYPE == JVMHelper.OS.MUSTDIE) { - Path rootDrive = Paths.get(System.getProperty("java.home")); - try { - trySearchJava(javaPaths, result, rootDrive.resolve("Program Files").resolve("Java")); - trySearchJava(javaPaths, result, rootDrive.resolve("Program Files").resolve("AdoptOpenJDK")); - } catch (IOException e) { - LogHelper.error(e); - } - } else if (JVMHelper.OS_TYPE == JVMHelper.OS.LINUX) { - try { - trySearchJava(javaPaths, result, Paths.get("/usr/lib/jvm")); - } catch (IOException e) { - LogHelper.error(e); - } - } - return result; - } - - public static boolean tryAddJava(List javaPaths, List result, ClientLauncherWrapper.JavaVersion version) throws IOException { - if (version == null) return false; - String path = version.jvmDir.toAbsolutePath().toString(); - if (javaPaths.contains(path)) return false; - javaPaths.add(path); - result.add(version); - return true; - } - - public static void trySearchJava(List javaPaths, List result, Path path) throws IOException { - if (!Files.isDirectory(path)) return; - Files.list(path).filter(p -> Files.exists(p.resolve("bin").resolve(JVMHelper.OS_TYPE == JVMHelper.OS.MUSTDIE ? "java.exe" : "java"))).forEach(e -> { - try { - tryAddJava(javaPaths, result, JavaVersion.getByPath(e)); - if (Files.exists(e.resolve("jre"))) { - tryAddJava(javaPaths, result, JavaVersion.getByPath(e.resolve("jre"))); - } - } catch (IOException ioException) { - LogHelper.error(ioException); - } - }); - } - - - public static class JavaVersionAndBuild { - public int version; - public int build; - - public JavaVersionAndBuild(int version, int build) { - this.version = version; - this.build = build; - } - - public JavaVersionAndBuild() { - } - } - - public static JavaVersionAndBuild getJavaVersion(String version) { - JavaVersionAndBuild result = new JavaVersionAndBuild(); - if (version.startsWith("1.")) { - result.version = Integer.parseInt(version.substring(2, 3)); - result.build = Integer.parseInt(version.substring(version.indexOf('_') + 1)); - } else { - int dot = version.indexOf("."); - if (dot != -1) { - result.version = Integer.parseInt(version.substring(0, dot)); - dot = version.lastIndexOf("."); - result.build = Integer.parseInt(version.substring(dot + 1)); - } - } - return result; - } - - public static class JavaVersion { - public final Path jvmDir; - public final int version; - public final int build; - public boolean enabledJavaFX; - - public JavaVersion(Path jvmDir, int version) { - this.jvmDir = jvmDir; - this.version = version; - this.build = 0; - this.enabledJavaFX = true; - } - - public JavaVersion(Path jvmDir, int version, int build, boolean enabledJavaFX) { - this.jvmDir = jvmDir; - this.version = version; - this.build = build; - this.enabledJavaFX = enabledJavaFX; - } - - public static JavaVersion getCurrentJavaVersion() { - return new JavaVersion(Paths.get(System.getProperty("java.home")), JVMHelper.getVersion(), 0, isCurrentJavaSupportJavaFX()); - } - - private static boolean isCurrentJavaSupportJavaFX() { - try { - Class.forName("javafx.application.Application"); - return true; - } catch (ClassNotFoundException e) { - if (JVMHelper.getVersion() > 8) { - Path jvmDir = Paths.get(System.getProperty("java.home")); - return tryFindModule(jvmDir, "javafx.base") != null; - } - return false; - } - } - - public static JavaVersion getByPath(Path jvmDir) throws IOException { - Path releaseFile = jvmDir.resolve("release"); - JavaVersionAndBuild versionAndBuild; - if (IOHelper.isFile(releaseFile)) { - Properties properties = new Properties(); - properties.load(IOHelper.newReader(releaseFile)); - versionAndBuild = getJavaVersion(properties.getProperty("JAVA_VERSION").replaceAll("\"", "")); - } else { - versionAndBuild = new JavaVersionAndBuild(isExistExtJavaLibrary(jvmDir, "jfxrt") ? 8 : 9, 0); - } - JavaVersion resultJavaVersion = new JavaVersion(jvmDir, versionAndBuild.version, versionAndBuild.build, false); - if (versionAndBuild.version <= 8) { - resultJavaVersion.enabledJavaFX = isExistExtJavaLibrary(jvmDir, "jfxrt"); - } else { - resultJavaVersion.enabledJavaFX = tryFindModule(jvmDir, "javafx.base") != null; - if (!resultJavaVersion.enabledJavaFX) - resultJavaVersion.enabledJavaFX = tryFindModule(jvmDir.resolve("jre"), "javafx.base") != null; - } - return resultJavaVersion; - } - - public static boolean isExistExtJavaLibrary(Path jvmDir, String name) { - Path jrePath = jvmDir.resolve("lib").resolve("ext").resolve(name.concat(".jar")); - Path jdkPath = jvmDir.resolve("jre").resolve("lib").resolve("ext").resolve(name.concat(".jar")); - return IOHelper.isFile(jrePath) || IOHelper.isFile(jdkPath); - } - } public static class ClientLauncherWrapperContext { - public JavaVersion javaVersion; + public JavaHelper.JavaVersion javaVersion; public Path executePath; public String mainClass; public int memoryLimit; diff --git a/Launcher/src/main/java/pro/gravit/launcher/LauncherEngine.java b/Launcher/src/main/java/pro/gravit/launcher/LauncherEngine.java index 63311a28..d8b63782 100644 --- a/Launcher/src/main/java/pro/gravit/launcher/LauncherEngine.java +++ b/Launcher/src/main/java/pro/gravit/launcher/LauncherEngine.java @@ -14,6 +14,7 @@ import pro.gravit.launcher.managers.ConsoleManager; import pro.gravit.launcher.modules.events.PreConfigPhase; import pro.gravit.launcher.profiles.optional.actions.OptionalAction; +import pro.gravit.launcher.profiles.optional.triggers.OptionalTrigger; import pro.gravit.launcher.request.Request; import pro.gravit.launcher.request.RequestException; import pro.gravit.launcher.request.auth.AuthRequest; @@ -120,6 +121,7 @@ public static void initGson(ClientModuleManager modulesManager) { AuthRequest.registerProviders(); GetAvailabilityAuthRequest.registerProviders(); OptionalAction.registerProviders(); + OptionalTrigger.registerProviders(); Launcher.gsonManager = new ClientGsonManager(modulesManager); Launcher.gsonManager.initGson(); } diff --git a/Launcher/src/main/java/pro/gravit/launcher/client/ClientLauncherEntryPoint.java b/Launcher/src/main/java/pro/gravit/launcher/client/ClientLauncherEntryPoint.java index c81914f2..8bfe5f27 100644 --- a/Launcher/src/main/java/pro/gravit/launcher/client/ClientLauncherEntryPoint.java +++ b/Launcher/src/main/java/pro/gravit/launcher/client/ClientLauncherEntryPoint.java @@ -16,6 +16,7 @@ import pro.gravit.launcher.profiles.optional.actions.OptionalAction; import pro.gravit.launcher.profiles.optional.actions.OptionalActionClassPath; import pro.gravit.launcher.profiles.optional.actions.OptionalActionClientArgs; +import pro.gravit.launcher.profiles.optional.triggers.OptionalTrigger; import pro.gravit.launcher.request.Request; import pro.gravit.launcher.request.RequestException; import pro.gravit.launcher.request.auth.AuthRequest; @@ -198,6 +199,7 @@ private static void initGson(ClientModuleManager moduleManager) { AuthRequest.registerProviders(); GetAvailabilityAuthRequest.registerProviders(); OptionalAction.registerProviders(); + OptionalTrigger.registerProviders(); Launcher.gsonManager = new ClientGsonManager(moduleManager); Launcher.gsonManager.initGson(); } diff --git a/Launcher/src/main/java/pro/gravit/launcher/client/ClientLauncherProcess.java b/Launcher/src/main/java/pro/gravit/launcher/client/ClientLauncherProcess.java index 75ba55f7..58b7037e 100644 --- a/Launcher/src/main/java/pro/gravit/launcher/client/ClientLauncherProcess.java +++ b/Launcher/src/main/java/pro/gravit/launcher/client/ClientLauncherProcess.java @@ -1,6 +1,5 @@ package pro.gravit.launcher.client; -import pro.gravit.launcher.ClientLauncherWrapper; import pro.gravit.launcher.Launcher; import pro.gravit.launcher.LauncherEngine; import pro.gravit.launcher.LauncherNetworkAPI; @@ -45,7 +44,7 @@ public class ClientLauncherProcess { public int bits; public boolean useLegacyJavaClassPathProperty; public boolean isStarted; - public ClientLauncherWrapper.JavaVersion javaVersion; + public JavaHelper.JavaVersion javaVersion; private transient Process process; public ClientLauncherProcess(Path executeFile, Path workDir, Path javaDir, String mainClass) { @@ -87,13 +86,13 @@ public ClientLauncherProcess(Path clientDir, Path assetDir, Path javaDir, Path r this.params.actions = view.getEnabledActions(); } try { - javaVersion = ClientLauncherWrapper.JavaVersion.getByPath(javaDir); + javaVersion = JavaHelper.JavaVersion.getByPath(javaDir); } catch (IOException e) { LogHelper.error(e); javaVersion = null; } if (javaVersion == null) { - javaVersion = ClientLauncherWrapper.JavaVersion.getCurrentJavaVersion(); + javaVersion = JavaHelper.JavaVersion.getCurrentJavaVersion(); } this.bits = JVMHelper.JVM_BITS; applyClientProfile(); @@ -187,14 +186,14 @@ public void start(boolean pipeOutput) throws IOException, InterruptedException { private void applyJava9Params(List processArgs) { jvmModulesPaths.add(javaVersion.jvmDir); jvmModulesPaths.add(javaVersion.jvmDir.resolve("jre")); - Path openjfxPath = ClientLauncherWrapper.tryGetOpenJFXPath(javaVersion.jvmDir); + Path openjfxPath = JavaHelper.tryGetOpenJFXPath(javaVersion.jvmDir); if (openjfxPath != null) { jvmModulesPaths.add(openjfxPath); } StringBuilder modulesPath = new StringBuilder(); StringBuilder modulesAdd = new StringBuilder(); for (String moduleName : jvmModules) { - boolean success = ClientLauncherWrapper.tryAddModule(jvmModulesPaths, moduleName, modulesPath); + boolean success = JavaHelper.tryAddModule(jvmModulesPaths, moduleName, modulesPath); if (success) { if (modulesAdd.length() > 0) modulesAdd.append(","); modulesAdd.append(moduleName); diff --git a/LauncherAPI/src/main/java/pro/gravit/launcher/profiles/optional/OptionalFile.java b/LauncherAPI/src/main/java/pro/gravit/launcher/profiles/optional/OptionalFile.java index e1253053..a5bca12e 100644 --- a/LauncherAPI/src/main/java/pro/gravit/launcher/profiles/optional/OptionalFile.java +++ b/LauncherAPI/src/main/java/pro/gravit/launcher/profiles/optional/OptionalFile.java @@ -16,6 +16,7 @@ public class OptionalFile { @LauncherNetworkAPI + @Deprecated public long permissions = 0L; @LauncherNetworkAPI @Deprecated @@ -34,6 +35,9 @@ public class OptionalFile { @LauncherNetworkAPI public String info; @LauncherNetworkAPI + public List triggersList; + @LauncherNetworkAPI + @Deprecated public OptionalTrigger[] triggers; @LauncherNetworkAPI public OptionalDepend[] dependenciesFile; @@ -106,6 +110,7 @@ public boolean isMark() { return mark; } + @Deprecated public long getPermissions() { return permissions; } diff --git a/LauncherAPI/src/main/java/pro/gravit/launcher/profiles/optional/OptionalTrigger.java b/LauncherAPI/src/main/java/pro/gravit/launcher/profiles/optional/OptionalTrigger.java index 83f180a9..bab150ba 100644 --- a/LauncherAPI/src/main/java/pro/gravit/launcher/profiles/optional/OptionalTrigger.java +++ b/LauncherAPI/src/main/java/pro/gravit/launcher/profiles/optional/OptionalTrigger.java @@ -1,7 +1,10 @@ package pro.gravit.launcher.profiles.optional; +import pro.gravit.launcher.profiles.optional.triggers.JavaTrigger; +import pro.gravit.launcher.profiles.optional.triggers.OSTrigger; import pro.gravit.utils.helper.JVMHelper; +@Deprecated public class OptionalTrigger { public TriggerType type; public boolean need = true; @@ -60,6 +63,36 @@ public boolean isTriggered() { else return test > value; } + public pro.gravit.launcher.profiles.optional.triggers.OptionalTrigger toTrigger() { + switch (type) { + case JAVA_VERSION: { + JavaTrigger trigger = new JavaTrigger((int) value, (int) value); + trigger.required = need; + if (compareMode > 0) { + trigger.maxVersion = 999; + } else if (compareMode < 0) { + trigger.minVersion = 0; + } + return trigger; + } + case JAVA_BITS: + case OS_BITS: + return null; + case OS_TYPE: { + JVMHelper.OS os; + if (value == 0) os = JVMHelper.OS.MUSTDIE; + else if (value == 1) os = JVMHelper.OS.LINUX; + else if (value == 2) os = JVMHelper.OS.MUSTDIE; + else throw new IllegalArgumentException(String.format("Os version %d unknown", value)); + OSTrigger trigger = new OSTrigger(os); + trigger.required = need; + if (compareMode != 0) trigger.inverted = true; + return trigger; + } + } + return null; + } + public enum TriggerType { JAVA_VERSION, JAVA_BITS, OS_BITS, OS_TYPE } diff --git a/LauncherAPI/src/main/java/pro/gravit/launcher/profiles/optional/triggers/JavaTrigger.java b/LauncherAPI/src/main/java/pro/gravit/launcher/profiles/optional/triggers/JavaTrigger.java new file mode 100644 index 00000000..d7ffad83 --- /dev/null +++ b/LauncherAPI/src/main/java/pro/gravit/launcher/profiles/optional/triggers/JavaTrigger.java @@ -0,0 +1,37 @@ +package pro.gravit.launcher.profiles.optional.triggers; + +import pro.gravit.launcher.profiles.optional.OptionalFile; +import pro.gravit.utils.helper.JavaHelper; + +public class JavaTrigger extends OptionalTrigger { + public int minVersion; + public int maxVersion; + public boolean requireJavaFX; + + public JavaTrigger(int minVersion, int maxVersion, boolean requireJavaFX) { + this.minVersion = minVersion; + this.maxVersion = maxVersion; + this.requireJavaFX = requireJavaFX; + } + + public JavaTrigger(int minVersion, int maxVersion) { + this.minVersion = minVersion; + this.maxVersion = maxVersion; + this.requireJavaFX = false; + } + + public JavaTrigger() { + this.minVersion = 8; + this.maxVersion = 999; + this.requireJavaFX = false; + } + + @Override + public boolean isTriggered(OptionalFile optional, OptionalTriggerContext context) { + JavaHelper.JavaVersion version = context.getJavaVersion(); + if (version.version < minVersion) return false; + if (version.version > maxVersion) return false; + if (requireJavaFX && !version.enabledJavaFX) return false; + return true; + } +} diff --git a/LauncherAPI/src/main/java/pro/gravit/launcher/profiles/optional/triggers/OSTrigger.java b/LauncherAPI/src/main/java/pro/gravit/launcher/profiles/optional/triggers/OSTrigger.java new file mode 100644 index 00000000..edbd4590 --- /dev/null +++ b/LauncherAPI/src/main/java/pro/gravit/launcher/profiles/optional/triggers/OSTrigger.java @@ -0,0 +1,17 @@ +package pro.gravit.launcher.profiles.optional.triggers; + +import pro.gravit.launcher.profiles.optional.OptionalFile; +import pro.gravit.utils.helper.JVMHelper; + +public class OSTrigger extends OptionalTrigger { + public JVMHelper.OS os; + + public OSTrigger(JVMHelper.OS os) { + this.os = os; + } + + @Override + public boolean isTriggered(OptionalFile optional, OptionalTriggerContext context) { + return JVMHelper.OS_TYPE == os; + } +} diff --git a/LauncherAPI/src/main/java/pro/gravit/launcher/profiles/optional/triggers/OptionalTrigger.java b/LauncherAPI/src/main/java/pro/gravit/launcher/profiles/optional/triggers/OptionalTrigger.java new file mode 100644 index 00000000..0e7cb119 --- /dev/null +++ b/LauncherAPI/src/main/java/pro/gravit/launcher/profiles/optional/triggers/OptionalTrigger.java @@ -0,0 +1,28 @@ +package pro.gravit.launcher.profiles.optional.triggers; + +import pro.gravit.launcher.profiles.optional.OptionalFile; +import pro.gravit.utils.ProviderMap; + +public abstract class OptionalTrigger { + public static ProviderMap providers = new ProviderMap<>("OptionalTriggers"); + private static boolean isRegisteredProviders = false; + + public static void registerProviders() { + if (!isRegisteredProviders) { + providers.register("java", JavaTrigger.class); + providers.register("os", OSTrigger.class); + isRegisteredProviders = true; + } + } + + public boolean required; + public boolean inverted; + + protected abstract boolean isTriggered(OptionalFile optional, OptionalTriggerContext context); + + public boolean check(OptionalFile optional, OptionalTriggerContext context) { + boolean result = isTriggered(optional, context); + if (inverted) result = !result; + return result; + } +} diff --git a/LauncherAPI/src/main/java/pro/gravit/launcher/profiles/optional/triggers/OptionalTriggerContext.java b/LauncherAPI/src/main/java/pro/gravit/launcher/profiles/optional/triggers/OptionalTriggerContext.java new file mode 100644 index 00000000..46598ff2 --- /dev/null +++ b/LauncherAPI/src/main/java/pro/gravit/launcher/profiles/optional/triggers/OptionalTriggerContext.java @@ -0,0 +1,22 @@ +package pro.gravit.launcher.profiles.optional.triggers; + +import pro.gravit.launcher.ClientPermissions; +import pro.gravit.launcher.profiles.ClientProfile; +import pro.gravit.launcher.profiles.PlayerProfile; +import pro.gravit.utils.helper.JavaHelper; + +public interface OptionalTriggerContext { + ClientProfile getProfile(); + + String getUsername(); + + JavaHelper.JavaVersion getJavaVersion(); + + default ClientPermissions getPermissions() { + return ClientPermissions.DEFAULT; + } + + default PlayerProfile getPlayerProfile() { + return null; + } +} diff --git a/LauncherAPI/src/main/java/pro/gravit/launcher/request/websockets/ClientWebSocketService.java b/LauncherAPI/src/main/java/pro/gravit/launcher/request/websockets/ClientWebSocketService.java index b4ee8dca..34970258 100644 --- a/LauncherAPI/src/main/java/pro/gravit/launcher/request/websockets/ClientWebSocketService.java +++ b/LauncherAPI/src/main/java/pro/gravit/launcher/request/websockets/ClientWebSocketService.java @@ -10,6 +10,7 @@ import pro.gravit.launcher.hasher.HashedEntry; import pro.gravit.launcher.hasher.HashedEntryAdapter; import pro.gravit.launcher.profiles.optional.actions.OptionalAction; +import pro.gravit.launcher.profiles.optional.triggers.OptionalTrigger; import pro.gravit.launcher.request.WebSocketEvent; import pro.gravit.launcher.request.auth.AuthRequest; import pro.gravit.launcher.request.auth.GetAvailabilityAuthRequest; @@ -44,6 +45,7 @@ public static void appendTypeAdapters(GsonBuilder builder) { builder.registerTypeAdapter(AuthRequest.AuthPasswordInterface.class, new UniversalJsonAdapter<>(AuthRequest.providers)); builder.registerTypeAdapter(GetAvailabilityAuthRequestEvent.AuthAvailabilityDetails.class, new UniversalJsonAdapter<>(GetAvailabilityAuthRequest.providers)); builder.registerTypeAdapter(OptionalAction.class, new UniversalJsonAdapter<>(OptionalAction.providers)); + builder.registerTypeAdapter(OptionalTrigger.class, new UniversalJsonAdapter<>(OptionalTrigger.providers)); } private static URI createURL(String address) { diff --git a/LauncherCore/src/main/java/pro/gravit/utils/helper/JavaHelper.java b/LauncherCore/src/main/java/pro/gravit/utils/helper/JavaHelper.java new file mode 100644 index 00000000..74fc155b --- /dev/null +++ b/LauncherCore/src/main/java/pro/gravit/utils/helper/JavaHelper.java @@ -0,0 +1,216 @@ +package pro.gravit.utils.helper; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +public class JavaHelper { + public static Path tryGetOpenJFXPath(Path jvmDir) { + String dirName = jvmDir.getFileName().toString(); + Path parent = jvmDir.getParent(); + if (parent == null) return null; + Path archJFXPath = parent.resolve(dirName.replace("openjdk", "openjfx")); + if (Files.isDirectory(archJFXPath)) { + return archJFXPath; + } + Path arch2JFXPath = parent.resolve(dirName.replace("jdk", "openjfx")); + if (Files.isDirectory(arch2JFXPath)) { + return arch2JFXPath; + } + if (JVMHelper.OS_TYPE == JVMHelper.OS.LINUX) { + Path debianJfxPath = Paths.get("/usr/share/openjfx"); + if (Files.isDirectory(debianJfxPath)) { + return debianJfxPath; + } + } + return null; + } + + public static Path tryFindModule(Path path, String moduleName) { + Path result = path.resolve(moduleName.concat(".jar")); + if (!IOHelper.isFile(result)) + result = path.resolve("lib").resolve(moduleName.concat(".jar")); + else return result; + if (!IOHelper.isFile(result)) + return null; + else return result; + } + + public static boolean tryAddModule(List paths, String moduleName, StringBuilder args) { + for (Path path : paths) { + if (path == null) continue; + Path result = tryFindModule(path, moduleName); + if (result != null) { + if (args.length() != 0) args.append(File.pathSeparatorChar); + args.append(result.toAbsolutePath().toString()); + return true; + } + } + return false; + } + + public static List findJava() { + List javaPaths = new ArrayList<>(4); + List result = new ArrayList<>(4); + try { + tryAddJava(javaPaths, result, JavaVersion.getCurrentJavaVersion()); + } catch (IOException e) { + LogHelper.error(e); + } + String[] path = System.getenv("PATH").split(JVMHelper.OS_TYPE == JVMHelper.OS.MUSTDIE ? ";" : ":"); + for (String p : path) { + try { + Path p1 = Paths.get(p); + Path javaExecPath = JVMHelper.OS_TYPE == JVMHelper.OS.MUSTDIE ? p1.resolve("java.exe") : p1.resolve("java"); + if (Files.exists(javaExecPath)) { + if (Files.isSymbolicLink(javaExecPath)) { + javaExecPath = javaExecPath.toRealPath(); + } + p1 = javaExecPath.getParent().getParent(); + tryAddJava(javaPaths, result, JavaVersion.getByPath(p1)); + trySearchJava(javaPaths, result, p1.getParent()); + } + } catch (IOException e) { + LogHelper.error(e); + } + } + if (JVMHelper.OS_TYPE == JVMHelper.OS.MUSTDIE) { + Path rootDrive = Paths.get(System.getProperty("java.home")); + try { + trySearchJava(javaPaths, result, rootDrive.resolve("Program Files").resolve("Java")); + trySearchJava(javaPaths, result, rootDrive.resolve("Program Files").resolve("AdoptOpenJDK")); + } catch (IOException e) { + LogHelper.error(e); + } + } else if (JVMHelper.OS_TYPE == JVMHelper.OS.LINUX) { + try { + trySearchJava(javaPaths, result, Paths.get("/usr/lib/jvm")); + } catch (IOException e) { + LogHelper.error(e); + } + } + return result; + } + + public static boolean tryAddJava(List javaPaths, List result, JavaVersion version) throws IOException { + if (version == null) return false; + String path = version.jvmDir.toAbsolutePath().toString(); + if (javaPaths.contains(path)) return false; + javaPaths.add(path); + result.add(version); + return true; + } + + public static void trySearchJava(List javaPaths, List result, Path path) throws IOException { + if (!Files.isDirectory(path)) return; + Files.list(path).filter(p -> Files.exists(p.resolve("bin").resolve(JVMHelper.OS_TYPE == JVMHelper.OS.MUSTDIE ? "java.exe" : "java"))).forEach(e -> { + try { + tryAddJava(javaPaths, result, JavaVersion.getByPath(e)); + if (Files.exists(e.resolve("jre"))) { + tryAddJava(javaPaths, result, JavaVersion.getByPath(e.resolve("jre"))); + } + } catch (IOException ioException) { + LogHelper.error(ioException); + } + }); + } + + public static JavaVersionAndBuild getJavaVersion(String version) { + JavaVersionAndBuild result = new JavaVersionAndBuild(); + if (version.startsWith("1.")) { + result.version = Integer.parseInt(version.substring(2, 3)); + result.build = Integer.parseInt(version.substring(version.indexOf('_') + 1)); + } else { + int dot = version.indexOf("."); + if (dot != -1) { + result.version = Integer.parseInt(version.substring(0, dot)); + dot = version.lastIndexOf("."); + result.build = Integer.parseInt(version.substring(dot + 1)); + } + } + return result; + } + + public static class JavaVersionAndBuild { + public int version; + public int build; + + public JavaVersionAndBuild(int version, int build) { + this.version = version; + this.build = build; + } + + public JavaVersionAndBuild() { + } + } + + public static class JavaVersion { + public final Path jvmDir; + public final int version; + public final int build; + public boolean enabledJavaFX; + + public JavaVersion(Path jvmDir, int version) { + this.jvmDir = jvmDir; + this.version = version; + this.build = 0; + this.enabledJavaFX = true; + } + + public JavaVersion(Path jvmDir, int version, int build, boolean enabledJavaFX) { + this.jvmDir = jvmDir; + this.version = version; + this.build = build; + this.enabledJavaFX = enabledJavaFX; + } + + public static JavaVersion getCurrentJavaVersion() { + return new JavaVersion(Paths.get(System.getProperty("java.home")), JVMHelper.getVersion(), 0, isCurrentJavaSupportJavaFX()); + } + + private static boolean isCurrentJavaSupportJavaFX() { + try { + Class.forName("javafx.application.Application"); + return true; + } catch (ClassNotFoundException e) { + if (JVMHelper.getVersion() > 8) { + Path jvmDir = Paths.get(System.getProperty("java.home")); + return tryFindModule(jvmDir, "javafx.base") != null; + } + return false; + } + } + + public static JavaVersion getByPath(Path jvmDir) throws IOException { + Path releaseFile = jvmDir.resolve("release"); + JavaVersionAndBuild versionAndBuild; + if (IOHelper.isFile(releaseFile)) { + Properties properties = new Properties(); + properties.load(IOHelper.newReader(releaseFile)); + versionAndBuild = getJavaVersion(properties.getProperty("JAVA_VERSION").replaceAll("\"", "")); + } else { + versionAndBuild = new JavaVersionAndBuild(isExistExtJavaLibrary(jvmDir, "jfxrt") ? 8 : 9, 0); + } + JavaVersion resultJavaVersion = new JavaVersion(jvmDir, versionAndBuild.version, versionAndBuild.build, false); + if (versionAndBuild.version <= 8) { + resultJavaVersion.enabledJavaFX = isExistExtJavaLibrary(jvmDir, "jfxrt"); + } else { + resultJavaVersion.enabledJavaFX = tryFindModule(jvmDir, "javafx.base") != null; + if (!resultJavaVersion.enabledJavaFX) + resultJavaVersion.enabledJavaFX = tryFindModule(jvmDir.resolve("jre"), "javafx.base") != null; + } + return resultJavaVersion; + } + + public static boolean isExistExtJavaLibrary(Path jvmDir, String name) { + Path jrePath = jvmDir.resolve("lib").resolve("ext").resolve(name.concat(".jar")); + Path jdkPath = jvmDir.resolve("jre").resolve("lib").resolve("ext").resolve(name.concat(".jar")); + return IOHelper.isFile(jrePath) || IOHelper.isFile(jdkPath); + } + } +} 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 a93d4840..eb604801 100644 --- a/ServerWrapper/src/main/java/pro/gravit/launcher/server/ServerWrapper.java +++ b/ServerWrapper/src/main/java/pro/gravit/launcher/server/ServerWrapper.java @@ -11,6 +11,7 @@ import pro.gravit.launcher.profiles.ClientProfile; import pro.gravit.launcher.profiles.PlayerProfile; import pro.gravit.launcher.profiles.optional.actions.OptionalAction; +import pro.gravit.launcher.profiles.optional.triggers.OptionalTrigger; import pro.gravit.launcher.request.Request; import pro.gravit.launcher.request.auth.AuthRequest; import pro.gravit.launcher.request.auth.GetAvailabilityAuthRequest; @@ -124,6 +125,7 @@ public void run(String... args) throws Throwable { AuthRequest.registerProviders(); GetAvailabilityAuthRequest.registerProviders(); OptionalAction.registerProviders(); + OptionalTrigger.registerProviders(); if (args.length > 0 && args[0].equals("setup") && !disableSetup) { LogHelper.debug("Read ServerWrapperConfig.json"); loadConfig();