Introduce cleaner "Instance" abstraction
This commit is contained in:
parent
390f6bc59b
commit
5c6266634a
|
@ -4,6 +4,8 @@ import io.gitlab.jfronny.commons.io.JFiles;
|
|||
import io.gitlab.jfronny.inceptum.common.MetaHolder;
|
||||
import io.gitlab.jfronny.inceptum.common.Utils;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
|
||||
import io.gitlab.jfronny.inceptum.launcher.util.InstanceList;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
|
@ -37,25 +39,24 @@ public abstract class BaseInstanceCommand extends Command {
|
|||
return;
|
||||
}
|
||||
Path instancePath = MetaHolder.INSTANCE_DIR.resolve(args.get(0));
|
||||
Path instanceMetaPath = instancePath.resolve("instance.json");
|
||||
if (!Files.exists(instanceMetaPath)) {
|
||||
if (!Files.exists(instancePath)) {
|
||||
Utils.LOGGER.error("Invalid instance: \"" + args.get(0) + "\"");
|
||||
return;
|
||||
}
|
||||
InstanceMeta meta;
|
||||
Instance instance;
|
||||
try {
|
||||
meta = JFiles.readObject(instanceMetaPath, InstanceMeta.class);
|
||||
instance = InstanceList.read(instancePath);
|
||||
} catch (IOException e) {
|
||||
Utils.LOGGER.error("Could not read instance metadata", e);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
invoke(args.subArgs(), instancePath, meta);
|
||||
invoke(args.subArgs(), instance);
|
||||
} catch (Exception e) {
|
||||
Utils.LOGGER.error("Could not execute command", e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void invoke(CommandArgs args, Path instancePath, InstanceMeta meta) throws Exception;
|
||||
protected abstract void invoke(CommandArgs args, Instance instance) throws Exception;
|
||||
}
|
||||
|
|
|
@ -2,12 +2,11 @@ package io.gitlab.jfronny.inceptum.cli.commands;
|
|||
|
||||
import io.gitlab.jfronny.inceptum.cli.*;
|
||||
import io.gitlab.jfronny.inceptum.common.R;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.export.Exporters;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.mds.ModsDirScanner;
|
||||
import io.gitlab.jfronny.inceptum.launcher.util.ProcessState;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -25,14 +24,13 @@ public class ExportCommand extends BaseInstanceCommand {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void invoke(CommandArgs args, Path instancePath, InstanceMeta meta) throws Exception {
|
||||
protected void invoke(CommandArgs args, Instance instance) throws Exception {
|
||||
if (args.length == 0) throw new IllegalAccessException("You must specify a target path");
|
||||
if (args.length == 1) throw new IllegalAccessException("You must specify a version number");
|
||||
if (args.length != 2) throw new IllegalAccessException("Too many arguments");
|
||||
ProcessState state = new ProcessState();
|
||||
ModsDirScanner mds = ModsDirScanner.get(instancePath.resolve("mods"), meta);
|
||||
mds.runOnce(R::nop);
|
||||
Exporters.CURSE_FORGE.generate(state, instancePath, meta, mds, Paths.get(args.get(0)), args.get(1));
|
||||
instance.getMds().runOnce(R::nop);
|
||||
Exporters.CURSE_FORGE.generate(state, instance, Paths.get(args.get(0)), args.get(1));
|
||||
}
|
||||
|
||||
private static class MultiMCExportCommand extends BaseInstanceCommand {
|
||||
|
@ -41,13 +39,12 @@ public class ExportCommand extends BaseInstanceCommand {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void invoke(CommandArgs args, Path instancePath, InstanceMeta meta) throws Exception {
|
||||
protected void invoke(CommandArgs args, Instance instance) throws Exception {
|
||||
if (args.length == 0) throw new IllegalAccessException("You must specify a target path");
|
||||
if (args.length != 1) throw new IllegalAccessException("Too many arguments");
|
||||
ProcessState state = new ProcessState();
|
||||
ModsDirScanner mds = ModsDirScanner.get(instancePath.resolve("mods"), meta);
|
||||
mds.runOnce(R::nop);
|
||||
Exporters.MULTI_MC.generate(state, instancePath, meta, mds, Paths.get(args.get(0)), "1.0");
|
||||
instance.getMds().runOnce(R::nop);
|
||||
Exporters.MULTI_MC.generate(state, instance, Paths.get(args.get(0)), "1.0");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -57,14 +54,13 @@ public class ExportCommand extends BaseInstanceCommand {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void invoke(CommandArgs args, Path instancePath, InstanceMeta meta) throws Exception {
|
||||
protected void invoke(CommandArgs args, Instance instance) throws Exception {
|
||||
if (args.length == 0) throw new IllegalAccessException("You must specify a target path");
|
||||
if (args.length == 1) throw new IllegalAccessException("You must specify a version number");
|
||||
if (args.length != 2) throw new IllegalAccessException("Too many arguments");
|
||||
ProcessState state = new ProcessState();
|
||||
ModsDirScanner mds = ModsDirScanner.get(instancePath.resolve("mods"), meta);
|
||||
mds.runOnce(R::nop);
|
||||
Exporters.MODRINTH.generate(state, instancePath, meta, mds, Paths.get(args.get(0)), args.get(1));
|
||||
instance.getMds().runOnce(R::nop);
|
||||
Exporters.MODRINTH.generate(state, instance, Paths.get(args.get(0)), args.get(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,13 +3,12 @@ package io.gitlab.jfronny.inceptum.cli.commands;
|
|||
import io.gitlab.jfronny.inceptum.cli.*;
|
||||
import io.gitlab.jfronny.inceptum.common.Utils;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.launch.InstanceLauncher;
|
||||
import io.gitlab.jfronny.inceptum.launcher.util.InstanceLock;
|
||||
import io.gitlab.jfronny.inceptum.launcher.api.account.AccountManager;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.install.Steps;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
|
||||
public class LaunchCommand extends BaseInstanceCommand {
|
||||
|
@ -37,16 +36,17 @@ public class LaunchCommand extends BaseInstanceCommand {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void invoke(CommandArgs args, Path instancePath, InstanceMeta meta) throws IOException, InstanceLauncher.LaunchException {
|
||||
if (InstanceLock.isSetupLocked(instancePath)) {
|
||||
protected void invoke(CommandArgs args, Instance instance) throws IOException, InstanceLauncher.LaunchException {
|
||||
if (instance.isSetupLocked()) {
|
||||
Utils.LOGGER.error("This instance is still being set up");
|
||||
return;
|
||||
}
|
||||
if (InstanceLock.isRunningLocked(instancePath)) {
|
||||
if (instance.isRunningLocked()) {
|
||||
Utils.LOGGER.error("This instance is already running");
|
||||
return;
|
||||
}
|
||||
if (args.length > 1) {
|
||||
InstanceMeta meta = instance.meta();
|
||||
if (meta.arguments == null) meta.arguments = new InstanceMeta.Arguments();
|
||||
meta.arguments.client = meta.arguments.client == null ? new ArrayList<>() : new ArrayList<>(meta.arguments.client);
|
||||
meta.arguments.server = meta.arguments.server == null ? new ArrayList<>() : new ArrayList<>(meta.arguments.server);
|
||||
|
@ -54,12 +54,12 @@ public class LaunchCommand extends BaseInstanceCommand {
|
|||
meta.arguments.client.addAll(args.after(0));
|
||||
meta.arguments.server.addAll(args.after(0));
|
||||
}
|
||||
Steps.reDownload(instancePath, Steps.createProcessState());
|
||||
Steps.reDownload(instance, Steps.createProcessState());
|
||||
if (server) {
|
||||
InstanceLauncher.launch(instancePath, meta, InstanceLauncher.LaunchType.Server, restart, AccountManager.NULL_AUTH);
|
||||
InstanceLauncher.launch(instance, InstanceLauncher.LaunchType.Server, restart, AccountManager.NULL_AUTH);
|
||||
} else {
|
||||
AccountManager.loadAccounts();
|
||||
InstanceLauncher.launchClient(instancePath, meta);
|
||||
InstanceLauncher.launchClient(instance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,8 +5,8 @@ import io.gitlab.jfronny.inceptum.common.MetaHolder;
|
|||
import io.gitlab.jfronny.inceptum.common.Utils;
|
||||
import io.gitlab.jfronny.inceptum.cli.Command;
|
||||
import io.gitlab.jfronny.inceptum.cli.CommandArgs;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta;
|
||||
import io.gitlab.jfronny.inceptum.launcher.util.InstanceLock;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
|
||||
import io.gitlab.jfronny.inceptum.launcher.util.InstanceList;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
|
@ -28,24 +28,24 @@ public class ListCommand extends Command {
|
|||
continue;
|
||||
}
|
||||
System.out.println("- \"" + path.getFileName().toString() + "\"");
|
||||
if (InstanceLock.isSetupLocked(path)) {
|
||||
System.out.println(" Status: Setting up");
|
||||
continue;
|
||||
}
|
||||
InstanceMeta instance;
|
||||
Instance instance;
|
||||
try {
|
||||
instance = JFiles.readObject(path.resolve("instance.json"), InstanceMeta.class);
|
||||
instance = InstanceList.read(path);
|
||||
} catch (IOException e) {
|
||||
Utils.LOGGER.error(" Could not load instance.json", e);
|
||||
continue;
|
||||
}
|
||||
System.out.println(" Status: " + (InstanceLock.isRunningLocked(path) ? "Running" : "Stopped"));
|
||||
System.out.println(" Version: " + instance.getMinecraftVersion());
|
||||
if (instance.isFabric()) System.out.println(" Fabric Loader: " + instance.getLoaderVersion());
|
||||
if (instance.java != null) System.out.println(" Custom Java: " + instance.java);
|
||||
if (instance.minMem != null || instance.maxMem != null)
|
||||
System.out.println(" Memory:" + (instance.minMem != null ? " Minimum: " + instance.minMem : "")
|
||||
+ (instance.maxMem != null ? " Maximum: " + instance.maxMem : ""));
|
||||
if (instance.isSetupLocked()) {
|
||||
System.out.println(" Status: Setting up");
|
||||
continue;
|
||||
}
|
||||
System.out.println(" Status: " + (instance.isRunningLocked() ? "Running" : "Stopped"));
|
||||
System.out.println(" Version: " + instance.meta().getMinecraftVersion());
|
||||
if (instance.isFabric()) System.out.println(" Fabric Loader: " + instance.meta().getLoaderVersion());
|
||||
if (instance.meta().java != null) System.out.println(" Custom Java: " + instance.meta().java);
|
||||
if (instance.meta().minMem != null || instance.meta().maxMem != null)
|
||||
System.out.println(" Memory:" + (instance.meta().minMem != null ? " Minimum: " + instance.meta().minMem : "")
|
||||
+ (instance.meta().maxMem != null ? " Maximum: " + instance.meta().maxMem : ""));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,10 +4,10 @@ import io.gitlab.jfronny.commons.io.JFiles;
|
|||
import io.gitlab.jfronny.commons.throwable.ThrowingBiFunction;
|
||||
import io.gitlab.jfronny.inceptum.cli.*;
|
||||
import io.gitlab.jfronny.inceptum.common.Utils;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
|
||||
import io.gitlab.jfronny.inceptum.launcher.util.ModManager;
|
||||
import io.gitlab.jfronny.inceptum.launcher.util.ModPath;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.mds.IWModDescription;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Mod;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.mds.ModsDirScanner;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.source.ModSource;
|
||||
|
||||
|
@ -47,14 +47,13 @@ public class ModCommand extends Command {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void invoke(CommandArgs args, Path instancePath, InstanceMeta meta) throws IOException {
|
||||
if (!meta.isFabric()) {
|
||||
protected void invoke(CommandArgs args, Instance instance) throws IOException {
|
||||
if (!instance.isFabric()) {
|
||||
System.err.println("This is not a fabric instance");
|
||||
return;
|
||||
}
|
||||
System.out.println("Scanning installed mods, this might take a while");
|
||||
ModsDirScanner mds = ModsDirScanner.get(instancePath.resolve("mods"), meta);
|
||||
mds.runOnce((path, mod) -> {
|
||||
instance.getMds().runOnce((path, mod) -> {
|
||||
boolean hasSources = mod.mod().isPresent() && !mod.mod().get().sources.isEmpty();
|
||||
boolean updatable = hasSources && mod.mod().get().sources.values().stream().anyMatch(Optional::isPresent);
|
||||
if (filterUpdatable && !updatable) return;
|
||||
|
@ -91,8 +90,8 @@ public class ModCommand extends Command {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void invoke(CommandArgs args, Path instancePath, InstanceMeta meta) throws IOException {
|
||||
if (!meta.isFabric()) {
|
||||
protected void invoke(CommandArgs args, Instance instance) throws IOException {
|
||||
if (!instance.isFabric()) {
|
||||
Utils.LOGGER.error("This is not a fabric instance");
|
||||
return;
|
||||
}
|
||||
|
@ -102,22 +101,22 @@ public class ModCommand extends Command {
|
|||
}
|
||||
Set<Path> mods = new HashSet<>();
|
||||
for (String arg : args) {
|
||||
Path p = instancePath.resolve("mods").resolve(arg);
|
||||
if (!Files.exists(p)) p = instancePath.resolve("mods").resolve(arg + ".imod");
|
||||
Path p = instance.modsDir().resolve(arg);
|
||||
if (!Files.exists(p)) p = instance.modsDir().resolve(arg + ".imod");
|
||||
if (!Files.exists(p)) {
|
||||
Utils.LOGGER.error("Nonexistant mod file: " + instancePath.resolve("mods").resolve(arg));
|
||||
Utils.LOGGER.error("Nonexistant mod file: " + instance.modsDir().resolve(arg));
|
||||
return;
|
||||
}
|
||||
mods.add(p);
|
||||
}
|
||||
ModsDirScanner mds = ModsDirScanner.get(instancePath.resolve("mods"), meta);
|
||||
ModsDirScanner mds = instance.getMds();
|
||||
if (!ignoreDependencies && !mds.isComplete()) {
|
||||
Utils.LOGGER.error("Scanning mods dir to search for dependencies. This might take a while");
|
||||
mds.runOnce((path, mod) -> System.out.println("Scanned " + path));
|
||||
}
|
||||
for (Path mod : mods) {
|
||||
try {
|
||||
ModManager.delete(mds.get(mod), instancePath.resolve("mods"), mds);
|
||||
ModManager.delete(mds.get(mod), instance.modsDir(), mds);
|
||||
} catch (IOException e) {
|
||||
Utils.LOGGER.error("Could not delete " + mod, e);
|
||||
return;
|
||||
|
@ -152,15 +151,15 @@ public class ModCommand extends Command {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void invoke(CommandArgs args, Path instancePath, InstanceMeta meta) throws IOException {
|
||||
if (!meta.isFabric()) {
|
||||
protected void invoke(CommandArgs args, Instance instance) throws IOException {
|
||||
if (!instance.isFabric()) {
|
||||
throw new IOException("This is not a fabric instance");
|
||||
}
|
||||
if (args.length == 0) {
|
||||
throw new IllegalArgumentException("You must specify mods to remove");
|
||||
}
|
||||
Set<Path> mods = pathSupplier.apply(args, instancePath);
|
||||
ModsDirScanner mds = ModsDirScanner.get(instancePath.resolve("mods"), meta);
|
||||
Set<Path> mods = pathSupplier.apply(args, instance.path());
|
||||
ModsDirScanner mds = instance.getMds();
|
||||
if (!mds.isComplete()) {
|
||||
Utils.LOGGER.error("Scanning mods dir to search for dependencies. This might take a while");
|
||||
mds.runOnce((path, mod) -> System.out.println("Scanned " + path));
|
||||
|
@ -168,8 +167,8 @@ public class ModCommand extends Command {
|
|||
for (Path mod : mods) {
|
||||
try {
|
||||
Utils.LOGGER.info("Updating " + mod);
|
||||
ModManager.delete(mds.get(mod), instancePath.resolve("mods"), mds);
|
||||
IWModDescription md = mds.get(mod);
|
||||
ModManager.delete(mds.get(mod), instance.modsDir(), mds);
|
||||
Mod md = mds.get(mod);
|
||||
if (md.mod().isEmpty()) {
|
||||
throw new IOException("Could not load mod description");
|
||||
}
|
||||
|
@ -179,7 +178,7 @@ public class ModCommand extends Command {
|
|||
if (ms.isPresent()) {
|
||||
try {
|
||||
Utils.LOGGER.info("Updating to " + ms.get().getVersion());
|
||||
Path imodPath = md.imod().isPresent() ? md.imod().get() : instancePath.resolve("mods").resolve(ms.get().getShortName() + ModPath.EXT_IMOD);
|
||||
Path imodPath = md.imod().isPresent() ? md.imod().get() : instance.modsDir().resolve(ms.get().getShortName() + ModPath.EXT_IMOD);
|
||||
ModManager.DownloadMeta dm = ModManager.download(ms.get(), imodPath, mds);
|
||||
Files.delete(md.path());
|
||||
if (md.imod().isPresent() && Files.exists(md.imod().get()))
|
||||
|
|
|
@ -10,10 +10,10 @@ import io.gitlab.jfronny.inceptum.gtk.window.NewInstanceWindow;
|
|||
import io.gitlab.jfronny.inceptum.launcher.LauncherEnv;
|
||||
import io.gitlab.jfronny.inceptum.launcher.api.account.AccountManager;
|
||||
import io.gitlab.jfronny.inceptum.launcher.api.account.MicrosoftAccount;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.install.Steps;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.launch.InstanceLauncher;
|
||||
import io.gitlab.jfronny.inceptum.launcher.util.InstanceList;
|
||||
import io.gitlab.jfronny.inceptum.launcher.util.InstanceLock;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
@ -53,21 +53,21 @@ public class GtkMenubar {
|
|||
}
|
||||
}
|
||||
|
||||
public static void launch(InstanceList.Entry instance) {
|
||||
public static void launch(Instance instance) {
|
||||
//TODO show popup during launch w/ cancel option (lock main UI)
|
||||
Runnable launch = () -> {
|
||||
try {
|
||||
Steps.reDownload(instance.path(), Steps.createProcessState());
|
||||
Steps.reDownload(instance, Steps.createProcessState());
|
||||
} catch (IOException e) {
|
||||
Utils.LOGGER.error("Could not redownload instance, trying to start anyways", e);
|
||||
}
|
||||
InstanceLauncher.launchClient(instance.path(), instance.meta());
|
||||
InstanceLauncher.launchClient(instance);
|
||||
};
|
||||
if (InstanceLock.isSetupLocked(instance.path())) {
|
||||
if (instance.isSetupLocked()) {
|
||||
LauncherEnv.showError(I18n.get("instance.launch.locked.setup"), I18n.get("instance.launch.locked"));
|
||||
return;
|
||||
}
|
||||
if (InstanceLock.isRunningLocked(instance.path())) {
|
||||
if (instance.isRunningLocked()) {
|
||||
LauncherEnv.showOkCancel(I18n.get("instance.launch.locked.running"), I18n.get("instance.launch.locked"), () -> {
|
||||
new Thread(launch).start(); //TODO loom
|
||||
}, R::nop);
|
||||
|
|
|
@ -4,17 +4,13 @@ import ch.bailu.gtk.GTK;
|
|||
import ch.bailu.gtk.bridge.ListIndex;
|
||||
import ch.bailu.gtk.gtk.*;
|
||||
import ch.bailu.gtk.pango.EllipsizeMode;
|
||||
import ch.bailu.gtk.type.Int;
|
||||
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 io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class InstanceGridEntryFactory extends SignalListItemFactory {
|
||||
public InstanceGridEntryFactory(List<InstanceList.Entry> instanceList) {
|
||||
public InstanceGridEntryFactory(List<Instance> instanceList) {
|
||||
super();
|
||||
//TODO better design
|
||||
onSetup(item -> {
|
||||
|
@ -70,7 +66,7 @@ public class InstanceGridEntryFactory extends SignalListItemFactory {
|
|||
InstanceThumbnail thumbnail = new InstanceThumbnail(box.getFirstChild().cast());
|
||||
Label label = new Label(thumbnail.getNextSibling().cast());
|
||||
|
||||
InstanceList.Entry instance = instanceList.get(ListIndex.toIndex(item));
|
||||
Instance instance = instanceList.get(ListIndex.toIndex(item));
|
||||
thumbnail.bind(instance);
|
||||
label.setText(new Str(instance.toString()));
|
||||
//TODO right click menu + double click action
|
||||
|
|
|
@ -8,12 +8,12 @@ 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 io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class InstanceListEntryFactory extends SignalListItemFactory {
|
||||
public InstanceListEntryFactory(List<InstanceList.Entry> instanceList) {
|
||||
public InstanceListEntryFactory(List<Instance> instanceList) {
|
||||
super();
|
||||
onSetup(item -> {
|
||||
var thumbnail = new InstanceThumbnail();
|
||||
|
@ -44,7 +44,7 @@ public class InstanceListEntryFactory extends SignalListItemFactory {
|
|||
//TODO kill current instance
|
||||
});
|
||||
onBind(item -> {
|
||||
InstanceList.Entry instance = instanceList.get(ListIndex.toIndex(item));
|
||||
Instance instance = instanceList.get(ListIndex.toIndex(item));
|
||||
ActionRow row = new ActionRow(item.getChild().cast());
|
||||
Box prefixes = new Box(row.getFirstChild().getFirstChild().cast());
|
||||
Box suffixes = new Box(row.getFirstChild().getLastChild().cast());
|
||||
|
|
|
@ -2,8 +2,7 @@ package io.gitlab.jfronny.inceptum.gtk.control;
|
|||
|
||||
import ch.bailu.gtk.gtk.*;
|
||||
import ch.bailu.gtk.type.*;
|
||||
import io.gitlab.jfronny.inceptum.launcher.util.InstanceList;
|
||||
import io.gitlab.jfronny.inceptum.launcher.util.InstanceLock;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
|
||||
|
||||
public class InstanceThumbnail extends Stack {
|
||||
private static final Str SPINNER = new Str("spinner");
|
||||
|
@ -28,12 +27,12 @@ public class InstanceThumbnail extends Stack {
|
|||
addNamed(generic, GENERIC);
|
||||
}
|
||||
|
||||
public void bind(InstanceList.Entry entry) {
|
||||
public void bind(Instance 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())) {
|
||||
if (entry.isSetupLocked()) {
|
||||
setVisibleChild(spinner);
|
||||
} else if (false) { // if the instance has an image, load the image data and set it as the visible child
|
||||
setVisibleChild(image);
|
||||
|
|
|
@ -14,6 +14,7 @@ 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.model.inceptum.rt.Instance;
|
||||
import io.gitlab.jfronny.inceptum.launcher.util.InstanceList;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -31,7 +32,7 @@ public class MainWindow extends ApplicationWindow {
|
|||
private final StatusPage empty;
|
||||
private final Clamp listView;
|
||||
private final GridView gridView;
|
||||
private final List<InstanceList.Entry> instanceList;
|
||||
private final List<Instance> instanceList;
|
||||
private final ListIndex instanceListIndex;
|
||||
|
||||
public MainWindow(Application app) {
|
||||
|
|
|
@ -9,10 +9,12 @@ import io.gitlab.jfronny.inceptum.imgui.window.GuiUtil;
|
|||
import io.gitlab.jfronny.inceptum.launcher.model.fabric.FabricVersionLoaderInfo;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.LoaderInfo;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.mojang.*;
|
||||
import io.gitlab.jfronny.inceptum.launcher.api.FabricMetaApi;
|
||||
import io.gitlab.jfronny.inceptum.launcher.api.McApi;
|
||||
import io.gitlab.jfronny.inceptum.launcher.util.InstanceNameTool;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
|
@ -34,22 +36,22 @@ public class InstanceManageControls {
|
|||
private VersionsListInfo selected;
|
||||
private FabricVersionLoaderInfo selectedFabric;
|
||||
|
||||
public InstanceManageControls(InstanceMeta meta, String defaultName) {
|
||||
public InstanceManageControls(@Nullable Instance instance) {
|
||||
selected = getVersions(false).get(0);
|
||||
if (meta != null) {
|
||||
if (instance != null) {
|
||||
for (VersionsListInfo ver : getVersions(true)) {
|
||||
if (ver.id.equals(meta.getMinecraftVersion()))
|
||||
if (ver.id.equals(instance.meta().getMinecraftVersion()))
|
||||
selected = ver;
|
||||
}
|
||||
}
|
||||
version.set(getVersions(snapshots.get()).indexOf(selected));
|
||||
name.set(defaultName == null ? InstanceNameTool.getDefaultName(selected.id, fabric.get()) : defaultName);
|
||||
fabric.set(meta == null || meta.isFabric());
|
||||
name.set(instance == null ? InstanceNameTool.getDefaultName(selected.id, fabric.get()) : instance.getName());
|
||||
fabric.set(instance == null || instance.isFabric());
|
||||
List<FabricVersionLoaderInfo> versions = getFabricLoaderInfo();
|
||||
for (int i = 0, fabricLoaderInfoSize = versions.size(); i < fabricLoaderInfoSize; i++) {
|
||||
FabricVersionLoaderInfo version = versions.get(i);
|
||||
if (meta != null && meta.isFabric()
|
||||
? version.loader.version.equals(meta.getLoaderVersion())
|
||||
if (instance != null && instance.isFabric()
|
||||
? version.loader.version.equals(instance.meta().getLoaderVersion())
|
||||
: version.loader.stable) {
|
||||
selectedFabric = version;
|
||||
fabricVersion.set(i);
|
||||
|
|
|
@ -2,58 +2,56 @@ package io.gitlab.jfronny.inceptum.imgui.control;
|
|||
|
||||
import imgui.ImGui;
|
||||
import imgui.flag.ImGuiTableFlags;
|
||||
import io.gitlab.jfronny.commons.cache.FileBackedRef;
|
||||
import io.gitlab.jfronny.inceptum.common.Utils;
|
||||
import io.gitlab.jfronny.inceptum.imgui.GuiMain;
|
||||
import io.gitlab.jfronny.inceptum.imgui.window.edit.InstanceEditWindow;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.launch.InstanceLauncher;
|
||||
import io.gitlab.jfronny.inceptum.launcher.util.InstanceList;
|
||||
import io.gitlab.jfronny.inceptum.launcher.util.InstanceLock;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.install.Steps;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
|
||||
public class InstanceView {
|
||||
public static void draw() throws IOException {
|
||||
List<InstanceList.Entry> entries = new ArrayList<>();
|
||||
//TODO clean up
|
||||
List<Instance> entries = new ArrayList<>();
|
||||
InstanceList.forEach(entries::add);
|
||||
if (entries.isEmpty()) {
|
||||
ImGui.text("You have not yet created an instance");
|
||||
ImGui.text("Use File->New Instance to do so");
|
||||
}
|
||||
if (ImGui.beginTable("Instances", 2, ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.Borders)) {
|
||||
for (InstanceList.Entry entry : entries) {
|
||||
if (InstanceLock.isSetupLocked(entry.path())) {
|
||||
for (Instance instance : entries) {
|
||||
if (instance.isSetupLocked()) {
|
||||
ImGui.tableNextColumn();
|
||||
ImGui.text("Setting up");
|
||||
ImGui.tableNextColumn();
|
||||
ImGui.text("This instance is currently being set up");
|
||||
continue;
|
||||
}
|
||||
if (!Files.exists(entry.path().resolve("instance.json"))) {
|
||||
Utils.LOGGER.error("Invalid instance (doesn't contain instance.json): " + entry);
|
||||
if (!Files.exists(instance.path().resolve("instance.json"))) {
|
||||
Utils.LOGGER.error("Invalid instance (doesn't contain instance.json): " + instance);
|
||||
continue;
|
||||
}
|
||||
ImGui.tableNextColumn();
|
||||
boolean runDisabled = InstanceLock.isRunningLocked(entry.path());
|
||||
boolean runDisabled = instance.isRunningLocked();
|
||||
if (runDisabled) ImGui.beginDisabled();
|
||||
if (ImGui.button(entry.toString())) {
|
||||
if (ImGui.button(instance.toString())) {
|
||||
try {
|
||||
Steps.reDownload(entry.path(), Steps.createProcessState());
|
||||
Steps.reDownload(instance, Steps.createProcessState());
|
||||
} catch (IOException e) {
|
||||
Utils.LOGGER.error("Could not redownload instance, trying to start anyways", e);
|
||||
}
|
||||
InstanceLauncher.launchClient(entry.path(), entry.meta());
|
||||
InstanceLauncher.launchClient(instance);
|
||||
}
|
||||
if (runDisabled) ImGui.endDisabled();
|
||||
ImGui.tableNextColumn();
|
||||
if (ImGui.button("Edit##" + entry.path())) {
|
||||
if (ImGui.button("Edit##" + instance.id())) {
|
||||
try {
|
||||
GuiMain.open(new InstanceEditWindow(entry.path(), entry.meta()));
|
||||
GuiMain.open(new InstanceEditWindow(instance));
|
||||
} catch (IOException e) {
|
||||
Utils.LOGGER.error("Could not open instance edit window", e);
|
||||
}
|
||||
|
|
|
@ -7,13 +7,14 @@ import io.gitlab.jfronny.inceptum.launcher.LauncherEnv;
|
|||
import io.gitlab.jfronny.inceptum.common.Utils;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.curseforge.CurseforgeMod;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.modrinth.*;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.source.*;
|
||||
import io.gitlab.jfronny.inceptum.launcher.util.ModManager;
|
||||
import io.gitlab.jfronny.inceptum.launcher.util.ModPath;
|
||||
import io.gitlab.jfronny.inceptum.launcher.api.CurseforgeApi;
|
||||
import io.gitlab.jfronny.inceptum.launcher.api.ModrinthApi;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.mds.IWModDescription;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Mod;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.mds.ModsDirScanner;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -32,11 +33,11 @@ public class AddModWindow extends Window {
|
|||
private ModrinthSearchResult mr = null;
|
||||
private List<CurseforgeMod> cf = null;
|
||||
|
||||
public AddModWindow(Path modsDir, InstanceMeta instance, ModsDirScanner mds) {
|
||||
super(modsDir.getParent().getFileName().toString() + " - Add Mods");
|
||||
this.modsDir = modsDir;
|
||||
this.instance = instance;
|
||||
this.mds = mds;
|
||||
public AddModWindow(Instance instance) throws IOException {
|
||||
super(instance.getName() + " - Add Mods");
|
||||
this.modsDir = instance.modsDir();
|
||||
this.instance = instance.meta();
|
||||
this.mds = instance.getMds();
|
||||
}
|
||||
|
||||
private void reSearch() throws IOException {
|
||||
|
@ -92,7 +93,7 @@ public class AddModWindow extends Window {
|
|||
ImGui.text(mod.description);
|
||||
ImGui.tableNextColumn();
|
||||
boolean alreadyPresent = false;
|
||||
for (IWModDescription mdsMod : mds.getMods()) {
|
||||
for (Mod mdsMod : mds.getMods()) {
|
||||
alreadyPresent = mdsMod.mod().isPresent()
|
||||
&& mdsMod.mod().get().sources.keySet().stream()
|
||||
.anyMatch(s -> s instanceof ModrinthModSource ms
|
||||
|
@ -168,7 +169,7 @@ public class AddModWindow extends Window {
|
|||
ImGui.text(mod.summary);
|
||||
ImGui.tableNextColumn();
|
||||
boolean alreadyPresent = false;
|
||||
for (IWModDescription mdsMod : mds.getMods()) {
|
||||
for (Mod mdsMod : mds.getMods()) {
|
||||
alreadyPresent = mdsMod.mod().isPresent()
|
||||
&& mdsMod.mod().get().sources.keySet().stream()
|
||||
.anyMatch(s -> s instanceof CurseforgeModSource ms
|
||||
|
|
|
@ -6,7 +6,9 @@ import io.gitlab.jfronny.inceptum.common.MetaHolder;
|
|||
import io.gitlab.jfronny.inceptum.common.Utils;
|
||||
import io.gitlab.jfronny.inceptum.imgui.GuiMain;
|
||||
import io.gitlab.jfronny.inceptum.imgui.window.dialog.ProcessStateWatcherWindow;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.install.*;
|
||||
import io.gitlab.jfronny.inceptum.launcher.util.InstanceList;
|
||||
import io.gitlab.jfronny.inceptum.launcher.util.ProcessState;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -21,19 +23,18 @@ public class GuiUtil {
|
|||
List<Path> paths = JFiles.list(MetaHolder.INSTANCE_DIR);
|
||||
ProcessState state = Steps.createProcessState().extend(paths.size());
|
||||
GuiMain.open(new ProcessStateWatcherWindow("Reloading data", "Could not reload resources", state, cToken -> {
|
||||
for (Path path : paths) {
|
||||
Steps.reDownload(path, state);
|
||||
}
|
||||
InstanceList.reset();
|
||||
InstanceList.forEach(instance -> Steps.reDownload(instance, state));
|
||||
}, null));
|
||||
} catch (IOException e) {
|
||||
LauncherEnv.showError("Could not reload", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void reload(Path instanceDir) {
|
||||
public static void reload(Instance instance) {
|
||||
ProcessState state = Steps.createProcessState();
|
||||
GuiMain.open(new ProcessStateWatcherWindow("Reloading data", "Could not reload resources", state, cToken -> {
|
||||
Steps.reDownload(instanceDir, state);
|
||||
Steps.reDownload(instance, state);
|
||||
}, null));
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ import java.nio.file.Path;
|
|||
import java.util.List;
|
||||
|
||||
public class NewInstanceWindow extends Window {
|
||||
private final InstanceManageControls imc = new InstanceManageControls(null, null);
|
||||
private final InstanceManageControls imc = new InstanceManageControls(null);
|
||||
|
||||
public NewInstanceWindow() {
|
||||
super("New Instance");
|
||||
|
|
|
@ -18,28 +18,29 @@ public class ArgumentsTab extends Tab {
|
|||
public ArgumentsTab(InstanceEditWindow window) {
|
||||
super("Arguments");
|
||||
this.window = window;
|
||||
if (window.instance.arguments == null) window.instance.arguments = new InstanceMeta.Arguments();
|
||||
if (window.instance.arguments.jvm == null) window.instance.arguments.jvm = new LinkedList<>();
|
||||
jvm.set(String.join("\n", window.instance.arguments.jvm));
|
||||
if (window.instance.arguments.client == null) window.instance.arguments.client = new LinkedList<>();
|
||||
client.set(String.join("\n", window.instance.arguments.client));
|
||||
if (window.instance.arguments.server == null) window.instance.arguments.server = new LinkedList<>();
|
||||
server.set(String.join("\n", window.instance.arguments.server));
|
||||
InstanceMeta meta = window.instance.meta();
|
||||
if (meta.arguments == null) meta.arguments = new InstanceMeta.Arguments();
|
||||
if (meta.arguments.jvm == null) meta.arguments.jvm = new LinkedList<>();
|
||||
jvm.set(String.join("\n", meta.arguments.jvm));
|
||||
if (meta.arguments.client == null) meta.arguments.client = new LinkedList<>();
|
||||
client.set(String.join("\n", meta.arguments.client));
|
||||
if (meta.arguments.server == null) meta.arguments.server = new LinkedList<>();
|
||||
server.set(String.join("\n", meta.arguments.server));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderInner() {
|
||||
if (ImGui.inputTextMultiline("JVM", jvm)) {
|
||||
window.instance.arguments.jvm = List.of(jvm.get().split("[\r\n]+"));
|
||||
window.save();
|
||||
window.instance.meta().arguments.jvm = List.of(jvm.get().split("[\r\n]+"));
|
||||
window.instance.writeMeta();
|
||||
}
|
||||
if (ImGui.inputTextMultiline("Client", client)) {
|
||||
window.instance.arguments.client = List.of(client.get().split("[\r\n]+"));
|
||||
window.save();
|
||||
window.instance.meta().arguments.client = List.of(client.get().split("[\r\n]+"));
|
||||
window.instance.writeMeta();
|
||||
}
|
||||
if (ImGui.inputTextMultiline("Server", server)) {
|
||||
window.instance.arguments.server = List.of(server.get().split("[\r\n]+"));
|
||||
window.save();
|
||||
window.instance.meta().arguments.server = List.of(server.get().split("[\r\n]+"));
|
||||
window.instance.writeMeta();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,14 +28,14 @@ public class ExportTab extends Tab {
|
|||
for (Exporter<?> exporter : Exporters.EXPORTERS) {
|
||||
if (ImGui.button(exporter.getName())) {
|
||||
GuiMain.open(new TextBoxWindow("Version", "Please enter the current version of your modpack", "1.0", version -> {
|
||||
String defaultName = window.name + " " + version + " (" + exporter.getName() + ")." + exporter.getFileExtension();
|
||||
String defaultName = window.instance.getName() + " " + version + " (" + exporter.getName() + ")." + exporter.getFileExtension();
|
||||
String filter = "*." + exporter.getFileExtension();
|
||||
Path exportPath = GuiMain.saveFileDialog("Export " + exporter.getName() + " Pack", defaultName, new String[] {filter}, exporter.getName() + " packs (" + filter + ")");
|
||||
if (exportPath != null) {
|
||||
ProcessState state = new ProcessState(Exporters.STEP_COUNT, "Initializing...");
|
||||
GuiMain.open(new ProcessStateWatcherWindow("Exporting", "Could not export pack", state, cToken -> {
|
||||
exporter.generate(state, window.path, window.instance, window.mds, exportPath, version);
|
||||
LauncherEnv.showInfo(window.name + " has been successfully exported to " + exportPath, "Successfully exported");
|
||||
exporter.generate(state, window.instance, exportPath, version);
|
||||
LauncherEnv.showInfo(window.instance.getName() + " has been successfully exported to " + exportPath, "Successfully exported");
|
||||
}, null));
|
||||
}
|
||||
}, R::nop));
|
||||
|
|
|
@ -25,20 +25,20 @@ public class GeneralTab extends Tab {
|
|||
public GeneralTab(InstanceEditWindow window) {
|
||||
super("General");
|
||||
this.window = window;
|
||||
imc = new InstanceManageControls(window.instance, window.name);
|
||||
customJava = new ImBoolean(window.instance.java != null);
|
||||
imc = new InstanceManageControls(window.instance);
|
||||
customJava = new ImBoolean(window.instance.meta().java != null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderInner() {
|
||||
if (ImGui.button("Open Directory")) {
|
||||
Utils.openFile(window.path.toFile());
|
||||
Utils.openFile(window.instance.path().toFile());
|
||||
}
|
||||
imc.nameBox("Rename", name -> {
|
||||
try {
|
||||
Path newPath = MetaHolder.INSTANCE_DIR.resolve(name);
|
||||
Files.move(window.path, newPath);
|
||||
GuiMain.open(new InstanceEditWindow(newPath, window.instance));
|
||||
Files.move(window.instance.path(), newPath);
|
||||
GuiMain.open(new InstanceEditWindow(window.instance));
|
||||
window.close();
|
||||
} catch (IOException e) {
|
||||
LauncherEnv.showError("Could not rename", e);
|
||||
|
@ -47,13 +47,13 @@ public class GeneralTab extends Tab {
|
|||
imc.snapshotsBox();
|
||||
imc.versionBox(ver -> {
|
||||
window.reDownload = true;
|
||||
window.instance.version = ver;
|
||||
window.save();
|
||||
window.instance.meta().version = ver;
|
||||
window.instance.writeMeta();
|
||||
});
|
||||
if (ImGui.button("Delete"))
|
||||
LauncherEnv.showOkCancel("This instance will be removed forever (a long time)", "Are you sure?", () -> {
|
||||
try {
|
||||
JFiles.deleteRecursive(window.path);
|
||||
JFiles.deleteRecursive(window.instance.path());
|
||||
} catch (IOException e) {
|
||||
LauncherEnv.showError("Could not delete the instance", e);
|
||||
}
|
||||
|
@ -61,16 +61,16 @@ public class GeneralTab extends Tab {
|
|||
}, R::nop);
|
||||
if (ImGui.checkbox("Custom Java", customJava)) {
|
||||
if (customJava.get()) {
|
||||
window.instance.java = OSUtils.getJvmBinary();
|
||||
customJavaPath.set(window.instance.java);
|
||||
window.instance.meta().java = OSUtils.getJvmBinary();
|
||||
customJavaPath.set(window.instance.meta().java);
|
||||
} else {
|
||||
window.instance.java = null;
|
||||
window.instance.meta().java = null;
|
||||
}
|
||||
window.save();
|
||||
window.instance.writeMeta();
|
||||
}
|
||||
if (customJava.get() && ImGui.inputText("Path", customJavaPath)) {
|
||||
window.instance.java = customJavaPath.get();
|
||||
window.save();
|
||||
window.instance.meta().java = customJavaPath.get();
|
||||
window.instance.writeMeta();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,34 +1,26 @@
|
|||
package io.gitlab.jfronny.inceptum.imgui.window.edit;
|
||||
|
||||
import imgui.ImGui;
|
||||
import io.gitlab.jfronny.commons.io.JFiles;
|
||||
import io.gitlab.jfronny.inceptum.common.Utils;
|
||||
import io.gitlab.jfronny.inceptum.imgui.control.Tab;
|
||||
import io.gitlab.jfronny.inceptum.imgui.window.GuiUtil;
|
||||
import io.gitlab.jfronny.inceptum.imgui.window.Window;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta;
|
||||
import io.gitlab.jfronny.inceptum.launcher.util.InstanceLock;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.mds.ModsDirScanner;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
|
||||
public class InstanceEditWindow extends Window {
|
||||
protected final Path path;
|
||||
protected final String name;
|
||||
protected final InstanceMeta instance;
|
||||
protected final Instance instance;
|
||||
protected final ModsDirScanner mds;
|
||||
private final List<Tab> tabs;
|
||||
protected boolean reDownload = false;
|
||||
protected boolean lastTabWasMods = false;
|
||||
|
||||
public InstanceEditWindow(Path path, InstanceMeta instance) throws IOException {
|
||||
super(path.getFileName().toString() + " - Edit");
|
||||
this.name = path.getFileName().toString();
|
||||
this.path = path;
|
||||
public InstanceEditWindow(Instance instance) throws IOException {
|
||||
super(instance.getName() + " - Edit");
|
||||
this.instance = instance;
|
||||
this.mds = ModsDirScanner.get(path.resolve("mods"), instance);
|
||||
this.mds = instance.getMds();
|
||||
this.mds.start();
|
||||
this.tabs = List.of(
|
||||
new GeneralTab(this),
|
||||
|
@ -40,33 +32,25 @@ public class InstanceEditWindow extends Window {
|
|||
|
||||
@Override
|
||||
public void draw() {
|
||||
if (InstanceLock.isSetupLocked(path)) {
|
||||
if (instance.isSetupLocked()) {
|
||||
ImGui.text("This instance is still being set up.");
|
||||
return;
|
||||
}
|
||||
if (InstanceLock.isRunningLocked(path)) {
|
||||
if (instance.isRunningLocked()) {
|
||||
ImGui.text("This instance is running. Edits in this state will result in breakage.");
|
||||
}
|
||||
lastTabWasMods = false;
|
||||
if (ImGui.beginTabBar("InstanceEdit" + path)) {
|
||||
if (ImGui.beginTabBar("InstanceEdit" + instance.id())) {
|
||||
for (Tab tab : tabs) tab.render();
|
||||
ImGui.endTabBar();
|
||||
}
|
||||
}
|
||||
|
||||
protected void save() {
|
||||
try {
|
||||
JFiles.writeObject(path.resolve("instance.json"), instance);
|
||||
} catch (IOException e) {
|
||||
Utils.LOGGER.error("Could not write instance config", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
super.close();
|
||||
if (reDownload) {
|
||||
GuiUtil.reload(path);
|
||||
GuiUtil.reload(instance);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ import io.gitlab.jfronny.inceptum.imgui.control.Tab;
|
|||
import io.gitlab.jfronny.inceptum.imgui.window.AddModWindow;
|
||||
import io.gitlab.jfronny.inceptum.launcher.util.ModManager;
|
||||
import io.gitlab.jfronny.inceptum.launcher.util.ModPath;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.mds.IWModDescription;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Mod;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.source.ModSource;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -30,31 +30,35 @@ public class ModsTab extends Tab {
|
|||
@Override
|
||||
protected void renderInner() {
|
||||
window.lastTabWasMods = true;
|
||||
if (!Files.exists(window.path.resolve("mods"))) {
|
||||
if (!Files.exists(window.instance.modsDir())) {
|
||||
try {
|
||||
Files.createDirectories(window.path.resolve("mods"));
|
||||
Files.createDirectories(window.instance.modsDir());
|
||||
} catch (IOException e) {
|
||||
Utils.LOGGER.error("Could not create mods directory which was missing from this modded instance", e);
|
||||
}
|
||||
}
|
||||
ImGui.beginChild("mods select", 200, 0);
|
||||
if (ImGui.button("Add")) {
|
||||
GuiMain.WINDOWS.add(new AddModWindow(window.path.resolve("mods"), window.instance, window.mds));
|
||||
try {
|
||||
GuiMain.WINDOWS.add(new AddModWindow(window.instance));
|
||||
} catch (IOException e) {
|
||||
Utils.LOGGER.error("Could not open window", e);
|
||||
}
|
||||
}
|
||||
ImGui.sameLine();
|
||||
if (Files.exists(window.path.resolve("mods")) && ImGui.button("Show")) {
|
||||
Utils.openFile(window.path.resolve("mods").toFile());
|
||||
if (Files.exists(window.instance.modsDir()) && ImGui.button("Show")) {
|
||||
Utils.openFile(window.instance.modsDir().toFile());
|
||||
}
|
||||
ImGui.sameLine();
|
||||
if (Files.exists(window.path.resolve("config")) && ImGui.button("Configs")) {
|
||||
Utils.openFile(window.path.resolve("config").toFile());
|
||||
if (Files.exists(window.instance.configDir()) && ImGui.button("Configs")) {
|
||||
Utils.openFile(window.instance.configDir().toFile());
|
||||
}
|
||||
try {
|
||||
Set<IWModDescription> modSet = window.mds.getMods();
|
||||
Set<Mod> modSet = window.mds.getMods();
|
||||
boolean updatesFound = false;
|
||||
float scannedPercentage = 0;
|
||||
boolean hasUnScanned = false;
|
||||
for (IWModDescription mod : modSet) {
|
||||
for (Mod mod : modSet) {
|
||||
if (window.mds.hasScanned(mod.path())) scannedPercentage++;
|
||||
else hasUnScanned = true;
|
||||
if (mod.mod().isEmpty()) continue;
|
||||
|
@ -74,7 +78,7 @@ public class ModsTab extends Tab {
|
|||
else
|
||||
filterUpdates.set(false);
|
||||
ImGui.separator();
|
||||
for (IWModDescription mod : modSet) {
|
||||
for (Mod mod : modSet) {
|
||||
updatesFound = false;
|
||||
if (mod.mod().isPresent()) {
|
||||
for (Optional<ModSource> value : mod.mod().get().sources.values()) {
|
||||
|
@ -88,7 +92,7 @@ public class ModsTab extends Tab {
|
|||
try {
|
||||
Files.move(mod.path(), newSel);
|
||||
if (mod.path().equals(selected)) selected = newSel;
|
||||
mod = new IWModDescription(newSel, mod);
|
||||
mod = new Mod(newSel, mod);
|
||||
} catch (IOException e) {
|
||||
LauncherEnv.showError("Could not change disabled state", e);
|
||||
}
|
||||
|
@ -105,7 +109,7 @@ public class ModsTab extends Tab {
|
|||
if (selected == null) {
|
||||
ImGui.text("Select a mod to view settings");
|
||||
} else if (window.mds.hasScanned(selected)) {
|
||||
IWModDescription md = window.mds.get(selected);
|
||||
Mod md = window.mds.get(selected);
|
||||
ImGui.text(md.getName());
|
||||
ImGui.separator();
|
||||
for (String s : md.getDescription()) {
|
||||
|
@ -125,7 +129,7 @@ public class ModsTab extends Tab {
|
|||
ImGui.sameLine();
|
||||
if (ImGui.button("Update to " + ms.get().getVersion())) {
|
||||
try {
|
||||
Path imodPath = md.imod().isPresent() ? md.imod().get() : window.path.resolve("mods").resolve(ms.get().getShortName() + ModPath.EXT_IMOD);
|
||||
Path imodPath = md.imod().isPresent() ? md.imod().get() : window.instance.modsDir().resolve(ms.get().getShortName() + ModPath.EXT_IMOD);
|
||||
ModManager.DownloadMeta dm = ModManager.download(ms.get(), imodPath, window.mds);
|
||||
Files.delete(md.path());
|
||||
if (md.imod().isPresent() && Files.exists(md.imod().get()))
|
||||
|
@ -159,8 +163,8 @@ public class ModsTab extends Tab {
|
|||
ImGui.endGroup();
|
||||
}
|
||||
|
||||
private void delete(IWModDescription md) throws IOException {
|
||||
ModManager.delete(md, window.path.resolve("mods"), window.mds);
|
||||
private void delete(Mod md) throws IOException {
|
||||
ModManager.delete(md, window.instance.modsDir(), window.mds);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt;
|
||||
|
||||
import io.gitlab.jfronny.commons.io.JFiles;
|
||||
import io.gitlab.jfronny.inceptum.common.Utils;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.mds.ModsDirScanner;
|
||||
import io.gitlab.jfronny.inceptum.launcher.util.ProcessUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
public record Instance(String id, Path path, InstanceMeta meta) implements Comparable<Instance> {
|
||||
private static final String INCEPTUM_LOCK = "inceptum.lock";
|
||||
private static final String INCEPTUM_SETUP_LOCK = "inceptum.setup.lock";
|
||||
|
||||
public Instance(Path path, InstanceMeta meta) {
|
||||
this(generateId(path.getFileName().toString()), path, meta);
|
||||
}
|
||||
|
||||
public Instance(String id, Path path, InstanceMeta meta) {
|
||||
this.id = id;
|
||||
this.path = path.toAbsolutePath().normalize();
|
||||
this.meta = meta;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts any string into a set of lowercase ascii chars
|
||||
* @param input string to convert
|
||||
* @return a string matching [a-p]*
|
||||
*/
|
||||
private static String generateId(String input) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
for (byte b : input.getBytes(StandardCharsets.UTF_8)) {
|
||||
int by = Byte.toUnsignedInt(b);
|
||||
int ch2 = by & 15; // right bits
|
||||
int ch1 = (by - ch2) / 16; // left bits
|
||||
result.append((char)('a' + ch1));
|
||||
result.append((char)('a' + ch2));
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(@NotNull Instance entry) {
|
||||
long time1 = meta.lastLaunched == null ? 0 : meta.lastLaunched;
|
||||
long time2 = entry.meta.lastLaunched == null ? 0 : entry.meta.lastLaunched;
|
||||
if (time1 == 0) {
|
||||
if (time2 == 0) return path.getFileName().toString().compareTo(entry.path.getFileName().toString());
|
||||
return -1;
|
||||
}
|
||||
if (time2 == 0) return 1;
|
||||
return Long.compare(time1, time2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return path.getFileName().toString();
|
||||
}
|
||||
|
||||
public Path modsDir() {
|
||||
return path.resolve("mods");
|
||||
}
|
||||
|
||||
public Path configDir() {
|
||||
return path.resolve("config");
|
||||
}
|
||||
|
||||
public ModsDirScanner getMds() throws IOException {
|
||||
return ModsDirScanner.get(modsDir(), meta);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return path.getFileName().toString();
|
||||
}
|
||||
|
||||
public boolean isFabric() {
|
||||
return meta.isFabric();
|
||||
}
|
||||
|
||||
public boolean isSetupLocked() {
|
||||
return Files.exists(path.resolve(INCEPTUM_SETUP_LOCK));
|
||||
}
|
||||
|
||||
public void setSetupLock(boolean state) throws IOException {
|
||||
setSetupLock(path, state);
|
||||
}
|
||||
|
||||
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));
|
||||
} else {
|
||||
if (state) Files.createDirectories(instanceDir.resolve(INCEPTUM_SETUP_LOCK));
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isRunningLocked() {
|
||||
if (!Files.exists(path.resolve(INCEPTUM_LOCK))) return false;
|
||||
try {
|
||||
if (ProcessUtils.isProcessAlive(Files.readString(path.resolve(INCEPTUM_LOCK))))
|
||||
return true;
|
||||
Files.delete(path.resolve(INCEPTUM_LOCK));
|
||||
} catch (IOException e) {
|
||||
Utils.LOGGER.error("Could not read running lock of " + getName(), e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setRunningLock(long pid) throws IOException {
|
||||
Files.writeString(path.resolve(INCEPTUM_LOCK), Long.toString(pid));
|
||||
}
|
||||
|
||||
public boolean isLocked() {
|
||||
return isSetupLocked() || isRunningLocked();
|
||||
}
|
||||
|
||||
public void writeMeta() {
|
||||
try {
|
||||
JFiles.writeObject(path.resolve("instance.json"), meta);
|
||||
} catch (IOException e) {
|
||||
Utils.LOGGER.error("Could not write instance config", e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.system.mds;
|
||||
package io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt;
|
||||
|
||||
import io.gitlab.jfronny.commons.io.JFiles;
|
||||
import io.gitlab.jfronny.inceptum.common.Utils;
|
||||
|
@ -11,8 +11,8 @@ import java.nio.file.Files;
|
|||
import java.nio.file.Path;
|
||||
import java.util.Optional;
|
||||
|
||||
public record IWModDescription(Path path, Optional<ModDescription> mod, Optional<FabricModJson> fmj,
|
||||
Optional<Path> imod) implements Comparable<IWModDescription> {
|
||||
public record Mod(Path path, Optional<ModDescription> mod, Optional<FabricModJson> fmj,
|
||||
Optional<Path> imod) implements Comparable<Mod> {
|
||||
public String getName() {
|
||||
if (fmj.isEmpty()) return path.getFileName().toString();
|
||||
String base;
|
||||
|
@ -45,7 +45,7 @@ public record IWModDescription(Path path, Optional<ModDescription> mod, Optional
|
|||
*
|
||||
* @param path The path of the mod entry
|
||||
*/
|
||||
public IWModDescription(Path path) {
|
||||
public Mod(Path path) {
|
||||
this(path,
|
||||
Files.isDirectory(path) ? Optional.empty() : Optional.of(ModDescription.of(path)),
|
||||
Optional.empty(),
|
||||
|
@ -58,12 +58,12 @@ public record IWModDescription(Path path, Optional<ModDescription> mod, Optional
|
|||
* @param path The new path to use
|
||||
* @param base The mod description to copy
|
||||
*/
|
||||
public IWModDescription(Path path, IWModDescription base) {
|
||||
public Mod(Path path, Mod base) {
|
||||
this(path, base.mod, base.fmj, base.imod);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(IWModDescription o) {
|
||||
public int compareTo(Mod o) {
|
||||
return getName().compareTo(o.getName());
|
||||
}
|
||||
}
|
|
@ -4,7 +4,8 @@ import io.gitlab.jfronny.commons.io.JFiles;
|
|||
import io.gitlab.jfronny.inceptum.common.InceptumConfig;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.curseforge.CurseforgeModpackManifest;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.mds.IWModDescription;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Mod;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.source.CurseforgeModSource;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.source.ModSource;
|
||||
import io.gitlab.jfronny.inceptum.launcher.util.ModPath;
|
||||
|
@ -23,20 +24,20 @@ public class CurseForgeExporter extends Exporter<CurseforgeModpackManifest> {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected CurseforgeModpackManifest generateManifests(Path root, InstanceMeta instance, String name, String version) throws IOException {
|
||||
protected CurseforgeModpackManifest generateManifests(Path root, Instance instance, String version) throws IOException {
|
||||
CurseforgeModpackManifest manifest = new CurseforgeModpackManifest();
|
||||
manifest.minecraft = new CurseforgeModpackManifest.Minecraft();
|
||||
manifest.minecraft.version = instance.getMinecraftVersion();
|
||||
manifest.minecraft.version = instance.meta().getMinecraftVersion();
|
||||
manifest.manifestType = "minecraftModpack";
|
||||
manifest.manifestVersion = 1;
|
||||
manifest.name = name;
|
||||
manifest.name = instance.getName();
|
||||
manifest.version = version;
|
||||
manifest.author = InceptumConfig.authorName;
|
||||
manifest.overrides = OVERRIDES_DIR_DEFAULT;
|
||||
manifest.minecraft.modLoaders = new LinkedHashSet<>();
|
||||
if (instance.isFabric()) {
|
||||
CurseforgeModpackManifest.Minecraft.ModLoader loader = new CurseforgeModpackManifest.Minecraft.ModLoader();
|
||||
loader.id = "fabric-" + instance.getLoaderVersion();
|
||||
loader.id = "fabric-" + instance.meta().getLoaderVersion();
|
||||
loader.primary = true;
|
||||
manifest.minecraft.modLoaders.add(loader);
|
||||
}
|
||||
|
@ -45,8 +46,8 @@ public class CurseForgeExporter extends Exporter<CurseforgeModpackManifest> {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void addMods(Path root, InstanceMeta instance, Iterable<IWModDescription> mods, CurseforgeModpackManifest manifest, Path modsOverrides) throws IOException {
|
||||
modsLoop: for(IWModDescription mod : mods) {
|
||||
protected void addMods(Path root, Instance instance, Iterable<Mod> mods, CurseforgeModpackManifest manifest, Path modsOverrides) throws IOException {
|
||||
modsLoop: for(Mod mod : mods) {
|
||||
if (ModPath.isImod(mod.path())) {
|
||||
Set<ModSource> sources = mod.mod().orElseThrow().sources.keySet();
|
||||
for (ModSource source : sources) {
|
||||
|
|
|
@ -2,7 +2,8 @@ package io.gitlab.jfronny.inceptum.launcher.system.export;
|
|||
|
||||
import io.gitlab.jfronny.inceptum.common.Utils;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.mds.IWModDescription;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Mod;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.mds.ModsDirScanner;
|
||||
import io.gitlab.jfronny.inceptum.launcher.util.*;
|
||||
import io.gitlab.jfronny.inceptum.launcher.util.ignore.IgnoringWalk;
|
||||
|
@ -23,28 +24,29 @@ public abstract class Exporter<Manifest> {
|
|||
this.overridesDirName = Objects.requireNonNull(overridesDirName);
|
||||
}
|
||||
|
||||
protected abstract Manifest generateManifests(Path root, InstanceMeta instance, String name, String version) throws IOException;
|
||||
protected abstract void addMods(Path root, InstanceMeta instance, Iterable<IWModDescription> mods, Manifest manifest, Path modsOverrides) throws IOException;
|
||||
protected abstract Manifest generateManifests(Path root, Instance instance, String version) throws IOException;
|
||||
protected abstract void addMods(Path root, Instance instance, Iterable<Mod> mods, Manifest manifest, Path modsOverrides) throws IOException;
|
||||
|
||||
public void generate(ProcessState state, Path instanceDir, InstanceMeta meta, ModsDirScanner mds, Path exportPath, String version) throws IOException {
|
||||
public void generate(ProcessState state, Instance instance, Path exportPath, String version) throws IOException {
|
||||
if (Files.exists(exportPath)) Files.delete(exportPath);
|
||||
try (FileSystem fs = Utils.openZipFile(exportPath, true)) {
|
||||
Path root = fs.getPath(".");
|
||||
Path overrides = fs.getPath(overridesDirName);
|
||||
state.incrementStep("Preparing manifests");
|
||||
Manifest manifest = generateManifests(root, meta, instanceDir.getFileName().toString(), version);
|
||||
if (meta.isFabric()) {
|
||||
Manifest manifest = generateManifests(root, instance, version);
|
||||
if (instance.isFabric()) {
|
||||
state.incrementStep("Adding mods");
|
||||
ModsDirScanner mds = instance.getMds();
|
||||
if (!mds.isComplete()) throw new IOException("Mods dir scan is not yet completed");
|
||||
addMods(root, meta, new StreamIterable<>(mds.getMods().stream().filter(mod -> {
|
||||
addMods(root, instance, new StreamIterable<>(mds.getMods().stream().filter(mod -> {
|
||||
if (!ModPath.isEnabled(mod.path())) return false;
|
||||
state.updateStep(mod.path().toString());
|
||||
return true;
|
||||
})), manifest, overrides.resolve("mods"));
|
||||
}
|
||||
state.incrementStep("Adding files");
|
||||
filesLoop: for (Path path : new StreamIterable<>(IgnoringWalk.walk(instanceDir))) {
|
||||
Path relativePath = instanceDir.relativize(path).normalize();
|
||||
filesLoop: for (Path path : new StreamIterable<>(IgnoringWalk.walk(instance.path()))) {
|
||||
Path relativePath = instance.path().relativize(path).normalize();
|
||||
Path target = overrides;
|
||||
for (Path segment : relativePath) {
|
||||
if (target == overrides && segment.toString().equals("mods")) continue filesLoop;
|
||||
|
|
|
@ -2,8 +2,9 @@ package io.gitlab.jfronny.inceptum.launcher.system.export;
|
|||
|
||||
import io.gitlab.jfronny.commons.io.JFiles;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.modrinth.ModrinthModpackManifest;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.mds.IWModDescription;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Mod;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.source.ModSource;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.source.ModrinthModSource;
|
||||
import io.gitlab.jfronny.inceptum.launcher.util.ModPath;
|
||||
|
@ -21,25 +22,25 @@ public class ModrinthExporter extends Exporter<ModrinthModpackManifest> {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected ModrinthModpackManifest generateManifests(Path root, InstanceMeta instance, String name, String version) throws IOException {
|
||||
protected ModrinthModpackManifest generateManifests(Path root, Instance instance, String version) throws IOException {
|
||||
ModrinthModpackManifest manifest = new ModrinthModpackManifest();
|
||||
manifest.formatVersion = 1;
|
||||
manifest.game = "minecraft";
|
||||
manifest.versionId = version;
|
||||
manifest.name = name;
|
||||
manifest.name = instance.getName();
|
||||
manifest.files = new ArrayList<>();
|
||||
manifest.dependencies = new ModrinthModpackManifest.Dependencies();
|
||||
manifest.dependencies.minecraft = instance.getMinecraftVersion();
|
||||
manifest.dependencies.minecraft = instance.meta().getMinecraftVersion();
|
||||
if (instance.isFabric()) {
|
||||
manifest.dependencies.fabricLoader = instance.getLoaderVersion();
|
||||
manifest.dependencies.fabricLoader = instance.meta().getLoaderVersion();
|
||||
}
|
||||
JFiles.writeObject(root.resolve("modrinth.index.json"), manifest);
|
||||
return manifest;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addMods(Path root, InstanceMeta instance, Iterable<IWModDescription> mods, ModrinthModpackManifest manifest, Path modsOverrides) throws IOException {
|
||||
modsLoop: for(IWModDescription mod : mods) {
|
||||
protected void addMods(Path root, Instance instance, Iterable<Mod> mods, ModrinthModpackManifest manifest, Path modsOverrides) throws IOException {
|
||||
modsLoop: for(Mod mod : mods) {
|
||||
if (ModPath.isImod(mod.path())) {
|
||||
Set<ModSource> sources = mod.mod().orElseThrow().sources.keySet();
|
||||
for (ModSource source : sources) {
|
||||
|
|
|
@ -2,8 +2,9 @@ package io.gitlab.jfronny.inceptum.launcher.system.export;
|
|||
|
||||
import io.gitlab.jfronny.commons.io.JFiles;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.multimc.MMCPackMeta;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.mds.IWModDescription;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Mod;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.source.ModSource;
|
||||
import io.gitlab.jfronny.inceptum.launcher.util.ModPath;
|
||||
|
||||
|
@ -21,7 +22,7 @@ public class MultiMCExporter extends Exporter<MMCPackMeta> {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected MMCPackMeta generateManifests(Path root, InstanceMeta instance, String name, String version) throws IOException {
|
||||
protected MMCPackMeta generateManifests(Path root, Instance instance, String version) throws IOException {
|
||||
{
|
||||
Files.writeString(root.resolve("instance.cfg"), String.format("""
|
||||
ForgeVersion=
|
||||
|
@ -47,7 +48,7 @@ public class MultiMCExporter extends Exporter<MMCPackMeta> {
|
|||
name=%s
|
||||
notes=
|
||||
totalTimePlayed=0
|
||||
""", Instant.now().toEpochMilli(), name));
|
||||
""", Instant.now().toEpochMilli(), instance.getName()));
|
||||
}
|
||||
{
|
||||
MMCPackMeta manifest = new MMCPackMeta();
|
||||
|
@ -61,17 +62,17 @@ public class MultiMCExporter extends Exporter<MMCPackMeta> {
|
|||
MMCPackMeta.Component minecraft = new MMCPackMeta.Component();
|
||||
minecraft.important = true;
|
||||
minecraft.uid = "net.minecraft";
|
||||
minecraft.version = instance.getMinecraftVersion();
|
||||
minecraft.version = instance.meta().getMinecraftVersion();
|
||||
manifest.components.add(minecraft);
|
||||
if (instance.isFabric()) {
|
||||
MMCPackMeta.Component intermediary = new MMCPackMeta.Component();
|
||||
intermediary.dependencyOnly = true;
|
||||
intermediary.uid = "net.fabricmc.intermediary";
|
||||
intermediary.version = instance.getMinecraftVersion();
|
||||
intermediary.version = instance.meta().getMinecraftVersion();
|
||||
manifest.components.add(intermediary);
|
||||
MMCPackMeta.Component fabric = new MMCPackMeta.Component();
|
||||
fabric.uid = "net.fabricmc.fabric-loader";
|
||||
fabric.version = instance.getLoaderVersion();
|
||||
fabric.version = instance.meta().getLoaderVersion();
|
||||
manifest.components.add(fabric);
|
||||
}
|
||||
JFiles.writeObject(root.resolve("mmc-pack.json"), manifest);
|
||||
|
@ -80,8 +81,8 @@ public class MultiMCExporter extends Exporter<MMCPackMeta> {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void addMods(Path root, InstanceMeta instance, Iterable<IWModDescription> mods, MMCPackMeta mmcPackMeta, Path modsOverrides) throws IOException {
|
||||
modsLoop: for (IWModDescription mod : mods) {
|
||||
protected void addMods(Path root, Instance instance, Iterable<Mod> mods, MMCPackMeta mmcPackMeta, Path modsOverrides) throws IOException {
|
||||
modsLoop: for (Mod mod : mods) {
|
||||
if (ModPath.isImod(mod.path())) {
|
||||
Set<ModSource> sources = mod.mod().orElseThrow().sources.keySet();
|
||||
for (ModSource source : sources) {
|
||||
|
|
|
@ -6,6 +6,7 @@ import io.gitlab.jfronny.inceptum.common.Utils;
|
|||
import io.gitlab.jfronny.inceptum.launcher.api.FabricMetaApi;
|
||||
import io.gitlab.jfronny.inceptum.launcher.api.McApi;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.install.Steps;
|
||||
import io.gitlab.jfronny.inceptum.launcher.util.*;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
@ -52,7 +53,7 @@ public abstract class Importer<T> {
|
|||
if (name == null || !Utils.VALID_FILENAME.matcher(name).matches()) name = "New Pack";
|
||||
name = InstanceNameTool.getNextValid(name);
|
||||
final Path iDir = MetaHolder.INSTANCE_DIR.resolve(name).toAbsolutePath().normalize();
|
||||
InstanceLock.setSetupLock(iDir, true);
|
||||
Instance.setSetupLock(iDir, true);
|
||||
InstanceMeta meta = new InstanceMeta();
|
||||
meta.version = createVersionString(man.gameVersion(), man.fabricVersion());
|
||||
JFiles.writeObject(iDir.resolve("instance.json"), meta);
|
||||
|
@ -67,8 +68,8 @@ public abstract class Importer<T> {
|
|||
JFiles.copyRecursive(path, iDir.resolve(path.getFileName().toString()));
|
||||
});
|
||||
}
|
||||
InstanceLock.setSetupLock(iDir, false);
|
||||
Steps.reDownload(iDir, state);
|
||||
Instance.setSetupLock(iDir, false);
|
||||
Steps.reDownload(InstanceList.read(iDir), state);
|
||||
return iDir;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,18 +1,15 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.system.install;
|
||||
|
||||
import io.gitlab.jfronny.commons.io.JFiles;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta;
|
||||
import io.gitlab.jfronny.inceptum.launcher.api.FabricMetaApi;
|
||||
import io.gitlab.jfronny.inceptum.launcher.api.McApi;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.LoaderInfo;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.mojang.VersionInfo;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.mojang.VersionsListInfo;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.install.steps.*;
|
||||
import io.gitlab.jfronny.inceptum.launcher.util.InstanceLock;
|
||||
import io.gitlab.jfronny.inceptum.launcher.util.ProcessState;
|
||||
import io.gitlab.jfronny.inceptum.launcher.api.FabricMetaApi;
|
||||
import io.gitlab.jfronny.inceptum.launcher.api.McApi;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
|
@ -31,26 +28,25 @@ public class Steps {
|
|||
return new ProcessState(STEPS.size(), "Initializing");
|
||||
}
|
||||
|
||||
public static void reDownload(Path instance, ProcessState state) throws IOException {
|
||||
if (InstanceLock.isLocked(instance)) return;
|
||||
InstanceMeta im = JFiles.readObject(instance.resolve("instance.json"), InstanceMeta.class);
|
||||
public static void reDownload(Instance instance, ProcessState state) throws IOException {
|
||||
if (instance.isLocked()) return;
|
||||
boolean found = false;
|
||||
for (VersionsListInfo version : McApi.getVersions().versions) {
|
||||
if (version.id.equals(im.getMinecraftVersion())) {
|
||||
if (version.id.equals(instance.meta().getMinecraftVersion())) {
|
||||
found = true;
|
||||
VersionInfo vi = McApi.getVersionInfo(version);
|
||||
if (im.isFabric())
|
||||
vi = FabricMetaApi.addFabric(vi, im.getLoaderVersion(), FabricMetaApi.FabricVersionInfoType.Both);
|
||||
LoaderInfo li = im.isFabric()
|
||||
? new LoaderInfo(LoaderInfo.Type.Fabric, im.getLoaderVersion())
|
||||
if (instance.isFabric())
|
||||
vi = FabricMetaApi.addFabric(vi, instance.meta().getLoaderVersion(), FabricMetaApi.FabricVersionInfoType.Both);
|
||||
LoaderInfo li = instance.isFabric()
|
||||
? new LoaderInfo(LoaderInfo.Type.Fabric, instance.meta().getLoaderVersion())
|
||||
: LoaderInfo.NONE;
|
||||
SetupStepInfo info = new SetupStepInfo(vi, li, instance.getFileName().toString(), state);
|
||||
SetupStepInfo info = new SetupStepInfo(vi, li, instance.getName(), state);
|
||||
for (Step step : Steps.STEPS) {
|
||||
state.incrementStep("Starting " + step.getClass().getSimpleName());
|
||||
step.execute(info, new AtomicBoolean(false));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found) throw new IOException("Could not identify minecraft version " + im.getMinecraftVersion());
|
||||
if (!found) throw new IOException("Could not identify minecraft version " + instance.meta().getMinecraftVersion());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,8 +3,8 @@ package io.gitlab.jfronny.inceptum.launcher.system.install.steps;
|
|||
import io.gitlab.jfronny.inceptum.common.MetaHolder;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.LoaderInfo;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.install.Step;
|
||||
import io.gitlab.jfronny.inceptum.launcher.util.InstanceLock;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.install.SetupStepInfo;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -17,7 +17,7 @@ public class SetupDirsStep implements Step {
|
|||
public void execute(SetupStepInfo info, AtomicBoolean stopThread) throws IOException {
|
||||
info.setState("Setting up instance dirs");
|
||||
Path iDir = MetaHolder.INSTANCE_DIR.resolve(info.name());
|
||||
InstanceLock.setSetupLock(iDir, true);
|
||||
Instance.setSetupLock(iDir, true);
|
||||
if (!Files.exists(iDir)) {
|
||||
Files.createDirectories(iDir.resolve("resourcepacks"));
|
||||
Files.createDirectories(iDir.resolve("saves"));
|
||||
|
|
|
@ -3,8 +3,8 @@ package io.gitlab.jfronny.inceptum.launcher.system.install.steps;
|
|||
import io.gitlab.jfronny.commons.io.JFiles;
|
||||
import io.gitlab.jfronny.inceptum.common.MetaHolder;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.install.Step;
|
||||
import io.gitlab.jfronny.inceptum.launcher.util.InstanceLock;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.install.SetupStepInfo;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -23,7 +23,7 @@ public class WriteMetadataStep implements Step {
|
|||
meta.version = info.version().id;
|
||||
JFiles.writeObject(metaPath, meta);
|
||||
}
|
||||
InstanceLock.setSetupLock(instance, false);
|
||||
Instance.setSetupLock(instance, false);
|
||||
if (!Files.exists(instance.resolve(".gitignore"))) {
|
||||
Files.writeString(instance.resolve(".gitignore"), """
|
||||
realms_persistence.json
|
||||
|
|
|
@ -6,6 +6,7 @@ import io.gitlab.jfronny.inceptum.common.api.MavenApi;
|
|||
import io.gitlab.jfronny.inceptum.launcher.LauncherEnv;
|
||||
import io.gitlab.jfronny.inceptum.common.*;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.*;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.mojang.*;
|
||||
import io.gitlab.jfronny.inceptum.launcher.api.FabricMetaApi;
|
||||
import io.gitlab.jfronny.inceptum.launcher.api.McApi;
|
||||
|
@ -24,7 +25,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
public class InstanceLauncher {
|
||||
public static void launchClient(Path path, InstanceMeta instance) {
|
||||
public static void launchClient(Instance instance) {
|
||||
if (AccountManager.accountMissing() && InceptumConfig.enforceAccount) {
|
||||
LauncherEnv.showError("You have not set up an account.\nDoing so is required to play Minecraft", "Not authenticated");
|
||||
return;
|
||||
|
@ -39,29 +40,29 @@ public class InstanceLauncher {
|
|||
InceptumConfig.offlineAccountLastName = name.equals(sysUser) ? null : name;
|
||||
InceptumConfig.saveConfig();
|
||||
AuthInfo infoNew = new AuthInfo(name, authInfo.uuid(), authInfo.accessToken(), authInfo.userType());
|
||||
launchClient(path, instance, infoNew);
|
||||
launchClient(instance, infoNew);
|
||||
}, R::nop);
|
||||
} catch (IOException e) {
|
||||
LauncherEnv.showError("Failed to request input", e);
|
||||
}
|
||||
} else launchClient(path, instance, authInfo);
|
||||
} else launchClient(instance, authInfo);
|
||||
}
|
||||
|
||||
private static void launchClient(Path path, InstanceMeta instance, AuthInfo authInfo) {
|
||||
private static void launchClient(Instance instance, AuthInfo authInfo) {
|
||||
try {
|
||||
launch(path, instance, LaunchType.Client, false, authInfo);
|
||||
launch(instance, LaunchType.Client, false, authInfo);
|
||||
} catch (LaunchException | IOException e) {
|
||||
LauncherEnv.showError("Could not launch client", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void launch(Path instancePath, InstanceMeta instance, LaunchType launchType, boolean restart, AuthInfo authInfo) throws LaunchException, IOException {
|
||||
public static void launch(Instance instance, LaunchType launchType, boolean restart, AuthInfo authInfo) throws LaunchException, IOException {
|
||||
if (authInfo == null) throw new LaunchException("authInfo is null");
|
||||
VersionsListInfo versionDataSimple = getVersion(instance.getMinecraftVersion());
|
||||
VersionsListInfo versionDataSimple = getVersion(instance.meta().getMinecraftVersion());
|
||||
VersionInfo versionInfo = McApi.getVersionInfo(versionDataSimple);
|
||||
// Add fabric metadata if using fabric
|
||||
if (instance.isFabric()) {
|
||||
versionInfo = FabricMetaApi.addFabric(versionInfo, instance.getLoaderVersion(), launchType.fabricMetaType);
|
||||
versionInfo = FabricMetaApi.addFabric(versionInfo, instance.meta().getLoaderVersion(), launchType.fabricMetaType);
|
||||
}
|
||||
// Ensure libs/assets are present
|
||||
DownloadLibrariesStep.execute(versionInfo, new AtomicBoolean(false), new ProcessState());
|
||||
|
@ -70,7 +71,7 @@ public class InstanceLauncher {
|
|||
// JVM path
|
||||
{
|
||||
final VersionInfo lambdaVersionInfo = versionInfo;
|
||||
args.add(Objects.requireNonNullElseGet(instance.java, () ->
|
||||
args.add(Objects.requireNonNullElseGet(instance.meta().java, () ->
|
||||
OSUtils.getJvmBinary(MetaHolder.NATIVES_DIR
|
||||
.resolve(lambdaVersionInfo.javaVersion.component)
|
||||
.resolve(Integer.toString(lambdaVersionInfo.javaVersion.majorVersion)))
|
||||
|
@ -88,10 +89,10 @@ public class InstanceLauncher {
|
|||
classPath.append(MetaHolder.LIBRARIES_DIR.resolve(MavenApi.mavenNotationToJarPath(DownloadLibrariesStep.getLaunchWrapperArtifact())));
|
||||
// JVM arguments
|
||||
if (launchType == LaunchType.Client && versionInfo.arguments != null)
|
||||
args.addAll(parse(versionInfo.arguments.jvm, versionInfo, instance, classPath.toString(), instancePath.toAbsolutePath().toString(), authInfo));
|
||||
if (instance.minMem != null) args.add("-Xms" + instance.minMem);
|
||||
if (instance.maxMem != null) args.add("-Xmx" + instance.maxMem);
|
||||
if (instance.arguments != null && instance.arguments.jvm != null) args.addAll(instance.arguments.jvm);
|
||||
args.addAll(parse(versionInfo.arguments.jvm, versionInfo, instance, classPath.toString(), authInfo));
|
||||
if (instance.meta().minMem != null) args.add("-Xms" + instance.meta().minMem);
|
||||
if (instance.meta().maxMem != null) args.add("-Xmx" + instance.meta().maxMem);
|
||||
if (instance.meta().arguments != null && instance.meta().arguments.jvm != null) args.addAll(instance.meta().arguments.jvm);
|
||||
// Forceload natives
|
||||
if (Files.exists(MetaHolder.FORCE_LOAD_PATH)) {
|
||||
args.add("-Dinceptum.forceloadNatives=" + MetaHolder.FORCE_LOAD_PATH);
|
||||
|
@ -99,9 +100,8 @@ public class InstanceLauncher {
|
|||
// Fabric imods
|
||||
if (instance.isFabric()) {
|
||||
StringBuilder fabricAddMods = new StringBuilder("-Dfabric.addMods=");
|
||||
Path mods = instancePath.resolve("mods");
|
||||
if (Files.exists(mods)) {
|
||||
for (Path imod : JFiles.list(mods, path -> ModPath.isImod(path) && ModPath.isEnabled(path))) {
|
||||
if (Files.exists(instance.modsDir())) {
|
||||
for (Path imod : JFiles.list(instance.modsDir(), path -> ModPath.isImod(path) && ModPath.isEnabled(path))) {
|
||||
String fn = imod.getFileName().toString();
|
||||
if (Files.exists(imod.getParent().resolve(fn.substring(0, fn.length() - 5))))
|
||||
continue;
|
||||
|
@ -123,44 +123,40 @@ public class InstanceLauncher {
|
|||
// Game arguments
|
||||
if (launchType == LaunchType.Client) {
|
||||
if (versionInfo.arguments != null)
|
||||
args.addAll(parse(versionInfo.arguments.game, versionInfo, instance, classPath.toString(), instancePath.toAbsolutePath().toString(), authInfo));
|
||||
args.addAll(parse(versionInfo.arguments.game, versionInfo, instance, classPath.toString(), authInfo));
|
||||
else if (versionInfo.minecraftArguments != null) {
|
||||
for (String s : versionInfo.minecraftArguments.split(" ")) {
|
||||
args.add(expandArg(s, versionInfo, instance, classPath.toString(), instancePath.toAbsolutePath().toString(), authInfo));
|
||||
args.add(expandArg(s, versionInfo, instance, classPath.toString(), authInfo));
|
||||
}
|
||||
} else throw new LaunchException("Could not launch: No valid source for client arguments found");
|
||||
}
|
||||
if (instance.arguments != null) {
|
||||
if (instance.meta().arguments != null) {
|
||||
switch (launchType) {
|
||||
case Client -> {
|
||||
if (instance.arguments.client != null)
|
||||
args.addAll(instance.arguments.client);
|
||||
if (instance.meta().arguments.client != null)
|
||||
args.addAll(instance.meta().arguments.client);
|
||||
}
|
||||
case Server -> {
|
||||
if (instance.arguments.server != null)
|
||||
args.addAll(instance.arguments.server);
|
||||
if (instance.meta().arguments.server != null)
|
||||
args.addAll(instance.meta().arguments.server);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Write launch time
|
||||
instance.lastLaunched = System.currentTimeMillis() / 1000L;
|
||||
try {
|
||||
JFiles.writeObject(instancePath.resolve("instance.json"), instance);
|
||||
} catch (IOException e) {
|
||||
Utils.LOGGER.error("Could not write instance config", e);
|
||||
}
|
||||
instance.meta().lastLaunched = System.currentTimeMillis() / 1000L;
|
||||
instance.writeMeta();
|
||||
// Log command used to start
|
||||
Utils.LOGGER.info(String.join(" ", args));
|
||||
// Create process
|
||||
ProcessBuilder pb = new ProcessBuilder(args.toArray(new String[0]));
|
||||
pb.directory(instancePath.toFile());
|
||||
pb.directory(instance.path().toFile());
|
||||
pb.redirectOutput(ProcessBuilder.Redirect.INHERIT);
|
||||
pb.redirectError(ProcessBuilder.Redirect.INHERIT);
|
||||
AtomicReference<Process> proc = new AtomicReference<>();
|
||||
Runnable starterRunner = () -> {
|
||||
try {
|
||||
proc.set(pb.start());
|
||||
InstanceLock.setRunningLock(instancePath, proc.get().pid());
|
||||
instance.setRunningLock(proc.get().pid());
|
||||
} catch (IOException e) {
|
||||
Utils.LOGGER.error("Could not start " + launchType.name, e);
|
||||
}
|
||||
|
@ -185,7 +181,7 @@ public class InstanceLauncher {
|
|||
}
|
||||
}
|
||||
|
||||
private static String resolveMainClass(InstanceMeta instance, VersionInfo versionInfo, Path gameJar, LaunchType launchType) throws LaunchException {
|
||||
private static String resolveMainClass(Instance instance, VersionInfo versionInfo, Path gameJar, LaunchType launchType) throws LaunchException {
|
||||
if (launchType == LaunchType.Client || instance.isFabric()) return versionInfo.mainClass;
|
||||
// Identify main class using MANIFEST.MF
|
||||
final String linePrefix = "Main-Class: ";
|
||||
|
@ -209,22 +205,22 @@ public class InstanceLauncher {
|
|||
throw new LaunchException("Could not find data for minecraft version: " + minecraftVersion);
|
||||
}
|
||||
|
||||
private static List<String> parse(List<MinecraftArgument> arguments, VersionInfo info, InstanceMeta instance, String classPath, String gameDirectory, AuthInfo authInfo) {
|
||||
private static List<String> parse(List<MinecraftArgument> arguments, VersionInfo info, Instance instance, String classPath, AuthInfo authInfo) {
|
||||
List<String> res = new ArrayList<>();
|
||||
for (MinecraftArgument argument : arguments) {
|
||||
for (String s : argument.arg()) {
|
||||
res.add(expandArg(s, info, instance, classPath, gameDirectory, authInfo));
|
||||
res.add(expandArg(s, info, instance, classPath, authInfo));
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
private static String expandArg(String arg, VersionInfo info, InstanceMeta instance, String classPath, String gameDirectory, AuthInfo authInfo) {
|
||||
private static String expandArg(String arg, VersionInfo info, Instance instance, String classPath, AuthInfo authInfo) {
|
||||
return arg
|
||||
// game args
|
||||
.replace("${auth_player_name}", authInfo.name())
|
||||
.replace("${version_name}", instance.getMinecraftVersion())
|
||||
.replace("${game_directory}", gameDirectory)
|
||||
.replace("${version_name}", instance.meta().getMinecraftVersion())
|
||||
.replace("${game_directory}", instance.path().toString())
|
||||
.replace("${assets_root}", MetaHolder.ASSETS_DIR.toAbsolutePath().toString())
|
||||
.replace("${assets_index_name}", info.assets)
|
||||
.replace("${auth_uuid}", authInfo.uuid())
|
||||
|
@ -234,7 +230,7 @@ public class InstanceLauncher {
|
|||
.replace("${resolution_width}", "1920") //TODO has_custom_resolution
|
||||
.replace("${resolution_height}", "1080") //TODO has_custom_resolution
|
||||
// jvm args
|
||||
.replace("${natives_directory}", MetaHolder.NATIVES_DIR.resolve(instance.getMinecraftVersion()).toAbsolutePath().toString())
|
||||
.replace("${natives_directory}", MetaHolder.NATIVES_DIR.resolve(instance.meta().getMinecraftVersion()).toAbsolutePath().toString())
|
||||
.replace("${launcher_name}", "Inceptum")
|
||||
.replace("${launcher_version}", BuildMetadata.VERSION.toString())
|
||||
.replace("${classpath}", classPath)
|
||||
|
|
|
@ -6,6 +6,7 @@ import io.gitlab.jfronny.gson.JsonParseException;
|
|||
import io.gitlab.jfronny.inceptum.common.Utils;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.fabric.FabricModJson;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.ModDescription;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Mod;
|
||||
import io.gitlab.jfronny.inceptum.launcher.util.ModPath;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.source.ModSource;
|
||||
|
||||
|
@ -17,13 +18,13 @@ import java.util.List;
|
|||
import java.util.Optional;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
public record FileScanTask(Path file, BiConsumer<Path, IWModDescription> discovered,
|
||||
public record FileScanTask(Path file, BiConsumer<Path, Mod> discovered,
|
||||
String gameVersion) implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!Files.exists(file)) return;
|
||||
if (Files.isDirectory(file)) {
|
||||
discovered.accept(file, new IWModDescription(file));
|
||||
discovered.accept(file, new Mod(file));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
|
@ -41,7 +42,7 @@ public record FileScanTask(Path file, BiConsumer<Path, IWModDescription> discove
|
|||
imod.i = newImod;
|
||||
imod.md = JFiles.readObject(imod.i, ModDescription.class);
|
||||
});
|
||||
discovered.accept(imod.i, new IWModDescription(file, Optional.of(imod.md), getFmj(file, imod.md), Optional.of(imod.i)));
|
||||
discovered.accept(imod.i, new Mod(file, Optional.of(imod.md), getFmj(file, imod.md), Optional.of(imod.i)));
|
||||
return;
|
||||
}
|
||||
if (ModPath.isImod(file)) {
|
||||
|
@ -55,10 +56,10 @@ public record FileScanTask(Path file, BiConsumer<Path, IWModDescription> discove
|
|||
imod.i = newImod;
|
||||
imod.md = JFiles.readObject(imod.i, ModDescription.class);
|
||||
});
|
||||
discovered.accept(imod.i, new IWModDescription(imod.i, Optional.of(imod.md), getFmj(modFile, imod.md), Optional.of(imod.i)));
|
||||
discovered.accept(imod.i, new Mod(imod.i, Optional.of(imod.md), getFmj(modFile, imod.md), Optional.of(imod.i)));
|
||||
return;
|
||||
}
|
||||
discovered.accept(file, new IWModDescription(file));
|
||||
discovered.accept(file, new Mod(file));
|
||||
} catch (IOException | URISyntaxException | JsonParseException e) {
|
||||
Utils.LOGGER.error("Could not scan file for mod info", e);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.system.mds;
|
||||
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Mod;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
|
@ -25,13 +26,13 @@ public interface ModsDirScanner extends Closeable {
|
|||
|
||||
String getGameVersion();
|
||||
|
||||
Set<IWModDescription> getMods() throws IOException;
|
||||
Set<Mod> getMods() throws IOException;
|
||||
|
||||
IWModDescription get(Path path);
|
||||
Mod get(Path path);
|
||||
|
||||
void invalidate(Path path);
|
||||
|
||||
boolean hasScanned(Path path);
|
||||
|
||||
void runOnce(BiConsumer<Path, IWModDescription> discovered);
|
||||
void runOnce(BiConsumer<Path, Mod> discovered);
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import io.gitlab.jfronny.commons.io.JFiles;
|
|||
import io.gitlab.jfronny.inceptum.common.R;
|
||||
import io.gitlab.jfronny.inceptum.common.Utils;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Mod;
|
||||
import io.gitlab.jfronny.inceptum.launcher.util.ModPath;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -17,7 +18,7 @@ import static java.nio.file.StandardWatchEventKinds.*;
|
|||
class ModsDirScannerImpl implements ModsDirScanner {
|
||||
private static final Map<Path, ModsDirScannerImpl> SCANNERS = new HashMap<>();
|
||||
private static final ExecutorService POOL = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors(), new NamedThreadFactory("mds"));
|
||||
private final Map<Path, IWModDescription> descriptions = new HashMap<>();
|
||||
private final Map<Path, Mod> descriptions = new HashMap<>();
|
||||
private final Set<Path> scannedPaths = new HashSet<>();
|
||||
private final Thread th;
|
||||
private final Path modsDir;
|
||||
|
@ -70,8 +71,8 @@ class ModsDirScannerImpl implements ModsDirScanner {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Set<IWModDescription> getMods() throws IOException {
|
||||
Set<IWModDescription> mods = new TreeSet<>();
|
||||
public Set<Mod> getMods() throws IOException {
|
||||
Set<Mod> mods = new TreeSet<>();
|
||||
if (Files.isDirectory(modsDir)) {
|
||||
for (Path path : JFiles.list(modsDir)) {
|
||||
if (ModPath.isImod(path) && Files.exists(ModPath.trimImod(path)))
|
||||
|
@ -83,10 +84,10 @@ class ModsDirScannerImpl implements ModsDirScanner {
|
|||
}
|
||||
|
||||
@Override
|
||||
public IWModDescription get(Path path) {
|
||||
public Mod get(Path path) {
|
||||
if (!descriptions.containsKey(path)) {
|
||||
// not yet scanned
|
||||
descriptions.put(path, new IWModDescription(path));
|
||||
descriptions.put(path, new Mod(path));
|
||||
}
|
||||
return descriptions.get(path);
|
||||
}
|
||||
|
@ -109,7 +110,7 @@ class ModsDirScannerImpl implements ModsDirScanner {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void runOnce(BiConsumer<Path, IWModDescription> discovered) {
|
||||
public void runOnce(BiConsumer<Path, Mod> discovered) {
|
||||
try {
|
||||
if (!Files.isDirectory(modsDir)) {
|
||||
return;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.system.mds;
|
||||
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Mod;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Set;
|
||||
|
@ -25,13 +27,13 @@ public record NoopMds(String gameVersion) implements ModsDirScanner {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Set<IWModDescription> getMods() throws IOException {
|
||||
public Set<Mod> getMods() throws IOException {
|
||||
return Set.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IWModDescription get(Path path) {
|
||||
return new IWModDescription(path);
|
||||
public Mod get(Path path) {
|
||||
return new Mod(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -44,6 +46,6 @@ public record NoopMds(String gameVersion) implements ModsDirScanner {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void runOnce(BiConsumer<Path, IWModDescription> discovered) {
|
||||
public void runOnce(BiConsumer<Path, Mod> discovered) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,27 +2,46 @@ package io.gitlab.jfronny.inceptum.launcher.util;
|
|||
|
||||
import io.gitlab.jfronny.commons.cache.FileBackedRef;
|
||||
import io.gitlab.jfronny.commons.io.JFiles;
|
||||
import io.gitlab.jfronny.commons.throwable.ThrowingConsumer;
|
||||
import io.gitlab.jfronny.inceptum.common.MetaHolder;
|
||||
import io.gitlab.jfronny.inceptum.common.Utils;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class InstanceList {
|
||||
private static final Map<Path, IEntry> metas = new LinkedHashMap<>();
|
||||
|
||||
public static void forEach(Consumer<Entry> target) throws IOException {
|
||||
public static void reset() {
|
||||
synchronized (metas) {
|
||||
for (IEntry value : metas.values()) {
|
||||
try {
|
||||
value.close();
|
||||
} catch (IOException e) {
|
||||
Utils.LOGGER.error("Could not close reference to instance meta", e);
|
||||
}
|
||||
}
|
||||
metas.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public static <TEx extends Exception> void forEach(ThrowingConsumer<Instance, TEx> target) throws IOException, TEx {
|
||||
Objects.requireNonNull(target);
|
||||
if (!Files.exists(MetaHolder.INSTANCE_DIR)) Files.createDirectories(MetaHolder.INSTANCE_DIR);
|
||||
JFiles.listTo(MetaHolder.INSTANCE_DIR, path -> {
|
||||
if (!Files.isDirectory(path)) return;
|
||||
target.accept(read(path));
|
||||
});
|
||||
try {
|
||||
JFiles.listTo(MetaHolder.INSTANCE_DIR, path -> {
|
||||
if (!Files.isDirectory(path)) return;
|
||||
target.accept(read(path));
|
||||
});
|
||||
} catch (Exception e) {
|
||||
//noinspection unchecked
|
||||
throw (TEx) e;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isEmpty() throws IOException {
|
||||
|
@ -30,12 +49,11 @@ public class InstanceList {
|
|||
return JFiles.list(MetaHolder.INSTANCE_DIR, Files::isDirectory).isEmpty();
|
||||
}
|
||||
|
||||
public static Entry read(Path instancePath) throws IOException {
|
||||
public static Instance read(Path instancePath) throws IOException {
|
||||
Objects.requireNonNull(instancePath);
|
||||
synchronized (metas) {
|
||||
if (!metas.containsKey(instancePath)) {
|
||||
metas.put(instancePath, new IEntry(
|
||||
toId(instancePath.getFileName().toString()),
|
||||
instancePath,
|
||||
new FileBackedRef<>(instancePath.resolve("instance.json"), InstanceMeta.class)
|
||||
));
|
||||
|
@ -44,50 +62,19 @@ public class InstanceList {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts any string into a set of lowercase ascii chars
|
||||
* @param input string to convert
|
||||
* @return a string matching [a-p]*
|
||||
*/
|
||||
private static String toId(String input) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
for (byte b : input.getBytes(StandardCharsets.UTF_8)) {
|
||||
int by = Byte.toUnsignedInt(b);
|
||||
int ch2 = by & 15; // right bits
|
||||
int ch1 = (by - ch2) / 16; // left bits
|
||||
result.append((char)('a' + ch1));
|
||||
result.append((char)('a' + ch2));
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
private record IEntry(String id, Path path, FileBackedRef<InstanceMeta> meta) {
|
||||
private record IEntry(Path path, FileBackedRef<InstanceMeta> meta) implements Closeable {
|
||||
@Override
|
||||
public String toString() {
|
||||
return path.getFileName().toString();
|
||||
}
|
||||
|
||||
public Entry toPub() throws IOException {
|
||||
return new Entry(id, path, meta.get());
|
||||
}
|
||||
}
|
||||
|
||||
public record Entry(String id, Path path, InstanceMeta meta) implements Comparable<Entry> {
|
||||
@Override
|
||||
public int compareTo(@NotNull InstanceList.Entry entry) {
|
||||
long time1 = meta.lastLaunched == null ? 0 : meta.lastLaunched;
|
||||
long time2 = entry.meta.lastLaunched == null ? 0 : entry.meta.lastLaunched;
|
||||
if (time1 == 0) {
|
||||
if (time2 == 0) return path.getFileName().toString().compareTo(entry.path.getFileName().toString());
|
||||
return -1;
|
||||
}
|
||||
if (time2 == 0) return 1;
|
||||
return Long.compare(time1, time2);
|
||||
public Instance toPub() throws IOException {
|
||||
return new Instance(path, meta.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return path.getFileName().toString();
|
||||
public void close() throws IOException {
|
||||
meta.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.util;
|
||||
|
||||
import io.gitlab.jfronny.inceptum.common.Utils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class InstanceLock {
|
||||
private static final String INCEPTUM_LOCK = "inceptum.lock";
|
||||
private static final String INCEPTUM_SETUP_LOCK = "inceptum.setup.lock";
|
||||
|
||||
public static void setSetupLock(Path instancePath, boolean state) throws IOException {
|
||||
if (isSetupLocked(instancePath)) {
|
||||
if (!state) Files.delete(instancePath.resolve(INCEPTUM_SETUP_LOCK));
|
||||
} else {
|
||||
if (state) Files.createDirectories(instancePath.resolve(INCEPTUM_SETUP_LOCK));
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isSetupLocked(Path instancePath) {
|
||||
return Files.exists(instancePath.resolve(INCEPTUM_SETUP_LOCK));
|
||||
}
|
||||
|
||||
public static void setRunningLock(Path instancePath, long pid) throws IOException {
|
||||
Files.writeString(instancePath.resolve(INCEPTUM_LOCK), Long.toString(pid));
|
||||
}
|
||||
|
||||
public static boolean isRunningLocked(Path instancePath) {
|
||||
if (!Files.exists(instancePath.resolve(INCEPTUM_LOCK))) return false;
|
||||
try {
|
||||
if (ProcessUtils.isProcessAlive(Files.readString(instancePath.resolve(INCEPTUM_LOCK))))
|
||||
return true;
|
||||
Files.delete(instancePath.resolve(INCEPTUM_LOCK));
|
||||
} catch (IOException e) {
|
||||
Utils.LOGGER.error("Could not read running lock of " + instancePath.getFileName().toString(), e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isLocked(Path instancePath) {
|
||||
return isSetupLocked(instancePath) || isRunningLocked(instancePath);
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@ package io.gitlab.jfronny.inceptum.launcher.util;
|
|||
|
||||
import io.gitlab.jfronny.commons.io.JFiles;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.ModDescription;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.mds.IWModDescription;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Mod;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.mds.ModsDirScanner;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.source.ModDownload;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.source.ModSource;
|
||||
|
@ -12,13 +12,13 @@ import java.nio.file.Files;
|
|||
import java.nio.file.Path;
|
||||
|
||||
public class ModManager {
|
||||
public static void delete(IWModDescription md, Path modsDirectory, ModsDirScanner mds) throws IOException {
|
||||
public static void delete(Mod md, Path modsDirectory, ModsDirScanner mds) throws IOException {
|
||||
JFiles.deleteRecursive(md.path());
|
||||
if (md.imod().isPresent() && Files.exists(md.imod().get())) Files.delete(md.imod().get());
|
||||
if (md.mod().isPresent()) {
|
||||
for (String dependency : md.mod().get().dependencies) {
|
||||
Path dep = modsDirectory.resolve(dependency);
|
||||
IWModDescription dmd = mds.get(dep);
|
||||
Mod dmd = mds.get(dep);
|
||||
if (dmd.mod().isPresent()) {
|
||||
dmd.mod().get().dependencies.remove(md.path().getFileName().toString());
|
||||
if (dmd.mod().get().dependencies.isEmpty()) delete(dmd, modsDirectory, mds);
|
||||
|
@ -29,7 +29,7 @@ public class ModManager {
|
|||
}
|
||||
|
||||
public static DownloadMeta download(ModSource ms, Path metaFile, ModsDirScanner mds) throws IOException {
|
||||
for (IWModDescription value : mds.getMods()) {
|
||||
for (Mod value : mds.getMods()) {
|
||||
if (value.mod().isEmpty()) continue;
|
||||
for (ModSource source : value.mod().get().sources.keySet()) {
|
||||
if (ms.equals(source)) {
|
||||
|
|
Loading…
Reference in New Issue