package io.gitlab.jfronny.glaunch.windows; import imgui.ImGui; import imgui.flag.ImGuiTableFlags; import imgui.flag.ImGuiWindowFlags; import imgui.type.ImBoolean; import io.gitlab.jfronny.glaunch.GLaunch; import io.gitlab.jfronny.glaunch.model.InstanceMeta; import io.gitlab.jfronny.glaunch.model.MinecraftArgument; import io.gitlab.jfronny.glaunch.model.VersionInfo; import io.gitlab.jfronny.glaunch.model.VersionsListInfo; import io.gitlab.jfronny.glaunch.util.Utils; import io.gitlab.jfronny.glaunch.util.VersionInfoLibraryResolver; import io.gitlab.jfronny.glaunch.util.mojang.McApi; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; public class MainWindow extends Window { private final ImBoolean darkTheme = new ImBoolean(GLaunch.CONFIG.darkTheme); private final ImBoolean debugTools = new ImBoolean(false); private final List instances; //TODO custom ordering public MainWindow() { super("GLaunch"); List instances = new ArrayList<>(); try { for (Path path : Files.list(GLaunch.INSTANCE_DIR).filter(Files::isDirectory).toList()) { if (Files.exists(path.resolve("instance.json"))) { InstanceMeta im = Utils.loadObject(path.resolve("instance.json"), InstanceMeta.class); im.instancePath = path; instances.add(im); } else { GLaunch.LOGGER.error("Invalid instance (doesn't contain instance.json): " + path); } } } catch (IOException e) { GLaunch.LOGGER.error("Could not list present instances", e); } this.instances = List.copyOf(instances); } @Override public int getFlags() { return ImGuiWindowFlags.MenuBar | ImGuiWindowFlags.AlwaysAutoResize; } @Override public void draw() { ImGui.beginMenuBar(); if (ImGui.beginMenu("File")) { if (ImGui.menuItem("New Instance")) GLaunch.open(new NewInstanceWindow()); if (ImGui.menuItem("Exit GLaunch2")) GLaunch.exit(); ImGui.endMenu(); } if (ImGui.beginMenu("Settings")) { if (ImGui.checkbox("Dark Theme", darkTheme)) { GLaunch.CONFIG.darkTheme = darkTheme.get(); GLaunch.saveConfig(); GLaunch.applyTheme(); } ImGui.endMenu(); } if (ImGui.beginMenu("Help")) { if (ImGui.menuItem("About")) GLaunch.open(new AboutWindow()); if (ImGui.menuItem("Log")) GLaunch.open(new LogWindow()); ImGui.checkbox("Debug Tools", debugTools); ImGui.endMenu(); } ImGui.endMenuBar(); if (debugTools.get()) { ImGui.showDemoWindow(); } if (instances.isEmpty()) { ImGui.text("You have not yet created an instance"); ImGui.text("Use File->New Instance to do so"); } else { if (ImGui.beginTable("Instances", 2, ImGuiTableFlags.Resizable | ImGuiTableFlags.Borders)) { for (InstanceMeta instance : instances) { ImGui.tableNextColumn(); if (ImGui.button(instance.instancePath.getFileName().toString())) { //TODO implement fabric support //TODO extract launch logic to separate class for (VersionsListInfo version : McApi.getVersions().versions) { if (version.id.equals(instance.version)) { try { List args = new ArrayList<>(); args.add("/lib/jvm/java-17-openjdk/bin/java"); //TODO allow selecting vm, detect with System.getProperty("java.home") VersionInfo info = McApi.getVersionInfo(version); StringBuilder classPath = new StringBuilder(); for (VersionInfo.Library.Downloads.Artifact artifact : VersionInfoLibraryResolver.getRelevant(info)) { classPath.append(GLaunch.LIBRARIES_DIR.resolve(artifact.path).toAbsolutePath()); classPath.append(':'); } classPath.append(GLaunch.LIBRARIES_DIR.resolve("net/minecraft/minecraft").resolve(version.id + ".jar").toAbsolutePath()); GLaunch.LOGGER.info(classPath.toString()); //TODO -Xms{lowMem} -Xmx{maxMem} args.addAll(parse(info.arguments.jvm, info, instance, classPath.toString())); args.add(info.mainClass); args.addAll(parse(info.arguments.game, info, instance, classPath.toString())); //Process p = Runtime.getRuntime().exec(args.toArray(new String[0]), new String[0], instance.instancePath.toFile()); ProcessBuilder pb = new ProcessBuilder(args.toArray(new String[0])); pb.directory(instance.instancePath.toFile()); pb.redirectOutput(ProcessBuilder.Redirect.INHERIT); pb.redirectError(ProcessBuilder.Redirect.INHERIT); pb.start(); } catch (IOException e) { e.printStackTrace(); } } } } ImGui.tableNextColumn(); if (ImGui.button("Edit")) { GLaunch.LOGGER.error("Editing not yet implemented"); //TODO allow changing name (moving), changing version, managing mods etc } } ImGui.endTable(); } } } private List parse(List arguments, VersionInfo info, InstanceMeta instance, String classPath) { List res = new ArrayList<>(); for (MinecraftArgument argument : arguments) { for (String s : argument.arg()) { //TODO support old versions res.add(s // game args .replace("${auth_player_name}", "Joe") //TODO auth support .replace("${version_name}", info.id) //TODO fabric support .replace("${game_directory}", instance.instancePath.toAbsolutePath().toString()) .replace("${assets_root}", GLaunch.ASSETS_DIR.toAbsolutePath().toString()) .replace("${assets_index_name}", info.assets) .replace("${auth_uuid}", "2536abce90e8476a871679918164abc5") //TODO auth support .replace("${auth_access_token}", "99abe417230342cb8e9e2168ab46297a") //TODO auth support .replace("${user_type}", "legacy") //TODO auth support .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}", GLaunch.INSTANCE_DIR.toAbsolutePath().toString()) .replace("${launcher_name}", "GLaunch") .replace("${launcher_version}", "1.0") //TODO automatically fill in .replace("${classpath}", classPath) ); } } return res; } }