From 728419398112927df08dfc6dc02924c762c4a3ba Mon Sep 17 00:00:00 2001 From: JFronny Date: Sun, 29 Jan 2023 15:45:51 +0100 Subject: [PATCH] GTK: Start working on accounts UI and complete more menu entries --- .../jfronny/inceptum/gtk/GtkEnvBackend.java | 2 +- .../gitlab/jfronny/inceptum/gtk/GtkMain.java | 3 + .../jfronny/inceptum/gtk/GtkMenubar.java | 60 ++++++++++++------- .../gtk/control/InstanceListEntryFactory.java | 16 +++-- .../gtk/control/{ => settings}/IRow.java | 3 +- .../settings}/SettingsTab.java | 11 ++-- .../settings/SettingsWindow.java} | 27 +++++---- .../gtk/window/LauncherSettingsWindow.java | 49 --------------- .../inceptum/gtk/window/MainWindow.java | 9 +-- .../window/dialog/MicrosoftLoginDialog.java | 9 ++- .../dialog/ProcessStateWatcherDialog.java | 4 +- .../instance}/ExportTab.java | 9 ++- .../instance}/GeneralTab.java | 8 +-- .../instance/InstanceSettingsWindow.java | 14 +++++ .../{edit => settings/instance}/ModsTab.java | 6 +- .../window/settings/launcher/AccountsTab.java | 13 ++++ .../window/settings/launcher/GeneralTab.java | 36 +++++++++++ .../launcher/LauncherSettingsWindow.java | 12 ++++ .../src/main/resources/inceptum.properties | 23 ++++--- .../src/main/resources/inceptum_de.properties | 25 +++++--- .../inceptum/imgui/window/GuiUtil.java | 1 + .../launcher/system/instance/Instance.java | 21 +++++++ .../system/instance/InstanceList.java | 15 +++++ .../system/launch/InstanceLauncher.java | 27 ++++++--- .../inceptum/launcher/system/setup/Step.java | 1 + .../inceptum/launcher/system/setup/Steps.java | 2 +- .../setup/steps/DownloadAssetsStep.java | 5 ++ .../setup/steps/DownloadClientStep.java | 5 ++ .../system/setup/steps/DownloadJavaStep.java | 5 ++ .../setup/steps/DownloadLibrariesStep.java | 5 ++ .../system/setup/steps/RunMdsStep.java | 5 ++ .../system/setup/steps/SetupDirsStep.java | 5 ++ .../system/setup/steps/WriteMetadataStep.java | 5 ++ .../inceptum/launcher/util/ProcessUtils.java | 20 +++++++ 34 files changed, 328 insertions(+), 133 deletions(-) rename launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/control/{ => settings}/IRow.java (96%) rename launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/{window/edit => control/settings}/SettingsTab.java (83%) rename launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/{window/InstanceSettingsWindow.java => control/settings/SettingsWindow.java} (57%) delete mode 100644 launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/LauncherSettingsWindow.java rename launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/{edit => settings/instance}/ExportTab.java (95%) rename launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/{edit => settings/instance}/GeneralTab.java (98%) create mode 100644 launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/settings/instance/InstanceSettingsWindow.java rename launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/{edit => settings/instance}/ModsTab.java (69%) create mode 100644 launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/settings/launcher/AccountsTab.java create mode 100644 launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/settings/launcher/GeneralTab.java create mode 100644 launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/settings/launcher/LauncherSettingsWindow.java diff --git a/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/GtkEnvBackend.java b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/GtkEnvBackend.java index 3736f0e..9bcadb4 100644 --- a/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/GtkEnvBackend.java +++ b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/GtkEnvBackend.java @@ -12,7 +12,7 @@ import org.jetbrains.annotations.Nullable; import java.util.function.Consumer; -public enum GtkEnvBackend implements LauncherEnv.EnvBackend { //TODO test +public enum GtkEnvBackend implements LauncherEnv.EnvBackend { INSTANCE; public Window dialogParent = null; diff --git a/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/GtkMain.java b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/GtkMain.java index 877660f..90050f6 100644 --- a/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/GtkMain.java +++ b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/GtkMain.java @@ -3,6 +3,7 @@ package io.gitlab.jfronny.inceptum.gtk; import io.gitlab.jfronny.inceptum.common.*; import io.gitlab.jfronny.inceptum.gtk.window.MainWindow; import io.gitlab.jfronny.inceptum.launcher.LauncherEnv; +import io.gitlab.jfronny.inceptum.launcher.api.account.AccountManager; import org.gtk.gio.ApplicationFlags; import org.gtk.glib.GLib; import org.gtk.gtk.Application; @@ -35,6 +36,8 @@ public class GtkMain { public static int showGui(String[] args) { return setupApplication(args, app -> { + //TODO update check + AccountManager.loadAccounts(); GtkMenubar.create(app); var window = new MainWindow(app); window.show(); diff --git a/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/GtkMenubar.java b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/GtkMenubar.java index 030bd6b..3202358 100644 --- a/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/GtkMenubar.java +++ b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/GtkMenubar.java @@ -1,6 +1,10 @@ package io.gitlab.jfronny.inceptum.gtk; +import io.gitlab.jfronny.commons.io.JFiles; +import io.gitlab.jfronny.inceptum.common.MetaHolder; +import io.gitlab.jfronny.inceptum.gtk.window.dialog.MicrosoftLoginDialog; import io.gitlab.jfronny.inceptum.gtk.window.dialog.ProcessStateWatcherDialog; +import io.gitlab.jfronny.inceptum.gtk.window.settings.launcher.LauncherSettingsWindow; import io.gitlab.jfronny.inceptum.launcher.system.launch.*; import io.gitlab.jfronny.inceptum.launcher.util.ProcessState; import org.gtk.gtk.Application; @@ -29,13 +33,32 @@ public class GtkMenubar { var file = menu.submenu("file"); file.button("new", () -> new NewInstanceWindow(app).show()); file.button("redownload", () -> { - //TODO + ProcessState state = new ProcessState(3 + Steps.STEPS.size() * InstanceList.size(), "Initializing"); + ProcessStateWatcherDialog.show( + GtkEnvBackend.INSTANCE.dialogParent, + "Reloading data", + "Could not execute refresh task", + state, + cancel -> { + state.incrementStep("Clearing cache directories"); + JFiles.clearDirectory(MetaHolder.ASSETS_DIR); + JFiles.clearDirectory(MetaHolder.LIBRARIES_DIR, path -> !path.startsWith(MetaHolder.LIBRARIES_DIR.resolve("io/gitlab/jfronny"))); + JFiles.clearDirectory(MetaHolder.NATIVES_DIR, path -> !path.startsWith(MetaHolder.NATIVES_DIR.resolve("forceload"))); + JFiles.clearDirectory(MetaHolder.CACHE_DIR); + if (cancel.get()) return; + state.incrementStep("Reloading instance list"); + InstanceList.reset(); + InstanceList.forEach(instance -> { + if (cancel.get()) return; + Steps.reDownload(instance, state, cancel); + }); + }, R::nop); }); file.button("exit", app::quit); launchMenu = menu.submenu("launch"); generateLaunchMenu(); accountsMenu = menu.submenu("account"); - generateAccountsMenu(); + generateAccountsMenu(app); var help = menu.submenu("help"); help.button("about", AboutWindow::createAndShow); help.button("log", () -> { @@ -58,17 +81,14 @@ public class GtkMenubar { public static void launch(Instance instance, LaunchType launchType) { if (instance.isSetupLocked) { LauncherEnv.showError(I18n.get("instance.launch.locked.setup"), I18n.get("instance.launch.locked")); - return; - } - if (instance.isRunningLocked) { + } else if (instance.isRunningLocked) { LauncherEnv.showOkCancel( I18n.get("instance.launch.locked.running"), I18n.get("instance.launch.locked"), () -> forceLaunch(instance, launchType), R::nop ); - } - forceLaunch(instance, launchType); + } else forceLaunch(instance, launchType); } private static void forceLaunch(Instance instance, LaunchType launchType) { @@ -80,31 +100,31 @@ public class GtkMenubar { state, cancel -> { try { - Steps.reDownload(instance, Steps.createProcessState(), cancel); + Steps.reDownload(instance, state, cancel); } catch (IOException e) { Utils.LOGGER.error("Could not fetch instance, trying to start anyways", e); } - if (!cancel.get()) { - try { - if (launchType == LaunchType.Client) InstanceLauncher.launchClient(instance); - else InstanceLauncher.launch(instance, launchType, false, AccountManager.NULL_AUTH); - } catch (Throwable e) { - LauncherEnv.showError("Could not start instance", e); - } + if (cancel.get()) return; + state.updateStep("Starting Game"); + try { + if (launchType == LaunchType.Client) InstanceLauncher.launchClient(instance); + else InstanceLauncher.launch(instance, launchType, false, AccountManager.NULL_AUTH); + } catch (Throwable e) { + LauncherEnv.showError("Could not start instance", e); } }, R::nop ); } - public static void generateAccountsMenu() { + public static void generateAccountsMenu(Application app) { Objects.requireNonNull(accountsMenu); accountsMenu.clear(); - accountsMenu.button("new", () -> { - //TODO - }); + accountsMenu.button("new", () -> new MicrosoftLoginDialog(GtkEnvBackend.INSTANCE.dialogParent, null).show()); accountsMenu.button("manage", () -> { - //TODO UI to add/remove accounts + var window = new LauncherSettingsWindow(app); + window.activePage = "settings.accounts"; + window.show(); }); List accounts = new ArrayList<>(AccountManager.accounts); accounts.add(null); diff --git a/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/control/InstanceListEntryFactory.java b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/control/InstanceListEntryFactory.java index 7c9727d..7173ec5 100644 --- a/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/control/InstanceListEntryFactory.java +++ b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/control/InstanceListEntryFactory.java @@ -9,7 +9,7 @@ import io.gitlab.jfronny.inceptum.gtk.GtkMenubar; import io.gitlab.jfronny.inceptum.gtk.menu.MenuBuilder; import io.gitlab.jfronny.inceptum.gtk.util.I18n; import io.gitlab.jfronny.inceptum.gtk.util.ListIndexItem; -import io.gitlab.jfronny.inceptum.gtk.window.InstanceSettingsWindow; +import io.gitlab.jfronny.inceptum.gtk.window.settings.instance.InstanceSettingsWindow; import io.gitlab.jfronny.inceptum.launcher.LauncherEnv; import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance; import io.gitlab.jfronny.inceptum.launcher.system.instance.InstanceNameTool; @@ -79,6 +79,14 @@ public class InstanceListEntryFactory extends SignalListItemFactory { var menuBuilder = new MenuBuilder(li.popoverMenu, li.instance.id); var launchSection = menuBuilder.literalSection("launch", null); + var kill = launchSection.literalButton("kill", I18n.get("instance.kill"), () -> { + //TODO test + LauncherEnv.showOkCancel(I18n.get("instance.kill.prompt"), I18n.get("instance.kill.details"), () -> { + if (!li.instance.kill()) LauncherEnv.showError(I18n.get("instance.kill.fail"), I18n.get("failed")); + }, R::nop); + }); + kill.enabled = li.instance.isRunningLocked; + launchSection.literalButton("launch.client", I18n.get("instance.launch.client"), () -> GtkMenubar.launch(li.instance, LaunchType.Client)) .iconName = "media-playback-start-symbolic"; @@ -98,7 +106,7 @@ public class InstanceListEntryFactory extends SignalListItemFactory { try { JFiles.copyRecursive(li.instance.path, MetaHolder.INSTANCE_DIR.resolve(InstanceNameTool.getNextValid(s))); } catch (IOException e) { - LauncherEnv.showError("Could not copy instance", e); + LauncherEnv.showError(I18n.get("instance.copy.fail"), e); } }, R::nop); }).iconName = "edit-copy-symbolic"; @@ -107,13 +115,11 @@ public class InstanceListEntryFactory extends SignalListItemFactory { try { JFiles.deleteRecursive(li.instance.path); } catch (IOException e) { - LauncherEnv.showError("Could not delete the instance", e); + LauncherEnv.showError(I18n.get("instance.delete.fail"), e); } }, R::nop); }).iconName = "edit-delete-symbolic"; - //TODO kill current instance - Consumer> dc = s -> toDisconnect.computeIfAbsent(li.instance.id, $ -> new HashSet<>()).add(s); dc.accept(li.launch.onClicked(() -> GtkMenubar.launch(li.instance, LaunchType.Client))); diff --git a/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/control/IRow.java b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/control/settings/IRow.java similarity index 96% rename from launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/control/IRow.java rename to launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/control/settings/IRow.java index 80099d4..79f8f58 100644 --- a/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/control/IRow.java +++ b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/control/settings/IRow.java @@ -1,5 +1,6 @@ -package io.gitlab.jfronny.inceptum.gtk.control; +package io.gitlab.jfronny.inceptum.gtk.control.settings; +import io.gitlab.jfronny.inceptum.gtk.control.ILabel; import io.gitlab.jfronny.inceptum.gtk.util.I18n; import org.gtk.gtk.*; import org.jetbrains.annotations.Nullable; diff --git a/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/edit/SettingsTab.java b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/control/settings/SettingsTab.java similarity index 83% rename from launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/edit/SettingsTab.java rename to launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/control/settings/SettingsTab.java index 9d910da..e8c4c75 100644 --- a/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/edit/SettingsTab.java +++ b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/control/settings/SettingsTab.java @@ -1,23 +1,20 @@ -package io.gitlab.jfronny.inceptum.gtk.window.edit; +package io.gitlab.jfronny.inceptum.gtk.control.settings; import io.gitlab.jfronny.commons.StringFormatter; import io.gitlab.jfronny.inceptum.gtk.GtkEnvBackend; import io.gitlab.jfronny.inceptum.gtk.control.ILabel; -import io.gitlab.jfronny.inceptum.gtk.control.IRow; +import io.gitlab.jfronny.inceptum.gtk.control.settings.IRow; import io.gitlab.jfronny.inceptum.gtk.util.I18n; -import io.gitlab.jfronny.inceptum.gtk.window.InstanceSettingsWindow; import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance; import org.gtk.gtk.*; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.PropertyKey; public class SettingsTab extends Box { - protected final Instance instance; - protected final InstanceSettingsWindow window; + protected final Window window; - public SettingsTab(Instance instance, InstanceSettingsWindow window) { + public SettingsTab(Window window) { super(Orientation.VERTICAL, 8); - this.instance = instance; this.marginHorizontal = 24; this.marginTop = 12; this.window = window; diff --git a/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/InstanceSettingsWindow.java b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/control/settings/SettingsWindow.java similarity index 57% rename from launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/InstanceSettingsWindow.java rename to launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/control/settings/SettingsWindow.java index ebe5f1c..319fcc4 100644 --- a/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/InstanceSettingsWindow.java +++ b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/control/settings/SettingsWindow.java @@ -1,20 +1,21 @@ -package io.gitlab.jfronny.inceptum.gtk.window; +package io.gitlab.jfronny.inceptum.gtk.control.settings; import io.gitlab.jfronny.inceptum.gtk.util.I18n; -import io.gitlab.jfronny.inceptum.gtk.window.edit.*; -import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance; -import org.gnome.adw.HeaderBar; import org.gnome.adw.*; +import org.gnome.adw.HeaderBar; import org.gtk.gobject.BindingFlags; +import org.gtk.gtk.*; import org.gtk.gtk.Application; import org.gtk.gtk.Window; -import org.gtk.gtk.*; +import org.jetbrains.annotations.PropertyKey; -public class InstanceSettingsWindow extends Window { - public InstanceSettingsWindow(Application app, Instance instance) { +public class SettingsWindow extends Window { + protected final ViewStack stack; + + public SettingsWindow(Application app) { this.application = app; - ViewStack stack = new ViewStack(); + this.stack = new ViewStack(); HeaderBar header = new HeaderBar(); ViewSwitcherTitle viewSwitcher = new ViewSwitcherTitle(); @@ -35,9 +36,13 @@ public class InstanceSettingsWindow extends Window { view.append(bottomBar); child = view; + } - stack.addTitledWithIcon(new GeneralTab(instance, this), null, I18n.get("instance.settings.general"), "preferences-other-symbolic"); - stack.addTitledWithIcon(new ModsTab(instance, this), null, I18n.get("instance.settings.mods"), "package-x-generic-symbolic"); - stack.addTitledWithIcon(new ExportTab(instance, this), null, I18n.get("instance.settings.export"), "send-to-symbolic"); + public void addTab(SettingsTab tab, @PropertyKey(resourceBundle = I18n.BUNDLE) String title, String iconName) { + stack.addTitledWithIcon(tab, title, I18n.get(title), iconName); + } + + public void setActivePage(@PropertyKey(resourceBundle = I18n.BUNDLE) String title) { + stack.visibleChildName = title; } } diff --git a/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/LauncherSettingsWindow.java b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/LauncherSettingsWindow.java deleted file mode 100644 index 1dc756b..0000000 --- a/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/LauncherSettingsWindow.java +++ /dev/null @@ -1,49 +0,0 @@ -package io.gitlab.jfronny.inceptum.gtk.window; - -import io.gitlab.jfronny.inceptum.common.InceptumConfig; -import io.gitlab.jfronny.inceptum.common.model.inceptum.UpdateChannel; -import io.gitlab.jfronny.inceptum.gtk.control.IRow; -import org.gtk.gtk.*; - -public class LauncherSettingsWindow extends Window { - public LauncherSettingsWindow(Application app) { - this.application = app; - - var box = new Box(Orientation.VERTICAL, 8); - box.marginHorizontal = 24; - box.marginTop = 12; - this.child = box; - - { - Frame frame = new Frame(null); - ListBox listBox = new ListBox(); - listBox.selectionMode = SelectionMode.NONE; - frame.child = listBox; - box.append(frame); - { - IRow row = new IRow("settings.snapshots", "settings.snapshots.subtitle"); - listBox.append(row); - row.setSwitch(InceptumConfig.snapshots, b -> { - InceptumConfig.snapshots = b; - InceptumConfig.saveConfig(); - }); - } - { - IRow row = new IRow("settings.update-channel", "settings.update-channel.subtitle"); - listBox.append(row); - row.setDropdown(new String[] {"Stable", "CI"}, InceptumConfig.channel == UpdateChannel.CI ? 1 : 0, state -> { - InceptumConfig.channel = state == 1 ? UpdateChannel.CI : UpdateChannel.Stable; - InceptumConfig.saveConfig(); - }); - } - { - IRow row = new IRow("settings.author-name", "settings.author-name.subtitle"); - listBox.append(row); - row.setEntry(InceptumConfig.authorName, s -> { - InceptumConfig.authorName = s; - InceptumConfig.saveConfig(); - }); - } - } - } -} diff --git a/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/MainWindow.java b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/MainWindow.java index 45a55d5..6726f87 100644 --- a/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/MainWindow.java +++ b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/MainWindow.java @@ -8,6 +8,7 @@ import io.gitlab.jfronny.inceptum.gtk.control.InstanceListEntryFactory; import io.gitlab.jfronny.inceptum.gtk.menu.MenuBuilder; import io.gitlab.jfronny.inceptum.gtk.util.I18n; import io.gitlab.jfronny.inceptum.gtk.util.ListIndexModel; +import io.gitlab.jfronny.inceptum.gtk.window.settings.launcher.LauncherSettingsWindow; import io.gitlab.jfronny.inceptum.launcher.system.instance.*; import io.gitlab.jfronny.inceptum.launcher.system.launch.LaunchType; import org.gnome.adw.Clamp; @@ -75,9 +76,9 @@ public class MainWindow extends ApplicationWindow { instanceList = new ArrayList<>(); instanceListIndex = new ListIndexModel(instanceList.size()); - var singleSelection = new NoSelection(instanceListIndex); + var selection = new NoSelection(instanceListIndex); - ListView listView = new ListView(singleSelection, new InstanceListEntryFactory(app, instanceList)); + ListView listView = new ListView(selection, new InstanceListEntryFactory(app, instanceList)); listView.addCssClass("rich-list"); listView.showSeparators = true; listView.onActivate(position -> { @@ -92,7 +93,7 @@ public class MainWindow extends ApplicationWindow { listContainer = new Clamp(); listContainer.maximumSize = 900; listContainer.child = frame; - gridView = new GridView(singleSelection, new InstanceGridEntryFactory(instanceList)); + gridView = new GridView(selection, new InstanceGridEntryFactory(instanceList)); empty = new StatusPage(); empty.title = I18n.get("main.empty.title"); empty.description = I18n.get("main.empty.description"); @@ -106,7 +107,7 @@ public class MainWindow extends ApplicationWindow { scroll.setPolicy(PolicyType.NEVER, PolicyType.AUTOMATIC); scroll.child = stack; - setDefaultSize(360, 720); + setDefaultSize(720, 360); title = "Inceptum"; titlebar = header; showMenubar = false; diff --git a/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/dialog/MicrosoftLoginDialog.java b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/dialog/MicrosoftLoginDialog.java index a2f5194..78bbc99 100644 --- a/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/dialog/MicrosoftLoginDialog.java +++ b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/dialog/MicrosoftLoginDialog.java @@ -16,7 +16,7 @@ public class MicrosoftLoginDialog extends MessageDialog { return flags; } - public MicrosoftLoginDialog(@Nullable Window parent, MicrosoftAccount account) { + public MicrosoftLoginDialog(@Nullable Window parent, @Nullable MicrosoftAccount account) { super( parent, flags(parent != null), @@ -25,6 +25,13 @@ public class MicrosoftLoginDialog extends MessageDialog { I18n.get("auth.description") ); title = I18n.get("auth.title"); + onResponse(responseId -> { + switch (ResponseType.of(responseId)) { + case CLOSE, CANCEL -> this.close(); + case DELETE_EVENT -> this.destroy(); + default -> Utils.LOGGER.error("Unexpected response type: " + responseId); + } + }); var btn = Button.newWithLabel(I18n.get("auth.open-browser")); ((Box) messageArea).append(btn); btn.onClicked(() -> { diff --git a/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/dialog/ProcessStateWatcherDialog.java b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/dialog/ProcessStateWatcherDialog.java index 7ad5eb8..be3cb85 100644 --- a/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/dialog/ProcessStateWatcherDialog.java +++ b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/dialog/ProcessStateWatcherDialog.java @@ -28,6 +28,8 @@ public class ProcessStateWatcherDialog extends MessageDialog { } public ProcessStateWatcherDialog(Window parent, String title, String errorMessage, ProcessState state, ThrowingConsumer executor, @Nullable Runnable cancel) { + //TODO alternate UI: Only show progress bar by default, but have a dropdown to a "console" with the actual steps + // this should make visualizing parallelized steps easier super(parent, DialogFlags.MODAL.or(DialogFlags.DESTROY_WITH_PARENT), MessageType.INFO, ButtonsType.NONE, null); this.state = state; this.cancel = cancel; @@ -61,7 +63,7 @@ public class ProcessStateWatcherDialog extends MessageDialog { if (!nc.equals(cachedState)) { cachedState = nc; setMarkup(cachedState.msg); - progress.fraction = cachedState.progress; + progress.fraction = Math.min(cachedState.progress, 1); widget.queueDraw(); } return GLib.SOURCE_CONTINUE; diff --git a/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/edit/ExportTab.java b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/settings/instance/ExportTab.java similarity index 95% rename from launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/edit/ExportTab.java rename to launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/settings/instance/ExportTab.java index e12df41..548e973 100644 --- a/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/edit/ExportTab.java +++ b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/settings/instance/ExportTab.java @@ -1,11 +1,11 @@ -package io.gitlab.jfronny.inceptum.gtk.window.edit; +package io.gitlab.jfronny.inceptum.gtk.window.settings.instance; import io.gitlab.jfronny.commons.ref.R; import io.gitlab.jfronny.inceptum.common.Utils; import io.gitlab.jfronny.inceptum.gtk.GtkEnvBackend; import io.gitlab.jfronny.inceptum.gtk.GtkMain; +import io.gitlab.jfronny.inceptum.gtk.control.settings.SettingsTab; import io.gitlab.jfronny.inceptum.gtk.util.I18n; -import io.gitlab.jfronny.inceptum.gtk.window.InstanceSettingsWindow; import io.gitlab.jfronny.inceptum.gtk.window.dialog.ProcessStateWatcherDialog; import io.gitlab.jfronny.inceptum.launcher.system.exporter.Exporter; import io.gitlab.jfronny.inceptum.launcher.system.exporter.Exporters; @@ -16,8 +16,11 @@ import org.gtk.gtk.*; import java.nio.file.Path; public class ExportTab extends SettingsTab { + private final Instance instance; + public ExportTab(Instance instance, InstanceSettingsWindow window) { - super(instance, window); + super(window); + this.instance = instance; section(null, section -> { { var row = section.row("instance.settings.export.version", "instance.settings.export.version.subtitle"); diff --git a/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/edit/GeneralTab.java b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/settings/instance/GeneralTab.java similarity index 98% rename from launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/edit/GeneralTab.java rename to launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/settings/instance/GeneralTab.java index 17893e1..254cae6 100644 --- a/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/edit/GeneralTab.java +++ b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/settings/instance/GeneralTab.java @@ -1,13 +1,13 @@ -package io.gitlab.jfronny.inceptum.gtk.window.edit; +package io.gitlab.jfronny.inceptum.gtk.window.settings.instance; import io.github.jwharm.javagi.GErrorException; import io.gitlab.jfronny.commons.ArgumentsTokenizer; import io.gitlab.jfronny.commons.io.JFiles; import io.gitlab.jfronny.inceptum.common.*; import io.gitlab.jfronny.inceptum.gtk.control.ILabel; +import io.gitlab.jfronny.inceptum.gtk.control.settings.SettingsTab; import io.gitlab.jfronny.inceptum.gtk.util.I18n; import io.gitlab.jfronny.inceptum.gtk.util.Memory; -import io.gitlab.jfronny.inceptum.gtk.window.InstanceSettingsWindow; import io.gitlab.jfronny.inceptum.launcher.api.FabricMetaApi; import io.gitlab.jfronny.inceptum.launcher.api.McApi; import io.gitlab.jfronny.inceptum.launcher.model.fabric.FabricVersionLoaderInfo; @@ -29,7 +29,7 @@ public class GeneralTab extends SettingsTab { private static final VersionsList VERSIONS = McApi.getVersions(); public GeneralTab(Instance instance, InstanceSettingsWindow window) { - super(instance, window); + super(window); section(null, section -> { var row = section.row("instance.settings.general.name", "instance.settings.general.name.placeholder"); Button apply = Button.newWithLabel(I18n.get("instance.settings.apply")); @@ -210,7 +210,7 @@ public class GeneralTab extends SettingsTab { dialog.close(); window.close(); } catch (IOException e) { - showError("Could not delete the instance", e); + showError(I18n.get("instance.delete.fail"), e); } dialog.close(); } diff --git a/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/settings/instance/InstanceSettingsWindow.java b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/settings/instance/InstanceSettingsWindow.java new file mode 100644 index 0000000..d9bdf71 --- /dev/null +++ b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/settings/instance/InstanceSettingsWindow.java @@ -0,0 +1,14 @@ +package io.gitlab.jfronny.inceptum.gtk.window.settings.instance; + +import io.gitlab.jfronny.inceptum.gtk.control.settings.SettingsWindow; +import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance; +import org.gtk.gtk.Application; + +public class InstanceSettingsWindow extends SettingsWindow { + public InstanceSettingsWindow(Application app, Instance instance) { + super(app); + addTab(new GeneralTab(instance, this), "instance.settings.general", "preferences-other-symbolic"); + addTab(new ModsTab(instance, this), "instance.settings.mods", "package-x-generic-symbolic"); + addTab(new ExportTab(instance, this), "instance.settings.export", "send-to-symbolic"); + } +} diff --git a/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/edit/ModsTab.java b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/settings/instance/ModsTab.java similarity index 69% rename from launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/edit/ModsTab.java rename to launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/settings/instance/ModsTab.java index 05e1f16..c71b63c 100644 --- a/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/edit/ModsTab.java +++ b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/settings/instance/ModsTab.java @@ -1,12 +1,12 @@ -package io.gitlab.jfronny.inceptum.gtk.window.edit; +package io.gitlab.jfronny.inceptum.gtk.window.settings.instance; import io.gitlab.jfronny.inceptum.gtk.control.ILabel; -import io.gitlab.jfronny.inceptum.gtk.window.InstanceSettingsWindow; +import io.gitlab.jfronny.inceptum.gtk.control.settings.SettingsTab; import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance; public class ModsTab extends SettingsTab { public ModsTab(Instance instance, InstanceSettingsWindow window) { - super(instance, window); + super(window); append(new ILabel("instance.settings.mods.unsupported")); //TODO implement this, somehow } diff --git a/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/settings/launcher/AccountsTab.java b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/settings/launcher/AccountsTab.java new file mode 100644 index 0000000..23729b4 --- /dev/null +++ b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/settings/launcher/AccountsTab.java @@ -0,0 +1,13 @@ +package io.gitlab.jfronny.inceptum.gtk.window.settings.launcher; + +import io.gitlab.jfronny.inceptum.gtk.control.settings.SettingsTab; +import org.gtk.gtk.Label; +import org.gtk.gtk.Window; + +public class AccountsTab extends SettingsTab { + public AccountsTab(Window window) { + super(window); + append(new Label("Account management is still in development")); + //TODO implement + } +} diff --git a/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/settings/launcher/GeneralTab.java b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/settings/launcher/GeneralTab.java new file mode 100644 index 0000000..7510daf --- /dev/null +++ b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/settings/launcher/GeneralTab.java @@ -0,0 +1,36 @@ +package io.gitlab.jfronny.inceptum.gtk.window.settings.launcher; + +import io.gitlab.jfronny.inceptum.common.InceptumConfig; +import io.gitlab.jfronny.inceptum.common.model.inceptum.UpdateChannel; +import io.gitlab.jfronny.inceptum.gtk.control.settings.IRow; +import io.gitlab.jfronny.inceptum.gtk.control.settings.SettingsTab; +import org.gtk.gtk.Window; + +public class GeneralTab extends SettingsTab { + public GeneralTab(Window window) { + super(window); + section(null, section -> { + { + IRow row = section.row("settings.general.snapshots", "settings.general.snapshots.subtitle"); + row.setSwitch(InceptumConfig.snapshots, b -> { + InceptumConfig.snapshots = b; + InceptumConfig.saveConfig(); + }); + } + { + IRow row = section.row("settings.general.update-channel", "settings.general.update-channel.subtitle"); + row.setDropdown(new String[] {"Stable", "CI"}, InceptumConfig.channel == UpdateChannel.CI ? 1 : 0, state -> { + InceptumConfig.channel = state == 1 ? UpdateChannel.CI : UpdateChannel.Stable; + InceptumConfig.saveConfig(); + }); + } + { + IRow row = section.row("settings.general.author-name", "settings.general.author-name.subtitle"); + row.setEntry(InceptumConfig.authorName, s -> { + InceptumConfig.authorName = s; + InceptumConfig.saveConfig(); + }); + } + }); + } +} diff --git a/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/settings/launcher/LauncherSettingsWindow.java b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/settings/launcher/LauncherSettingsWindow.java new file mode 100644 index 0000000..fa79d1c --- /dev/null +++ b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/window/settings/launcher/LauncherSettingsWindow.java @@ -0,0 +1,12 @@ +package io.gitlab.jfronny.inceptum.gtk.window.settings.launcher; + +import io.gitlab.jfronny.inceptum.gtk.control.settings.SettingsWindow; +import org.gtk.gtk.Application; + +public class LauncherSettingsWindow extends SettingsWindow { + public LauncherSettingsWindow(Application app) { + super(app); + addTab(new GeneralTab(this), "settings.general", "preferences-other-symbolic"); + addTab(new AccountsTab(this), "settings.accounts", "system-users-symbolic"); + } +} diff --git a/launcher-gtk/src/main/resources/inceptum.properties b/launcher-gtk/src/main/resources/inceptum.properties index 382530c..06c4cdc 100644 --- a/launcher-gtk/src/main/resources/inceptum.properties +++ b/launcher-gtk/src/main/resources/inceptum.properties @@ -21,6 +21,7 @@ cancel=Cancel show=Show save=Save select=Select +failed=Failed menu.hamburger.support=Support menu.hamburger.preferences=Preferences menu.hamburger.about=About @@ -79,12 +80,13 @@ instance.settings.general.last-launched=Last launched: %1$s instance.settings.general.game=Game instance.settings.general.game.version=Version instance.settings.general.game.version.subtitle=Minecraft version of this instance -settings.author-name=Author Name -settings.snapshots=Snapshots -settings.update-channel=Update Channel -settings.snapshots.subtitle=Whether to show snapshots in the version selector for new instances -settings.update-channel.subtitle=The update channel. I personnaly recommend the CI channel as it gest the latest features and fixes more quickly, but it might be more unstable -settings.author-name.subtitle=The author name to add to packs where the metadata format requires specifying one +settings.general=General +settings.general.author-name=Author Name +settings.general.snapshots=Snapshots +settings.general.update-channel=Update Channel +settings.general.snapshots.subtitle=Whether to show snapshots in the version selector for new instances +settings.general.update-channel.subtitle=The update channel. I personnaly recommend the CI channel as it gest the latest features and fixes more quickly, but it might be more unstable +settings.general.author-name.subtitle=The author name to add to packs where the metadata format requires specifying one instance.settings.general.game.fabric.enabled=Fabric instance.settings.general.game.fabric.enabled.subtitle=Whether the Fabric Loader should be used for this instance instance.settings.general.game.fabric.version=Fabric Version @@ -94,4 +96,11 @@ instance.settings.general.game.java.subtitle=The path of the custom Java binary instance.settings.general.game.memory.min=Minimum Memory instance.settings.general.game.memory.min.subtitle=The minimum amount of Memory Minecraft will allocate (in MiB) instance.settings.general.game.memory.max=Maximum Memory -instance.settings.general.game.memory.max.subtitle=The maximum amount of Memory Minecraft will allocate (in MiB) \ No newline at end of file +instance.settings.general.game.memory.max.subtitle=The maximum amount of Memory Minecraft will allocate (in MiB) +settings.accounts=Accounts +instance.delete.fail=Could not delete the instance +instance.copy.fail=Could not copy instance +instance.kill.fail=Could not kill the Instance +instance.kill.prompt=Are you sure? +instance.kill.details=Killing this Instance may cause data corruption and should be avoided if possible +instance.kill=Kill \ No newline at end of file diff --git a/launcher-gtk/src/main/resources/inceptum_de.properties b/launcher-gtk/src/main/resources/inceptum_de.properties index 29a727c..41fc441 100644 --- a/launcher-gtk/src/main/resources/inceptum_de.properties +++ b/launcher-gtk/src/main/resources/inceptum_de.properties @@ -20,6 +20,7 @@ cancel=Abbrechen show=Anzeigen save=Speichern select=Auswählen +failed=Erfolglos menu.hamburger.support=Unterstützung menu.hamburger.preferences=Einstellungen menu.hamburger.about=Über @@ -42,7 +43,7 @@ instance.copy=Klonen instance.delete=Löschen instance.delete.subtitle=Diese Instanz unwiederruflich löschen instance.delete.confirm=Diese Instanz wird unwiederruflich gelöscht -instance.delete.confirm.title=Bist du sicher? +instance.delete.confirm.title=Sind Sie sicher? instance.copy.prompt=Neuer Name instance.copy.details=Gib den Namen für die neue Instanz ein instance.settings.general=Allgemein @@ -79,12 +80,13 @@ instance.settings.general.last-launched=Zuletzt gestartet: %1$s instance.settings.general.game=Game instance.settings.general.game.version=Version instance.settings.general.game.version.subtitle=Minecraft-Version dieser Instanz -settings.author-name=Name des Authors -settings.snapshots=Vorschauversionen -settings.update-channel=Updatekanal -settings.snapshots.subtitle=Ob Vorschauversionen im Versions-Auswahlmenü gezeigt werden sollen -settings.update-channel.subtitle=Der Update-Kanal. Ich empfehle den etwas instabileren, aber häufiger aktualisierten CI-Kanal -settings.author-name.subtitle=Der Name, der bei Modpack-Exporten, deren Metadaten einen Autor angeben, aufgelistet werden soll +settings.general=Allgemein +settings.general.author-name=Name des Authors +settings.general.snapshots=Vorschauversionen +settings.general.update-channel=Updatekanal +settings.general.snapshots.subtitle=Ob Vorschauversionen im Versions-Auswahlmenü gezeigt werden sollen +settings.general.update-channel.subtitle=Der Update-Kanal. Ich empfehle den etwas instabileren, aber häufiger aktualisierten CI-Kanal +settings.general.author-name.subtitle=Der Name, der bei Modpack-Exporten, deren Metadaten einen Autor angeben, aufgelistet werden soll instance.settings.general.game.fabric.enabled=Fabric instance.settings.general.game.fabric.enabled.subtitle=Ob Fabric-Loader für diese Instanz aktiviert werden soll instance.settings.general.game.fabric.version=Fabric-Version @@ -94,4 +96,11 @@ instance.settings.general.game.java.subtitle=Pfad der Java-Bin instance.settings.general.game.memory.min=Minimale Speichernutzung instance.settings.general.game.memory.min.subtitle=Die minimale Speichernutzung dieser Instanz (in MiB) instance.settings.general.game.memory.max=Maximale Speichernutzung -instance.settings.general.game.memory.max.subtitle=Die maximale Speichernutzung dieser Instanz (in MiB) \ No newline at end of file +instance.settings.general.game.memory.max.subtitle=Die maximale Speichernutzung dieser Instanz (in MiB) +settings.accounts=Konten +instance.delete.fail=Konnte die Instanz nicht löschen +instance.copy.fail=Konnte die Instanz nicht kopieren +instance.kill.fail=Ausführung konnte nicht abgebrochen werden +instance.kill.prompt=Sind Sie sicher? +instance.kill.details=Das vorzeitige Beenden von Instanzen kann zu Datenverlust führen und sollte vermieden werden +instance.kill=Beenden \ No newline at end of file diff --git a/launcher-imgui/src/main/java/io/gitlab/jfronny/inceptum/imgui/window/GuiUtil.java b/launcher-imgui/src/main/java/io/gitlab/jfronny/inceptum/imgui/window/GuiUtil.java index 7354bcc..8d9d7ac 100644 --- a/launcher-imgui/src/main/java/io/gitlab/jfronny/inceptum/imgui/window/GuiUtil.java +++ b/launcher-imgui/src/main/java/io/gitlab/jfronny/inceptum/imgui/window/GuiUtil.java @@ -44,6 +44,7 @@ public class GuiUtil { GuiMain.open(new ProcessStateWatcherWindow("Creating Instance", "Could not create instance", pState, cToken -> { for (Step step : Steps.STEPS) { if (cToken.get()) return; + pState.incrementStep(step.name); step.execute(state, cToken); } LauncherEnv.showInfo("The instance was successfully created. You can now launch it using the main menu", "Successfully installed"); diff --git a/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/instance/Instance.java b/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/instance/Instance.java index 6598497..a9085e5 100644 --- a/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/instance/Instance.java +++ b/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/instance/Instance.java @@ -123,6 +123,27 @@ public record Instance(String id, Path path, InstanceMeta meta, ModsDirScanner m return false; } + public boolean kill() { + if (!isRunningLocked()) { + Utils.LOGGER.info("Already killed"); + return false; + } + try { + if (!ProcessUtils.kill(Files.readString(path.resolve(LOCK_NAME)))) { + Utils.LOGGER.error("Could not kill instance"); + return false; + } + if (isRunningLocked()) { + Utils.LOGGER.error("Still running after kill"); + return false; + } + return true; + } catch (IOException e) { + Utils.LOGGER.error("Could not read running lock of " + name, e); + } + return false; + } + public void setRunningLock(long pid) throws IOException { Files.writeString(path.resolve(LOCK_NAME), Long.toString(pid)); } diff --git a/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/instance/InstanceList.java b/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/instance/InstanceList.java index f23b928..ddbcb80 100644 --- a/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/instance/InstanceList.java +++ b/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/instance/InstanceList.java @@ -3,6 +3,7 @@ package io.gitlab.jfronny.inceptum.launcher.system.instance; import gsoncompile.extensions.io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta.GC_InstanceMeta; import io.gitlab.jfronny.commons.io.JFiles; import io.gitlab.jfronny.commons.throwable.ThrowingConsumer; +import io.gitlab.jfronny.commons.throwable.ThrowingRunnable; import io.gitlab.jfronny.inceptum.common.MetaHolder; import io.gitlab.jfronny.inceptum.common.Utils; import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta; @@ -13,10 +14,17 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.*; +import java.util.stream.Stream; public class InstanceList { private static final Map metas = new LinkedHashMap<>(); + public static void lock(ThrowingRunnable task) throws TEx { + synchronized (metas) { + task.run(); + } + } + public static void reset() { synchronized (metas) { for (var entry : metas.entrySet()) { @@ -55,6 +63,13 @@ public class InstanceList { return JFiles.list(MetaHolder.INSTANCE_DIR, InstanceList::isInstance).isEmpty; } + public static int size() throws IOException { + if (!Files.exists(MetaHolder.INSTANCE_DIR)) return 0; + try (Stream list = Files.list(MetaHolder.INSTANCE_DIR)) { + return (int) list.filter(InstanceList::isInstance).count(); + } + } + public static Instance read(Path instancePath) throws IOException { Objects.requireNonNull(instancePath); synchronized (metas) { diff --git a/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/launch/InstanceLauncher.java b/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/launch/InstanceLauncher.java index a60fffd..a22c979 100644 --- a/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/launch/InstanceLauncher.java +++ b/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/launch/InstanceLauncher.java @@ -149,28 +149,41 @@ public class InstanceLauncher { Runnable starterRunner = () -> { try { proc.set(pb.start()); - instance.setRunningLock(proc.get().pid()); + instance.runningLock = proc.get().pid(); } catch (IOException e) { Utils.LOGGER.error("Could not start " + launchType.name, e); } }; - starterRunner.run(); if (restart) { new Thread(() -> { while (true) { + starterRunner.run(); + if (!proc.get().isAlive) { + Utils.LOGGER.error("Could not create server process"); + instance.isRunningLocked(); + return; + } try { proc.get().waitFor(); } catch (InterruptedException e) { Utils.LOGGER.error("Could not wait for server to finish", e); } Utils.LOGGER.info("Restarting server"); - starterRunner.run(); - if (!proc.get().isAlive) { - Utils.LOGGER.error("Could not restart server"); - return; - } } }).start(); + } else { + var th = new Thread(() -> { + starterRunner.run(); + try { + proc.get().waitFor(); + } catch (InterruptedException e) { + Utils.LOGGER.error("Could not wait for thread", e); + return; + } + instance.isRunningLocked(); + }); + th.isDaemon = true; + th.start(); } } diff --git a/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/setup/Step.java b/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/setup/Step.java index 4e623da..7f25cd8 100644 --- a/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/setup/Step.java +++ b/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/setup/Step.java @@ -5,4 +5,5 @@ import java.util.concurrent.atomic.AtomicBoolean; public interface Step { void execute(SetupStepInfo info, AtomicBoolean stopThread) throws IOException; + String getName(); } diff --git a/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/setup/Steps.java b/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/setup/Steps.java index fc0efaa..5eee9fa 100644 --- a/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/setup/Steps.java +++ b/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/setup/Steps.java @@ -46,7 +46,7 @@ public class Steps { : LoaderInfo.NONE; SetupStepInfo info = new SetupStepInfo(vi, li, instance.name, state); for (Step step : Steps.STEPS) { - state.incrementStep("Starting " + step.getClass().getSimpleName()); + state.incrementStep(step.name); step.execute(info, cancel); if (cancel.get()) return; } diff --git a/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/setup/steps/DownloadAssetsStep.java b/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/setup/steps/DownloadAssetsStep.java index ae4c71f..541b2ac 100644 --- a/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/setup/steps/DownloadAssetsStep.java +++ b/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/setup/steps/DownloadAssetsStep.java @@ -31,4 +31,9 @@ public class DownloadAssetsStep implements Step { throw new IOException("Could not download assets", e); } } + + @Override + public String getName() { + return "Downloading Assets"; + } } diff --git a/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/setup/steps/DownloadClientStep.java b/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/setup/steps/DownloadClientStep.java index a03d485..98a4c0a 100644 --- a/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/setup/steps/DownloadClientStep.java +++ b/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/setup/steps/DownloadClientStep.java @@ -52,4 +52,9 @@ public class DownloadClientStep implements Step { throw new IOException("Could not download client", e); } } + + @Override + public String getName() { + return "Downloading Game"; + } } diff --git a/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/setup/steps/DownloadJavaStep.java b/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/setup/steps/DownloadJavaStep.java index c40ba83..a131701 100644 --- a/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/setup/steps/DownloadJavaStep.java +++ b/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/setup/steps/DownloadJavaStep.java @@ -41,4 +41,9 @@ public class DownloadJavaStep implements Step { } } } + + @Override + public String getName() { + return "Downloading Java"; + } } diff --git a/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/setup/steps/DownloadLibrariesStep.java b/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/setup/steps/DownloadLibrariesStep.java index 6907189..a3d0875 100644 --- a/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/setup/steps/DownloadLibrariesStep.java +++ b/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/setup/steps/DownloadLibrariesStep.java @@ -23,6 +23,11 @@ public class DownloadLibrariesStep implements Step { execute(info.version, stopThread, info.currentState); } + @Override + public String getName() { + return "Downloading Libraries"; + } + public static void execute(VersionInfo version, AtomicBoolean stopThread, ProcessState currentState) throws IOException { for (ArtifactInfo artifact : VersionInfoLibraryResolver.getRelevant(version)) { if (stopThread.get()) return; diff --git a/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/setup/steps/RunMdsStep.java b/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/setup/steps/RunMdsStep.java index d51943d..0123f69 100644 --- a/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/setup/steps/RunMdsStep.java +++ b/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/setup/steps/RunMdsStep.java @@ -19,4 +19,9 @@ public class RunMdsStep implements Step { ModsDirScanner.get(instance.resolve("mods"), GC_InstanceMeta.read(instance.resolve(Instance.CONFIG_NAME))) .runOnce((path, iwModDescription) -> info.setState("Scanned " + path)); } + + @Override + public String getName() { + return "Running mod discovery system"; + } } diff --git a/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/setup/steps/SetupDirsStep.java b/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/setup/steps/SetupDirsStep.java index 7e7b0d0..79b33ed 100644 --- a/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/setup/steps/SetupDirsStep.java +++ b/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/setup/steps/SetupDirsStep.java @@ -35,4 +35,9 @@ public class SetupDirsStep implements Step { } Files.createDirectories(MetaHolder.NATIVES_DIR.resolve(GameVersionParser.getGameVersion(info.version.id))); } + + @Override + public String getName() { + return "Setting up directories"; + } } diff --git a/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/setup/steps/WriteMetadataStep.java b/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/setup/steps/WriteMetadataStep.java index 953e224..f0194f0 100644 --- a/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/setup/steps/WriteMetadataStep.java +++ b/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/setup/steps/WriteMetadataStep.java @@ -43,4 +43,9 @@ public class WriteMetadataStep implements Step { Files.writeString(instance.resolve(".iceignore"), Instance.CONFIG_NAME); } } + + @Override + public String getName() { + return "Writing Metadata"; + } } diff --git a/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/util/ProcessUtils.java b/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/util/ProcessUtils.java index 34502c0..2e9e657 100644 --- a/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/util/ProcessUtils.java +++ b/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/util/ProcessUtils.java @@ -13,6 +13,13 @@ public class ProcessUtils { return isProcessIdRunning(pid, "ps", "-p", pid); } + public static boolean kill(String pid) { + //TODO test on windows + if (OSUtils.TYPE == OSUtils.Type.WINDOWS) + return kill("taskkill", "/f", "/pid", pid); + return kill("kill", "--timeout", "500", "KILL", pid); + } + private static boolean isProcessIdRunning(String pid, String... command) { try { Runtime rt = Runtime.getRuntime(); @@ -33,4 +40,17 @@ public class ProcessUtils { return true; } } + + private static boolean kill(String... command) { + try { + Runtime rt = Runtime.getRuntime(); + Process pr = rt.exec(command); + pr.waitFor(); + Thread.sleep(100); // Ensure the signal is processed by waiting this randomly picked amount of time + return pr.exitValue() == 0; + } catch (Exception e) { + Utils.LOGGER.error("Could not kill process", e); + return false; + } + } }