package io.gitlab.jfronny.inceptum.windows.control; import imgui.ImGui; import imgui.flag.ImGuiTableFlags; 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.ProcessUtils; import io.gitlab.jfronny.inceptum.util.Utils; import io.gitlab.jfronny.inceptum.util.VersionInfoLibraryResolver; 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 io.gitlab.jfronny.inceptum.windows.InstanceEditWindow; 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 InstanceView { public static void draw(List paths) { if (ImGui.beginTable("Instances", 2, ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.Borders)) { for (Path path : paths) { if (Files.exists(path.resolve("inceptum.setup.lock"))) { ImGui.tableNextColumn(); ImGui.text("Setting up"); ImGui.tableNextColumn(); ImGui.text("This instance is currently being set up"); continue; } if (!Files.exists(path.resolve("instance.json"))) { Inceptum.LOGGER.error("Invalid instance (doesn't contain instance.json): " + path); continue; } InstanceMeta instance; try { instance = Utils.loadObject(path.resolve("instance.json"), InstanceMeta.class); } catch (IOException e) { Inceptum.LOGGER.error("Could not load instance.json", e); continue; } ImGui.tableNextColumn(); boolean disabled = false; if (Files.exists(path.resolve("inceptum.lock"))) { try { if (ProcessUtils.isProcessAlive(Files.readString(path.resolve("inceptum.lock")))) disabled = true; else Files.delete(path.resolve("inceptum.lock")); } catch (IOException e) { continue; } } if (disabled) ImGui.beginDisabled(); if (ImGui.button(path.getFileName().toString())) launch(path, instance); ImGui.tableNextColumn(); if (ImGui.button("Edit##" + path)) Inceptum.open(new InstanceEditWindow(path, instance)); if (disabled) ImGui.endDisabled(); } ImGui.endTable(); } } private 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()); } args.add(Objects.requireNonNullElseGet(instance.java, () -> Utils.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(':'); } classPath.append(Inceptum.LIBRARIES_DIR.resolve("net/minecraft/minecraft").resolve(version.id + ".jar").toAbsolutePath()); //TODO custom JVM args 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 (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; } 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) { e.printStackTrace(); } } } } 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) .replace("${classpath}", classPath) .replace("${user_properties}", "{}"); } }