GTK: Implement instance exporting, break launching
This commit is contained in:
parent
e15ef8c485
commit
a93f2c8411
|
@ -24,9 +24,9 @@ public class ExportCommand extends BaseInstanceCommand {
|
|||
@Override
|
||||
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");
|
||||
Exporters.CURSE_FORGE.generate(new ProcessState(), instance, Paths.get(args[0]), args[1]);
|
||||
if (args.length > 2) throw new IllegalAccessException("Too many arguments");
|
||||
if (args.length > 1) instance.meta.instanceVersion = args[1];
|
||||
Exporters.CURSE_FORGE.generate(new ProcessState(), instance, Paths.get(args[0]));
|
||||
}
|
||||
|
||||
private static class MultiMCExportCommand extends BaseInstanceCommand {
|
||||
|
@ -38,7 +38,7 @@ public class ExportCommand extends BaseInstanceCommand {
|
|||
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");
|
||||
Exporters.MULTI_MC.generate(new ProcessState(), instance, Paths.get(args[0]), "1.0");
|
||||
Exporters.MULTI_MC.generate(new ProcessState(), instance, Paths.get(args[0]));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -50,9 +50,9 @@ public class ExportCommand extends BaseInstanceCommand {
|
|||
@Override
|
||||
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");
|
||||
Exporters.MODRINTH.generate(new ProcessState(), instance, Paths.get(args[0]), args[1]);
|
||||
if (args.length > 2) throw new IllegalAccessException("Too many arguments");
|
||||
if (args.length > 1) instance.meta.instanceVersion = args[1];
|
||||
Exporters.MODRINTH.generate(new ProcessState(), instance, Paths.get(args[0]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,15 +67,19 @@ public enum GtkEnvBackend implements LauncherEnv.EnvBackend { //TODO test
|
|||
|
||||
private void simpleDialog(String markup, String title, MessageType type, ButtonsType buttons, Runnable ok, Runnable cancel) {
|
||||
GtkMain.schedule(() -> {
|
||||
MessageDialog dialog = new MessageDialog(dialogParent, DialogFlags.MODAL.or(DialogFlags.DESTROY_WITH_PARENT), type, buttons, null);
|
||||
dialog.title = title;
|
||||
dialog.markup = markup;
|
||||
dialog.onResponse(processResponses(dialog, ok, cancel));
|
||||
dialog.show();
|
||||
simpleDialog(dialogParent, markup, title, type, buttons, ok, cancel);
|
||||
});
|
||||
}
|
||||
|
||||
private Dialog.Response processResponses(Dialog dialog, @Nullable Runnable ok, @Nullable Runnable cancel) {
|
||||
public static void simpleDialog(Window parent, String markup, String title, MessageType type, ButtonsType buttons, @Nullable Runnable ok, @Nullable Runnable cancel) {
|
||||
MessageDialog dialog = new MessageDialog(parent, DialogFlags.MODAL.or(DialogFlags.DESTROY_WITH_PARENT), type, buttons, null);
|
||||
dialog.title = title;
|
||||
dialog.markup = markup;
|
||||
dialog.onResponse(processResponses(dialog, ok, cancel));
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
private static Dialog.Response processResponses(Dialog dialog, @Nullable Runnable ok, @Nullable Runnable cancel) {
|
||||
return responseId -> {
|
||||
switch (ResponseType.of(responseId)) {
|
||||
case OK -> {
|
||||
|
|
|
@ -9,6 +9,7 @@ import org.gtk.gtk.Application;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class GtkMain {
|
||||
public static final String ID = "io.gitlab.jfronny.inceptum";
|
||||
|
@ -23,7 +24,6 @@ public class GtkMain {
|
|||
LauncherEnv.initialize(GtkEnvBackend.INSTANCE);
|
||||
Utils.LOGGER.info("Launching Inceptum v" + BuildMetadata.VERSION);
|
||||
Utils.LOGGER.info("Loading from " + MetaHolder.BASE_PATH);
|
||||
//TODO look into java-gtk samples for window architecture
|
||||
int statusCode = -1;
|
||||
try {
|
||||
statusCode = showGui(args);
|
||||
|
@ -33,12 +33,23 @@ public class GtkMain {
|
|||
}
|
||||
}
|
||||
|
||||
public static int showGui(String[] args) throws IOException {
|
||||
var app = new Application(ID, ApplicationFlags.FLAGS_NONE);
|
||||
app.onActivate(() -> {
|
||||
public static int showGui(String[] args) {
|
||||
return setupApplication(args, app -> {
|
||||
GtkMenubar.create(app);
|
||||
var window = new MainWindow(app);
|
||||
window.show();
|
||||
GtkEnvBackend.INSTANCE.dialogParent = window;
|
||||
window.onCloseRequest(() -> {
|
||||
GtkEnvBackend.INSTANCE.dialogParent = null;
|
||||
app.quit();
|
||||
return false;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public static int setupApplication(String[] args, Consumer<Application> onActivate) {
|
||||
var app = new Application(ID, ApplicationFlags.FLAGS_NONE);
|
||||
app.onActivate(() -> {
|
||||
GLib.idleAdd(() -> {
|
||||
Runnable r;
|
||||
while ((r = SCHEDULED.poll()) != null) {
|
||||
|
@ -50,12 +61,7 @@ public class GtkMain {
|
|||
}
|
||||
return true;
|
||||
});
|
||||
GtkEnvBackend.INSTANCE.dialogParent = window;
|
||||
window.onCloseRequest(() -> {
|
||||
GtkEnvBackend.INSTANCE.dialogParent = null;
|
||||
app.quit();
|
||||
return false;
|
||||
});
|
||||
onActivate.accept(app);
|
||||
});
|
||||
return app.run(args);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package io.gitlab.jfronny.inceptum.gtk;
|
||||
|
||||
import io.gitlab.jfronny.inceptum.gtk.window.dialog.ProcessStateWatcherDialog;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.launch.*;
|
||||
import io.gitlab.jfronny.inceptum.launcher.util.ProcessState;
|
||||
import org.gtk.gtk.Application;
|
||||
import io.gitlab.jfronny.commons.ref.R;
|
||||
import io.gitlab.jfronny.inceptum.common.Utils;
|
||||
|
@ -54,32 +56,47 @@ public class GtkMenubar {
|
|||
}
|
||||
|
||||
public static void launch(Instance instance, LaunchType launchType) {
|
||||
//TODO show popup during launch w/ cancel option (lock main UI)
|
||||
Runnable launch = () -> {
|
||||
try {
|
||||
Steps.reDownload(instance, Steps.createProcessState());
|
||||
} catch (IOException e) {
|
||||
Utils.LOGGER.error("Could not redownload instance, trying to start anyways", e);
|
||||
}
|
||||
if (launchType == LaunchType.Client) InstanceLauncher.launchClient(instance);
|
||||
else {
|
||||
try {
|
||||
InstanceLauncher.launch(instance, launchType, false, AccountManager.NULL_AUTH);
|
||||
} catch (LaunchException | IOException e) {
|
||||
LauncherEnv.showError("Could not start instance", e);
|
||||
}
|
||||
}
|
||||
};
|
||||
if (instance.isSetupLocked) {
|
||||
LauncherEnv.showError(I18n.get("instance.launch.locked.setup"), I18n.get("instance.launch.locked"));
|
||||
return;
|
||||
}
|
||||
if (instance.isRunningLocked) {
|
||||
LauncherEnv.showOkCancel(I18n.get("instance.launch.locked.running"), I18n.get("instance.launch.locked"), () -> {
|
||||
new Thread(launch).start(); //TODO loom
|
||||
}, R::nop);
|
||||
LauncherEnv.showOkCancel(
|
||||
I18n.get("instance.launch.locked.running"),
|
||||
I18n.get("instance.launch.locked"),
|
||||
() -> forceLaunch(instance, launchType),
|
||||
R::nop
|
||||
);
|
||||
}
|
||||
new Thread(launch).start();
|
||||
forceLaunch(instance, launchType);
|
||||
}
|
||||
|
||||
private static void forceLaunch(Instance instance, LaunchType launchType) {
|
||||
ProcessState state = Steps.createProcessState();
|
||||
ProcessStateWatcherDialog.show(
|
||||
GtkEnvBackend.INSTANCE.dialogParent,
|
||||
I18n.get("instance.launch.title"),
|
||||
I18n.get("instance.launch.error"),
|
||||
state,
|
||||
cancel -> {
|
||||
try {
|
||||
Steps.reDownload(instance, Steps.createProcessState(), cancel);
|
||||
} catch (IOException e) {
|
||||
Utils.LOGGER.error("Could not fetch instance, trying to start anyways", e);
|
||||
}
|
||||
if (!cancel.get()) {
|
||||
if (launchType == LaunchType.Client) InstanceLauncher.launchClient(instance);
|
||||
else {
|
||||
try {
|
||||
InstanceLauncher.launch(instance, launchType, false, AccountManager.NULL_AUTH);
|
||||
} catch (LaunchException | IOException e) {
|
||||
LauncherEnv.showError("Could not start instance", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
R::nop
|
||||
);
|
||||
}
|
||||
|
||||
public static void generateAccountsMenu() {
|
||||
|
|
|
@ -31,12 +31,12 @@ public class ILabel extends Label {
|
|||
}
|
||||
}
|
||||
|
||||
public ILabel(@PropertyKey(resourceBundle = I18n.BUNDLE) String str) {
|
||||
this(str, Mode.NORMAL);
|
||||
public ILabel(@PropertyKey(resourceBundle = I18n.BUNDLE) String str, Object... args) {
|
||||
this(str, Mode.NORMAL, args);
|
||||
}
|
||||
|
||||
public ILabel(@PropertyKey(resourceBundle = I18n.BUNDLE) String str, Mode mode) {
|
||||
super(I18n.get(str));
|
||||
public ILabel(@PropertyKey(resourceBundle = I18n.BUNDLE) String str, Mode mode, Object... args) {
|
||||
super(I18n.get(str, args));
|
||||
theme(this, mode);
|
||||
}
|
||||
|
||||
|
|
|
@ -6,16 +6,16 @@ import org.jetbrains.annotations.Nullable;
|
|||
import org.jetbrains.annotations.PropertyKey;
|
||||
|
||||
public class IRow extends Box {
|
||||
public IRow(@PropertyKey(resourceBundle = I18n.BUNDLE) String title, @PropertyKey(resourceBundle = I18n.BUNDLE) @Nullable String subtitle) {
|
||||
public IRow(@PropertyKey(resourceBundle = I18n.BUNDLE) String title, @PropertyKey(resourceBundle = I18n.BUNDLE) @Nullable String subtitle, Object... args) {
|
||||
super(Orientation.HORIZONTAL, 40);
|
||||
margin = 8;
|
||||
Widget head;
|
||||
ILabel lab = new ILabel(title);
|
||||
ILabel lab = new ILabel(title, args);
|
||||
lab.halign = Align.START;
|
||||
if (subtitle != null) {
|
||||
Box headB = new Box(Orientation.VERTICAL, 0);
|
||||
headB.append(lab);
|
||||
ILabel lab1 = new ILabel(subtitle, ILabel.Mode.SUBTITLE);
|
||||
ILabel lab1 = new ILabel(subtitle, ILabel.Mode.SUBTITLE, args);
|
||||
lab1.halign = Align.START;
|
||||
headB.append(lab1);
|
||||
head = headB;
|
||||
|
|
|
@ -1,18 +1,25 @@
|
|||
package io.gitlab.jfronny.inceptum.gtk.window;
|
||||
|
||||
import io.gitlab.jfronny.commons.ArgumentsTokenizer;
|
||||
import io.gitlab.jfronny.commons.StringFormatter;
|
||||
import io.gitlab.jfronny.commons.ref.R;
|
||||
import io.gitlab.jfronny.inceptum.common.MetaHolder;
|
||||
import io.gitlab.jfronny.inceptum.common.Utils;
|
||||
import io.gitlab.jfronny.inceptum.gtk.GtkEnvBackend;
|
||||
import io.gitlab.jfronny.inceptum.gtk.GtkMain;
|
||||
import io.gitlab.jfronny.inceptum.gtk.control.*;
|
||||
import io.gitlab.jfronny.inceptum.gtk.util.I18n;
|
||||
import io.gitlab.jfronny.inceptum.launcher.LauncherEnv;
|
||||
import io.gitlab.jfronny.inceptum.gtk.window.dialog.ProcessStateWatcherDialog;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.exporter.Exporter;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.exporter.Exporters;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.instance.*;
|
||||
import org.gnome.adw.*;
|
||||
import io.gitlab.jfronny.inceptum.launcher.util.ProcessState;
|
||||
import org.gnome.adw.HeaderBar;
|
||||
import org.gnome.adw.*;
|
||||
import org.gtk.gobject.BindingFlags;
|
||||
import org.gtk.gtk.*;
|
||||
import org.gtk.gtk.Application;
|
||||
import org.gtk.gtk.Window;
|
||||
import org.gtk.gtk.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
|
@ -20,8 +27,11 @@ import java.nio.file.Path;
|
|||
import java.util.List;
|
||||
|
||||
public class InstanceSettingsWindow extends Window {
|
||||
private final Instance instance;
|
||||
|
||||
public InstanceSettingsWindow(Application app, Instance instance) {
|
||||
this.application = app;
|
||||
this.instance = instance;
|
||||
|
||||
ViewStack stack = new ViewStack();
|
||||
|
||||
|
@ -71,7 +81,15 @@ public class InstanceSettingsWindow extends Window {
|
|||
close();
|
||||
new InstanceSettingsWindow(application, InstanceList.read(newPath)).show();
|
||||
} catch (IOException e) {
|
||||
LauncherEnv.showError("Could not rename", e);
|
||||
GtkEnvBackend.simpleDialog(
|
||||
this,
|
||||
StringFormatter.toString(e),
|
||||
"Could not rename",
|
||||
MessageType.ERROR,
|
||||
ButtonsType.CLOSE,
|
||||
null,
|
||||
null
|
||||
);
|
||||
}
|
||||
});
|
||||
entry.onChanged(s -> {
|
||||
|
@ -133,7 +151,8 @@ public class InstanceSettingsWindow extends Window {
|
|||
var box = new Box(Orientation.VERTICAL, 0);
|
||||
box.marginHorizontal = 24;
|
||||
box.marginTop = 12;
|
||||
//TODO show "currently unsupported in GTK UI (idk how I'd visualize this)
|
||||
box.append(new ILabel("instance.settings.mods.unsupported"));
|
||||
//TODO implement this, somehow
|
||||
stack.addTitledWithIcon(box, null, I18n.get("instance.settings.mods"), "package-x-generic-symbolic");
|
||||
}
|
||||
|
||||
|
@ -142,10 +161,100 @@ public class InstanceSettingsWindow extends Window {
|
|||
var box = new Box(Orientation.VERTICAL, 0);
|
||||
box.marginHorizontal = 24;
|
||||
box.marginTop = 12;
|
||||
//TODO CurseForge (button) -> see imgui
|
||||
//TODO Modrinth (button) -> see imgui
|
||||
//TODO MultiMC (button) -> see imgui
|
||||
{
|
||||
Frame frame = new Frame(null);
|
||||
ListBox lb = new ListBox();
|
||||
lb.selectionMode = SelectionMode.NONE;
|
||||
frame.child = lb;
|
||||
box.append(frame);
|
||||
{
|
||||
var row = new IRow("instance.settings.export.version", "instance.settings.export.version.subtitle");
|
||||
ISEntry entry = new ISEntry(instance.meta.instanceVersion);
|
||||
entry.onChanged(s -> {
|
||||
instance.meta.instanceVersion = s;
|
||||
instance.writeMeta();
|
||||
});
|
||||
row.append(entry);
|
||||
lb.append(row);
|
||||
}
|
||||
for (Exporter<?> exporter : Exporters.EXPORTERS) {
|
||||
var row = new IRow("instance.settings.export.title", "instance.settings.export.subtitle", exporter.name, exporter.fileExtension);
|
||||
row.firstChild.hexpand = true;
|
||||
Button btn = Button.newWithLabel(I18n.get("instance.settings.export"));
|
||||
btn.valign = Align.CENTER;
|
||||
btn.halign = Align.END;
|
||||
btn.onClicked(() -> {
|
||||
FileChooserNative dialog = new FileChooserNative(
|
||||
I18n.get("instance.settings.export.dialog.title", exporter.name),
|
||||
this,
|
||||
FileChooserAction.SAVE,
|
||||
"_" + I18n.get("save"),
|
||||
"_" + I18n.get("cancel")
|
||||
);
|
||||
dialog.currentName = exporter.getDefaultFileName(instance);
|
||||
dialog.onResponse(responseId -> {
|
||||
if (responseId == ResponseType.ACCEPT.value) {
|
||||
var file = dialog.getFile().path;
|
||||
if (file == null) {
|
||||
GtkEnvBackend.simpleDialog(
|
||||
this,
|
||||
"The path returned by the file dialog is null",
|
||||
"Could not export",
|
||||
MessageType.ERROR,
|
||||
ButtonsType.CLOSE,
|
||||
null,
|
||||
null
|
||||
);
|
||||
return;
|
||||
}
|
||||
export(exporter, Path.of(file));
|
||||
}
|
||||
});
|
||||
dialog.show();
|
||||
});
|
||||
row.append(btn);
|
||||
lb.append(row);
|
||||
}
|
||||
}
|
||||
stack.addTitledWithIcon(box, null, I18n.get("instance.settings.export"), "send-to-symbolic");
|
||||
}
|
||||
}
|
||||
|
||||
private void export(Exporter<?> exporter, Path path) {
|
||||
ProcessState state = new ProcessState(Exporters.STEP_COUNT, "Initializing...");
|
||||
ProcessStateWatcherDialog.show(
|
||||
this,
|
||||
I18n.get("instance.settings.export.dialog.title", exporter.name),
|
||||
I18n.get("instance.settings.export.dialog.error", instance.name),
|
||||
state,
|
||||
cancel -> {
|
||||
exporter.generate(state, instance, path);
|
||||
GtkMain.schedule(() -> {
|
||||
Dialog success = Dialog.newWithButtons(
|
||||
I18n.get("instance.settings.export.dialog.success.title"),
|
||||
this,
|
||||
DialogFlags.MODAL.or(DialogFlags.DESTROY_WITH_PARENT),
|
||||
I18n.get("show"),
|
||||
ResponseType.OK,
|
||||
I18n.get("ok"),
|
||||
ResponseType.CANCEL,
|
||||
null
|
||||
);
|
||||
success.contentArea.append(new ILabel("instance.settings.export.dialog.success", instance.name, path.toString()));
|
||||
success.onResponse(responseId1 -> {
|
||||
switch (ResponseType.of(responseId1)) {
|
||||
case OK -> {
|
||||
success.close();
|
||||
Utils.openFile(path.toFile());
|
||||
}
|
||||
case CLOSE, CANCEL -> success.close();
|
||||
case DELETE_EVENT -> success.destroy();
|
||||
}
|
||||
});
|
||||
success.show();
|
||||
});
|
||||
},
|
||||
R::nop
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
package io.gitlab.jfronny.inceptum.gtk.window.dialog;
|
||||
|
||||
import io.gitlab.jfronny.commons.throwable.ThrowingConsumer;
|
||||
import io.gitlab.jfronny.inceptum.gtk.GtkMain;
|
||||
import io.gitlab.jfronny.inceptum.launcher.LauncherEnv;
|
||||
import io.gitlab.jfronny.inceptum.launcher.util.ProcessState;
|
||||
import org.gtk.glib.GLib;
|
||||
import org.gtk.gtk.*;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class ProcessStateWatcherDialog extends MessageDialog {
|
||||
private final ProcessState state;
|
||||
private final Runnable cancel;
|
||||
private final AtomicBoolean canceled = new AtomicBoolean(false);
|
||||
private final AtomicBoolean finished = new AtomicBoolean(false);
|
||||
private State cachedState = null;
|
||||
|
||||
public static ProcessStateWatcherDialog show(Window parent, String title, String errorMessage, ProcessState state, ThrowingConsumer<AtomicBoolean, ?> executor, @Nullable Runnable cancel) {
|
||||
ProcessStateWatcherDialog dialog = new ProcessStateWatcherDialog(parent, title, errorMessage, state, executor, cancel);
|
||||
dialog.show();
|
||||
return dialog;
|
||||
}
|
||||
|
||||
public ProcessStateWatcherDialog(Window parent, String title, String errorMessage, ProcessState state, ThrowingConsumer<AtomicBoolean, ?> executor, @Nullable Runnable cancel) {
|
||||
super(parent, DialogFlags.MODAL.or(DialogFlags.DESTROY_WITH_PARENT), MessageType.INFO, ButtonsType.CANCEL, null);
|
||||
this.state = state;
|
||||
this.cancel = cancel;
|
||||
this.title = title;
|
||||
if (cancel != null) addButton("Cancel", ResponseType.CANCEL.value);
|
||||
onResponse(responseId -> {
|
||||
if (responseId == ResponseType.CANCEL.value) {
|
||||
canceled.set(true);
|
||||
close();
|
||||
}
|
||||
});
|
||||
onCloseRequest(() -> {
|
||||
if (finished.get()) return false;
|
||||
if (cancel == null) return true;
|
||||
canceled.set(true);
|
||||
cancel.run();
|
||||
return false;
|
||||
});
|
||||
onClose(() -> {
|
||||
if (canceled.get() && cancel != null) cancel.run();
|
||||
});
|
||||
var progress = new ProgressBar();
|
||||
contentArea.append(progress);
|
||||
addTickCallback((widget, clock) -> {
|
||||
if (finished.get()) return GLib.SOURCE_REMOVE;
|
||||
var nc = new State(state);
|
||||
if (!nc.equals(cachedState)) {
|
||||
cachedState = nc;
|
||||
setMarkup(cachedState.msg);
|
||||
progress.fraction = cachedState.progress;
|
||||
widget.queueDraw();
|
||||
}
|
||||
return GLib.SOURCE_CONTINUE;
|
||||
}, null);
|
||||
new Thread(() -> {
|
||||
try {
|
||||
executor.accept(canceled);
|
||||
} catch (Throwable e) {
|
||||
canceled.set(true);
|
||||
LauncherEnv.showError(errorMessage, e);
|
||||
} finally {
|
||||
finished.set(true);
|
||||
GtkMain.schedule(this::close);
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
record State(String msg, float progress) {
|
||||
State(ProcessState source) {
|
||||
this(source.currentStep, source.progress);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -50,4 +50,18 @@ instance.settings.general.args.server=Server
|
|||
instance.settings.general.args.client.subtitle=Arguments to add to Minecraft Clients
|
||||
instance.settings.general.args.server.subtitle=Arguments to add to Minecraft Servers
|
||||
instance.settings.export=Export
|
||||
instance.settings.mods=Mods
|
||||
instance.settings.mods=Mods
|
||||
instance.settings.mods.unsupported=Mod management is currently unavailable in the GTK UI.\
|
||||
Please use the ImGUI or CLI to manage mods for now.
|
||||
instance.settings.export.title=%1$s
|
||||
instance.settings.export.subtitle=Export this Pack as a %1$s %2$s file
|
||||
instance.settings.export.version=Version
|
||||
instance.settings.export.version.subtitle=Version of the exported Pack
|
||||
save=Save
|
||||
instance.settings.export.dialog.title=Export %1$s Pack
|
||||
instance.settings.export.dialog.success=%1$s has been successfully exported to %2$s
|
||||
instance.settings.export.dialog.success.title=Sucessfully exported
|
||||
instance.settings.export.dialog.error=Could not export %1$s
|
||||
instance.launch.error=Could not start instance
|
||||
instance.launch.title=Starting instance
|
||||
show=Show
|
|
@ -1,6 +1,6 @@
|
|||
account.none=Keiner
|
||||
about.contact=Kontakt
|
||||
about.license=Dieses Programm komt OHNE JEGLICHE GARANTIE.\
|
||||
about.license=Dieses Programm kommt OHNE JEGLICHE GARANTIE.\
|
||||
Dies ist freie Software, die Sie unter bestimmten Bedingungen gerne weitergeben dürfen.
|
||||
menu.account=Konto
|
||||
menu.account.manage=Verwalten
|
||||
|
@ -22,11 +22,11 @@ menu.hamburger.preferences=Einstellungen
|
|||
menu.hamburger.about=Über
|
||||
instance.launch.locked=Instanz kann momentan nicht gestartet werden
|
||||
instance.launch.locked.setup=Diese Instanz wird noch eingerichtet.\
|
||||
Bitte warte, bis dieser Prozess abgeschlossen ist,\
|
||||
bevor du sie startest.
|
||||
Bitte warten Sie, bis dieser Prozess abgeschlossen ist,\
|
||||
bevor Sie die Instanz starten.
|
||||
instance.launch.locked.running=Diese Instanz läuft bereits.\
|
||||
Bestätigen sie den Start mit OK, um sie ein zweites mal zu starten.\
|
||||
Bitte seien sie sich bewusst, dass dies zu Problemen führen wird und NICHT UNTERSÜTZT ist.
|
||||
Bestätigen Sie den Start mit OK, um Sie ein zweites Mal zu starten.\
|
||||
Bitte seien Sie sich bewusst, dass dies zu Problemen führen wird und NICHT UNTERSTÜTZT ist.
|
||||
instance.launch=Starten
|
||||
main.empty.title=Willkommen bei Inceptum
|
||||
main.empty.description=Importiere oder erstelle um anzufangen eine Instanz mit dem +
|
||||
|
@ -50,4 +50,18 @@ instance.settings.general.args.server=Server
|
|||
instance.settings.general.args.client.subtitle=Argumente für Minecraft-Clients
|
||||
instance.settings.general.args.server.subtitle=Argumente für Minecraft-Server
|
||||
instance.settings.export=Export
|
||||
instance.settings.mods=Mods
|
||||
instance.settings.mods=Mods
|
||||
instance.settings.mods.unsupported=Die Verwaltung von Modifikationen ist momentan noch in Entwicklung.\
|
||||
Bitte verwenden Sie vorerst die ImGUI oder CLI, um Mods zu verwalten.
|
||||
instance.settings.export.title=%1$s
|
||||
instance.settings.export.subtitle=Dieses Pack als %2$s für %1$s exportieren
|
||||
instance.settings.export.version=Version
|
||||
instance.settings.export.version.subtitle=Version des exportierten Packs
|
||||
save=Speichern
|
||||
instance.settings.export.dialog.title=%1$s-Pack exportieren
|
||||
instance.settings.export.dialog.success=%1$s wurde erfolgreich nach %2$s exportiert
|
||||
instance.settings.export.dialog.success.title=Erfolgreich exportiert
|
||||
instance.settings.export.dialog.error=Konnte %1$s nicht exportieren
|
||||
instance.launch.error=Konnte Instanz nicht starten
|
||||
instance.launch.title=Starting instance
|
||||
show=Anzeigen
|
|
@ -1,9 +1,11 @@
|
|||
package io.gitlab.jfronny.inceptum.imgui.window.edit;
|
||||
|
||||
import imgui.ImGui;
|
||||
import imgui.type.ImString;
|
||||
import io.gitlab.jfronny.commons.ref.R;
|
||||
import io.gitlab.jfronny.inceptum.imgui.GuiMain;
|
||||
import io.gitlab.jfronny.inceptum.imgui.control.Tab;
|
||||
import io.gitlab.jfronny.inceptum.imgui.window.GuiUtil;
|
||||
import io.gitlab.jfronny.inceptum.imgui.window.dialog.ProcessStateWatcherWindow;
|
||||
import io.gitlab.jfronny.inceptum.imgui.window.dialog.TextBoxWindow;
|
||||
import io.gitlab.jfronny.inceptum.launcher.LauncherEnv;
|
||||
|
@ -15,29 +17,33 @@ import java.nio.file.Path;
|
|||
|
||||
public class ExportTab extends Tab {
|
||||
private final InstanceEditWindow window;
|
||||
private final ImString instanceVersion = new ImString("", GuiUtil.INPUT_FIELD_LENGTH);
|
||||
|
||||
public ExportTab(InstanceEditWindow window) {
|
||||
super("Export");
|
||||
this.window = window;
|
||||
instanceVersion.set(window.instance.meta.instanceVersion);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderInner() {
|
||||
if (ImGui.inputTextWithHint("Version", "Version of the exported Pack", instanceVersion)) {
|
||||
window.instance.meta.instanceVersion = instanceVersion.get();
|
||||
window.instance.writeMeta();
|
||||
}
|
||||
if (window.instance.mds.isComplete) {
|
||||
for (Exporter<?> exporter : Exporters.EXPORTERS) {
|
||||
if (ImGui.button(exporter.name)) {
|
||||
GuiMain.open(new TextBoxWindow("Version", "Please enter the current version of your modpack", "1.0", version -> {
|
||||
String defaultName = window.instance.name + " " + version + " (" + exporter.name + ")." + exporter.fileExtension;
|
||||
String filter = "*." + exporter.fileExtension;
|
||||
Path exportPath = GuiMain.saveFileDialog("Export " + exporter.name + " Pack", defaultName, new String[]{filter}, exporter.name + " 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.instance, exportPath, version);
|
||||
LauncherEnv.showInfo(window.instance.name + " has been successfully exported to " + exportPath, "Successfully exported");
|
||||
}, null));
|
||||
}
|
||||
}, R::nop));
|
||||
String defaultName = exporter.getDefaultFileName(window.instance);
|
||||
String filter = "*." + exporter.fileExtension;
|
||||
Path exportPath = GuiMain.saveFileDialog("Export " + exporter.name + " Pack", defaultName, new String[]{filter}, exporter.name + " 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.instance, exportPath);
|
||||
LauncherEnv.showInfo(window.instance.name + " has been successfully exported to " + exportPath, "Successfully exported");
|
||||
}, null));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -50,7 +50,7 @@ public class GeneralTab extends Tab {
|
|||
imc.snapshotsBox();
|
||||
imc.versionBox(ver -> {
|
||||
window.reDownload = true;
|
||||
window.instance.meta().version = ver;
|
||||
window.instance.meta.gameVersion = ver;
|
||||
window.instance.writeMeta();
|
||||
});
|
||||
if (ImGui.button("Delete"))
|
||||
|
|
|
@ -8,19 +8,24 @@ import java.util.Objects;
|
|||
|
||||
@GSerializable(configure = GsonPreset.Config.class)
|
||||
public class InstanceMeta {
|
||||
public String version;
|
||||
public String instanceVersion = "1.0";
|
||||
public String gameVersion;
|
||||
public String java;
|
||||
public Long minMem;
|
||||
public Long maxMem;
|
||||
public Long lastLaunched;
|
||||
public Arguments arguments;
|
||||
|
||||
public void setVersion(String version) {
|
||||
this.gameVersion = version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) return true;
|
||||
if (obj == null || obj.getClass() != this.getClass()) return false;
|
||||
var that = (InstanceMeta) obj;
|
||||
return Objects.equals(this.version, that.version) &&
|
||||
return Objects.equals(this.gameVersion, that.gameVersion) &&
|
||||
Objects.equals(this.java, that.java) &&
|
||||
Objects.equals(this.minMem, that.minMem) &&
|
||||
Objects.equals(this.maxMem, that.maxMem) &&
|
||||
|
@ -30,7 +35,7 @@ public class InstanceMeta {
|
|||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(version, java, minMem, maxMem, lastLaunched, arguments);
|
||||
return Objects.hash(gameVersion, java, minMem, maxMem, lastLaunched, arguments);
|
||||
}
|
||||
|
||||
@GSerializable(configure = GsonPreset.Config.class)
|
||||
|
|
|
@ -28,20 +28,20 @@ public abstract class Exporter<Manifest> {
|
|||
|
||||
protected abstract void addMods(Path root, Instance instance, Iterable<Mod> mods, Manifest manifest, Path modsOverrides) throws IOException;
|
||||
|
||||
public void generate(ProcessState state, Instance instance, Path exportPath, String version) throws IOException {
|
||||
public void generate(ProcessState state, Instance instance, Path exportPath) 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, instance, version);
|
||||
Manifest manifest = generateManifests(root, instance, instance.meta.instanceVersion);
|
||||
if (instance.isFabric) {
|
||||
state.incrementStep("Adding mods");
|
||||
addMods(root, instance, instance.mods.stream().filter(mod -> {
|
||||
if (!mod.isEnabled) return false;
|
||||
state.updateStep(mod.name);
|
||||
return true;
|
||||
}), manifest, overrides.resolve("mods"));
|
||||
}).toList(), manifest, overrides.resolve("mods"));
|
||||
}
|
||||
state.incrementStep("Adding files");
|
||||
filesLoop: for (Path path : IgnoringWalk.walk(instance.path)) {
|
||||
|
@ -74,4 +74,8 @@ public abstract class Exporter<Manifest> {
|
|||
public String getFileExtension() {
|
||||
return fileExtension;
|
||||
}
|
||||
|
||||
public String getDefaultFileName(Instance instance) {
|
||||
return instance.name + " " + instance.meta.instanceVersion + " (" + name + ")." + fileExtension;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ public abstract class Importer<T> {
|
|||
final Path iDir = MetaHolder.INSTANCE_DIR.resolve(name).toAbsolutePath().normalize();
|
||||
Instance.setSetupLock(iDir, true);
|
||||
InstanceMeta meta = new InstanceMeta();
|
||||
meta.version = createVersionString(man.gameVersion, man.fabricVersion);
|
||||
meta.gameVersion = createVersionString(man.gameVersion, man.fabricVersion);
|
||||
GC_InstanceMeta.write(meta, iDir.resolve(InstanceList.INSTANCE_CONFIG_NAME));
|
||||
|
||||
state.incrementStep("Downloading mods");
|
||||
|
|
|
@ -83,15 +83,15 @@ public record Instance(String id, Path path, InstanceMeta meta, ModsDirScanner m
|
|||
}
|
||||
|
||||
public boolean isFabric() {
|
||||
return GameVersionParser.isFabric(meta.version);
|
||||
return GameVersionParser.isFabric(meta.gameVersion);
|
||||
}
|
||||
|
||||
public String getGameVersion() {
|
||||
return GameVersionParser.getGameVersion(meta.version);
|
||||
return GameVersionParser.getGameVersion(meta.gameVersion);
|
||||
}
|
||||
|
||||
public String getLoaderVersion() {
|
||||
return GameVersionParser.getLoaderVersion(meta.version);
|
||||
return GameVersionParser.getLoaderVersion(meta.gameVersion);
|
||||
}
|
||||
|
||||
public boolean isSetupLocked() {
|
||||
|
|
|
@ -15,7 +15,7 @@ import java.util.function.BiConsumer;
|
|||
public interface ModsDirScanner extends Closeable {
|
||||
static ModsDirScanner get(Path modsDir, InstanceMeta meta) throws IOException {
|
||||
if (Files.exists(modsDir)) return ModsDirScannerImpl.get(modsDir, meta);
|
||||
return new NoopMds(GameVersionParser.getGameVersion(meta.version));
|
||||
return new NoopMds(GameVersionParser.getGameVersion(meta.gameVersion));
|
||||
}
|
||||
|
||||
static void closeAll() {
|
||||
|
|
|
@ -65,7 +65,7 @@ class ModsDirScannerImpl implements ModsDirScanner {
|
|||
|
||||
@Override
|
||||
public String getGameVersion() {
|
||||
return GameVersionParser.getGameVersion(instance.meta.version);
|
||||
return GameVersionParser.getGameVersion(instance.meta.gameVersion);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -29,6 +29,10 @@ public class Steps {
|
|||
}
|
||||
|
||||
public static void reDownload(Instance instance, ProcessState state) throws IOException {
|
||||
reDownload(instance, state, new AtomicBoolean(false));
|
||||
}
|
||||
|
||||
public static void reDownload(Instance instance, ProcessState state, AtomicBoolean cancel) throws IOException {
|
||||
if (instance.isLocked) return;
|
||||
boolean found = false;
|
||||
for (VersionsListInfo version : McApi.getVersions().versions) {
|
||||
|
@ -43,7 +47,8 @@ public class Steps {
|
|||
SetupStepInfo info = new SetupStepInfo(vi, li, instance.name, state);
|
||||
for (Step step : Steps.STEPS) {
|
||||
state.incrementStep("Starting " + step.getClass().getSimpleName());
|
||||
step.execute(info, new AtomicBoolean(false));
|
||||
step.execute(info, cancel);
|
||||
if (cancel.get()) return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ public class WriteMetadataStep implements Step {
|
|||
Path metaPath = instance.resolve(InstanceList.INSTANCE_CONFIG_NAME);
|
||||
if (!Files.exists(metaPath)) {
|
||||
InstanceMeta meta = new InstanceMeta();
|
||||
meta.version = info.version.id;
|
||||
meta.gameVersion = info.version.id;
|
||||
GC_InstanceMeta.write(meta, metaPath);
|
||||
}
|
||||
Instance.setSetupLock(instance, false);
|
||||
|
|
Loading…
Reference in New Issue