From 97251ea548b2599313bab898d37425ea49d82786 Mon Sep 17 00:00:00 2001 From: JFronny Date: Sat, 30 Oct 2021 22:05:24 +0200 Subject: [PATCH] Server support --- .gitlab-ci.yml | 1 + .../io/gitlab/jfronny/inceptum/Inceptum.java | 224 +++--------------- .../gitlab/jfronny/inceptum/InceptumGui.java | 202 ++++++++++++++++ .../gitlab/jfronny/inceptum/cli/Command.java | 33 +++ .../jfronny/inceptum/cli/GuiCommand.java | 21 ++ .../jfronny/inceptum/cli/HelpCommand.java | 16 ++ .../jfronny/inceptum/cli/JvmStateCommand.java | 28 +++ .../jfronny/inceptum/cli/LaunchCommand.java | 58 +++++ .../jfronny/inceptum/install/Steps.java | 42 ++++ .../install/steps/DownloadClientStep.java | 23 +- .../install/steps/WriteMetadataStep.java | 8 +- .../inceptum/model/inceptum/InstanceMeta.java | 4 + .../jfronny/inceptum/util/ClientLauncher.java | 112 +++++++++ .../jfronny/inceptum/util/ServerLauncher.java | 81 +++++++ .../gitlab/jfronny/inceptum/util/Utils.java | 8 +- .../inceptum/util/api/FabricMetaApi.java | 18 +- .../util/api/account/AccountManager.java | 6 +- .../util/api/account/MicrosoftAccount.java | 7 +- .../windows/InstanceCreateProcessWindow.java | 8 +- .../inceptum/windows/InstanceEditWindow.java | 31 ++- .../jfronny/inceptum/windows/MainWindow.java | 40 +--- .../windows/MicrosoftLoginWindow.java | 7 +- .../inceptum/windows/NewInstanceWindow.java | 8 +- .../jfronny/inceptum/windows/Window.java | 4 +- .../control/InstanceManageControls.java | 14 +- .../windows/control/InstanceView.java | 107 +-------- 26 files changed, 736 insertions(+), 375 deletions(-) create mode 100644 src/main/java/io/gitlab/jfronny/inceptum/InceptumGui.java create mode 100644 src/main/java/io/gitlab/jfronny/inceptum/cli/Command.java create mode 100644 src/main/java/io/gitlab/jfronny/inceptum/cli/GuiCommand.java create mode 100644 src/main/java/io/gitlab/jfronny/inceptum/cli/HelpCommand.java create mode 100644 src/main/java/io/gitlab/jfronny/inceptum/cli/JvmStateCommand.java create mode 100644 src/main/java/io/gitlab/jfronny/inceptum/cli/LaunchCommand.java create mode 100644 src/main/java/io/gitlab/jfronny/inceptum/util/ClientLauncher.java create mode 100644 src/main/java/io/gitlab/jfronny/inceptum/util/ServerLauncher.java diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index cde36f8..9b001d1 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -9,6 +9,7 @@ before_script: build_test: stage: deploy script: + - gradle --build-cache build -Pflavor=nogui - gradle --build-cache build -Pflavor=fat - gradle --build-cache build -Pflavor=windows - gradle --build-cache build -Pflavor=linux diff --git a/src/main/java/io/gitlab/jfronny/inceptum/Inceptum.java b/src/main/java/io/gitlab/jfronny/inceptum/Inceptum.java index b10e9f5..6ed70ae 100644 --- a/src/main/java/io/gitlab/jfronny/inceptum/Inceptum.java +++ b/src/main/java/io/gitlab/jfronny/inceptum/Inceptum.java @@ -2,11 +2,7 @@ package io.gitlab.jfronny.inceptum; import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import imgui.ImGui; -import imgui.ImGuiIO; -import imgui.flag.ImGuiConfigFlags; -import imgui.gl3.ImGuiImplGl3; -import imgui.glfw.ImGuiImplGlfw; +import io.gitlab.jfronny.inceptum.cli.*; import io.gitlab.jfronny.inceptum.gson.GsonIgnoreExclusionStrategy; import io.gitlab.jfronny.inceptum.gson.MinecraftArgumentDeserializer; import io.gitlab.jfronny.inceptum.gson.OauthTokenResponseDeserializer; @@ -16,17 +12,7 @@ import io.gitlab.jfronny.inceptum.model.microsoft.OauthTokenResponse; import io.gitlab.jfronny.inceptum.model.mojang.MinecraftArgument; import io.gitlab.jfronny.inceptum.model.mojang.Rules; import io.gitlab.jfronny.inceptum.util.Utils; -import io.gitlab.jfronny.inceptum.util.api.account.AccountManager; -import io.gitlab.jfronny.inceptum.windows.MainWindow; -import io.gitlab.jfronny.inceptum.windows.Window; -import org.lwjgl.glfw.Callbacks; -import org.lwjgl.glfw.GLFW; -import org.lwjgl.glfw.GLFWErrorCallback; -import org.lwjgl.glfw.GLFWVidMode; -import org.lwjgl.opengl.GL; -import org.lwjgl.opengl.GL32; -import org.lwjgl.system.MemoryStack; -import org.lwjgl.system.MemoryUtil; +import io.gitlab.jfronny.inceptum.windows.AlertWindow; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -34,11 +20,8 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.lang.reflect.Modifier; -import java.nio.IntBuffer; import java.nio.file.Files; import java.nio.file.Path; -import java.util.LinkedHashSet; -import java.util.Objects; import java.util.Set; //TODO generate gitignore @@ -46,7 +29,9 @@ import java.util.Set; //TODO allow instance sync through metadata //TODO update checker public class Inceptum { - public static final Set WINDOWS = new LinkedHashSet<>(); + public static final Set COMMANDS = Set.of(new HelpCommand(), new GuiCommand(), new LaunchCommand(), new JvmStateCommand()); + public static boolean IS_GUI; + public static final Logger LOGGER = LoggerFactory.getLogger("Inceptum"); public static final Gson GSON = new GsonBuilder() .registerTypeAdapter(MinecraftArgument.class, new MinecraftArgumentDeserializer()) @@ -73,20 +58,32 @@ public class Inceptum { InputStreamReader isr = new InputStreamReader(is)) { VERSION = GSON.fromJson(isr, InceptumVersion.class); } - LOGGER.info("Launching Inceptum v" + VERSION.version); - LOGGER.info("Setting up cache dir"); + if (args.length == 0) args = new String[]{"gui"}; + Command cmd = null; + for (Command command : COMMANDS) { + if (command.isAlias(args[0])) { + cmd = command; + break; + } + } + if (cmd == null) { + System.out.println("Command not found"); + return; + } + if (cmd.enableLog()) { + LOGGER.info("Launching Inceptum v" + VERSION.version); + LOGGER.info("Setting up cache dir"); + } + if (!Files.exists(CONFIG_PATH.getParent())) Files.createDirectories(CONFIG_PATH.getParent()); if (!Files.exists(CONFIG_PATH)) Utils.writeObject(CONFIG_PATH, new Config()); CONFIG = Utils.loadObject(CONFIG_PATH, Config.class); if (!Files.exists(CACHE_DIR)) Files.createDirectories(CACHE_DIR); + Utils.clearDirectory(CACHE_DIR); if (!Files.exists(INSTANCE_DIR)) Files.createDirectories(INSTANCE_DIR); if (!Files.exists(ASSETS_DIR)) Files.createDirectories(ASSETS_DIR); if (!Files.exists(LIBRARIES_DIR)) Files.createDirectories(LIBRARIES_DIR); - AccountManager.loadAccounts(); - LOGGER.info("Initializing UI"); - WINDOWS.add(new MainWindow()); - init(); - run(); - dispose(); + + cmd.invoke(args); } public static void saveConfig() { @@ -97,169 +94,24 @@ public class Inceptum { } } - public static void open(Window window) { - WINDOWS.add(window); + public static void showError(String message, String title) { + LOGGER.error(message); + if (IS_GUI) InceptumGui.WINDOWS.add(new AlertWindow(title, message)); } - private static final ImGuiImplGlfw imGuiGlfw = new ImGuiImplGlfw(); - private static final ImGuiImplGl3 imGuiGl3 = new ImGuiImplGl3(); - - private static String glslVersion = null; - - /** - * Pointer to the native GLFW window. - */ - protected static long handle; - - /** - * Method to initialize application. - */ - protected static void init() { - initWindow(); - initImGui(); - imGuiGlfw.init(handle, true); - imGuiGl3.init(glslVersion); + public static void showError(String message, Throwable t) { + LOGGER.error(message, t); + if (IS_GUI) InceptumGui.WINDOWS.add(new AlertWindow(message, t.toString())); } - /** - * Method to dispose all used application resources and destroy its window. - */ - protected static void dispose() { - imGuiGl3.dispose(); - imGuiGlfw.dispose(); - //TODO figure out why this is a problem - //ImGui.destroyContext(); - Callbacks.glfwFreeCallbacks(handle); - GLFW.glfwDestroyWindow(handle); - GLFW.glfwTerminate(); - Objects.requireNonNull(GLFW.glfwSetErrorCallback(null)).free(); + public static void showInfo(String message, String title) { + LOGGER.info(message); + if (IS_GUI) InceptumGui.WINDOWS.add(new AlertWindow(title, message)); } - /** - * Method to create and initialize GLFW window. - */ - protected static void initWindow() { - GLFWErrorCallback.createPrint(System.err).set(); - - if (!GLFW.glfwInit()) { - throw new IllegalStateException("Unable to initialize GLFW"); - } - - decideGlGlslVersions(); - - GLFW.glfwWindowHint(GLFW.GLFW_VISIBLE, GLFW.GLFW_FALSE); - GLFW.glfwWindowHint(GLFW.GLFW_RESIZABLE, GLFW.GLFW_FALSE); - handle = GLFW.glfwCreateWindow(10, 10, "Inceptum", MemoryUtil.NULL, MemoryUtil.NULL); - - if (handle == MemoryUtil.NULL) { - throw new RuntimeException("Failed to create the GLFW window"); - } - - try (MemoryStack stack = MemoryStack.stackPush()) { - final IntBuffer pWidth = stack.mallocInt(1); // int* - final IntBuffer pHeight = stack.mallocInt(1); // int* - - GLFW.glfwGetWindowSize(handle, pWidth, pHeight); - final GLFWVidMode vidmode = Objects.requireNonNull(GLFW.glfwGetVideoMode(GLFW.glfwGetPrimaryMonitor())); - GLFW.glfwSetWindowPos(handle, (vidmode.width() - pWidth.get(0)) / 2, (vidmode.height() - pHeight.get(0)) / 2); - } - - GLFW.glfwMakeContextCurrent(handle); - - GL.createCapabilities(); - - GLFW.glfwSwapInterval(GLFW.GLFW_TRUE); - - clearBuffer(); - renderBuffer(); - } - - private static void decideGlGlslVersions() { - final boolean isMac = System.getProperty("os.name").toLowerCase().contains("mac"); - if (isMac) { - glslVersion = "#version 150"; - GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MAJOR, 3); - GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MINOR, 2); - GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_PROFILE, GLFW.GLFW_OPENGL_CORE_PROFILE); // 3.2+ only - GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_FORWARD_COMPAT, GLFW.GLFW_TRUE); // Required on Mac - } else { - glslVersion = "#version 130"; - GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MAJOR, 3); - GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MINOR, 0); - } - } - - /** - * Method to initialize Dear ImGui context. Could be overridden to do custom Dear ImGui setup before application start. - */ - protected static void initImGui() { - ImGui.createContext(); - ImGuiIO io = ImGui.getIO(); - io.addConfigFlags(ImGuiConfigFlags.ViewportsEnable); - //io.setConfigViewportsNoDecoration(false); - io.setConfigViewportsNoAutoMerge(true); - //TODO use included icons (https://www.nerdfonts.com/cheat-sheet) - //Nerd Fonts-patched ubuntu font - try (InputStream is = Inceptum.class.getClassLoader().getResourceAsStream("font.ttf")) { - assert is != null; - io.setFontDefault(io.getFonts().addFontFromMemoryTTF(is.readAllBytes(), 16f)); - } catch (IOException e) { - e.printStackTrace(); - } - applyTheme(); - } - - /** - * Main application loop. - */ - protected static void run() { - while (!GLFW.glfwWindowShouldClose(handle)) { - //frame - clearBuffer(); - imGuiGlfw.newFrame(); - ImGui.newFrame(); - //render - if (Inceptum.WINDOWS.isEmpty()) exit(); - else { - Window[] array = Inceptum.WINDOWS.toArray(new Window[0]); - for (int i = 0, arrayLength = array.length; i < arrayLength; i++) { - Window window = array[i]; - if (window.isNew()) window.preFirstDraw(); - if (ImGui.begin(window.getName() + "##" + i, window.getOpenState(), window.getFlags())) - window.draw(); - ImGui.end(); - if (!window.getOpenState().get()) window.close(); - } - } - //end frame - ImGui.render(); - imGuiGl3.renderDrawData(ImGui.getDrawData()); - - if (ImGui.getIO().hasConfigFlags(ImGuiConfigFlags.ViewportsEnable)) { - final long backupWindowPtr = GLFW.glfwGetCurrentContext(); - ImGui.updatePlatformWindows(); - ImGui.renderPlatformWindowsDefault(); - GLFW.glfwMakeContextCurrent(backupWindowPtr); - } - - renderBuffer(); - } - } - - private static void clearBuffer() { - GL32.glClear(GL32.GL_COLOR_BUFFER_BIT | GL32.GL_DEPTH_BUFFER_BIT); - } - - private static void renderBuffer() { - GLFW.glfwSwapBuffers(handle); - GLFW.glfwPollEvents(); - } - - public static void exit() { - GLFW.glfwSetWindowShouldClose(handle, true); - } - public static void applyTheme() { - if (CONFIG.darkTheme) ImGui.styleColorsDark(); - else ImGui.styleColorsLight(); + public static void showOkCancel(String message, String title, Runnable ok, Runnable cancel) { + LOGGER.info(message); + if (IS_GUI) InceptumGui.WINDOWS.add(new AlertWindow(title, message, ok, cancel)); + else ok.run(); } } diff --git a/src/main/java/io/gitlab/jfronny/inceptum/InceptumGui.java b/src/main/java/io/gitlab/jfronny/inceptum/InceptumGui.java new file mode 100644 index 0000000..7cfe9dc --- /dev/null +++ b/src/main/java/io/gitlab/jfronny/inceptum/InceptumGui.java @@ -0,0 +1,202 @@ +package io.gitlab.jfronny.inceptum; + +import imgui.ImGui; +import imgui.ImGuiIO; +import imgui.flag.ImGuiConfigFlags; +import imgui.gl3.ImGuiImplGl3; +import imgui.glfw.ImGuiImplGlfw; +import io.gitlab.jfronny.inceptum.util.api.account.AccountManager; +import io.gitlab.jfronny.inceptum.windows.MainWindow; +import io.gitlab.jfronny.inceptum.windows.Window; +import org.lwjgl.glfw.Callbacks; +import org.lwjgl.glfw.GLFW; +import org.lwjgl.glfw.GLFWErrorCallback; +import org.lwjgl.glfw.GLFWVidMode; +import org.lwjgl.opengl.GL; +import org.lwjgl.opengl.GL32; +import org.lwjgl.system.MemoryStack; +import org.lwjgl.system.MemoryUtil; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.IntBuffer; +import java.util.LinkedHashSet; +import java.util.Objects; +import java.util.Set; + +public class InceptumGui { + public static final Set WINDOWS = new LinkedHashSet<>(); + private static final ImGuiImplGlfw imGuiGlfw = new ImGuiImplGlfw(); + private static final ImGuiImplGl3 imGuiGl3 = new ImGuiImplGl3(); + /** + * Pointer to the native GLFW window. + */ + protected static long handle; + private static String glslVersion = null; + + public static void main(String[] args) { + AccountManager.loadAccounts(); + Inceptum.LOGGER.info("Initializing UI"); + InceptumGui.WINDOWS.add(new MainWindow()); + InceptumGui.init(); + InceptumGui.run(); + InceptumGui.dispose(); + } + + public static void open(Window window) { + WINDOWS.add(window); + } + + /** + * Method to initialize application. + */ + public static void init() { + initWindow(); + initImGui(); + imGuiGlfw.init(handle, true); + imGuiGl3.init(glslVersion); + } + + /** + * Method to dispose all used application resources and destroy its window. + */ + public static void dispose() { + imGuiGl3.dispose(); + imGuiGlfw.dispose(); + //TODO figure out why this is a problem + //ImGui.destroyContext(); + Callbacks.glfwFreeCallbacks(handle); + GLFW.glfwDestroyWindow(handle); + GLFW.glfwTerminate(); + Objects.requireNonNull(GLFW.glfwSetErrorCallback(null)).free(); + } + + /** + * Method to create and initialize GLFW window. + */ + protected static void initWindow() { + GLFWErrorCallback.createPrint(System.err).set(); + + if (!GLFW.glfwInit()) { + throw new IllegalStateException("Unable to initialize GLFW"); + } + + decideGlGlslVersions(); + + GLFW.glfwWindowHint(GLFW.GLFW_VISIBLE, GLFW.GLFW_FALSE); + GLFW.glfwWindowHint(GLFW.GLFW_RESIZABLE, GLFW.GLFW_FALSE); + handle = GLFW.glfwCreateWindow(10, 10, "Inceptum", MemoryUtil.NULL, MemoryUtil.NULL); + + if (handle == MemoryUtil.NULL) { + throw new RuntimeException("Failed to create the GLFW window"); + } + + try (MemoryStack stack = MemoryStack.stackPush()) { + final IntBuffer pWidth = stack.mallocInt(1); // int* + final IntBuffer pHeight = stack.mallocInt(1); // int* + + GLFW.glfwGetWindowSize(handle, pWidth, pHeight); + final GLFWVidMode vidmode = Objects.requireNonNull(GLFW.glfwGetVideoMode(GLFW.glfwGetPrimaryMonitor())); + GLFW.glfwSetWindowPos(handle, (vidmode.width() - pWidth.get(0)) / 2, (vidmode.height() - pHeight.get(0)) / 2); + } + + GLFW.glfwMakeContextCurrent(handle); + + GL.createCapabilities(); + + GLFW.glfwSwapInterval(GLFW.GLFW_TRUE); + + clearBuffer(); + renderBuffer(); + } + + private static void decideGlGlslVersions() { + final boolean isMac = System.getProperty("os.name").toLowerCase().contains("mac"); + if (isMac) { + glslVersion = "#version 150"; + GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MAJOR, 3); + GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MINOR, 2); + GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_PROFILE, GLFW.GLFW_OPENGL_CORE_PROFILE); // 3.2+ only + GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_FORWARD_COMPAT, GLFW.GLFW_TRUE); // Required on Mac + } else { + glslVersion = "#version 130"; + GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MAJOR, 3); + GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MINOR, 0); + } + } + + /** + * Method to initialize Dear ImGui context. Could be overridden to do custom Dear ImGui setup before application start. + */ + protected static void initImGui() { + ImGui.createContext(); + ImGuiIO io = ImGui.getIO(); + io.addConfigFlags(ImGuiConfigFlags.ViewportsEnable); + //io.setConfigViewportsNoDecoration(false); + io.setConfigViewportsNoAutoMerge(true); + //TODO use included icons (https://www.nerdfonts.com/cheat-sheet) + //Nerd Fonts-patched ubuntu font + try (InputStream is = Inceptum.class.getClassLoader().getResourceAsStream("font.ttf")) { + assert is != null; + io.setFontDefault(io.getFonts().addFontFromMemoryTTF(is.readAllBytes(), 16f)); + } catch (IOException e) { + e.printStackTrace(); + } + applyTheme(); + } + + /** + * Main application loop. + */ + public static void run() { + while (!GLFW.glfwWindowShouldClose(handle)) { + //frame + clearBuffer(); + imGuiGlfw.newFrame(); + ImGui.newFrame(); + //render + if (WINDOWS.isEmpty()) exit(); + else { + Window[] array = WINDOWS.toArray(new Window[0]); + for (int i = 0, arrayLength = array.length; i < arrayLength; i++) { + Window window = array[i]; + if (window.isNew()) window.preFirstDraw(); + if (ImGui.begin(window.getName() + "##" + i, window.getOpenState(), window.getFlags())) + window.draw(); + ImGui.end(); + if (!window.getOpenState().get()) window.close(); + } + } + //end frame + ImGui.render(); + imGuiGl3.renderDrawData(ImGui.getDrawData()); + + if (ImGui.getIO().hasConfigFlags(ImGuiConfigFlags.ViewportsEnable)) { + final long backupWindowPtr = GLFW.glfwGetCurrentContext(); + ImGui.updatePlatformWindows(); + ImGui.renderPlatformWindowsDefault(); + GLFW.glfwMakeContextCurrent(backupWindowPtr); + } + + renderBuffer(); + } + } + + private static void clearBuffer() { + GL32.glClear(GL32.GL_COLOR_BUFFER_BIT | GL32.GL_DEPTH_BUFFER_BIT); + } + + private static void renderBuffer() { + GLFW.glfwSwapBuffers(handle); + GLFW.glfwPollEvents(); + } + + public static void exit() { + GLFW.glfwSetWindowShouldClose(handle, true); + } + + public static void applyTheme() { + if (Inceptum.CONFIG.darkTheme) ImGui.styleColorsDark(); + else ImGui.styleColorsLight(); + } +} diff --git a/src/main/java/io/gitlab/jfronny/inceptum/cli/Command.java b/src/main/java/io/gitlab/jfronny/inceptum/cli/Command.java new file mode 100644 index 0000000..190e10f --- /dev/null +++ b/src/main/java/io/gitlab/jfronny/inceptum/cli/Command.java @@ -0,0 +1,33 @@ +package io.gitlab.jfronny.inceptum.cli; + +import java.util.Arrays; +import java.util.List; +import java.util.Locale; + +public abstract class Command { + private final String help; + private final List aliases; + + public Command(String help, String... aliases) { + this.help = help; + this.aliases = Arrays.asList(aliases); + } + + public boolean isAlias(String text) { + return aliases.contains(text.replaceAll("^[-/]*", "").toLowerCase(Locale.ROOT)); + } + + public String getName() { + return aliases.get(0); + } + + public String getHelp() { + return help; + } + + public boolean enableLog() { + return false; + } + + public abstract void invoke(String[] args); +} diff --git a/src/main/java/io/gitlab/jfronny/inceptum/cli/GuiCommand.java b/src/main/java/io/gitlab/jfronny/inceptum/cli/GuiCommand.java new file mode 100644 index 0000000..08f8ef2 --- /dev/null +++ b/src/main/java/io/gitlab/jfronny/inceptum/cli/GuiCommand.java @@ -0,0 +1,21 @@ +package io.gitlab.jfronny.inceptum.cli; + +import io.gitlab.jfronny.inceptum.Inceptum; +import io.gitlab.jfronny.inceptum.InceptumGui; + +public class GuiCommand extends Command { + public GuiCommand() { + super("Displays the Inceptum UI", "gui", "show"); + } + + @Override + public void invoke(String[] args) { + Inceptum.IS_GUI = true; + InceptumGui.main(args); + } + + @Override + public boolean enableLog() { + return true; + } +} diff --git a/src/main/java/io/gitlab/jfronny/inceptum/cli/HelpCommand.java b/src/main/java/io/gitlab/jfronny/inceptum/cli/HelpCommand.java new file mode 100644 index 0000000..87467c8 --- /dev/null +++ b/src/main/java/io/gitlab/jfronny/inceptum/cli/HelpCommand.java @@ -0,0 +1,16 @@ +package io.gitlab.jfronny.inceptum.cli; + +import io.gitlab.jfronny.inceptum.Inceptum; + +public class HelpCommand extends Command { + public HelpCommand() { + super("Displays this screen", "help"); + } + @Override + public void invoke(String[] args) { + System.out.println("Inceptum v" + Inceptum.VERSION.version + "\n\nCommands:"); + for (Command command : Inceptum.COMMANDS) { + System.out.println(" " + command.getName() + " - " + command.getHelp()); + } + } +} diff --git a/src/main/java/io/gitlab/jfronny/inceptum/cli/JvmStateCommand.java b/src/main/java/io/gitlab/jfronny/inceptum/cli/JvmStateCommand.java new file mode 100644 index 0000000..b41f14d --- /dev/null +++ b/src/main/java/io/gitlab/jfronny/inceptum/cli/JvmStateCommand.java @@ -0,0 +1,28 @@ +package io.gitlab.jfronny.inceptum.cli; + +import java.net.URLClassLoader; +import java.util.Arrays; + +public class JvmStateCommand extends Command { + public JvmStateCommand() { + super("Displays information about the JVM state. For debugging", "jvmstate"); + } + + @Override + public void invoke(String[] args) { + System.out.println(System.getProperty("java.class.path")); + dumpClasspath(JvmStateCommand.class.getClassLoader()); + } + + private static void dumpClasspath(ClassLoader loader) { + System.out.println("Classloader " + loader + ":"); + + if (loader instanceof URLClassLoader uc) + System.out.println("\t" + Arrays.toString(uc.getURLs())); + else + System.out.println("\t(cannot display components as not a URLClassLoader)"); + + if (loader.getParent() != null) + dumpClasspath(loader.getParent()); + } +} diff --git a/src/main/java/io/gitlab/jfronny/inceptum/cli/LaunchCommand.java b/src/main/java/io/gitlab/jfronny/inceptum/cli/LaunchCommand.java new file mode 100644 index 0000000..c2611e2 --- /dev/null +++ b/src/main/java/io/gitlab/jfronny/inceptum/cli/LaunchCommand.java @@ -0,0 +1,58 @@ +package io.gitlab.jfronny.inceptum.cli; + +import io.gitlab.jfronny.inceptum.Inceptum; +import io.gitlab.jfronny.inceptum.model.inceptum.InstanceMeta; +import io.gitlab.jfronny.inceptum.util.ClientLauncher; +import io.gitlab.jfronny.inceptum.util.ProcessUtils; +import io.gitlab.jfronny.inceptum.util.ServerLauncher; +import io.gitlab.jfronny.inceptum.util.Utils; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Locale; + +public class LaunchCommand extends Command { + public LaunchCommand() { + super("Launches the game. Optionally specify \"server\" or \"client\"", "run", "launch", "start"); + } + + @Override + public void invoke(String[] args) { + if (args.length < 2) { + Inceptum.LOGGER.error("You must provide an instance name or path"); + return; + } + String pArg = args.length == 2 ? args[1] : args[2]; + Path instanceDir = Files.exists(Path.of(pArg)) ? Path.of(pArg) : Inceptum.INSTANCE_DIR.resolve(pArg); + if (!Files.exists(instanceDir.resolve("instance.json"))) { + Inceptum.LOGGER.error("Not a valid instance"); + return; + } + if (Files.exists(instanceDir.resolve("inceptum.setup.lock"))) { + Inceptum.LOGGER.error("This instance is still being set up"); + return; + } + if (Files.exists(instanceDir.resolve("inceptum.lock"))) { + try { + if (ProcessUtils.isProcessAlive(Files.readString(instanceDir.resolve("inceptum.lock")))) { + Inceptum.LOGGER.error("This instance is already being ran"); + return; + } + } catch (IOException e) { + Inceptum.showError("Could not read inceptum lock", e); + return; + } + } + InstanceMeta instance; + try { + instance = Utils.loadObject(instanceDir.resolve("instance.json"), InstanceMeta.class); + } catch (IOException e) { + Inceptum.showError("Not a valid instance", e); + return; + } + if (args.length >= 3 && "server".equals(args[1].toLowerCase(Locale.ROOT))) + ServerLauncher.launch(instanceDir, instance); + else ClientLauncher.launch(instanceDir, instance); + } +} diff --git a/src/main/java/io/gitlab/jfronny/inceptum/install/Steps.java b/src/main/java/io/gitlab/jfronny/inceptum/install/Steps.java index 6c0842a..5a8ecb1 100644 --- a/src/main/java/io/gitlab/jfronny/inceptum/install/Steps.java +++ b/src/main/java/io/gitlab/jfronny/inceptum/install/Steps.java @@ -1,10 +1,23 @@ package io.gitlab.jfronny.inceptum.install; +import io.gitlab.jfronny.inceptum.Inceptum; import io.gitlab.jfronny.inceptum.install.steps.*; +import io.gitlab.jfronny.inceptum.model.inceptum.InstanceMeta; +import io.gitlab.jfronny.inceptum.model.inceptum.LoaderInfo; +import io.gitlab.jfronny.inceptum.model.mojang.VersionInfo; +import io.gitlab.jfronny.inceptum.model.mojang.VersionsListInfo; +import io.gitlab.jfronny.inceptum.util.Utils; +import io.gitlab.jfronny.inceptum.util.api.FabricMetaApi; +import io.gitlab.jfronny.inceptum.util.api.McApi; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; public class Steps { public static Set STEPS = new LinkedHashSet<>(List.of( @@ -15,4 +28,33 @@ public class Steps { new DownloadLibrariesStep(), new WriteMetadataStep()) ); + + public static void reDownload() throws IOException { + Files.list(Inceptum.INSTANCE_DIR).forEach(p -> { + try { + reDownload(p); + } catch (IOException e) { + Inceptum.showError("Could not execute refresh task", e); + } + }); + } + + public static void reDownload(Path instance) throws IOException { + if (Files.exists(instance.resolve("inceptum.setup.lock"))) return; + if (Files.exists(instance.resolve("inceptum.lock"))) return; + InstanceMeta im = Utils.loadObject(instance.resolve("instance.json"), InstanceMeta.class); + for (VersionsListInfo version : McApi.getVersions().versions) { + if (version.id.equals(im.getMinecraftVersion())) { + VersionInfo vi = McApi.getVersionInfo(version); + if (im.isFabric()) FabricMetaApi.addFabric(vi, im.getLoaderVersion(), FabricMetaApi.FabricVersionInfoType.Both); + LoaderInfo li = im.isFabric() + ? new LoaderInfo(LoaderInfo.Type.Fabric, im.getLoaderVersion()) + : LoaderInfo.NONE; + SetupStepInfo info = new SetupStepInfo(vi, li, instance.getFileName().toString(), new AtomicReference<>("Reloading")); + for (Step step : Steps.STEPS) { + step.execute(info, new AtomicBoolean(false)); + } + } + } + } } diff --git a/src/main/java/io/gitlab/jfronny/inceptum/install/steps/DownloadClientStep.java b/src/main/java/io/gitlab/jfronny/inceptum/install/steps/DownloadClientStep.java index d7bd19e..0c7e3d6 100644 --- a/src/main/java/io/gitlab/jfronny/inceptum/install/steps/DownloadClientStep.java +++ b/src/main/java/io/gitlab/jfronny/inceptum/install/steps/DownloadClientStep.java @@ -16,12 +16,21 @@ import java.util.concurrent.atomic.AtomicBoolean; public class DownloadClientStep implements Step { @Override public void execute(SetupStepInfo info, AtomicBoolean stopThread) throws IOException { - Path path = Inceptum.LIBRARIES_DIR.resolve("net/minecraft/minecraft"); - if (!Files.exists(path)) Files.createDirectories(path); - path = path.resolve(InstanceMeta.getMinecraftVersion(info.version().id) + ".jar"); - if (Files.exists(path)) return; - MojangFileDownload client = info.version().downloads.client; - info.setState("Downloading Client"); - Utils.downloadFile(client.url, client.sha1, path); + Path clientPath = Inceptum.LIBRARIES_DIR.resolve("net/minecraft/client"); + Path serverPath = Inceptum.LIBRARIES_DIR.resolve("net/minecraft/server"); + if (!Files.exists(clientPath)) Files.createDirectories(clientPath); + if (!Files.exists(serverPath)) Files.createDirectories(serverPath); + clientPath = clientPath.resolve(InstanceMeta.getMinecraftVersion(info.version().id) + ".jar"); + serverPath = serverPath.resolve(InstanceMeta.getMinecraftVersion(info.version().id) + ".jar"); + if (!Files.exists(clientPath)) { + MojangFileDownload client = info.version().downloads.client; + info.setState("Downloading Client"); + Utils.downloadFile(client.url, client.sha1, clientPath); + } + if (!Files.exists(serverPath)) { + MojangFileDownload client = info.version().downloads.server; + info.setState("Downloading Server"); + Utils.downloadFile(client.url, client.sha1, serverPath); + } } } diff --git a/src/main/java/io/gitlab/jfronny/inceptum/install/steps/WriteMetadataStep.java b/src/main/java/io/gitlab/jfronny/inceptum/install/steps/WriteMetadataStep.java index 12971cf..f6a1085 100644 --- a/src/main/java/io/gitlab/jfronny/inceptum/install/steps/WriteMetadataStep.java +++ b/src/main/java/io/gitlab/jfronny/inceptum/install/steps/WriteMetadataStep.java @@ -1,6 +1,7 @@ package io.gitlab.jfronny.inceptum.install.steps; import io.gitlab.jfronny.inceptum.Inceptum; +import io.gitlab.jfronny.inceptum.InceptumGui; import io.gitlab.jfronny.inceptum.install.SetupStepInfo; import io.gitlab.jfronny.inceptum.install.Step; import io.gitlab.jfronny.inceptum.model.inceptum.InstanceMeta; @@ -33,7 +34,9 @@ public class WriteMetadataStep implements Step { logs/ .mixin.out/ .fabric/ - mods/*.jar"""); + mods/*.jar + *.lock + eula.txt"""); } Path gitDir = instance.resolve(".git"); if (!Files.exists(gitDir)) { @@ -47,8 +50,7 @@ public class WriteMetadataStep implements Step { .setSign(false) .setAuthor("Inceptum", "inceptum@jfronny.gitlab.io").call(); } catch (GitAPIException e) { - Inceptum.LOGGER.error("Could not initialize git", e); - Inceptum.open(new AlertWindow("Could not initialize git", e.toString())); + Inceptum.showError("Could not initialize Git", e); } } } diff --git a/src/main/java/io/gitlab/jfronny/inceptum/model/inceptum/InstanceMeta.java b/src/main/java/io/gitlab/jfronny/inceptum/model/inceptum/InstanceMeta.java index 436d6a3..aae11bb 100644 --- a/src/main/java/io/gitlab/jfronny/inceptum/model/inceptum/InstanceMeta.java +++ b/src/main/java/io/gitlab/jfronny/inceptum/model/inceptum/InstanceMeta.java @@ -2,12 +2,16 @@ package io.gitlab.jfronny.inceptum.model.inceptum; import io.gitlab.jfronny.inceptum.gson.GsonIgnore; +import java.util.List; + public class InstanceMeta { @GsonIgnore public static final String floaderPrefix = "fabric-loader-"; public String version; public String java; //TODO allow configuring public Long minMem; public Long maxMem; + public List jvmArgsCustom; //TODO allow configuring + public List gameArgsCustom; //TODO allow configuring public boolean isFabric() { return version.startsWith(floaderPrefix); diff --git a/src/main/java/io/gitlab/jfronny/inceptum/util/ClientLauncher.java b/src/main/java/io/gitlab/jfronny/inceptum/util/ClientLauncher.java new file mode 100644 index 0000000..e2c6341 --- /dev/null +++ b/src/main/java/io/gitlab/jfronny/inceptum/util/ClientLauncher.java @@ -0,0 +1,112 @@ +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.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, () -> + 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/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) + .replace("${classpath}", classPath) + .replace("${user_properties}", "{}"); + } +} diff --git a/src/main/java/io/gitlab/jfronny/inceptum/util/ServerLauncher.java b/src/main/java/io/gitlab/jfronny/inceptum/util/ServerLauncher.java new file mode 100644 index 0000000..09d7987 --- /dev/null +++ b/src/main/java/io/gitlab/jfronny/inceptum/util/ServerLauncher.java @@ -0,0 +1,81 @@ +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.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 java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; + +public class ServerLauncher { + 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); + String mainClass = null; + if (instance.isFabric()) { + FabricMetaApi.addFabric(info, instance.getLoaderVersion(), FabricMetaApi.FabricVersionInfoType.Server); + mainClass = info.mainClass; + } + 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(':'); + } + Path serverJar = Inceptum.LIBRARIES_DIR.resolve("net/minecraft/server").resolve(version.id + ".jar").toAbsolutePath(); + classPath.append(serverJar); + 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); + args.add("-cp"); + args.add(classPath.toString()); + if (mainClass == null) { + final String linePrefix = "Main-Class: "; + try (FileSystem fs = FileSystems.newFileSystem(new URI("jar", serverJar.toUri().toString(), null), new HashMap<>())) { + for (String line : Files.readAllLines(fs.getPath("META-INF/MANIFEST.MF"))) { + if (line.startsWith(linePrefix)) { + mainClass = line.substring(linePrefix.length()); + } + } + } + } + if (mainClass == null) throw new IOException("Could not identify entrypoint"); + args.add(mainClass); + 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 | URISyntaxException e) { + Inceptum.showError("Could not launch server", e); + } + } + } + } +} diff --git a/src/main/java/io/gitlab/jfronny/inceptum/util/Utils.java b/src/main/java/io/gitlab/jfronny/inceptum/util/Utils.java index 9ed7c9d..cadf7d7 100644 --- a/src/main/java/io/gitlab/jfronny/inceptum/util/Utils.java +++ b/src/main/java/io/gitlab/jfronny/inceptum/util/Utils.java @@ -71,16 +71,14 @@ public class Utils { private static T downloadObject(String url, ThrowingSupplier sourceString, Function builder) throws IOException { Path cache = Inceptum.CACHE_DIR.resolve(Integer.toString(url.hashCode())); + if (Files.exists(cache)) + return builder.apply(Files.readString(cache)); try { String download = sourceString.get(); Files.writeString(cache, download); return builder.apply(download); } catch (IOException e) { - if (Files.exists(cache)) { - Inceptum.LOGGER.info("Using cache for " + url, e); - return builder.apply(Files.readString(cache)); - } else - throw new IOException("Could not download object and no cache exists", e); + throw new IOException("Could not download object and no cache exists", e); } } diff --git a/src/main/java/io/gitlab/jfronny/inceptum/util/api/FabricMetaApi.java b/src/main/java/io/gitlab/jfronny/inceptum/util/api/FabricMetaApi.java index 3b8dee4..499044c 100644 --- a/src/main/java/io/gitlab/jfronny/inceptum/util/api/FabricMetaApi.java +++ b/src/main/java/io/gitlab/jfronny/inceptum/util/api/FabricMetaApi.java @@ -30,17 +30,23 @@ public class FabricMetaApi { return Utils.downloadObject(META_URL + "v2/versions/loader/" + gameVersion.id + "/" + fabricVersion, FabricVersionLoaderInfo.WithMeta.class); } - public static void addFabric(VersionInfo version, String fabricVersion) throws IOException { + public static void addFabric(VersionInfo version, String fabricVersion, FabricVersionInfoType type) throws IOException { FabricVersionLoaderInfo ver = getLoaderVersion(version, fabricVersion); if (!(ver instanceof FabricVersionLoaderInfo.WithMeta verWithMeta)) throw new IOException("Doesn't hold metadata"); FabricVersionLoaderInfo.WithMeta.LauncherMeta meta = verWithMeta.launcherMeta; if (meta.version != 1) throw new IOException("Unsupported fabric launcherMeta version: " + meta.version); - version.mainClass = meta.mainClass.client; + version.mainClass = type == FabricVersionInfoType.Server ? meta.mainClass.server : meta.mainClass.client; List libs = new ArrayList<>(version.libraries); for (FabricVersionLoaderInfo.WithMeta.LauncherMeta.Libraries.Library library : meta.libraries.common) libs.add(convertLib(library)); - for (FabricVersionLoaderInfo.WithMeta.LauncherMeta.Libraries.Library library : meta.libraries.client) - libs.add(convertLib(library)); + if (type == FabricVersionInfoType.Client || type == FabricVersionInfoType.Both) { + for (FabricVersionLoaderInfo.WithMeta.LauncherMeta.Libraries.Library library : meta.libraries.client) + libs.add(convertLib(library)); + } + if (type == FabricVersionInfoType.Server || type == FabricVersionInfoType.Both) { + for (FabricVersionLoaderInfo.WithMeta.LauncherMeta.Libraries.Library library : meta.libraries.server) + libs.add(convertLib(library)); + } var floader = new FabricVersionLoaderInfo.WithMeta.LauncherMeta.Libraries.Library(); floader.name = "net.fabricmc:fabric-loader:" + fabricVersion; floader.url = "https://maven.fabricmc.net/"; @@ -65,4 +71,8 @@ public class FabricMetaApi { res.downloads.artifact.url = library.url + res.downloads.artifact.path; return res; } + + public enum FabricVersionInfoType { + Client, Server, Both + } } diff --git a/src/main/java/io/gitlab/jfronny/inceptum/util/api/account/AccountManager.java b/src/main/java/io/gitlab/jfronny/inceptum/util/api/account/AccountManager.java index cf0c838..d47ea8d 100644 --- a/src/main/java/io/gitlab/jfronny/inceptum/util/api/account/AccountManager.java +++ b/src/main/java/io/gitlab/jfronny/inceptum/util/api/account/AccountManager.java @@ -2,6 +2,7 @@ package io.gitlab.jfronny.inceptum.util.api.account; import com.google.gson.reflect.TypeToken; import io.gitlab.jfronny.inceptum.Inceptum; +import io.gitlab.jfronny.inceptum.InceptumGui; import io.gitlab.jfronny.inceptum.util.Utils; import io.gitlab.jfronny.inceptum.windows.AlertWindow; @@ -10,7 +11,6 @@ import java.lang.reflect.Type; import java.nio.file.Files; import java.util.ArrayList; import java.util.List; -import java.util.function.Consumer; public class AccountManager { private static final Type abstractAccountListType = new TypeToken>() {}.getType(); @@ -67,9 +67,7 @@ public class AccountManager { public static void addAccount(MicrosoftAccount account) { ACCOUNTS.add(account); if (ACCOUNTS.size() > 1) { - Inceptum.open(new AlertWindow("Success", "Account added successfully. Switch to it now?", - () -> switchAccount(account), - () -> {})); + Inceptum.showOkCancel("Account added successfully. Switch to it now?", "Success", () -> switchAccount(account), () -> {}); } else switchAccount(account); saveAccounts(); diff --git a/src/main/java/io/gitlab/jfronny/inceptum/util/api/account/MicrosoftAccount.java b/src/main/java/io/gitlab/jfronny/inceptum/util/api/account/MicrosoftAccount.java index f9bff9c..0daf69e 100644 --- a/src/main/java/io/gitlab/jfronny/inceptum/util/api/account/MicrosoftAccount.java +++ b/src/main/java/io/gitlab/jfronny/inceptum/util/api/account/MicrosoftAccount.java @@ -1,6 +1,7 @@ package io.gitlab.jfronny.inceptum.util.api.account; import io.gitlab.jfronny.inceptum.Inceptum; +import io.gitlab.jfronny.inceptum.InceptumGui; import io.gitlab.jfronny.inceptum.model.microsoft.LoginResponse; import io.gitlab.jfronny.inceptum.model.microsoft.OauthTokenResponse; import io.gitlab.jfronny.inceptum.model.microsoft.Profile; @@ -187,8 +188,8 @@ public class MicrosoftAccount { public boolean ensureAccessTokenValid(Consumer isValid) { if (mustLogin) { - Inceptum.open(new AlertWindow("Login expired", "You must login again in order to continue", () -> { - Inceptum.open(new MicrosoftLoginWindow(this)); + Inceptum.showOkCancel("You must login again in order to continue", "Login expired", () -> { + InceptumGui.open(new MicrosoftLoginWindow(this)); if (!new Date().after(accessTokenExpiresAt)) { @@ -206,7 +207,7 @@ public class MicrosoftAccount { } isValid.accept(false); - }, () -> isValid.accept(false))); + }, () -> isValid.accept(false)); return false; } else return true; } diff --git a/src/main/java/io/gitlab/jfronny/inceptum/windows/InstanceCreateProcessWindow.java b/src/main/java/io/gitlab/jfronny/inceptum/windows/InstanceCreateProcessWindow.java index 900d44f..23394c7 100644 --- a/src/main/java/io/gitlab/jfronny/inceptum/windows/InstanceCreateProcessWindow.java +++ b/src/main/java/io/gitlab/jfronny/inceptum/windows/InstanceCreateProcessWindow.java @@ -2,16 +2,15 @@ package io.gitlab.jfronny.inceptum.windows; import imgui.ImGui; import io.gitlab.jfronny.inceptum.Inceptum; +import io.gitlab.jfronny.inceptum.InceptumGui; import io.gitlab.jfronny.inceptum.install.SetupStepInfo; import io.gitlab.jfronny.inceptum.install.Step; import io.gitlab.jfronny.inceptum.install.Steps; -import io.gitlab.jfronny.inceptum.util.MapAppender; import io.gitlab.jfronny.inceptum.util.Utils; import java.io.IOException; import java.nio.file.Files; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicReference; public class InstanceCreateProcessWindow extends Window { private final SetupStepInfo stepInfo; @@ -48,11 +47,10 @@ public class InstanceCreateProcessWindow extends Window { step.execute(stepInfo, finalize); } finalize.set(true); - Inceptum.open(new AlertWindow("Successfully installed", "The instance was successfully created. You can now launch it using the main menu")); + Inceptum.showInfo("The instance was successfully created. You can now launch it using the main menu", "Successfully installed"); close(); } catch (Throwable e) { - Inceptum.LOGGER.error("Could not initialize instance", e); - Inceptum.open(new AlertWindow("Could not create the instance", e.toString())); + Inceptum.showError("Could not create the instance", e); close(); cleanUp(); } diff --git a/src/main/java/io/gitlab/jfronny/inceptum/windows/InstanceEditWindow.java b/src/main/java/io/gitlab/jfronny/inceptum/windows/InstanceEditWindow.java index 0de8b42..7723592 100644 --- a/src/main/java/io/gitlab/jfronny/inceptum/windows/InstanceEditWindow.java +++ b/src/main/java/io/gitlab/jfronny/inceptum/windows/InstanceEditWindow.java @@ -4,6 +4,8 @@ import imgui.ImGui; import imgui.type.ImBoolean; import imgui.type.ImString; import io.gitlab.jfronny.inceptum.Inceptum; +import io.gitlab.jfronny.inceptum.InceptumGui; +import io.gitlab.jfronny.inceptum.install.Steps; import io.gitlab.jfronny.inceptum.model.inceptum.InstanceMeta; import io.gitlab.jfronny.inceptum.util.Utils; import io.gitlab.jfronny.inceptum.windows.control.InstanceManageControls; @@ -15,15 +17,17 @@ import java.nio.file.Path; public class InstanceEditWindow extends Window { private final Path path; private final InstanceMeta instance; - private final InstanceManageControls imc = new InstanceManageControls(); + private final InstanceManageControls imc; private final ImBoolean customJava; private final ImString customJavaPath = new ImString(128); + private boolean reDownload = false; public InstanceEditWindow(Path path, InstanceMeta instance) { super("Edit " + path.getFileName().toString()); this.path = path; this.instance = instance; customJava = new ImBoolean(instance.java != null); + imc = new InstanceManageControls(instance.getLoaderVersion()); } @Override @@ -34,26 +38,27 @@ public class InstanceEditWindow extends Window { try { Path newPath = Inceptum.INSTANCE_DIR.resolve(name); Files.move(path, newPath); + InceptumGui.open(new InstanceEditWindow(newPath, instance)); close(); - Inceptum.open(new InstanceEditWindow(newPath, instance)); } catch (IOException e) { e.printStackTrace(); } }); imc.snapshotsBox(); imc.versionBox(ver -> { + //TODO ensure version is downloaded + reDownload = true; instance.version = ver; save(); }); - if (ImGui.button("Delete")) Inceptum.open(new AlertWindow("Are you sure?", "This instance will be removed forever (a long time)", () -> { - close(); + if (ImGui.button("Delete")) Inceptum.showOkCancel("This instance will be removed forever (a long time)", "Are you sure?", () -> { try { Utils.deleteRecursive(path); } catch (IOException e) { - Inceptum.LOGGER.error("Could not delete the instance", e); - Inceptum.open(new AlertWindow("Could not delete", e.toString())); + Inceptum.showError("Could not delete the instance", e); } - }, () -> {})); + close(); + }, () -> {}); if (ImGui.checkbox("Custom Java", customJava)) { if (customJava.get()) { instance.java = Utils.getJvmMain(Path.of(System.getProperty("java.home"))).toAbsolutePath().toString(); @@ -87,4 +92,16 @@ public class InstanceEditWindow extends Window { Inceptum.LOGGER.error("Could not write instance config", e); } } + + @Override + public void close() { + super.close(); + if (reDownload) { + try { + Steps.reDownload(path); + } catch (IOException e) { + Inceptum.showError("Could not re-download data", e); + } + } + } } diff --git a/src/main/java/io/gitlab/jfronny/inceptum/windows/MainWindow.java b/src/main/java/io/gitlab/jfronny/inceptum/windows/MainWindow.java index d23d8ed..c7e1ef6 100644 --- a/src/main/java/io/gitlab/jfronny/inceptum/windows/MainWindow.java +++ b/src/main/java/io/gitlab/jfronny/inceptum/windows/MainWindow.java @@ -5,6 +5,7 @@ import imgui.flag.ImGuiWindowFlags; import imgui.type.ImBoolean; import imgui.type.ImInt; import io.gitlab.jfronny.inceptum.Inceptum; +import io.gitlab.jfronny.inceptum.InceptumGui; import io.gitlab.jfronny.inceptum.install.SetupStepInfo; import io.gitlab.jfronny.inceptum.install.Step; import io.gitlab.jfronny.inceptum.install.Steps; @@ -45,46 +46,23 @@ public class MainWindow extends Window { public void draw() { ImGui.beginMenuBar(); if (ImGui.beginMenu("File")) { - if (ImGui.menuItem("New Instance")) Inceptum.open(new NewInstanceWindow()); + if (ImGui.menuItem("New Instance")) InceptumGui.open(new NewInstanceWindow()); if (ImGui.menuItem("Re-download resources")) { try { Utils.clearDirectory(Inceptum.ASSETS_DIR); Utils.clearDirectory(Inceptum.LIBRARIES_DIR); Utils.clearDirectory(Inceptum.NATIVES_DIR); Utils.clearDirectory(Inceptum.CACHE_DIR); - Files.list(Inceptum.INSTANCE_DIR).forEach(p -> { - try { - if (Files.exists(p.resolve("inceptum.setup.lock"))) return; - if (Files.exists(p.resolve("inceptum.lock"))) return; - InstanceMeta im = Utils.loadObject(p.resolve("instance.json"), InstanceMeta.class); - for (VersionsListInfo version : McApi.getVersions().versions) { - if (version.id.equals(im.getMinecraftVersion())) { - VersionInfo vi = McApi.getVersionInfo(version); - if (im.isFabric()) FabricMetaApi.addFabric(vi, im.getLoaderVersion()); - LoaderInfo li = im.isFabric() - ? new LoaderInfo(LoaderInfo.Type.Fabric, im.getLoaderVersion()) - : LoaderInfo.NONE; - SetupStepInfo info = new SetupStepInfo(vi, li, p.getFileName().toString(), new AtomicReference<>("Reloading")); - for (Step step : Steps.STEPS) { - step.execute(info, new AtomicBoolean(false)); - } - } - } - } catch (IOException e) { - Inceptum.LOGGER.error("Could not execute refresh task", e); - Inceptum.open(new AlertWindow("Something went wrong", e.toString())); - } - }); + Steps.reDownload(); } catch (IOException e) { - Inceptum.LOGGER.error("Could not execute refresh task", e); - Inceptum.open(new AlertWindow("Something went wrong", e.toString())); + Inceptum.showError("Could not execute refresh task", e); } } - if (ImGui.menuItem("Exit Inceptum")) Inceptum.exit(); + if (ImGui.menuItem("Exit Inceptum")) InceptumGui.exit(); ImGui.endMenu(); } if (ImGui.beginMenu("Account")) { - if (ImGui.menuItem("New")) Inceptum.open(new MicrosoftLoginWindow()); + if (ImGui.menuItem("New")) InceptumGui.open(new MicrosoftLoginWindow()); AuthInfo selected = AccountManager.getSelectedAccount(); List accounts = AccountManager.getAccounts(); for (int i = 0, accountsSize = accounts.size(); i < accountsSize; i++) { @@ -102,13 +80,13 @@ public class MainWindow extends Window { if (ImGui.checkbox("Dark Theme", darkTheme)) { Inceptum.CONFIG.darkTheme = darkTheme.get(); Inceptum.saveConfig(); - Inceptum.applyTheme(); + InceptumGui.applyTheme(); } ImGui.endMenu(); } if (ImGui.beginMenu("Help")) { - if (ImGui.menuItem("About")) Inceptum.open(new AboutWindow()); - if (ImGui.menuItem("Log")) Inceptum.open(new LogWindow(MapAppender.LOG)); + if (ImGui.menuItem("About")) InceptumGui.open(new AboutWindow()); + if (ImGui.menuItem("Log")) InceptumGui.open(new LogWindow(MapAppender.LOG)); ImGui.checkbox("Debug Tools", debugTools); ImGui.endMenu(); } diff --git a/src/main/java/io/gitlab/jfronny/inceptum/windows/MicrosoftLoginWindow.java b/src/main/java/io/gitlab/jfronny/inceptum/windows/MicrosoftLoginWindow.java index 22d61a1..42c9676 100644 --- a/src/main/java/io/gitlab/jfronny/inceptum/windows/MicrosoftLoginWindow.java +++ b/src/main/java/io/gitlab/jfronny/inceptum/windows/MicrosoftLoginWindow.java @@ -2,6 +2,7 @@ package io.gitlab.jfronny.inceptum.windows; import imgui.ImGui; import io.gitlab.jfronny.inceptum.Inceptum; +import io.gitlab.jfronny.inceptum.InceptumGui; import io.gitlab.jfronny.inceptum.model.microsoft.*; import io.gitlab.jfronny.inceptum.util.api.account.AccountManager; import io.gitlab.jfronny.inceptum.util.api.account.MicrosoftAccount; @@ -147,7 +148,7 @@ public class MicrosoftLoginWindow extends Window { if (!(store.items.stream().anyMatch(i -> i.name.equalsIgnoreCase("product_minecraft")) && store.items.stream().anyMatch(i -> i.name.equalsIgnoreCase("game_minecraft")))) { - Inceptum.open(new AlertWindow("Doesn't own Minecraft", "This account doesn't have a valid purchase of Minecraft.\nPlease make sure you've bought the Java edition of Minecraft and then try again.")); + Inceptum.showError("This account doesn't have a valid purchase of Minecraft.\nPlease make sure you've bought the Java edition of Minecraft and then try again.", "Doesn't own Minecraft"); throw new Exception("Account does not own Minecraft"); } @@ -172,8 +173,8 @@ public class MicrosoftLoginWindow extends Window { } // if forced to relogin, then make sure they logged into correct account - if (account != null && this.account != null && account.accountId != this.account.accountId) { - Inceptum.open(new AlertWindow("Incorrect account", "Logged into incorrect account. Please login again on the Accounts tab")); + if (this.account != null && account.accountId != this.account.accountId) { + Inceptum.showError("Logged into incorrect account. Please login again on the Accounts tab", "Incorrect account"); return; } diff --git a/src/main/java/io/gitlab/jfronny/inceptum/windows/NewInstanceWindow.java b/src/main/java/io/gitlab/jfronny/inceptum/windows/NewInstanceWindow.java index c0bcd6d..70753f3 100644 --- a/src/main/java/io/gitlab/jfronny/inceptum/windows/NewInstanceWindow.java +++ b/src/main/java/io/gitlab/jfronny/inceptum/windows/NewInstanceWindow.java @@ -1,14 +1,16 @@ package io.gitlab.jfronny.inceptum.windows; import io.gitlab.jfronny.inceptum.Inceptum; +import io.gitlab.jfronny.inceptum.InceptumGui; import io.gitlab.jfronny.inceptum.install.SetupStepInfo; +import io.gitlab.jfronny.inceptum.util.api.FabricMetaApi; import io.gitlab.jfronny.inceptum.windows.control.InstanceManageControls; import java.io.IOException; import java.util.concurrent.atomic.AtomicReference; public class NewInstanceWindow extends Window { - InstanceManageControls imc = new InstanceManageControls(); + InstanceManageControls imc = new InstanceManageControls(null); public NewInstanceWindow() { super("New Instance"); } @@ -19,15 +21,15 @@ public class NewInstanceWindow extends Window { imc.versionBox(ver -> {}); //TODO forge imc.nameBox("OK", name -> { - close(); try { - Inceptum.open(new InstanceCreateProcessWindow(new SetupStepInfo(imc.getVersionInfo(), + InceptumGui.open(new InstanceCreateProcessWindow(new SetupStepInfo(imc.getVersionInfo(), imc.getLoaderInfo(), name, new AtomicReference<>("Initializing")))); } catch (IOException e) { Inceptum.LOGGER.error("Could not initialize instance creation", e); } + close(); }); } } diff --git a/src/main/java/io/gitlab/jfronny/inceptum/windows/Window.java b/src/main/java/io/gitlab/jfronny/inceptum/windows/Window.java index 6313f0b..5f2d884 100644 --- a/src/main/java/io/gitlab/jfronny/inceptum/windows/Window.java +++ b/src/main/java/io/gitlab/jfronny/inceptum/windows/Window.java @@ -2,7 +2,7 @@ package io.gitlab.jfronny.inceptum.windows; import imgui.flag.ImGuiWindowFlags; import imgui.type.ImBoolean; -import io.gitlab.jfronny.inceptum.Inceptum; +import io.gitlab.jfronny.inceptum.InceptumGui; import java.io.Closeable; @@ -26,7 +26,7 @@ public abstract class Window implements Closeable { @Override public void close() { openState.set(false); - Inceptum.WINDOWS.remove(this); + InceptumGui.WINDOWS.remove(this); } public boolean isNew() { diff --git a/src/main/java/io/gitlab/jfronny/inceptum/windows/control/InstanceManageControls.java b/src/main/java/io/gitlab/jfronny/inceptum/windows/control/InstanceManageControls.java index e607e7f..8d4f5b9 100644 --- a/src/main/java/io/gitlab/jfronny/inceptum/windows/control/InstanceManageControls.java +++ b/src/main/java/io/gitlab/jfronny/inceptum/windows/control/InstanceManageControls.java @@ -26,7 +26,6 @@ public class InstanceManageControls { public static final int MAX_NAME_LENGTH = 128; private final VersionsList manifest = McApi.getVersions(); private final Map> loaderInfoCache = new HashMap<>(); - private final Map versionInfoCache = new HashMap<>(); private final ImInt version = new ImInt(0); private final ImString name = new ImString("", MAX_NAME_LENGTH); private final ImInt fabricVersion = new ImInt(0); @@ -35,7 +34,7 @@ public class InstanceManageControls { private VersionsListInfo selected; private FabricVersionLoaderInfo selectedFabric; - public InstanceManageControls() { + public InstanceManageControls(String loaderVersion) { selected = getVersions(false).get(0); if (Inceptum.CONFIG.snapshots) version.set(manifest.versions.indexOf(selected)); @@ -43,7 +42,7 @@ public class InstanceManageControls { List versions = getFabricLoaderInfo(); for (int i = 0, fabricLoaderInfoSize = versions.size(); i < fabricLoaderInfoSize; i++) { FabricVersionLoaderInfo version = versions.get(i); - if (version.loader.stable) { + if (((loaderVersion == null || loaderVersion.equals("")) && version.loader.stable) || (version.loader.version.equals(loaderVersion))) { selectedFabric = version; fabricVersion.set(i); break; @@ -117,12 +116,9 @@ public class InstanceManageControls { } public VersionInfo getVersionInfo() throws IOException { - if (!versionInfoCache.containsKey(selected)) { - VersionInfo vi = McApi.getVersionInfo(selected); - if (fabric.get()) FabricMetaApi.addFabric(vi, selectedFabric.loader.version); - versionInfoCache.put(selected, vi); - } - return versionInfoCache.get(selected); + VersionInfo vi = McApi.getVersionInfo(selected); + if (fabric.get()) FabricMetaApi.addFabric(vi, selectedFabric.loader.version, FabricMetaApi.FabricVersionInfoType.Both); + return vi; } public LoaderInfo getLoaderInfo() { diff --git a/src/main/java/io/gitlab/jfronny/inceptum/windows/control/InstanceView.java b/src/main/java/io/gitlab/jfronny/inceptum/windows/control/InstanceView.java index 153dc0d..212f5a2 100644 --- a/src/main/java/io/gitlab/jfronny/inceptum/windows/control/InstanceView.java +++ b/src/main/java/io/gitlab/jfronny/inceptum/windows/control/InstanceView.java @@ -3,29 +3,17 @@ 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.InceptumGui; 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.ClientLauncher; 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) { @@ -61,99 +49,12 @@ public class InstanceView { } } if (disabled) ImGui.beginDisabled(); - if (ImGui.button(path.getFileName().toString())) launch(path, instance); + if (ImGui.button(path.getFileName().toString())) ClientLauncher.launch(path, instance); ImGui.tableNextColumn(); - if (ImGui.button("Edit##" + path)) Inceptum.open(new InstanceEditWindow(path, instance)); + if (ImGui.button("Edit##" + path)) InceptumGui.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}", "{}"); - } }