Don't lock up everything while creating an instance

This commit is contained in:
JFronny 2021-10-29 23:16:03 +02:00
parent e2178809ab
commit 72ab7c27b9
No known key found for this signature in database
GPG Key ID: BEC5ACBBD4EE17E5
14 changed files with 141 additions and 81 deletions

View File

@ -1,7 +1,8 @@
package io.gitlab.jfronny.inceptum.install;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicBoolean;
public interface Step {
void execute(SetupStepInfo info) throws IOException;
void execute(SetupStepInfo info, AtomicBoolean stopThread) throws IOException;
}

View File

@ -10,12 +10,14 @@ import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
public class DownloadAssetsStep implements Step {
@Override
public void execute(SetupStepInfo info) throws IOException {
public void execute(SetupStepInfo info, AtomicBoolean stopThread) throws IOException {
Path o = Inceptum.ASSETS_DIR.resolve("objects");
for (Map.Entry<String, AssetIndex.Asset> entry : McApi.getAssetIndex(info.version()).objects.entrySet()) {
if (stopThread.get()) return;
Path fPath = o.resolve(entry.getValue().hash.substring(0, 2));
if (!Files.exists(fPath)) Files.createDirectories(fPath);
fPath = fPath.resolve(entry.getValue().hash);

View File

@ -9,10 +9,11 @@ import io.gitlab.jfronny.inceptum.util.Utils;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.concurrent.atomic.AtomicBoolean;
public class DownloadClientStep implements Step {
@Override
public void execute(SetupStepInfo info) throws IOException {
public void execute(SetupStepInfo info, AtomicBoolean stopThread) throws IOException {
VersionInfo.Downloads.Download client = info.version().downloads.client;
Inceptum.LOGGER.info("Downloading client");
Path parentPath = Inceptum.LIBRARIES_DIR.resolve("net/minecraft/minecraft");

View File

@ -10,11 +10,13 @@ import io.gitlab.jfronny.inceptum.util.VersionInfoLibraryResolver;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.concurrent.atomic.AtomicBoolean;
public class DownloadLibrariesStep implements Step {
@Override
public void execute(SetupStepInfo info) throws IOException {
public void execute(SetupStepInfo info, AtomicBoolean stopThread) throws IOException {
for (VersionInfo.Library.Downloads.Artifact artifact : VersionInfoLibraryResolver.getRelevant(info.version())) {
if (stopThread.get()) return;
Path path = Inceptum.LIBRARIES_DIR.resolve(artifact.path);
if (Files.exists(path)) return;
//TODO allow maven-like download for fabric

View File

@ -8,10 +8,11 @@ import io.gitlab.jfronny.inceptum.windows.NewInstanceWindow;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.concurrent.atomic.AtomicBoolean;
public class SetupDirsStep implements Step {
@Override
public void execute(SetupStepInfo info) throws IOException {
public void execute(SetupStepInfo info, AtomicBoolean stopThread) throws IOException {
Inceptum.LOGGER.info("Setting up instance dirs");
Path iDir = Inceptum.INSTANCE_DIR.resolve(info.name());
if (!Files.exists(iDir)) {

View File

@ -8,10 +8,11 @@ import io.gitlab.jfronny.inceptum.util.Utils;
import java.io.IOException;
import java.nio.file.Path;
import java.util.concurrent.atomic.AtomicBoolean;
public class WriteMetadataStep implements Step {
@Override
public void execute(SetupStepInfo info) throws IOException {
public void execute(SetupStepInfo info, AtomicBoolean stopThread) throws IOException {
Inceptum.LOGGER.info("Writing metadata");
Path metaDir = Inceptum.INSTANCE_DIR.resolve(info.name()).resolve("instance.json");
InstanceMeta meta = new InstanceMeta();

View File

@ -21,6 +21,7 @@ import java.util.concurrent.ConcurrentMap;
public class MapAppender extends AbstractAppender {
public static final ConcurrentMap<String, LogEvent> EVENT_MAP = new ConcurrentHashMap<>();
public static final Set<String> LOG = new LinkedHashSet<>();
public static final Set<String> LOG_MESSAGES = new LinkedHashSet<>();
protected MapAppender(String name, Filter filter) {
//super(name, filter, null);
@ -45,8 +46,14 @@ public class MapAppender extends AbstractAppender {
.append("] ")
.append(event.getSource().getClassName())
.append(" - ");
if (event.getMessage() instanceof StringBuilderFormattable sbf) sbf.formatTo(msg);
else msg.append(event.getMessage().getFormattedMessage());
String msgText;
if (event.getMessage() instanceof StringBuilderFormattable sbf) {
StringBuilder sb = new StringBuilder();
sbf.formatTo(sb);
msgText = sb.toString();
} else msgText = event.getMessage().getFormattedMessage();
msg.append(msgText);
LOG.add(msg.toString());
LOG_MESSAGES.add(msgText);
}
}

View File

@ -56,7 +56,7 @@ public class AccountManager {
public static void addAccount(MicrosoftAccount account) {
ACCOUNTS.add(account);
if (ACCOUNTS.size() > 1) {
Inceptum.open(new AlertWindow("Account added successfully. Switch to it now?",
Inceptum.open(new AlertWindow("Success", "Account added successfully. Switch to it now?",
() -> switchAccount(account),
() -> {}));
}

View File

@ -188,7 +188,7 @@ public class MicrosoftAccount {
public void ensureAccessTokenValid(Consumer<Boolean> isValid) {
boolean hasCancelled = false;
if (mustLogin) {
Inceptum.open(new AlertWindow("You must login again in order to continue", () -> {
Inceptum.open(new AlertWindow("Login expired", "You must login again in order to continue", () -> {
Inceptum.open(new MicrosoftLoginWindow(this));

View File

@ -1,18 +1,19 @@
package io.gitlab.jfronny.inceptum.windows;
import imgui.ImGui;
import imgui.flag.ImGuiWindowFlags;
public class AlertWindow extends Window {
private final String message;
private final Runnable onOk;
private final Runnable onCancel;
public AlertWindow(String message) {
this(message, null, null);
public AlertWindow(String title, String message) {
this(title, message, null, null);
}
public AlertWindow(String message, Runnable onOk, Runnable onCancel) {
super("Warning");
public AlertWindow(String title, String message, Runnable onOk, Runnable onCancel) {
super(title);
this.message = message;
this.onOk = onOk;
this.onCancel = onCancel;
@ -33,4 +34,9 @@ public class AlertWindow extends Window {
}
}
}
@Override
public int getFlags() {
return super.getFlags() | ImGuiWindowFlags.NoSavedSettings;
}
}

View File

@ -0,0 +1,69 @@
package io.gitlab.jfronny.inceptum.windows;
import imgui.ImGui;
import io.gitlab.jfronny.inceptum.Inceptum;
import io.gitlab.jfronny.inceptum.install.SetupStepInfo;
import io.gitlab.jfronny.inceptum.install.Step;
import io.gitlab.jfronny.inceptum.install.Steps;
import io.gitlab.jfronny.inceptum.util.MapAppender;
import io.gitlab.jfronny.inceptum.util.Utils;
import java.io.IOException;
import java.nio.file.Files;
import java.util.concurrent.atomic.AtomicBoolean;
public class InstanceCreateProcessWindow extends Window {
private final SetupStepInfo stepInfo;
private final AtomicBoolean finalize = new AtomicBoolean(false);
public InstanceCreateProcessWindow(SetupStepInfo stepInfo) {
super("Creating Instance");
this.stepInfo = stepInfo;
new Thread(this::creationThread).start();
}
@Override
public void draw() {
if (finalize.get()) {
close();
return;
}
String last = "Initializing";
for (String s : MapAppender.LOG_MESSAGES) last = s;
ImGui.textUnformatted(last);
if (ImGui.button("Cancel")) finalize.set(true);
}
private void creationThread() {
if (Files.exists(Inceptum.INSTANCE_DIR.resolve(stepInfo.name()))) {
finalize.set(true);
return;
}
Inceptum.LOGGER.info("Starting install process");
try {
for (Step step : Steps.STEPS) {
if (finalize.get()) {
cleanUp();
return;
}
step.execute(stepInfo, finalize);
}
finalize.set(true);
Inceptum.open(new AlertWindow("Successfully installed", "The instance was successfully created. You can now launch it using the main menu"));
close();
} catch (Throwable e) {
Inceptum.LOGGER.error("Could not initialize instance", e);
Inceptum.open(new AlertWindow("Could not create the instance", e.toString()));
close();
cleanUp();
}
}
private void cleanUp() {
try {
Utils.deleteRecursive(Inceptum.INSTANCE_DIR.resolve(stepInfo.name()));
} catch (IOException e) {
Inceptum.LOGGER.error("Could not delete instance dir", e);
}
}
}

View File

@ -1,7 +1,6 @@
package io.gitlab.jfronny.inceptum.windows;
import imgui.ImGui;
import io.gitlab.jfronny.inceptum.util.MapAppender;
import java.util.Set;

View File

@ -147,7 +147,7 @@ public class MicrosoftLoginWindow extends Window {
if (!(store.items.stream().anyMatch(i -> i.name.equalsIgnoreCase("product_minecraft"))
&& store.items.stream().anyMatch(i -> i.name.equalsIgnoreCase("game_minecraft")))) {
Inceptum.open(new AlertWindow("This account doesn't have a valid purchase of Minecraft.\nPlease make sure you've bought the Java edition of Minecraft and then try again."));
Inceptum.open(new AlertWindow("Doesn't own Minecraft", "This account doesn't have a valid purchase of Minecraft.\nPlease make sure you've bought the Java edition of Minecraft and then try again."));
throw new Exception("Account does not own Minecraft");
}
@ -173,7 +173,7 @@ public class MicrosoftLoginWindow extends Window {
// if forced to relogin, then make sure they logged into correct account
if (account != null && this.account != null && account.accountId != this.account.accountId) {
Inceptum.open(new AlertWindow("Logged into incorrect account. Please login again on the Accounts tab"));
Inceptum.open(new AlertWindow("Incorrect account", "Logged into incorrect account. Please login again on the Accounts tab"));
return;
}

View File

@ -6,12 +6,10 @@ import imgui.type.ImInt;
import imgui.type.ImString;
import io.gitlab.jfronny.inceptum.Inceptum;
import io.gitlab.jfronny.inceptum.install.SetupStepInfo;
import io.gitlab.jfronny.inceptum.install.Step;
import io.gitlab.jfronny.inceptum.install.Steps;
import io.gitlab.jfronny.inceptum.model.mojang.VersionsList;
import io.gitlab.jfronny.inceptum.model.mojang.VersionsListInfo;
import io.gitlab.jfronny.inceptum.util.Utils;
import io.gitlab.jfronny.inceptum.util.McApi;
import io.gitlab.jfronny.inceptum.util.Utils;
import java.io.IOException;
import java.nio.file.Files;
@ -21,8 +19,7 @@ import java.util.List;
public class NewInstanceWindow extends Window {
VersionsList manifest = McApi.getVersions();
VersionsListInfo selected;
State state = State.Configure;
ImInt version = new ImInt(0); //TODO select latest stable
ImInt version = new ImInt(0);
ImString name = new ImString("", 128);
ImBoolean snapshots = new ImBoolean(Inceptum.CONFIG.snapshots);
ImBoolean fabric = new ImBoolean(true);
@ -36,60 +33,39 @@ public class NewInstanceWindow extends Window {
@Override
public void draw() {
switch (state) {
case Configure -> {
if (ImGui.checkbox("Show snapshots", snapshots)) {
boolean prev = Inceptum.CONFIG.snapshots;
Inceptum.CONFIG.snapshots = snapshots.get();
Inceptum.saveConfig();
//fix version index
int i = getVersions(Inceptum.CONFIG.snapshots).indexOf(getVersions(prev).get(version.get()));
if (i == -1) version.set(0);
else version.set(i);
}
List<VersionsListInfo> vil = getVersions(Inceptum.CONFIG.snapshots);
if (ImGui.combo("Version", version, vil.stream().map(info -> info.id).toArray(String[]::new))) {
VersionsListInfo prev = selected;
selected = vil.get(version.get());
if (getDefaultName(prev, fabric.get()).equals(name.get()))
name.set(getDefaultName(selected, fabric.get())); //TODO "<ver> (1)" etc if exists
}
if (ImGui.checkbox("Fabric support", fabric)) {
if (getDefaultName(selected, !fabric.get()).equals(name.get()))
name.set(getDefaultName(selected, fabric.get()));
}
//TODO forge
//TODO implement fabric support
ImGui.inputTextWithHint("Name", "Select a name", name);
if (!Utils.VALID_FILENAME.matcher(name.get()).matches())
ImGui.text("Invalid name");
else if (Files.exists(Inceptum.INSTANCE_DIR.resolve(name.get())))
ImGui.text("Already exists");
else if (ImGui.button("OK"))
state = State.Installing;
}
case Installing -> {
if (Files.exists(Inceptum.INSTANCE_DIR.resolve(name.get()))) {
ImGui.text("Already exists");
}
ImGui.text("Installing..."); //TODO update UI during process
try {
SetupStepInfo stepInfo = new SetupStepInfo(McApi.getVersionInfo(selected), fabric.get() ? LoaderType.Fabric : LoaderType.None, name.get());
for (Step step : Steps.STEPS) {
step.execute(stepInfo);
}
Inceptum.open(new AlertWindow("Successfully installed!"));
close();
} catch (Throwable e) {
Inceptum.LOGGER.error("Could not initialize instance", e);
Inceptum.open(new AlertWindow("Could not initialize instance, look at the log for details"));
close();
try {
Utils.deleteRecursive(Inceptum.INSTANCE_DIR.resolve(name.get()));
} catch (IOException ex) {
Inceptum.LOGGER.error("Could not delete instance dir", e);
}
}
if (ImGui.checkbox("Show snapshots", snapshots)) {
boolean prev = Inceptum.CONFIG.snapshots;
Inceptum.CONFIG.snapshots = snapshots.get();
Inceptum.saveConfig();
//fix version index
int i = getVersions(Inceptum.CONFIG.snapshots).indexOf(getVersions(prev).get(version.get()));
if (i == -1) version.set(0);
else version.set(i);
}
List<VersionsListInfo> vil = getVersions(Inceptum.CONFIG.snapshots);
if (ImGui.combo("Version", version, vil.stream().map(info -> info.id).toArray(String[]::new))) {
VersionsListInfo prev = selected;
selected = vil.get(version.get());
if (getDefaultName(prev, fabric.get()).equals(name.get()))
name.set(getDefaultName(selected, fabric.get())); //TODO "<ver> (1)" etc if exists
}
if (ImGui.checkbox("Fabric support", fabric)) {
if (getDefaultName(selected, !fabric.get()).equals(name.get()))
name.set(getDefaultName(selected, fabric.get()));
}
//TODO forge
//TODO implement fabric support
ImGui.inputTextWithHint("Name", "Select a name", name);
if (!Utils.VALID_FILENAME.matcher(name.get()).matches())
ImGui.text("Invalid name");
else if (Files.exists(Inceptum.INSTANCE_DIR.resolve(name.get())))
ImGui.text("Already exists");
else if (ImGui.button("OK")) {
close();
try {
Inceptum.open(new InstanceCreateProcessWindow(new SetupStepInfo(McApi.getVersionInfo(selected), fabric.get() ? LoaderType.Fabric : LoaderType.None, name.get())));
} catch (IOException e) {
Inceptum.LOGGER.error("Could not initialize instance creation", e);
}
}
}
@ -104,11 +80,6 @@ public class NewInstanceWindow extends Window {
return fabric ? "Fabric " + info.id : info.id;
}
enum State {
Configure,
Installing
}
public enum LoaderType {
None,
Fabric