diff --git a/launcher-cli/src/main/java/io/gitlab/jfronny/inceptum/cli/commands/LaunchCommand.java b/launcher-cli/src/main/java/io/gitlab/jfronny/inceptum/cli/commands/LaunchCommand.java index 3d2d8fd..aa31b31 100644 --- a/launcher-cli/src/main/java/io/gitlab/jfronny/inceptum/cli/commands/LaunchCommand.java +++ b/launcher-cli/src/main/java/io/gitlab/jfronny/inceptum/cli/commands/LaunchCommand.java @@ -19,7 +19,7 @@ public class LaunchCommand extends BaseInstanceCommand { public LaunchCommand() { super("Launches an instance of the game (client by default). Non-blocking (batch commands will continue if this is ran)", "[game arguments...]", - List.of("run", "launch", "start"), + List.of("run", "instance.launch", "start"), List.of( new LaunchCommand("Explicitly launch a client", "client", false, false), new LaunchCommand("Launch a server", "server", true, false, 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 6ebf174..8e32cd6 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 @@ -44,21 +44,24 @@ public enum GtkEnvBackend implements LauncherEnv.EnvBackend { //TODO test @Override public void getInput(String prompt, String details, String defaultValue, Consumer ok, Runnable cancel) { //TODO spacing - Dialog dialog = new Dialog(); - if (dialogParent != null) dialog.setTransientFor(dialogParent); - dialog.setModal(GTK.TRUE); - if (dialogParent != null) dialog.setDestroyWithParent(GTK.TRUE); - dialog.setTitle(new Str(prompt)); - Box box = dialog.getContentArea(); - box.append(new Label(new Str(details))); - Entry entry = new Entry(); - Editable entryEditable = new Editable(entry.cast()); - entryEditable.setText(new Str(defaultValue)); - box.append(entry); - dialog.addButton(I18n.str("ok"), ResponseType.OK); - dialog.addButton(I18n.str("cancel"), ResponseType.CANCEL); - dialog.onResponse(processResponses(dialog, () -> ok.accept(entryEditable.getText().toString()), cancel)); - dialog.show(); + //TODO run on main thread + GtkMain.schedule(() -> { + Dialog dialog = new Dialog(); + if (dialogParent != null) dialog.setTransientFor(dialogParent); + dialog.setModal(GTK.TRUE); + if (dialogParent != null) dialog.setDestroyWithParent(GTK.TRUE); + dialog.setTitle(new Str(prompt)); + Box box = dialog.getContentArea(); + box.append(new Label(new Str(details))); + Entry entry = new Entry(); + Editable entryEditable = new Editable(entry.cast()); + entryEditable.setText(new Str(defaultValue)); + box.append(entry); + dialog.addButton(I18n.str("ok"), ResponseType.OK); + dialog.addButton(I18n.str("cancel"), ResponseType.CANCEL); + dialog.onResponse(processResponses(dialog, () -> ok.accept(entryEditable.getText().toString()), cancel)); + dialog.show(); + }); } @Override @@ -67,11 +70,13 @@ public enum GtkEnvBackend implements LauncherEnv.EnvBackend { //TODO test } private void simpleDialog(String markup, String title, int type, int buttons, Runnable ok, Runnable cancel) { - MessageDialog dialog = new MessageDialog(dialogParent, DialogFlags.MODAL | DialogFlags.DESTROY_WITH_PARENT, type, buttons, null); - dialog.setTitle(new Str(title)); - dialog.setMarkup(new Str(markup)); - dialog.onResponse(processResponses(dialog, ok, cancel)); - dialog.show(); + GtkMain.schedule(() -> { + MessageDialog dialog = new MessageDialog(dialogParent, DialogFlags.MODAL | DialogFlags.DESTROY_WITH_PARENT, type, buttons, null); + dialog.setTitle(new Str(title)); + dialog.setMarkup(new Str(markup)); + dialog.onResponse(processResponses(dialog, ok, cancel)); + dialog.show(); + }); } private Dialog.OnResponse processResponses(Dialog dialog, @Nullable Runnable ok, @Nullable Runnable cancel) { 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 c87ebc9..67e16d4 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 @@ -2,6 +2,7 @@ package io.gitlab.jfronny.inceptum.gtk; import ch.bailu.gtk.GTK; import ch.bailu.gtk.gio.ApplicationFlags; +import ch.bailu.gtk.glib.Glib; import ch.bailu.gtk.gtk.Application; import ch.bailu.gtk.type.Str; import ch.bailu.gtk.type.Strs; @@ -10,9 +11,11 @@ import io.gitlab.jfronny.inceptum.gtk.window.MainWindow; import io.gitlab.jfronny.inceptum.launcher.LauncherEnv; import java.io.IOException; +import java.util.*; public class GtkMain { public static final Str ID = new Str("io.gitlab.jfronny.inceptum"); + private static final Queue SCHEDULED = new ArrayDeque<>(); public static void main(String[] args) throws IOException { LauncherEnv.initialize(GtkEnvBackend.INSTANCE); @@ -28,12 +31,27 @@ public class GtkMain { } } + public static void schedule(Runnable task) { + SCHEDULED.add(Objects.requireNonNull(task)); + } + public static int showGui(String[] args) throws IOException { var app = new Application(ID, ApplicationFlags.FLAGS_NONE); app.onActivate(() -> { GtkMenubar.create(app); var window = new MainWindow(app); window.show(); + Glib.idleAdd(user_data -> { + Runnable r; + while ((r = SCHEDULED.poll()) != null) { + try { + r.run(); + } catch (Throwable t) { + Utils.LOGGER.error("Could not run scheduled task", t); + } + } + return GTK.TRUE; + }, null); GtkEnvBackend.INSTANCE.dialogParent = window; window.onCloseRequest(() -> { GtkEnvBackend.INSTANCE.dialogParent = null; 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 fe0c01a..e117b5e 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 @@ -46,32 +46,35 @@ public class GtkMenubar { launchMenu.clear(); try { InstanceList.forEach(entry -> { - launchMenu.literalButton(entry.id(), entry.toString(), () -> { - Runnable launch = () -> { - try { - Steps.reDownload(entry.path(), Steps.createProcessState()); - } catch (IOException e) { - Utils.LOGGER.error("Could not redownload instance, trying to start anyways", e); - } - InstanceLauncher.launchClient(entry.path(), entry.meta()); - }; - if (InstanceLock.isSetupLocked(entry.path())) { - LauncherEnv.showError(I18n.get("launch.locked.setup"), I18n.get("launch.locked")); - return; - } - if (InstanceLock.isRunningLocked(entry.path())) { - LauncherEnv.showOkCancel(I18n.get("launch.locked.running"), I18n.get("launch.locked"), () -> { - new Thread(launch).start(); //TODO loom - }, R::nop); - } - new Thread(launch).start(); - }); + launchMenu.literalButton(entry.id(), entry.toString(), () -> launch(entry)); }); } catch (IOException e) { Utils.LOGGER.error("Could not generate launch menu", e); } } + public static void launch(InstanceList.Entry instance) { + //TODO show popup during launch w/ cancel option (lock main UI) + Runnable launch = () -> { + try { + Steps.reDownload(instance.path(), Steps.createProcessState()); + } catch (IOException e) { + Utils.LOGGER.error("Could not redownload instance, trying to start anyways", e); + } + InstanceLauncher.launchClient(instance.path(), instance.meta()); + }; + if (InstanceLock.isSetupLocked(instance.path())) { + LauncherEnv.showError(I18n.get("instance.launch.locked.setup"), I18n.get("instance.launch.locked")); + return; + } + if (InstanceLock.isRunningLocked(instance.path())) { + LauncherEnv.showOkCancel(I18n.get("instance.launch.locked.running"), I18n.get("instance.launch.locked"), () -> { + new Thread(launch).start(); //TODO loom + }, R::nop); + } + new Thread(launch).start(); + } + public static void generateAccountsMenu() { Objects.requireNonNull(accountsMenu); accountsMenu.clear(); diff --git a/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/TestStart.java b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/TestStart.java index 18612ee..bfe0468 100644 --- a/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/TestStart.java +++ b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/TestStart.java @@ -5,6 +5,7 @@ import ch.bailu.gtk.gio.ApplicationFlags; import ch.bailu.gtk.gtk.*; import ch.bailu.gtk.type.Str; import ch.bailu.gtk.type.Strs; +import io.gitlab.jfronny.inceptum.common.R; public class TestStart { public static void main(String[] args) { @@ -30,6 +31,7 @@ public class TestStart { private static void test() { GtkEnvBackend backend = GtkEnvBackend.INSTANCE; + backend.getInput("Ae", "IoU\naee", "Def", s -> {}, R::nop); // backend.showInfo("Some message", "Title"); // backend.showError("Yes!", "AAee"); // backend.showError("Nes!", new ArrayIndexOutOfBoundsException("Top 500 cheese")); diff --git a/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/control/InstanceGridEntryFactory.java b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/control/InstanceGridEntryFactory.java new file mode 100644 index 0000000..497eea3 --- /dev/null +++ b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/control/InstanceGridEntryFactory.java @@ -0,0 +1,54 @@ +package io.gitlab.jfronny.inceptum.gtk.control; + +import ch.bailu.gtk.GTK; +import ch.bailu.gtk.bridge.ListIndex; +import ch.bailu.gtk.gtk.*; +import ch.bailu.gtk.type.Str; +import io.gitlab.jfronny.inceptum.common.Utils; +import io.gitlab.jfronny.inceptum.gtk.GtkMenubar; +import io.gitlab.jfronny.inceptum.gtk.util.I18n; +import io.gitlab.jfronny.inceptum.launcher.util.InstanceList; + +import java.util.List; + +public class InstanceGridEntryFactory extends SignalListItemFactory { + public InstanceGridEntryFactory(List instanceList) { + super(); + //TODO better design + onSetup(item -> { + var box = new Box(Orientation.HORIZONTAL, 5); + + Label label = new Label(Str.NULL); +// label.setXalign(0); + label.setWidthChars(20); + label.setMarginEnd(10); + box.append(label); + + Button launch = new Button(); + launch.setIconName(new Str("computer-symbolic")); + launch.setTooltipText(I18n.str("instance.launch")); + launch.setHasTooltip(GTK.TRUE); + box.append(launch); + + Button openDir = new Button(); + openDir.setIconName(new Str("folder-symbolic")); + openDir.setTooltipText(I18n.str("instance.directory")); + openDir.setHasTooltip(GTK.TRUE); + box.append(openDir); + + item.setChild(box); + //TODO server launch with network-server-symbolic + //TODO kill current instance + }); + onBind(item -> { + Label label = new Label(item.getChild().getFirstChild().cast()); + Button launch = new Button(label.getNextSibling().cast()); + Button openDir = new Button(launch.getNextSibling().cast()); + InstanceList.Entry instance = instanceList.get(ListIndex.toIndex(item)); + label.setText(new Str(instance.toString())); + launch.onClicked(() -> GtkMenubar.launch(instance)); + openDir.onClicked(() -> Utils.openFile(instance.path().toFile())); + //TODO edit button document-edit-symbolic -> edit-delete-symbolic, edit-copy-symbolic + }); + } +} 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 new file mode 100644 index 0000000..0a31753 --- /dev/null +++ b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/control/InstanceListEntryFactory.java @@ -0,0 +1,69 @@ +package io.gitlab.jfronny.inceptum.gtk.control; + +import ch.bailu.gtk.GTK; +import ch.bailu.gtk.bridge.ListIndex; +import ch.bailu.gtk.gtk.*; +import ch.bailu.gtk.type.Str; +import io.gitlab.jfronny.inceptum.common.Utils; +import io.gitlab.jfronny.inceptum.gtk.GtkMenubar; +import io.gitlab.jfronny.inceptum.gtk.util.I18n; +import io.gitlab.jfronny.inceptum.launcher.util.InstanceList; + +import java.util.List; + +public class InstanceListEntryFactory extends SignalListItemFactory { + public InstanceListEntryFactory(List instanceList) { + super(); + onSetup(item -> { + var thumbnail = new InstanceThumbnail(); + + var label = new Label(Str.NULL); + label.setHexpand(GTK.TRUE); + + var launch = new Button(); + launch.setIconName(new Str("computer-symbolic")); + launch.setTooltipText(I18n.str("instance.launch")); + launch.setHasTooltip(GTK.TRUE); + + var openDir = new Button(); + openDir.setIconName(new Str("folder-symbolic")); + openDir.setTooltipText(I18n.str("instance.directory")); + openDir.setHasTooltip(GTK.TRUE); + + var row = new Box(Orientation.HORIZONTAL, 8); + row.append(thumbnail); + row.append(label); + row.append(launch); + row.append(openDir); + + item.setChild(row); + + //TODO server launch with network-server-symbolic + //TODO kill current instance + }); + onBind(item -> { + InstanceList.Entry instance = instanceList.get(ListIndex.toIndex(item)); + Box row = new Box(item.getChild().cast()); + InstanceThumbnail thumbnail = new InstanceThumbnail(row.getFirstChild().cast()); + Label label = new Label(thumbnail.getNextSibling().cast()); + Button launch = new Button(label.getNextSibling().cast()); + Button openDir = new Button(launch.getNextSibling().cast()); + + thumbnail.bind(instance); + label.setText(new Str(instance.toString())); + launch.onClicked(() -> GtkMenubar.launch(instance)); + openDir.onClicked(() -> Utils.openFile(instance.path().toFile())); + + //TODO why the hell does this crash the VM? +// var controller = new EventControllerLegacy(); +// controller.onEvent(event -> { +// if (event.getEventType() == EventType.BUTTON_RELEASE) { +// Utils.LOGGER.info("Button " + new ButtonEvent(event.cast()).getButton()); +// } +// return GTK.FALSE; +// }); +// row.addController(controller); + //TODO edit button document-edit-symbolic -> edit-delete-symbolic, edit-copy-symbolic + }); + } +} diff --git a/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/control/InstanceThumbnail.java b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/control/InstanceThumbnail.java new file mode 100644 index 0000000..ca9421c --- /dev/null +++ b/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/control/InstanceThumbnail.java @@ -0,0 +1,42 @@ +package io.gitlab.jfronny.inceptum.gtk.control; + +import ch.bailu.gtk.gtk.*; +import ch.bailu.gtk.type.CPointer; +import ch.bailu.gtk.type.Str; +import io.gitlab.jfronny.inceptum.launcher.util.InstanceList; +import io.gitlab.jfronny.inceptum.launcher.util.InstanceLock; + +public class InstanceThumbnail extends Stack { + private static final Str SPINNER = new Str("spinner"); + private static final Str IMAGE = new Str("image"); + private static final Str GENERIC = new Str("generic"); + + public InstanceThumbnail(CPointer pointer) { + super(pointer); + } + + public InstanceThumbnail() { + super(); + var spinner = new Spinner(); + var image = new Image(); + var generic = new Image(); + generic.setFromIconName(new Str("media-playback-start-symbolic")); //TODO better default icon + addNamed(spinner, SPINNER); + addNamed(image, IMAGE); + addNamed(generic, GENERIC); + } + + public void bind(InstanceList.Entry entry) { + var spinner = new Spinner(getChildByName(SPINNER).cast()); + var image = new Image(getChildByName(IMAGE).cast()); //TODO + var generic = new Image(getChildByName(GENERIC).cast()); + //TODO mark instance being played + if (InstanceLock.isSetupLocked(entry.path())) { + setVisibleChild(spinner); + } else if (false) { // if the instance has an image, load the image data and set it as the visible child + setVisibleChild(image); + } else { + setVisibleChild(generic); + } + } +} 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 4cf7f76..3c8af29 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 @@ -1,29 +1,47 @@ package io.gitlab.jfronny.inceptum.gtk.window; import ch.bailu.gtk.GTK; +import ch.bailu.gtk.adw.StatusPage; +import ch.bailu.gtk.bridge.ListIndex; import ch.bailu.gtk.gio.Menu; +import ch.bailu.gtk.glib.Glib; import ch.bailu.gtk.gtk.*; import ch.bailu.gtk.type.Str; -import io.gitlab.jfronny.inceptum.common.InceptumConfig; -import io.gitlab.jfronny.inceptum.common.Utils; +import io.gitlab.jfronny.inceptum.common.*; import io.gitlab.jfronny.inceptum.gtk.GtkMenubar; +import io.gitlab.jfronny.inceptum.gtk.control.InstanceGridEntryFactory; +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.launcher.util.InstanceList; +import java.io.IOException; import java.net.URI; +import java.nio.file.*; +import java.util.ArrayList; +import java.util.List; + +import static java.nio.file.StandardWatchEventKinds.*; public class MainWindow extends ApplicationWindow { private final Button listButton; private final Button gridButton; + private final Stack stack; + private final Box empty; + private final ListView listView; + private final GridView gridView; + private final List instanceList; + private final ListIndex instanceListIndex; public MainWindow(Application app) { super(app); - var header = new HeaderBar(); - var newButton = new Button(); + HeaderBar header = new HeaderBar(); + Button newButton = new Button(); newButton.setIconName(new Str("list-add-symbolic")); newButton.onClicked(NewInstanceWindow::createAndShow); - var accountsButton = new MenuButton(); + MenuButton accountsButton = new MenuButton(); accountsButton.setIconName(new Str("avatar-default-symbolic")); accountsButton.setPopover(GtkMenubar.accountsMenu.asPopover()); @@ -43,11 +61,13 @@ public class MainWindow extends ApplicationWindow { generateWindowBody(); }); - var uiMenu = new MenuBuilder(app, new Menu(), "hamburger"); + //TODO search button like boxes + + MenuBuilder uiMenu = new MenuBuilder(app, new Menu(), "hamburger"); uiMenu.button("support", () -> Utils.openWebBrowser(new URI("https://gitlab.com/jfmods/inceptum/-/issues"))); uiMenu.button("preferences", () -> {}); //TODO preferences UI inspired by boxes uiMenu.button("about", AboutWindow::createAndShow); - var menuButton = new MenuButton(); + MenuButton menuButton = new MenuButton(); menuButton.setIconName(new Str("open-menu-symbolic")); menuButton.setPopover(uiMenu.asPopover()); @@ -58,18 +78,87 @@ public class MainWindow extends ApplicationWindow { header.packEnd(listButton); header.packEnd(accountsButton); + instanceList = new ArrayList<>(); + instanceListIndex = new ListIndex(); + + listView = new ListView(instanceListIndex.inSelectionModel(), new InstanceListEntryFactory(instanceList)); + gridView = new GridView(instanceListIndex.inSelectionModel(), new InstanceGridEntryFactory(instanceList)); + empty = new Box(Orientation.VERTICAL, 8); + empty.setHalign(Align.CENTER); + empty.setValign(Align.CENTER); + var emptyTitle = new Label(Str.NULL); + emptyTitle.setMarkup(I18n.str("main.empty.title")); + emptyTitle.setHalign(Align.CENTER); + var emptyDescription = new Label(I18n.str("main.empty.description")); + emptyDescription.setHalign(Align.CENTER); + empty.append(emptyTitle); + empty.append(emptyDescription); + //TODO empty.setIconName(new Str()); + stack = new Stack(); + stack.addChild(listView); + stack.addChild(gridView); + + ScrolledWindow scroll = new ScrolledWindow(); + scroll.setPolicy(PolicyType.NEVER, PolicyType.AUTOMATIC); + scroll.setChild(stack); + setDefaultSize(360, 720); setTitle(new Str("Inceptum")); setTitlebar(header); setShowMenubar(GTK.FALSE); - setChild(new TextView()); + setChild(scroll); generateWindowBody(); + //TODO DropTarget to add mods/instances + + try { + setupDirWatcher(); + } catch (IOException e) { + Utils.LOGGER.error("Could not set up watch service, live updates of the instance dir will be unavailable", e); + } + } + + private void setupDirWatcher() throws IOException { //TODO test (including after lock state change) + WatchService ws = FileSystems.getDefault().newWatchService(); + MetaHolder.INSTANCE_DIR.register(ws, ENTRY_MODIFY, ENTRY_CREATE, ENTRY_DELETE); + int source = Glib.idleAdd(user_data -> { + //TODO watch instance dirs for locks + WatchKey key = ws.poll(); + boolean instancesChanged = false; + if (key != null) { + for (WatchEvent event : key.pollEvents()) { + if (event.context() instanceof Path p) { + p = MetaHolder.INSTANCE_DIR.resolve(p); + instancesChanged |= Files.exists(p.resolve("instance.json")); + } + } + } + if (instancesChanged) generateWindowBody(); + return GTK.TRUE; + }, null); + onCloseRequest(() -> { + try { + ws.close(); + } catch (IOException ignored) { + } + Glib.sourceRemove(source); + return GTK.FALSE; + }); } private void generateWindowBody() { if (listButton != null) listButton.setVisible(GTK.is(!InceptumConfig.listView)); if (gridButton != null) gridButton.setVisible(GTK.is(InceptumConfig.listView)); - //TODO create list/grid view + try { + instanceList.clear(); + InstanceList.forEach(instanceList::add); + instanceListIndex.setSize(instanceList.size()); + + if (InstanceList.isEmpty()) stack.setVisibleChild(empty); + else if (InceptumConfig.listView) stack.setVisibleChild(listView); + else stack.setVisibleChild(gridView); + } catch (IOException e) { + Utils.LOGGER.error("Could not generate window body", e); + } } } diff --git a/launcher-gtk/src/main/resources/inceptum.properties b/launcher-gtk/src/main/resources/inceptum.properties index ecfc218..6638c22 100644 --- a/launcher-gtk/src/main/resources/inceptum.properties +++ b/launcher-gtk/src/main/resources/inceptum.properties @@ -21,9 +21,13 @@ cancel=Cancel menu.hamburger.support=Support menu.hamburger.preferences=Preferences menu.hamburger.about=About -launch.locked=Can't launch right now -launch.locked.setup=This instance is currently setting up.\ +instance.launch.locked=Can't launch right now +instance.launch.locked.setup=This instance is currently setting up.\ Please wait until that is finished before playing. -launch.locked.running=This instance is currently running.\ +instance.launch.locked.running=This instance is currently running.\ Click OK to start a second instance of the game.\ Please be aware that doing so is unsupported and WILL cause issues! +instance.launch=Launch +main.empty.title=# Welcome to Inceptum +main.empty.description=To get started, create (or import) a new instance using the + button +instance.directory=Open Directory diff --git a/launcher-gtk/src/main/resources/inceptum_de.properties b/launcher-gtk/src/main/resources/inceptum_de.properties index ef8e39c..a4c5e86 100644 --- a/launcher-gtk/src/main/resources/inceptum_de.properties +++ b/launcher-gtk/src/main/resources/inceptum_de.properties @@ -20,10 +20,14 @@ cancel=Abbrechen menu.hamburger.support=Unterstützung menu.hamburger.preferences=Einstellungen menu.hamburger.about=Über -launch.locked=Instanz kann momentan nicht gestartet werden -launch.locked.setup=Diese Instanz wird noch eingerichtet.\ +instance.launch.locked=Instanz kann momentan nicht gestartet werden +instance.launch.locked.setup=Diese Instanz wird noch eingerichtet.\ Bitte warte, bis dieser Prozess abgeschlossen ist,\ bevor du sie startest. -launch.locked.running=Diese Instanz läuft bereits.\ +instance.launch.locked.running=Diese Instanz läuft bereits.\ Bestätigen sie den Start mit OK, um sie ein zweites mal zu starten.\ Bitte seien sie sich bewusst, dass dies zu Problemen führen wird und NICHT UNTERSÜTZT ist. +instance.launch=Starten +main.empty.title=# Willkommen bei Inceptum +main.empty.description=Importiere oder erstelle um anzufangen eine Instanz mit dem + +instance.directory=Verzeichnis öffnen diff --git a/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/mds/ModsDirScannerImpl.java b/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/mds/ModsDirScannerImpl.java index 3bf3b93..af1e141 100644 --- a/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/mds/ModsDirScannerImpl.java +++ b/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/system/mds/ModsDirScannerImpl.java @@ -128,10 +128,11 @@ class ModsDirScannerImpl implements ModsDirScanner { WatchKey key = service.poll(); if (key != null) { for (WatchEvent event : key.pollEvents()) { - if (event.context() instanceof Path p) - toScan.add(p); + if (event.context() instanceof Path p) { + toScan.add(modsDir.resolve(p)); + } } - key.reset(); + if (!key.reset()) Utils.LOGGER.warn("Could not reset config watch key"); } JFiles.listTo(modsDir, path -> { if (!descriptions.containsKey(path)) diff --git a/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/util/InstanceList.java b/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/util/InstanceList.java index 99454b6..87b3d7f 100644 --- a/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/util/InstanceList.java +++ b/launcher/src/main/java/io/gitlab/jfronny/inceptum/launcher/util/InstanceList.java @@ -25,10 +25,9 @@ public class InstanceList { }); } - public static void forEachLaunchable(Consumer target) throws IOException { - forEach(entry -> { - if (!InstanceLock.isLocked(entry.path)) target.accept(entry); - }); + public static boolean isEmpty() throws IOException { + if (!Files.exists(MetaHolder.INSTANCE_DIR)) return true; + return JFiles.list(MetaHolder.INSTANCE_DIR, Files::isDirectory).isEmpty(); } public static Entry read(Path instancePath) throws IOException {