package io.gitlab.jfronny.inceptum.util; import io.gitlab.jfronny.inceptum.Inceptum; import io.gitlab.jfronny.inceptum.install.steps.DownloadLibrariesStep; import io.gitlab.jfronny.inceptum.model.inceptum.ArtifactInfo; import io.gitlab.jfronny.inceptum.model.inceptum.InstanceMeta; import io.gitlab.jfronny.inceptum.model.mojang.MinecraftArgument; import io.gitlab.jfronny.inceptum.model.mojang.VersionInfo; import io.gitlab.jfronny.inceptum.model.mojang.VersionsListInfo; import io.gitlab.jfronny.inceptum.util.api.FabricMetaApi; import io.gitlab.jfronny.inceptum.util.api.McApi; import io.gitlab.jfronny.inceptum.util.api.account.AccountManager; import io.gitlab.jfronny.inceptum.util.api.account.AuthInfo; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; public class ClientLauncher { public static void launch(Path path, InstanceMeta instance) { for (VersionsListInfo version : McApi.getVersions().versions) { if (version.id.equals(instance.getMinecraftVersion())) { try { List args = new ArrayList<>(); VersionInfo info = McApi.getVersionInfo(version); if (instance.isFabric()) { FabricMetaApi.addFabric(info, instance.getLoaderVersion(), FabricMetaApi.FabricVersionInfoType.Client); } args.add(Objects.requireNonNullElseGet(instance.java, () -> JvmUtils.getJvmMain(Inceptum.NATIVES_DIR .resolve(info.javaVersion.component) .resolve(Integer.toString(info.javaVersion.majorVersion))) .toAbsolutePath().toString())); DownloadLibrariesStep.execute(info, new AtomicBoolean(false), new AtomicReference<>()); StringBuilder classPath = new StringBuilder(); for (ArtifactInfo artifact : VersionInfoLibraryResolver.getRelevant(info)) { classPath.append(Inceptum.LIBRARIES_DIR.resolve(artifact.path).toAbsolutePath()); classPath.append(File.pathSeparatorChar); } classPath.append(Inceptum.LIBRARIES_DIR.resolve("net/minecraft/client").resolve(version.id + ".jar").toAbsolutePath()); if (info.arguments != null) args.addAll(parse(info.arguments.jvm, info, instance, classPath.toString(), path.toAbsolutePath().toString())); if (instance.minMem != null) args.add("-Xms" + instance.minMem); if (instance.maxMem != null) args.add("-Xmx" + instance.maxMem); if (instance.jvmArgsCustom != null) args.addAll(instance.jvmArgsCustom); if (info.minecraftArguments != null) { args.add("-cp"); args.add(classPath.toString()); args.add("-Djava.library.path=" + Inceptum.NATIVES_DIR.resolve(instance.getMinecraftVersion()).toAbsolutePath()); } args.add(info.mainClass); if (info.arguments != null) args.addAll(parse(info.arguments.game, info, instance, classPath.toString(), path.toAbsolutePath().toString())); else if (info.minecraftArguments != null) { for (String s : info.minecraftArguments.split(" ")) { args.add(expandArg(s, info, instance, classPath.toString(), path.toAbsolutePath().toString())); } } else { Inceptum.LOGGER.error("Could not launch: No valid argument source found"); return; } if (instance.gameArgsCustom != null) args.addAll(instance.gameArgsCustom); Inceptum.LOGGER.info(String.join(" ", args)); ProcessBuilder pb = new ProcessBuilder(args.toArray(new String[0])); pb.directory(path.toFile()); pb.redirectOutput(ProcessBuilder.Redirect.INHERIT); pb.redirectError(ProcessBuilder.Redirect.INHERIT); Files.writeString(path.resolve("inceptum.lock"), Long.toString(pb.start().pid())); } catch (IOException e) { Inceptum.showError("Could not launch client", e); } } } } private static List parse(List arguments, VersionInfo info, InstanceMeta instance, String classPath, String gameDirectory) { List res = new ArrayList<>(); for (MinecraftArgument argument : arguments) { for (String s : argument.arg()) { res.add(expandArg(s, info, instance, classPath, gameDirectory)); } } return res; } private static String expandArg(String arg, VersionInfo info, InstanceMeta instance, String classPath, String gameDirectory) { AuthInfo authInfo = AccountManager.getSelectedAccount(); return arg // game args .replace("${auth_player_name}", authInfo.name()) .replace("${version_name}", instance.getMinecraftVersion()) .replace("${game_directory}", gameDirectory) .replace("${assets_root}", Inceptum.ASSETS_DIR.toAbsolutePath().toString()) .replace("${assets_index_name}", info.assets) .replace("${auth_uuid}", authInfo.uuid()) .replace("${auth_access_token}", authInfo.accessToken()) .replace("${user_type}", authInfo.userType()) .replace("${version_type}", info.type) .replace("${resolution_width}", "1920") //TODO has_custom_resolution .replace("${resolution_height}", "1080") //TODO has_custom_resolution // jvm args .replace("${natives_directory}", Inceptum.NATIVES_DIR.resolve(instance.getMinecraftVersion()).toAbsolutePath().toString()) .replace("${launcher_name}", "Inceptum") .replace("${launcher_version}", Inceptum.VERSION.version.toString()) .replace("${classpath}", classPath) .replace("${user_properties}", "{}"); } }