GTK: Fix instance list auto-updating
This commit is contained in:
parent
08bb13f994
commit
0cb3df331a
|
@ -35,8 +35,8 @@ public abstract class BaseInstanceCommand extends Command {
|
|||
}
|
||||
Instance instance;
|
||||
Path normalPath = Path.of(args[0]);
|
||||
if (Files.exists(normalPath.resolve(InstanceList.INSTANCE_CONFIG_NAME))) {
|
||||
instance = new Instance(normalPath, GC_InstanceMeta.read(normalPath.resolve(InstanceList.INSTANCE_CONFIG_NAME)));
|
||||
if (Files.exists(normalPath.resolve(Instance.CONFIG_NAME))) {
|
||||
instance = new Instance(normalPath, GC_InstanceMeta.read(normalPath.resolve(Instance.CONFIG_NAME)));
|
||||
} else {
|
||||
Path instancePath = MetaHolder.INSTANCE_DIR.resolve(args[0]).normalize();
|
||||
if (!instancePath.startsWith(MetaHolder.INSTANCE_DIR)) {
|
||||
|
|
|
@ -23,7 +23,7 @@ public class ListCommand extends Command {
|
|||
List<Path> paths = JFiles.list(MetaHolder.INSTANCE_DIR);
|
||||
if (paths.isEmpty) System.out.println("No instances are currently present");
|
||||
for (Path path : paths) {
|
||||
if (!Files.exists(path.resolve(InstanceList.INSTANCE_CONFIG_NAME))) {
|
||||
if (!Files.exists(path.resolve(Instance.CONFIG_NAME))) {
|
||||
System.out.println("- Invalid instance: " + path + " (no instance metadata)");
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
package io.gitlab.jfronny.inceptum.gtk.window;
|
||||
|
||||
import io.gitlab.jfronny.inceptum.common.*;
|
||||
import io.gitlab.jfronny.inceptum.common.InceptumConfig;
|
||||
import io.gitlab.jfronny.inceptum.common.Utils;
|
||||
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.gtk.util.ListIndexModel;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.instance.InstanceList;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.instance.*;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.launch.LaunchType;
|
||||
import org.gnome.adw.Clamp;
|
||||
import org.gnome.adw.StatusPage;
|
||||
|
@ -18,12 +18,9 @@ import org.gtk.gtk.*;
|
|||
|
||||
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;
|
||||
|
@ -128,30 +125,21 @@ public class MainWindow extends ApplicationWindow {
|
|||
}
|
||||
}
|
||||
|
||||
private void setupDirWatcher() throws IOException { //TODO fix this never running properly (or at least not updating)
|
||||
WatchService ws = FileSystems.getDefault().newWatchService();
|
||||
MetaHolder.INSTANCE_DIR.register(ws, ENTRY_MODIFY, ENTRY_CREATE, ENTRY_DELETE);
|
||||
int source = GLib.idleAdd(() -> {
|
||||
//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(InstanceList.INSTANCE_CONFIG_NAME));
|
||||
}
|
||||
}
|
||||
private void setupDirWatcher() throws IOException {
|
||||
InstanceListWatcher isw = new InstanceListWatcher();
|
||||
addTickCallback((widget, clock) -> {
|
||||
try {
|
||||
if (isw.poll()) generateWindowBody();
|
||||
} catch (IOException e) {
|
||||
Utils.LOGGER.error("Could not run update task", e);
|
||||
}
|
||||
if (instancesChanged) generateWindowBody();
|
||||
return true;
|
||||
});
|
||||
return GLib.SOURCE_CONTINUE;
|
||||
}, null);
|
||||
onCloseRequest(() -> {
|
||||
try {
|
||||
ws.close();
|
||||
isw.close();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
GLib.sourceRemove(source);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
@ -167,6 +155,9 @@ public class MainWindow extends ApplicationWindow {
|
|||
if (InstanceList.isEmpty) stack.visibleChild = empty;
|
||||
else if (InceptumConfig.listView) stack.visibleChild = listContainer;
|
||||
else stack.visibleChild = gridView;
|
||||
|
||||
stack.queueResize();
|
||||
stack.queueDraw();
|
||||
} catch (IOException e) {
|
||||
Utils.LOGGER.error("Could not generate window body", e);
|
||||
}
|
||||
|
|
|
@ -29,8 +29,8 @@ public class InstanceView {
|
|||
ImGui.text("This instance is currently being set up");
|
||||
continue;
|
||||
}
|
||||
if (!Files.exists(instance.path.resolve(InstanceList.INSTANCE_CONFIG_NAME))) {
|
||||
Utils.LOGGER.error("Invalid instance (doesn't contain " + InstanceList.INSTANCE_CONFIG_NAME + "): " + instance);
|
||||
if (!Files.exists(instance.path.resolve(Instance.CONFIG_NAME))) {
|
||||
Utils.LOGGER.error("Invalid instance (doesn't contain " + Instance.CONFIG_NAME + "): " + instance);
|
||||
continue;
|
||||
}
|
||||
ImGui.tableNextColumn();
|
||||
|
|
|
@ -60,7 +60,7 @@ public abstract class Importer<T> {
|
|||
Instance.setSetupLock(iDir, true);
|
||||
InstanceMeta meta = new InstanceMeta();
|
||||
meta.gameVersion = createVersionString(man.gameVersion, man.fabricVersion);
|
||||
GC_InstanceMeta.write(meta, iDir.resolve(InstanceList.INSTANCE_CONFIG_NAME));
|
||||
GC_InstanceMeta.write(meta, iDir.resolve(Instance.CONFIG_NAME));
|
||||
|
||||
state.incrementStep("Downloading mods");
|
||||
downloadMods(manifest, iDir, state);
|
||||
|
|
|
@ -16,8 +16,9 @@ import java.nio.file.Path;
|
|||
import java.util.Set;
|
||||
|
||||
public record Instance(String id, Path path, InstanceMeta meta, ModsDirScanner mds) implements Comparable<Instance> {
|
||||
private static final String INCEPTUM_LOCK = "inceptum.lock";
|
||||
private static final String INCEPTUM_SETUP_LOCK = "inceptum.setup.lock";
|
||||
public static final String LOCK_NAME = "inceptum.lock";
|
||||
public static final String SETUP_LOCK_NAME = "inceptum.setup.lock";
|
||||
public static final String CONFIG_NAME = "instance.json";
|
||||
|
||||
public Instance(Path path, InstanceMeta meta) throws IOException {
|
||||
this(generateId(path.fileName.toString()), path, meta, ModsDirScanner.get(path.resolve("mods"), meta));
|
||||
|
@ -95,7 +96,7 @@ public record Instance(String id, Path path, InstanceMeta meta, ModsDirScanner m
|
|||
}
|
||||
|
||||
public boolean isSetupLocked() {
|
||||
return Files.exists(path.resolve(INCEPTUM_SETUP_LOCK));
|
||||
return Files.exists(path.resolve(SETUP_LOCK_NAME));
|
||||
}
|
||||
|
||||
public void setSetupLock(boolean state) throws IOException {
|
||||
|
@ -103,19 +104,19 @@ public record Instance(String id, Path path, InstanceMeta meta, ModsDirScanner m
|
|||
}
|
||||
|
||||
public static void setSetupLock(Path instanceDir, boolean state) throws IOException {
|
||||
if (Files.exists(instanceDir.resolve(INCEPTUM_SETUP_LOCK))) {
|
||||
if (!state) Files.delete(instanceDir.resolve(INCEPTUM_SETUP_LOCK));
|
||||
if (Files.exists(instanceDir.resolve(SETUP_LOCK_NAME))) {
|
||||
if (!state) Files.delete(instanceDir.resolve(SETUP_LOCK_NAME));
|
||||
} else {
|
||||
if (state) Files.createDirectories(instanceDir.resolve(INCEPTUM_SETUP_LOCK));
|
||||
if (state) Files.createDirectories(instanceDir.resolve(SETUP_LOCK_NAME));
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isRunningLocked() {
|
||||
if (!Files.exists(path.resolve(INCEPTUM_LOCK))) return false;
|
||||
if (!Files.exists(path.resolve(LOCK_NAME))) return false;
|
||||
try {
|
||||
if (ProcessUtils.isProcessAlive(Files.readString(path.resolve(INCEPTUM_LOCK))))
|
||||
if (ProcessUtils.isProcessAlive(Files.readString(path.resolve(LOCK_NAME))))
|
||||
return true;
|
||||
Files.delete(path.resolve(INCEPTUM_LOCK));
|
||||
Files.delete(path.resolve(LOCK_NAME));
|
||||
} catch (IOException e) {
|
||||
Utils.LOGGER.error("Could not read running lock of " + name, e);
|
||||
}
|
||||
|
@ -123,7 +124,7 @@ public record Instance(String id, Path path, InstanceMeta meta, ModsDirScanner m
|
|||
}
|
||||
|
||||
public void setRunningLock(long pid) throws IOException {
|
||||
Files.writeString(path.resolve(INCEPTUM_LOCK), Long.toString(pid));
|
||||
Files.writeString(path.resolve(LOCK_NAME), Long.toString(pid));
|
||||
}
|
||||
|
||||
public boolean isLocked() {
|
||||
|
@ -132,7 +133,7 @@ public record Instance(String id, Path path, InstanceMeta meta, ModsDirScanner m
|
|||
|
||||
public void writeMeta() {
|
||||
try {
|
||||
GC_InstanceMeta.write(meta, path.resolve(InstanceList.INSTANCE_CONFIG_NAME));
|
||||
GC_InstanceMeta.write(meta, path.resolve(CONFIG_NAME));
|
||||
} catch (IOException e) {
|
||||
Utils.LOGGER.error("Could not write instance config", e);
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@ import java.util.*;
|
|||
|
||||
public class InstanceList {
|
||||
private static final Map<Path, IEntry> metas = new LinkedHashMap<>();
|
||||
public static final String INSTANCE_CONFIG_NAME = "instance.json";
|
||||
|
||||
public static void reset() {
|
||||
synchronized (metas) {
|
||||
|
@ -62,7 +61,7 @@ public class InstanceList {
|
|||
if (!metas.containsKey(instancePath)) {
|
||||
metas[instancePath] = new IEntry(
|
||||
instancePath,
|
||||
new FileBackedRef<>(instancePath.resolve(INSTANCE_CONFIG_NAME), GC_InstanceMeta::read)
|
||||
new FileBackedRef<>(instancePath.resolve(Instance.CONFIG_NAME), GC_InstanceMeta::read)
|
||||
);
|
||||
}
|
||||
return metas[instancePath].toPub();
|
||||
|
@ -70,7 +69,7 @@ public class InstanceList {
|
|||
}
|
||||
|
||||
private static boolean isInstance(Path path) {
|
||||
return Files.isDirectory(path) && Files.exists(path.resolve(INSTANCE_CONFIG_NAME));
|
||||
return Files.isDirectory(path) && Files.exists(path.resolve(Instance.CONFIG_NAME));
|
||||
}
|
||||
|
||||
private record IEntry(Path path, FileBackedRef<InstanceMeta> meta) implements Closeable {
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.system.instance;
|
||||
|
||||
import io.gitlab.jfronny.commons.io.JFiles;
|
||||
import io.gitlab.jfronny.inceptum.common.MetaHolder;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static java.nio.file.StandardWatchEventKinds.*;
|
||||
|
||||
public class InstanceListWatcher implements Closeable {
|
||||
private final WatchService watcher = FileSystems.getDefault().newWatchService();
|
||||
private final Map<WatchKey, Path> keys = new HashMap<>();
|
||||
|
||||
private void register(Path dir) throws IOException {
|
||||
keys.put(dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY), dir);
|
||||
}
|
||||
|
||||
public InstanceListWatcher() throws IOException {
|
||||
register(MetaHolder.INSTANCE_DIR);
|
||||
JFiles.listTo(MetaHolder.INSTANCE_DIR, this::register);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
watcher.close();
|
||||
}
|
||||
|
||||
public boolean poll() throws IOException {
|
||||
boolean changed = false;
|
||||
WatchKey key;
|
||||
while ((key = watcher.poll()) != null) {
|
||||
Path dir = keys.get(key);
|
||||
for (WatchEvent<?> event : key.pollEvents()) {
|
||||
var kind = event.kind();
|
||||
if (kind == OVERFLOW) continue;
|
||||
@SuppressWarnings("unchecked") WatchEvent<Path> ev = (WatchEvent<Path>) event;
|
||||
Path name = ev.context();
|
||||
Path child = dir.resolve(name);
|
||||
if (MetaHolder.INSTANCE_DIR.equals(dir)) {
|
||||
if (kind == ENTRY_CREATE) {
|
||||
changed = true;
|
||||
register(child);
|
||||
}
|
||||
if (kind == ENTRY_DELETE) changed = true;
|
||||
} else if (Files.exists(dir.resolve(Instance.CONFIG_NAME))) {
|
||||
String fn = child.fileName.toString();
|
||||
if (fn.equals(Instance.CONFIG_NAME)
|
||||
|| fn.equals(Instance.LOCK_NAME)
|
||||
|| fn.equals(Instance.SETUP_LOCK_NAME)) {
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!key.reset()) {
|
||||
keys.remove(key);
|
||||
if (MetaHolder.INSTANCE_DIR.equals(dir)) {
|
||||
Files.createDirectories(MetaHolder.INSTANCE_DIR);
|
||||
register(MetaHolder.INSTANCE_DIR);
|
||||
}
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@ package io.gitlab.jfronny.inceptum.launcher.system.setup.steps;
|
|||
|
||||
import gsoncompile.extensions.io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta.GC_InstanceMeta;
|
||||
import io.gitlab.jfronny.inceptum.common.MetaHolder;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.instance.InstanceList;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.mds.ModsDirScanner;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.setup.SetupStepInfo;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.setup.Step;
|
||||
|
@ -16,7 +16,7 @@ public class RunMdsStep implements Step {
|
|||
public void execute(SetupStepInfo info, AtomicBoolean stopThread) throws IOException {
|
||||
info.setState("Running MDS");
|
||||
Path instance = MetaHolder.INSTANCE_DIR.resolve(info.name);
|
||||
ModsDirScanner.get(instance.resolve("mods"), GC_InstanceMeta.read(instance.resolve(InstanceList.INSTANCE_CONFIG_NAME)))
|
||||
ModsDirScanner.get(instance.resolve("mods"), GC_InstanceMeta.read(instance.resolve(Instance.CONFIG_NAME)))
|
||||
.runOnce((path, iwModDescription) -> info.setState("Scanned " + path));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ import gsoncompile.extensions.io.gitlab.jfronny.inceptum.launcher.model.inceptum
|
|||
import io.gitlab.jfronny.inceptum.common.MetaHolder;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.instance.InstanceList;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.setup.SetupStepInfo;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.setup.Step;
|
||||
|
||||
|
@ -18,7 +17,7 @@ public class WriteMetadataStep implements Step {
|
|||
public void execute(SetupStepInfo info, AtomicBoolean stopThread) throws IOException {
|
||||
info.setState("Writing metadata");
|
||||
Path instance = MetaHolder.INSTANCE_DIR.resolve(info.name);
|
||||
Path metaPath = instance.resolve(InstanceList.INSTANCE_CONFIG_NAME);
|
||||
Path metaPath = instance.resolve(Instance.CONFIG_NAME);
|
||||
if (!Files.exists(metaPath)) {
|
||||
InstanceMeta meta = new InstanceMeta();
|
||||
meta.gameVersion = info.version.id;
|
||||
|
@ -41,7 +40,7 @@ public class WriteMetadataStep implements Step {
|
|||
realms_persistence.json""");
|
||||
}
|
||||
if (!Files.exists(instance.resolve(".iceignore"))) {
|
||||
Files.writeString(instance.resolve(".iceignore"), InstanceList.INSTANCE_CONFIG_NAME);
|
||||
Files.writeString(instance.resolve(".iceignore"), Instance.CONFIG_NAME);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue