Basic instance editing, 1.8.9 support
This commit is contained in:
parent
ea2b2e5452
commit
2adf5cac1b
|
@ -59,6 +59,7 @@ public class Inceptum {
|
|||
public static final Path INSTANCE_DIR = Path.of("run/instances");
|
||||
public static final Path ASSETS_DIR = Path.of("run/assets");
|
||||
public static final Path LIBRARIES_DIR = Path.of("run/libraries");
|
||||
public static final Path NATIVES_DIR = Path.of("run/natives");
|
||||
private static final Path CONFIG_PATH = Path.of("run/glaunch2.json");
|
||||
public static final Path ACCOUNTS_PATH = Path.of("run/accounts.json");
|
||||
public static InceptumVersion VERSION;
|
||||
|
@ -123,7 +124,8 @@ public class Inceptum {
|
|||
protected static void dispose() {
|
||||
imGuiGl3.dispose();
|
||||
imGuiGlfw.dispose();
|
||||
ImGui.destroyContext();
|
||||
//TODO figure out why this is a problem
|
||||
//ImGui.destroyContext();
|
||||
Callbacks.glfwFreeCallbacks(handle);
|
||||
GLFW.glfwDestroyWindow(handle);
|
||||
GLFW.glfwTerminate();
|
||||
|
|
|
@ -3,6 +3,7 @@ package io.gitlab.jfronny.inceptum.install.steps;
|
|||
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.model.inceptum.InstanceMeta;
|
||||
import io.gitlab.jfronny.inceptum.model.mojang.VersionInfo;
|
||||
import io.gitlab.jfronny.inceptum.util.Utils;
|
||||
|
||||
|
@ -16,7 +17,7 @@ public class DownloadClientStep implements Step {
|
|||
public void execute(SetupStepInfo info, AtomicBoolean stopThread) throws IOException {
|
||||
Path path = Inceptum.LIBRARIES_DIR.resolve("net/minecraft/minecraft");
|
||||
if (!Files.exists(path)) Files.createDirectories(path);
|
||||
path = path.resolve(info.version().id + ".jar");
|
||||
path = path.resolve(InstanceMeta.getMinecraftVersion(info.version().id) + ".jar");
|
||||
if (Files.exists(path)) return;
|
||||
VersionInfo.Downloads.Download client = info.version().downloads.client;
|
||||
Inceptum.LOGGER.info("Downloading client");
|
||||
|
|
|
@ -3,30 +3,47 @@ package io.gitlab.jfronny.inceptum.install.steps;
|
|||
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.model.mojang.VersionInfo;
|
||||
import io.gitlab.jfronny.inceptum.model.inceptum.ArtifactInfo;
|
||||
import io.gitlab.jfronny.inceptum.model.inceptum.InstanceMeta;
|
||||
import io.gitlab.jfronny.inceptum.util.Utils;
|
||||
import io.gitlab.jfronny.inceptum.util.VersionInfoLibraryResolver;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class DownloadLibrariesStep implements Step {
|
||||
@Override
|
||||
public void execute(SetupStepInfo info, AtomicBoolean stopThread) throws IOException {
|
||||
for (VersionInfo.Library.Downloads.Artifact artifact : VersionInfoLibraryResolver.getRelevant(info.version())) {
|
||||
for (ArtifactInfo artifact : VersionInfoLibraryResolver.getRelevant(info.version())) {
|
||||
if (stopThread.get()) return;
|
||||
Path path = Inceptum.LIBRARIES_DIR.resolve(artifact.path);
|
||||
if (Files.exists(path)) continue;
|
||||
//TODO allow maven-like download for fabric
|
||||
Inceptum.LOGGER.info("Downloading library: " + artifact.path);
|
||||
if (!Files.exists(path.getParent())) Files.createDirectories(path.getParent());
|
||||
if (!artifact.url.endsWith(".jar")) {
|
||||
Inceptum.LOGGER.info("Not a valid URL for a jar: " + artifact.url);
|
||||
continue;
|
||||
if (!Files.exists(path)) {
|
||||
Inceptum.LOGGER.info("Downloading library: " + artifact.path);
|
||||
if (!Files.exists(path.getParent())) Files.createDirectories(path.getParent());
|
||||
if (!artifact.url.endsWith(".jar")) {
|
||||
Inceptum.LOGGER.info("Not a valid URL for a jar: " + artifact.url);
|
||||
continue;
|
||||
}
|
||||
Utils.downloadFile(artifact.url, artifact.sha1, path);
|
||||
}
|
||||
if (artifact.isNative) {
|
||||
Inceptum.LOGGER.info("Extracting natives");
|
||||
try (FileSystem libFs = FileSystems.newFileSystem(new URI("jar", path.toUri().toString(), null), new HashMap<>())) {
|
||||
for (Path path1 : Files.list(libFs.getPath(".")).toList()) {
|
||||
Utils.copyRecursive(path1, Inceptum.NATIVES_DIR.resolve(InstanceMeta.getMinecraftVersion(info.version().id)));
|
||||
}
|
||||
}
|
||||
catch (Throwable t) {
|
||||
Files.delete(path);
|
||||
throw new IOException("Could not extract native", t);
|
||||
}
|
||||
}
|
||||
Utils.downloadFile(artifact.url, artifact.sha1, path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package io.gitlab.jfronny.inceptum.install.steps;
|
|||
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.model.inceptum.InstanceMeta;
|
||||
import io.gitlab.jfronny.inceptum.model.inceptum.LoaderInfo;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -24,5 +25,6 @@ public class SetupDirsStep implements Step {
|
|||
Files.createDirectories(iDir.resolve("saves"));
|
||||
Files.createDirectories(iDir.resolve("screenshots"));
|
||||
}
|
||||
Files.createDirectories(Inceptum.NATIVES_DIR.resolve(InstanceMeta.getMinecraftVersion(info.version().id)));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,10 +15,11 @@ public class WriteMetadataStep implements Step {
|
|||
@Override
|
||||
public void execute(SetupStepInfo info, AtomicBoolean stopThread) throws IOException {
|
||||
Inceptum.LOGGER.info("Writing metadata");
|
||||
Path metaDir = Inceptum.INSTANCE_DIR.resolve(info.name()).resolve("inceptum.lock");
|
||||
Path metaDir = Inceptum.INSTANCE_DIR.resolve(info.name()).resolve("instance.json");
|
||||
InstanceMeta meta = new InstanceMeta();
|
||||
meta.version = info.version().id;
|
||||
Utils.writeObject(metaDir, meta);
|
||||
Files.delete(Inceptum.INSTANCE_DIR.resolve(info.name()).resolve("SETUP"));
|
||||
Path lock = Inceptum.INSTANCE_DIR.resolve(info.name()).resolve("inceptum.setup.lock");
|
||||
if (Files.exists(lock)) Files.delete(lock);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
package io.gitlab.jfronny.inceptum.model.inceptum;
|
||||
|
||||
import io.gitlab.jfronny.inceptum.model.mojang.VersionInfo;
|
||||
|
||||
public class ArtifactInfo {
|
||||
public final String path;
|
||||
public final String sha1;
|
||||
public final int size;
|
||||
public final String url;
|
||||
public final boolean isNative;
|
||||
|
||||
public ArtifactInfo(VersionInfo.Library.Downloads.Artifact artifact, boolean isNative) {
|
||||
path = artifact.path;
|
||||
sha1 = artifact.sha1;
|
||||
size = artifact.size;
|
||||
url = artifact.url;
|
||||
this.isNative = isNative;
|
||||
}
|
||||
}
|
|
@ -1,18 +1,42 @@
|
|||
package io.gitlab.jfronny.inceptum.model.inceptum;
|
||||
|
||||
import io.gitlab.jfronny.inceptum.gson.GsonIgnore;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class InstanceMeta {
|
||||
private static final String floaderPrefix = "fabric-loader-";
|
||||
@GsonIgnore public static final String floaderPrefix = "fabric-loader-";
|
||||
public String version;
|
||||
public String java; //TODO allow configuring
|
||||
public Long minMem;
|
||||
public Long maxMem;
|
||||
|
||||
public boolean isFabric() {
|
||||
return version.startsWith(floaderPrefix);
|
||||
}
|
||||
|
||||
public String getMinecraftVersion() {
|
||||
return isFabric() ? version.substring(version.lastIndexOf('-') + 1) : version;
|
||||
return getMinecraftVersion(version);
|
||||
}
|
||||
|
||||
public static String getMinecraftVersion(String id) {
|
||||
return id.startsWith(floaderPrefix) ? id.substring(id.lastIndexOf('-') + 1) : id;
|
||||
}
|
||||
|
||||
public String getLoaderVersion() {
|
||||
return isFabric() ? version.substring(floaderPrefix.length()).split("-")[0] : "";
|
||||
}
|
||||
|
||||
public String getJava() {
|
||||
if (java == null) {
|
||||
//TODO allow manually selecting a default JVM, MultiMC autodetect
|
||||
Path f = Path.of(System.getProperty("java.home")).resolve("bin");
|
||||
Path t = f.resolve("java");
|
||||
if (!Files.exists(t)) t = f.resolve("javaw");
|
||||
if (!Files.exists(t)) t = f.resolve("java.exe");
|
||||
if (!Files.exists(t)) t = f.resolve("javaw.exe");
|
||||
return t.toAbsolutePath().toString();
|
||||
} else return java;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ public class VersionInfo extends VersionsListInfo {
|
|||
public JavaVersion javaVersion;
|
||||
public List<Library> libraries;
|
||||
public String mainClass;
|
||||
public String minecraftArguments;
|
||||
public Integer minimumLauncherVersion;
|
||||
|
||||
public static class Arguments {
|
||||
|
|
|
@ -11,6 +11,7 @@ import java.nio.file.*;
|
|||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Formatter;
|
||||
import java.util.Locale;
|
||||
import java.util.function.Function;
|
||||
|
@ -129,6 +130,41 @@ public class Utils {
|
|||
});
|
||||
}
|
||||
|
||||
public static void copyRecursive(Path source, Path destination) throws IOException {
|
||||
copyRecursive(source, destination, StandardCopyOption.COPY_ATTRIBUTES);
|
||||
}
|
||||
|
||||
public static void copyRecursive(Path source, Path destination, CopyOption... copyOptions) throws IOException {
|
||||
if (!Files.exists(destination)) Files.createDirectories(destination);
|
||||
if(Files.isDirectory(source)) {
|
||||
/*Files.walk(source)
|
||||
.forEach(sourcePath -> {
|
||||
try {
|
||||
Path destinationPath = destination.resolve(source.getFileName().toString());
|
||||
Path targetPath = destinationPath.resolve(source.relativize(sourcePath).toString());
|
||||
Files.copy(sourcePath, targetPath, copyOptions);
|
||||
} catch (IOException e) {
|
||||
Inceptum.LOGGER.error("Could not recursively copy", e);
|
||||
}
|
||||
});*/
|
||||
Files.list(source).forEach(sourcePath -> {
|
||||
try {
|
||||
copyRecursive(sourcePath, destination.resolve(sourcePath.getFileName().toString()), copyOptions);
|
||||
} catch (IOException e) {
|
||||
Inceptum.LOGGER.error("Could not recursively copy", e);
|
||||
}
|
||||
});
|
||||
} else if(Files.exists(source)) {
|
||||
Path target = destination.resolve(source.getFileName().toString());
|
||||
if (!Files.exists(target)
|
||||
|| Arrays.asList(copyOptions).contains(StandardCopyOption.REPLACE_EXISTING))
|
||||
Files.copy(source, target, copyOptions);
|
||||
} else {
|
||||
throw new FileNotFoundException(source.toAbsolutePath().toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void openWebBrowser(URI uri) {
|
||||
try {
|
||||
if (OS.equals("linux") && Utils.executableInPath("xdg-open")) {
|
||||
|
|
|
@ -1,24 +1,25 @@
|
|||
package io.gitlab.jfronny.inceptum.util;
|
||||
|
||||
import io.gitlab.jfronny.inceptum.Inceptum;
|
||||
import io.gitlab.jfronny.inceptum.model.inceptum.ArtifactInfo;
|
||||
import io.gitlab.jfronny.inceptum.model.mojang.VersionInfo;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class VersionInfoLibraryResolver {
|
||||
public static Set<VersionInfo.Library.Downloads.Artifact> getRelevant(VersionInfo version) {
|
||||
Set<VersionInfo.Library.Downloads.Artifact> artifacts = new LinkedHashSet<>();
|
||||
public static Set<ArtifactInfo> getRelevant(VersionInfo version) {
|
||||
Set<ArtifactInfo> artifacts = new LinkedHashSet<>();
|
||||
for (VersionInfo.Library library : version.libraries) {
|
||||
if (library.rules != null && !library.rules.allow()) continue;
|
||||
if (library.downloads.classifiers != null && library.natives != null && library.natives.containsKey(Utils.OS)) {
|
||||
artifacts.add(library.downloads.classifiers.get(library.natives.get(Utils.OS)));
|
||||
artifacts.add(new ArtifactInfo(library.downloads.classifiers.get(library.natives.get(Utils.OS)), true));
|
||||
}
|
||||
if (library.downloads.artifact == null) {
|
||||
Inceptum.LOGGER.info("Null library artifact @ " + library.name);
|
||||
continue;
|
||||
}
|
||||
artifacts.add(library.downloads.artifact);
|
||||
artifacts.add(new ArtifactInfo(library.downloads.artifact, false));
|
||||
}
|
||||
return artifacts;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package io.gitlab.jfronny.inceptum.util.api;
|
|||
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import io.gitlab.jfronny.inceptum.model.fabric.FabricVersionLoaderInfo;
|
||||
import io.gitlab.jfronny.inceptum.model.inceptum.InstanceMeta;
|
||||
import io.gitlab.jfronny.inceptum.model.mojang.Rules;
|
||||
import io.gitlab.jfronny.inceptum.model.mojang.VersionInfo;
|
||||
import io.gitlab.jfronny.inceptum.model.mojang.VersionsListInfo;
|
||||
|
@ -45,7 +46,7 @@ public class FabricMetaApi {
|
|||
floader.url = "https://maven.fabricmc.net/";
|
||||
libs.add(convertLib(floader));
|
||||
version.libraries = List.copyOf(libs);
|
||||
version.id = "fabric-loader-" + fabricVersion + "-" + version.id;
|
||||
version.id = InstanceMeta.floaderPrefix + fabricVersion + "-" + version.id;
|
||||
}
|
||||
|
||||
private static VersionInfo.Library convertLib(FabricVersionLoaderInfo.WithMeta.LauncherMeta.Libraries.Library library) {
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
package io.gitlab.jfronny.inceptum.windows;
|
||||
|
||||
import imgui.ImGui;
|
||||
import imgui.type.ImString;
|
||||
import io.gitlab.jfronny.inceptum.Inceptum;
|
||||
import io.gitlab.jfronny.inceptum.model.inceptum.InstanceMeta;
|
||||
import io.gitlab.jfronny.inceptum.util.Utils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
//TODO allow changing name (moving), changing version, managing mods etc
|
||||
public class InstanceEditWindow extends Window {
|
||||
private final Path path;
|
||||
private final InstanceMeta instance;
|
||||
private final ImString name;
|
||||
|
||||
public InstanceEditWindow(Path path, InstanceMeta instance) {
|
||||
super("Edit " + path.getFileName().toString());
|
||||
this.path = path;
|
||||
this.instance = instance;
|
||||
name = new ImString(path.getFileName().toString(), NewInstanceWindow.MAX_NAME_LENGTH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw() {
|
||||
if (ImGui.beginTabBar("InstanceEdit" + path)) {
|
||||
if (ImGui.beginTabItem("General")) {
|
||||
ImGui.inputTextWithHint("Name", "Name of this instance", name);
|
||||
if (!Utils.VALID_FILENAME.matcher(name.get()).matches())
|
||||
ImGui.text("Invalid name");
|
||||
else if (!Files.exists(Inceptum.INSTANCE_DIR.resolve(name.get())) && ImGui.button("Rename")) {
|
||||
try {
|
||||
Path newPath = Inceptum.INSTANCE_DIR.resolve(name.get());
|
||||
Files.move(path, newPath);
|
||||
close();
|
||||
Inceptum.open(new InstanceEditWindow(newPath, instance));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (ImGui.button("Delete")) Inceptum.open(new AlertWindow("Are you sure?", "This instance will be removed forever (a long time)", () -> {
|
||||
close();
|
||||
try {
|
||||
Utils.deleteRecursive(path);
|
||||
} catch (IOException e) {
|
||||
Inceptum.LOGGER.error("Could not delete the instance", e);
|
||||
Inceptum.open(new AlertWindow("Could not delete", e.toString()));
|
||||
}
|
||||
}, () -> {}));
|
||||
ImGui.endTabItem();
|
||||
}
|
||||
if (instance.isFabric() && ImGui.beginTabItem("Mods")) {
|
||||
ImGui.text("Mod editing is not currently implemented");
|
||||
ImGui.text("Please be patient");
|
||||
ImGui.endTabItem();
|
||||
}
|
||||
ImGui.endTabBar();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,30 +1,31 @@
|
|||
package io.gitlab.jfronny.inceptum.windows;
|
||||
|
||||
import imgui.ImGui;
|
||||
import imgui.flag.ImGuiTableFlags;
|
||||
import imgui.flag.ImGuiWindowFlags;
|
||||
import imgui.type.ImBoolean;
|
||||
import imgui.type.ImInt;
|
||||
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.inceptum.InstanceMeta;
|
||||
import io.gitlab.jfronny.inceptum.model.mojang.MinecraftArgument;
|
||||
import io.gitlab.jfronny.inceptum.model.inceptum.LoaderInfo;
|
||||
import io.gitlab.jfronny.inceptum.model.mojang.VersionInfo;
|
||||
import io.gitlab.jfronny.inceptum.model.mojang.VersionsListInfo;
|
||||
import io.gitlab.jfronny.inceptum.util.MapAppender;
|
||||
import io.gitlab.jfronny.inceptum.util.ProcessUtils;
|
||||
import io.gitlab.jfronny.inceptum.util.Utils;
|
||||
import io.gitlab.jfronny.inceptum.util.VersionInfoLibraryResolver;
|
||||
import io.gitlab.jfronny.inceptum.util.api.FabricMetaApi;
|
||||
import io.gitlab.jfronny.inceptum.util.api.McApi;
|
||||
import io.gitlab.jfronny.inceptum.util.api.account.AccountManager;
|
||||
import io.gitlab.jfronny.inceptum.util.api.account.AuthInfo;
|
||||
import io.gitlab.jfronny.inceptum.util.api.account.MicrosoftAccount;
|
||||
import io.gitlab.jfronny.inceptum.windows.control.InstanceView;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class MainWindow extends Window {
|
||||
private final ImBoolean darkTheme = new ImBoolean(Inceptum.CONFIG.darkTheme);
|
||||
|
@ -44,6 +45,36 @@ public class MainWindow extends Window {
|
|||
ImGui.beginMenuBar();
|
||||
if (ImGui.beginMenu("File")) {
|
||||
if (ImGui.menuItem("New Instance")) Inceptum.open(new NewInstanceWindow());
|
||||
if (ImGui.menuItem("Re-download resources")) {
|
||||
try {
|
||||
Files.list(Inceptum.INSTANCE_DIR).forEach(p -> {
|
||||
try {
|
||||
if (Files.exists(p.resolve("inceptum.setup.lock"))) return;
|
||||
if (Files.exists(p.resolve("inceptum.lock"))) return;
|
||||
InstanceMeta im = Utils.loadObject(p.resolve("instance.json"), InstanceMeta.class);
|
||||
for (VersionsListInfo version : McApi.getVersions().versions) {
|
||||
if (version.id.equals(im.getMinecraftVersion())) {
|
||||
VersionInfo vi = McApi.getVersionInfo(version);
|
||||
if (im.isFabric()) FabricMetaApi.addFabric(vi, im.getLoaderVersion());
|
||||
LoaderInfo li = im.isFabric()
|
||||
? new LoaderInfo(LoaderInfo.Type.Fabric, im.getLoaderVersion())
|
||||
: LoaderInfo.NONE;
|
||||
SetupStepInfo info = new SetupStepInfo(vi, li, p.getFileName().toString());
|
||||
for (Step step : Steps.STEPS) {
|
||||
step.execute(info, new AtomicBoolean(false));
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Inceptum.LOGGER.error("Could not execute refresh task", e);
|
||||
Inceptum.open(new AlertWindow("Something went wrong", e.toString()));
|
||||
}
|
||||
});
|
||||
} catch (IOException e) {
|
||||
Inceptum.LOGGER.error("Could not execute refresh task", e);
|
||||
Inceptum.open(new AlertWindow("Something went wrong", e.toString()));
|
||||
}
|
||||
}
|
||||
if (ImGui.menuItem("Exit Inceptum")) Inceptum.exit();
|
||||
ImGui.endMenu();
|
||||
}
|
||||
|
@ -93,109 +124,6 @@ public class MainWindow extends Window {
|
|||
ImGui.text("You have not yet created an instance");
|
||||
ImGui.text("Use File->New Instance to do so");
|
||||
}
|
||||
else if (ImGui.beginTable("Instances", 2, ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.Borders)) {
|
||||
for (Path path : paths) {
|
||||
if (Files.exists(path.resolve("inceptum.setup.lock"))) {
|
||||
ImGui.tableNextColumn();
|
||||
ImGui.text("Setting up");
|
||||
ImGui.tableNextColumn();
|
||||
ImGui.text("This instance is currently being set up");
|
||||
continue;
|
||||
}
|
||||
if (!Files.exists(path.resolve("instance.json"))) {
|
||||
Inceptum.LOGGER.error("Invalid instance (doesn't contain instance.json): " + path);
|
||||
continue;
|
||||
}
|
||||
InstanceMeta instance;
|
||||
try {
|
||||
instance = Utils.loadObject(path.resolve("instance.json"), InstanceMeta.class);
|
||||
} catch (IOException e) {
|
||||
Inceptum.LOGGER.error("Could not load instance.json", e);
|
||||
continue;
|
||||
}
|
||||
ImGui.tableNextColumn();
|
||||
boolean disabled = false;
|
||||
if (Files.exists(path.resolve("inceptum.lock"))) {
|
||||
try {
|
||||
if (ProcessUtils.isProcessAlive(Files.readString(path.resolve("inceptum.lock"))))
|
||||
disabled = true;
|
||||
else Files.delete(path.resolve("inceptum.lock"));
|
||||
}
|
||||
catch (IOException e) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (disabled) ImGui.beginDisabled();
|
||||
if (ImGui.button(path.getFileName().toString())) {
|
||||
//TODO extract launch logic to separate class
|
||||
for (VersionsListInfo version : McApi.getVersions().versions) {
|
||||
if (version.id.equals(instance.getMinecraftVersion())) {
|
||||
try {
|
||||
List<String> args = new ArrayList<>();
|
||||
args.add("/lib/jvm/java-17-openjdk/bin/java"); //TODO allow selecting vm, detect with System.getProperty("java.home")
|
||||
VersionInfo info = McApi.getVersionInfo(version);
|
||||
if (instance.isFabric()) {
|
||||
FabricMetaApi.addFabric(info, instance.getLoaderVersion());
|
||||
}
|
||||
StringBuilder classPath = new StringBuilder();
|
||||
for (VersionInfo.Library.Downloads.Artifact artifact : VersionInfoLibraryResolver.getRelevant(info)) {
|
||||
classPath.append(Inceptum.LIBRARIES_DIR.resolve(artifact.path).toAbsolutePath());
|
||||
classPath.append(':');
|
||||
}
|
||||
classPath.append(Inceptum.LIBRARIES_DIR.resolve("net/minecraft/minecraft").resolve(version.id + ".jar").toAbsolutePath());
|
||||
//TODO -Xms{lowMem} -Xmx{maxMem}
|
||||
args.addAll(parse(info.arguments.jvm, info, instance, classPath.toString(), path.toAbsolutePath().toString()));
|
||||
args.add(info.mainClass);
|
||||
args.addAll(parse(info.arguments.game, info, instance, classPath.toString(), path.toAbsolutePath().toString()));
|
||||
Inceptum.LOGGER.info(String.join(" ", args));
|
||||
ProcessBuilder pb = new ProcessBuilder(args.toArray(new String[0]));
|
||||
pb.directory(path.toFile());
|
||||
pb.redirectOutput(ProcessBuilder.Redirect.INHERIT);
|
||||
pb.redirectError(ProcessBuilder.Redirect.INHERIT);
|
||||
Files.writeString(path.resolve("inceptum.lock"), Long.toString(pb.start().pid()));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui.tableNextColumn();
|
||||
if (ImGui.button("Edit")) {
|
||||
Inceptum.LOGGER.error("Editing not yet implemented"); //TODO allow changing name (moving), changing version, managing mods etc
|
||||
}
|
||||
if (disabled) ImGui.endDisabled();
|
||||
}
|
||||
ImGui.endTable();
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> parse(List<MinecraftArgument> arguments, VersionInfo info, InstanceMeta instance, String classPath, String gameDirectory) {
|
||||
List<String> res = new ArrayList<>();
|
||||
for (MinecraftArgument argument : arguments) {
|
||||
for (String s : argument.arg()) {
|
||||
//TODO support old versions
|
||||
AuthInfo authInfo = AccountManager.getSelectedAccount();
|
||||
res.add(s
|
||||
// game args
|
||||
.replace("${auth_player_name}", authInfo.name())
|
||||
.replace("${version_name}", instance.getMinecraftVersion())
|
||||
.replace("${game_directory}", gameDirectory)
|
||||
.replace("${assets_root}", Inceptum.ASSETS_DIR.toAbsolutePath().toString())
|
||||
.replace("${assets_index_name}", info.assets)
|
||||
.replace("${auth_uuid}", authInfo.uuid())
|
||||
.replace("${auth_access_token}", authInfo.accessToken())
|
||||
.replace("${user_type}", authInfo.userType())
|
||||
.replace("${version_type}", info.type)
|
||||
.replace("${resolution_width}", "1920") //TODO has_custom_resolution
|
||||
.replace("${resolution_height}", "1080") //TODO has_custom_resolution
|
||||
// jvm args
|
||||
.replace("${natives_directory}", Inceptum.INSTANCE_DIR.toAbsolutePath().toString())
|
||||
.replace("${launcher_name}", "Inceptum")
|
||||
.replace("${launcher_version}", Inceptum.VERSION.version) //TODO automatically fill in
|
||||
.replace("${classpath}", classPath)
|
||||
);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
else InstanceView.draw(paths);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,12 +23,13 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
|
||||
public class NewInstanceWindow extends Window {
|
||||
public static final int MAX_NAME_LENGTH = 128;
|
||||
VersionsList manifest = McApi.getVersions();
|
||||
VersionsListInfo selected;
|
||||
Map<VersionsListInfo, List<FabricVersionLoaderInfo>> loaderInfoCache = new HashMap<>();
|
||||
FabricVersionLoaderInfo selectedFabric;
|
||||
ImInt version = new ImInt(0);
|
||||
ImString name = new ImString("", 128);
|
||||
ImString name = new ImString("", MAX_NAME_LENGTH);
|
||||
ImInt fabricVersion = new ImInt(0);
|
||||
ImBoolean snapshots = new ImBoolean(Inceptum.CONFIG.snapshots);
|
||||
ImBoolean fabric = new ImBoolean(true);
|
||||
|
@ -67,15 +68,21 @@ public class NewInstanceWindow extends Window {
|
|||
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()));
|
||||
}
|
||||
if (fabric.get()) {
|
||||
ImGui.sameLine();
|
||||
List<FabricVersionLoaderInfo> versions = getFabricLoaderInfo();
|
||||
if (ImGui.combo("Loader", fabricVersion, versions.stream().map(info -> info.loader.version).toArray(String[]::new))) {
|
||||
selectedFabric = versions.get(fabricVersion.get());
|
||||
if (getFabricLoaderInfo().isEmpty()) {
|
||||
if (fabric.get() && getDefaultName(selected, true).equals(name.get()))
|
||||
name.set(getDefaultName(selected, false));
|
||||
fabric.set(false);
|
||||
} else {
|
||||
if (ImGui.checkbox("Fabric support", fabric)) {
|
||||
if (getDefaultName(selected, !fabric.get()).equals(name.get()))
|
||||
name.set(getDefaultName(selected, fabric.get()));
|
||||
}
|
||||
if (fabric.get()) {
|
||||
ImGui.sameLine();
|
||||
List<FabricVersionLoaderInfo> versions = getFabricLoaderInfo();
|
||||
if (ImGui.combo("Loader", fabricVersion, versions.stream().map(info -> info.loader.version).toArray(String[]::new))) {
|
||||
selectedFabric = versions.get(fabricVersion.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
//TODO forge
|
||||
|
|
|
@ -0,0 +1,147 @@
|
|||
package io.gitlab.jfronny.inceptum.windows.control;
|
||||
|
||||
import imgui.ImGui;
|
||||
import imgui.flag.ImGuiTableFlags;
|
||||
import io.gitlab.jfronny.inceptum.Inceptum;
|
||||
import io.gitlab.jfronny.inceptum.model.inceptum.ArtifactInfo;
|
||||
import io.gitlab.jfronny.inceptum.model.inceptum.InstanceMeta;
|
||||
import io.gitlab.jfronny.inceptum.model.mojang.MinecraftArgument;
|
||||
import io.gitlab.jfronny.inceptum.model.mojang.VersionInfo;
|
||||
import io.gitlab.jfronny.inceptum.model.mojang.VersionsListInfo;
|
||||
import io.gitlab.jfronny.inceptum.util.ProcessUtils;
|
||||
import io.gitlab.jfronny.inceptum.util.Utils;
|
||||
import io.gitlab.jfronny.inceptum.util.VersionInfoLibraryResolver;
|
||||
import io.gitlab.jfronny.inceptum.util.api.FabricMetaApi;
|
||||
import io.gitlab.jfronny.inceptum.util.api.McApi;
|
||||
import io.gitlab.jfronny.inceptum.util.api.account.AccountManager;
|
||||
import io.gitlab.jfronny.inceptum.util.api.account.AuthInfo;
|
||||
import io.gitlab.jfronny.inceptum.windows.InstanceEditWindow;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class InstanceView {
|
||||
public static void draw(List<Path> paths) {
|
||||
if (ImGui.beginTable("Instances", 2, ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.Borders)) {
|
||||
for (Path path : paths) {
|
||||
if (Files.exists(path.resolve("inceptum.setup.lock"))) {
|
||||
ImGui.tableNextColumn();
|
||||
ImGui.text("Setting up");
|
||||
ImGui.tableNextColumn();
|
||||
ImGui.text("This instance is currently being set up");
|
||||
continue;
|
||||
}
|
||||
if (!Files.exists(path.resolve("instance.json"))) {
|
||||
Inceptum.LOGGER.error("Invalid instance (doesn't contain instance.json): " + path);
|
||||
continue;
|
||||
}
|
||||
InstanceMeta instance;
|
||||
try {
|
||||
instance = Utils.loadObject(path.resolve("instance.json"), InstanceMeta.class);
|
||||
} catch (IOException e) {
|
||||
Inceptum.LOGGER.error("Could not load instance.json", e);
|
||||
continue;
|
||||
}
|
||||
ImGui.tableNextColumn();
|
||||
boolean disabled = false;
|
||||
if (Files.exists(path.resolve("inceptum.lock"))) {
|
||||
try {
|
||||
if (ProcessUtils.isProcessAlive(Files.readString(path.resolve("inceptum.lock"))))
|
||||
disabled = true;
|
||||
else Files.delete(path.resolve("inceptum.lock"));
|
||||
} catch (IOException e) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (disabled) ImGui.beginDisabled();
|
||||
if (ImGui.button(path.getFileName().toString())) launch(path, instance);
|
||||
ImGui.tableNextColumn();
|
||||
if (ImGui.button("Edit")) Inceptum.open(new InstanceEditWindow(path, instance));
|
||||
if (disabled) ImGui.endDisabled();
|
||||
}
|
||||
ImGui.endTable();
|
||||
}
|
||||
}
|
||||
|
||||
private static void launch(Path path, InstanceMeta instance) {
|
||||
for (VersionsListInfo version : McApi.getVersions().versions) {
|
||||
if (version.id.equals(instance.getMinecraftVersion())) {
|
||||
try {
|
||||
List<String> args = new ArrayList<>();
|
||||
args.add(instance.getJava());
|
||||
//args.add("/lib/jvm/java-17-openjdk/bin/java");
|
||||
VersionInfo info = McApi.getVersionInfo(version);
|
||||
if (instance.isFabric()) {
|
||||
FabricMetaApi.addFabric(info, instance.getLoaderVersion());
|
||||
}
|
||||
StringBuilder classPath = new StringBuilder();
|
||||
for (ArtifactInfo artifact : VersionInfoLibraryResolver.getRelevant(info)) {
|
||||
classPath.append(Inceptum.LIBRARIES_DIR.resolve(artifact.path).toAbsolutePath());
|
||||
classPath.append(':');
|
||||
}
|
||||
classPath.append(Inceptum.LIBRARIES_DIR.resolve("net/minecraft/minecraft").resolve(version.id + ".jar").toAbsolutePath());
|
||||
//TODO custom JVM args
|
||||
if (info.arguments != null) args.addAll(parse(info.arguments.jvm, info, instance, classPath.toString(), path.toAbsolutePath().toString()));
|
||||
if (instance.minMem != null) args.add("-Xms" + instance.minMem);
|
||||
if (instance.maxMem != null) args.add("-Xmx" + instance.maxMem);
|
||||
if (info.minecraftArguments != null) {
|
||||
args.add("-cp");
|
||||
args.add(classPath.toString());
|
||||
args.add("-Djava.library.path=" + Inceptum.NATIVES_DIR.resolve(instance.getMinecraftVersion()).toAbsolutePath());
|
||||
}
|
||||
args.add(info.mainClass);
|
||||
if (info.arguments != null) args.addAll(parse(info.arguments.game, info, instance, classPath.toString(), path.toAbsolutePath().toString()));
|
||||
else {
|
||||
for (String s : info.minecraftArguments.split(" ")) {
|
||||
args.add(expandArg(s, info, instance, classPath.toString(), path.toAbsolutePath().toString()));
|
||||
}
|
||||
}
|
||||
Inceptum.LOGGER.info(String.join(" ", args));
|
||||
ProcessBuilder pb = new ProcessBuilder(args.toArray(new String[0]));
|
||||
pb.directory(path.toFile());
|
||||
pb.redirectOutput(ProcessBuilder.Redirect.INHERIT);
|
||||
pb.redirectError(ProcessBuilder.Redirect.INHERIT);
|
||||
Files.writeString(path.resolve("inceptum.lock"), Long.toString(pb.start().pid()));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static List<String> parse(List<MinecraftArgument> arguments, VersionInfo info, InstanceMeta instance, String classPath, String gameDirectory) {
|
||||
List<String> res = new ArrayList<>();
|
||||
for (MinecraftArgument argument : arguments) {
|
||||
for (String s : argument.arg()) {
|
||||
res.add(expandArg(s, info, instance, classPath, gameDirectory));
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
private static String expandArg(String arg, VersionInfo info, InstanceMeta instance, String classPath, String gameDirectory) {
|
||||
AuthInfo authInfo = AccountManager.getSelectedAccount();
|
||||
return arg
|
||||
// game args
|
||||
.replace("${auth_player_name}", authInfo.name())
|
||||
.replace("${version_name}", instance.getMinecraftVersion())
|
||||
.replace("${game_directory}", gameDirectory)
|
||||
.replace("${assets_root}", Inceptum.ASSETS_DIR.toAbsolutePath().toString())
|
||||
.replace("${assets_index_name}", info.assets)
|
||||
.replace("${auth_uuid}", authInfo.uuid())
|
||||
.replace("${auth_access_token}", authInfo.accessToken())
|
||||
.replace("${user_type}", authInfo.userType())
|
||||
.replace("${version_type}", info.type)
|
||||
.replace("${resolution_width}", "1920") //TODO has_custom_resolution
|
||||
.replace("${resolution_height}", "1080") //TODO has_custom_resolution
|
||||
// jvm args
|
||||
.replace("${natives_directory}", Inceptum.NATIVES_DIR.resolve(instance.getMinecraftVersion()).toAbsolutePath().toString())
|
||||
.replace("${launcher_name}", "Inceptum")
|
||||
.replace("${launcher_version}", Inceptum.VERSION.version)
|
||||
.replace("${classpath}", classPath)
|
||||
.replace("${user_properties}", "{}");
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue