Server support

This commit is contained in:
JFronny 2021-10-30 22:05:24 +02:00
parent d73aefd99e
commit 97251ea548
No known key found for this signature in database
GPG Key ID: BEC5ACBBD4EE17E5
26 changed files with 736 additions and 375 deletions

View File

@ -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

View File

@ -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<Window> WINDOWS = new LinkedHashSet<>();
public static final Set<Command> 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();
}
}

View File

@ -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<Window> 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();
}
}

View File

@ -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<String> 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);
}

View File

@ -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;
}
}

View File

@ -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());
}
}
}

View File

@ -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());
}
}

View File

@ -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);
}
}

View File

@ -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<Step> 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));
}
}
}
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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<String> jvmArgsCustom; //TODO allow configuring
public List<String> gameArgsCustom; //TODO allow configuring
public boolean isFabric() {
return version.startsWith(floaderPrefix);

View File

@ -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<String> 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<String> parse(List<MinecraftArgument> arguments, VersionInfo info, InstanceMeta instance, String classPath, String gameDirectory) {
List<String> 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}", "{}");
}
}

View File

@ -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<String> 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);
}
}
}
}
}

View File

@ -71,16 +71,14 @@ public class Utils {
private static <T> T downloadObject(String url, ThrowingSupplier<String, IOException> sourceString, Function<String, T> 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);
}
}

View File

@ -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<VersionInfo.Library> 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
}
}

View File

@ -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<List<MicrosoftAccount>>() {}.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();

View File

@ -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<Boolean> 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;
}

View File

@ -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();
}

View File

@ -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);
}
}
}
}

View File

@ -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<MicrosoftAccount> 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();
}

View File

@ -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;
}

View File

@ -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();
});
}
}

View File

@ -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() {

View File

@ -26,7 +26,6 @@ public class InstanceManageControls {
public static final int MAX_NAME_LENGTH = 128;
private final VersionsList manifest = McApi.getVersions();
private final Map<VersionsListInfo, List<FabricVersionLoaderInfo>> loaderInfoCache = new HashMap<>();
private final Map<VersionsListInfo, VersionInfo> 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<FabricVersionLoaderInfo> 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() {

View File

@ -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<Path> 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<String> 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<String> parse(List<MinecraftArgument> arguments, VersionInfo info, InstanceMeta instance, String classPath, String gameDirectory) {
List<String> 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}", "{}");
}
}