Initial fabric support, instance locking

This commit is contained in:
JFronny 2021-10-30 14:22:07 +02:00
parent d9336264b5
commit ea2b2e5452
No known key found for this signature in database
GPG Key ID: BEC5ACBBD4EE17E5
26 changed files with 349 additions and 118 deletions

View File

@ -11,12 +11,12 @@ import io.gitlab.jfronny.inceptum.gson.GsonIgnoreExclusionStrategy;
import io.gitlab.jfronny.inceptum.gson.MinecraftArgumentDeserializer;
import io.gitlab.jfronny.inceptum.gson.OauthTokenResponseDeserializer;
import io.gitlab.jfronny.inceptum.gson.RulesDeserializer;
import io.gitlab.jfronny.inceptum.model.InceptumVersion;
import io.gitlab.jfronny.inceptum.model.inceptum.InceptumVersion;
import io.gitlab.jfronny.inceptum.model.microsoft.OauthTokenResponse;
import io.gitlab.jfronny.inceptum.model.mojang.MinecraftArgument;
import io.gitlab.jfronny.inceptum.model.mojang.Rules;
import io.gitlab.jfronny.inceptum.util.Utils;
import io.gitlab.jfronny.inceptum.util.account.AccountManager;
import io.gitlab.jfronny.inceptum.util.api.account.AccountManager;
import io.gitlab.jfronny.inceptum.windows.MainWindow;
import io.gitlab.jfronny.inceptum.windows.Window;
import org.apache.logging.log4j.LogManager;

View File

@ -1,9 +1,9 @@
package io.gitlab.jfronny.inceptum.install;
import io.gitlab.jfronny.inceptum.model.inceptum.LoaderInfo;
import io.gitlab.jfronny.inceptum.model.mojang.VersionInfo;
import io.gitlab.jfronny.inceptum.windows.NewInstanceWindow;
public record SetupStepInfo(VersionInfo version,
NewInstanceWindow.LoaderType loaderType,
LoaderInfo loader,
String name) {
}

View File

@ -4,7 +4,7 @@ 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.AssetIndex;
import io.gitlab.jfronny.inceptum.util.McApi;
import io.gitlab.jfronny.inceptum.util.api.McApi;
import java.io.IOException;
import java.nio.file.Files;

View File

@ -14,10 +14,12 @@ import java.util.concurrent.atomic.AtomicBoolean;
public class DownloadClientStep implements Step {
@Override
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");
if (Files.exists(path)) return;
VersionInfo.Downloads.Download client = info.version().downloads.client;
Inceptum.LOGGER.info("Downloading client");
Path parentPath = Inceptum.LIBRARIES_DIR.resolve("net/minecraft/minecraft");
if (!Files.exists(parentPath)) Files.createDirectories(parentPath);
Utils.downloadFile(client.url, client.sha1, parentPath.resolve(info.version().id + ".jar"));
Utils.downloadFile(client.url, client.sha1, path);
}
}

View File

@ -18,10 +18,14 @@ public class DownloadLibrariesStep implements Step {
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;
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;
}
Utils.downloadFile(artifact.url, artifact.sha1, path);
}
}

View File

@ -3,7 +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.windows.NewInstanceWindow;
import io.gitlab.jfronny.inceptum.model.inceptum.LoaderInfo;
import java.io.IOException;
import java.nio.file.Files;
@ -16,9 +16,9 @@ public class SetupDirsStep implements Step {
Inceptum.LOGGER.info("Setting up instance dirs");
Path iDir = Inceptum.INSTANCE_DIR.resolve(info.name());
if (!Files.exists(iDir)) {
Files.createDirectories(iDir);
Files.createDirectories(iDir.resolve("inceptum.setup.lock"));
Files.createDirectories(iDir.resolve("config"));
if (info.loaderType() != NewInstanceWindow.LoaderType.None)
if (info.loader().type() != LoaderInfo.Type.None)
Files.createDirectories(iDir.resolve("mods"));
Files.createDirectories(iDir.resolve("resourcepacks"));
Files.createDirectories(iDir.resolve("saves"));

View File

@ -3,10 +3,11 @@ 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.InstanceMeta;
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;
import java.util.concurrent.atomic.AtomicBoolean;
@ -14,10 +15,10 @@ 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("instance.json");
Path metaDir = Inceptum.INSTANCE_DIR.resolve(info.name()).resolve("inceptum.lock");
InstanceMeta meta = new InstanceMeta();
meta.loaderType = info.loaderType();
meta.version = info.version().id;
Utils.writeObject(metaDir, meta);
Files.delete(Inceptum.INSTANCE_DIR.resolve(info.name()).resolve("SETUP"));
}
}

View File

@ -1,12 +0,0 @@
package io.gitlab.jfronny.inceptum.model;
import io.gitlab.jfronny.inceptum.gson.GsonIgnore;
import io.gitlab.jfronny.inceptum.windows.NewInstanceWindow;
import java.nio.file.Path;
public class InstanceMeta {
public NewInstanceWindow.LoaderType loaderType;
public String version;
@GsonIgnore public Path instancePath;
}

View File

@ -0,0 +1,9 @@
package io.gitlab.jfronny.inceptum.model.fabric;
public class FabricLoaderVersion {
public String separator;
public Integer build;
public String maven;
public String version;
public Boolean stable;
}

View File

@ -0,0 +1,34 @@
package io.gitlab.jfronny.inceptum.model.fabric;
import java.util.List;
public class FabricVersionLoaderInfo {
public FabricLoaderVersion loader;
public IntermediaryVersion intermediary;
public static class WithMeta extends FabricVersionLoaderInfo {
public LauncherMeta launcherMeta;
public static class LauncherMeta {
public int version;
public Libraries libraries;
public MainClass mainClass;
public static class Libraries {
public List<Library> client;
public List<Library> common;
public List<Library> server;
public static class Library {
public String name;
public String url;
}
}
public static class MainClass {
public String client;
public String server;
}
}
}
}

View File

@ -0,0 +1,7 @@
package io.gitlab.jfronny.inceptum.model.fabric;
public class IntermediaryVersion {
public String maven;
public String version;
public boolean stable;
}

View File

@ -1,4 +1,4 @@
package io.gitlab.jfronny.inceptum.model;
package io.gitlab.jfronny.inceptum.model.inceptum;
public class InceptumVersion {
public String version;

View File

@ -0,0 +1,18 @@
package io.gitlab.jfronny.inceptum.model.inceptum;
public class InstanceMeta {
private static final String floaderPrefix = "fabric-loader-";
public String version;
public boolean isFabric() {
return version.startsWith(floaderPrefix);
}
public String getMinecraftVersion() {
return isFabric() ? version.substring(version.lastIndexOf('-') + 1) : version;
}
public String getLoaderVersion() {
return isFabric() ? version.substring(floaderPrefix.length()).split("-")[0] : "";
}
}

View File

@ -0,0 +1,14 @@
package io.gitlab.jfronny.inceptum.model.inceptum;
import io.gitlab.jfronny.inceptum.model.fabric.FabricLoaderVersion;
public record LoaderInfo(Type type, String version) {
public static LoaderInfo NONE = new LoaderInfo(Type.None, "");
public enum Type {
None, Fabric
}
public LoaderInfo(FabricLoaderVersion fabricVersion) {
this(LoaderInfo.Type.Fabric, fabricVersion.version);
}
}

View File

@ -3,20 +3,16 @@ package io.gitlab.jfronny.inceptum.model.mojang;
import java.util.List;
import java.util.Map;
public class VersionInfo {
public class VersionInfo extends VersionsListInfo {
public Arguments arguments;
public AssetIndex assetIndex;
public String assets;
public int complianceLevel;
public Downloads downloads;
public String id;
public JavaVersion javaVersion;
public List<Library> libraries;
public String mainClass;
public Integer minimumLauncherVersion;
public String releaseTime;
public String time;
public String type;
public static class Arguments {
public List<MinecraftArgument> game;

View File

@ -0,0 +1,35 @@
package io.gitlab.jfronny.inceptum.util;
import io.gitlab.jfronny.inceptum.Inceptum;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class ProcessUtils {
public static boolean isProcessAlive(String pid) {
return isProcessIdRunning(pid, Utils.OS.equals("windows")
? "cmd /c tasklist /FI \"PID eq " + pid + "\""
: "ps -p " + pid);
}
private static boolean isProcessIdRunning(String pid, String command) {
try {
Runtime rt = Runtime.getRuntime();
Process pr = rt.exec(command);
InputStreamReader isReader = new InputStreamReader(pr.getInputStream());
BufferedReader bReader = new BufferedReader(isReader);
String strLine;
while ((strLine= bReader.readLine()) != null) {
if (strLine.contains(" " + pid + " ")) {
return true;
}
}
return false;
} catch (Exception e) {
Inceptum.LOGGER.error("Could not get process state", e);
return true;
}
}
}

View File

@ -13,6 +13,7 @@ import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Formatter;
import java.util.Locale;
import java.util.function.Function;
import java.util.regex.Pattern;
public class Utils {
@ -50,32 +51,33 @@ public class Utils {
public static byte[] downloadData(String url, String sha1) throws IOException {
byte[] buf = downloadData(url);
if (sha1 == null) return buf;
if (!Utils.hash(buf).equals(sha1)) throw new IOException("Invalid hash");
return buf;
}
public static <T> T downloadObject(String url, Class<T> type) throws IOException {
return downloadObject(url, () -> HttpUtils.get(url).sendString(), type);
return downloadObject(url, () -> HttpUtils.get(url).sendString(), s -> Inceptum.GSON.fromJson(s, type));
}
public static <T> T downloadObject(String url, Type type) throws IOException {
return downloadObject(url, () -> HttpUtils.get(url).sendString(), s -> Inceptum.GSON.fromJson(s, type));
}
public static <T> T downloadObject(String url, String sha1, Class<T> type) throws IOException {
return downloadObject(url, () -> downloadString(url, sha1), type);
return downloadObject(url, () -> downloadString(url, sha1), s -> Inceptum.GSON.fromJson(s, type));
}
private static <T> T downloadObject(String url, ThrowingSupplier<String, IOException> sourceString, Class<T> type) throws IOException {
private static <T> T downloadObject(String url, ThrowingSupplier<String, IOException> sourceString, Function<String, T> builder) throws IOException {
Path cache = Inceptum.CACHE_DIR.resolve(Integer.toString(url.hashCode()));
try {
String download = sourceString.get();
Files.writeString(cache, download);
return Inceptum.GSON.fromJson(download, type);
return builder.apply(download);
} catch (IOException e) {
if (Files.exists(cache)) {
Inceptum.LOGGER.info("Using cache for " + url, e);
try (BufferedReader br = Files.newBufferedReader(cache)) {
return Inceptum.GSON.fromJson(br, type);
} catch (IOException ioE) {
throw new IOException("Could not download object and failed loading cache", ioE);
}
return builder.apply(Files.readString(cache));
} else
throw new IOException("Could not download object and no cache exists", e);
}

View File

@ -0,0 +1,67 @@
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.mojang.Rules;
import io.gitlab.jfronny.inceptum.model.mojang.VersionInfo;
import io.gitlab.jfronny.inceptum.model.mojang.VersionsListInfo;
import io.gitlab.jfronny.inceptum.util.Utils;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class FabricMetaApi {
private static final Type fabricLoaderVersionListType = new TypeToken<List<FabricVersionLoaderInfo>>() {}.getType();
private static final String META_URL = "https://meta.fabricmc.net/";
public static List<FabricVersionLoaderInfo> getLoaderVersions(VersionsListInfo version) {
try {
return Utils.downloadObject(META_URL + "v2/versions/loader/" + version.id, fabricLoaderVersionListType);
} catch (IOException e) {
throw new RuntimeException("Could not get fabric loader versions", e);
}
}
public static FabricVersionLoaderInfo getLoaderVersion(VersionsListInfo gameVersion, String fabricVersion) throws IOException {
return Utils.downloadObject(META_URL + "v2/versions/loader/" + gameVersion.id + "/" + fabricVersion, FabricVersionLoaderInfo.WithMeta.class);
}
public static void addFabric(VersionInfo version, String fabricVersion) throws IOException {
FabricVersionLoaderInfo ver = getLoaderVersion(version, fabricVersion);
if (!(ver instanceof FabricVersionLoaderInfo.WithMeta verWithMeta)) throw new IOException("Doesn't hold metadata");
FabricVersionLoaderInfo.WithMeta.LauncherMeta meta = verWithMeta.launcherMeta;
if (meta.version != 1) throw new IOException("Unsupported fabric launcherMeta version: " + meta.version);
version.mainClass = meta.mainClass.client;
List<VersionInfo.Library> libs = new ArrayList<>(version.libraries);
for (FabricVersionLoaderInfo.WithMeta.LauncherMeta.Libraries.Library library : meta.libraries.common)
libs.add(convertLib(library));
for (FabricVersionLoaderInfo.WithMeta.LauncherMeta.Libraries.Library library : meta.libraries.client)
libs.add(convertLib(library));
var floader = new FabricVersionLoaderInfo.WithMeta.LauncherMeta.Libraries.Library();
floader.name = "net.fabricmc:fabric-loader:" + fabricVersion;
floader.url = "https://maven.fabricmc.net/";
libs.add(convertLib(floader));
version.libraries = List.copyOf(libs);
version.id = "fabric-loader-" + fabricVersion + "-" + version.id;
}
private static VersionInfo.Library convertLib(FabricVersionLoaderInfo.WithMeta.LauncherMeta.Libraries.Library library) {
VersionInfo.Library res = new VersionInfo.Library();
res.name = library.name;
res.rules = new Rules(true);
res.natives = new HashMap<>();
res.downloads = new VersionInfo.Library.Downloads();
res.downloads.classifiers = null;
res.downloads.artifact = new VersionInfo.Library.Downloads.Artifact();
String[] lib = library.name.split(":");
assert lib.length == 3;
res.downloads.artifact.path = lib[0].replace('.', '/') + '/' + lib[1] + '/' + lib[2] + '/' + lib[1] + '-' + lib[2] + ".jar";
res.downloads.artifact.size = -1;
res.downloads.artifact.sha1 = null;
res.downloads.artifact.url = library.url + res.downloads.artifact.path;
return res;
}
}

View File

@ -1,10 +1,11 @@
package io.gitlab.jfronny.inceptum.util;
package io.gitlab.jfronny.inceptum.util.api;
import io.gitlab.jfronny.inceptum.Inceptum;
import io.gitlab.jfronny.inceptum.model.mojang.AssetIndex;
import io.gitlab.jfronny.inceptum.model.mojang.VersionInfo;
import io.gitlab.jfronny.inceptum.model.mojang.VersionsList;
import io.gitlab.jfronny.inceptum.model.mojang.VersionsListInfo;
import io.gitlab.jfronny.inceptum.util.Utils;
import java.io.IOException;
import java.nio.file.Files;

View File

@ -1,4 +1,4 @@
package io.gitlab.jfronny.inceptum.util.account;
package io.gitlab.jfronny.inceptum.util.api.account;
import com.google.gson.reflect.TypeToken;
import io.gitlab.jfronny.inceptum.Inceptum;

View File

@ -1,4 +1,4 @@
package io.gitlab.jfronny.inceptum.util.account;
package io.gitlab.jfronny.inceptum.util.api.account;
public record AuthInfo(String name, String uuid, String accessToken, String userType) {
public AuthInfo(MicrosoftAccount account) {

View File

@ -1,4 +1,4 @@
package io.gitlab.jfronny.inceptum.util.account;
package io.gitlab.jfronny.inceptum.util.api.account;
import io.gitlab.jfronny.inceptum.Inceptum;
import io.gitlab.jfronny.inceptum.model.microsoft.LoginResponse;

View File

@ -1,4 +1,4 @@
package io.gitlab.jfronny.inceptum.util.account;
package io.gitlab.jfronny.inceptum.util.api.account;
import io.gitlab.jfronny.inceptum.model.microsoft.*;
import io.gitlab.jfronny.inceptum.util.HttpUtils;

View File

@ -6,17 +6,19 @@ import imgui.flag.ImGuiWindowFlags;
import imgui.type.ImBoolean;
import imgui.type.ImInt;
import io.gitlab.jfronny.inceptum.Inceptum;
import io.gitlab.jfronny.inceptum.model.InstanceMeta;
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.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.McApi;
import io.gitlab.jfronny.inceptum.util.account.AccountManager;
import io.gitlab.jfronny.inceptum.util.account.AuthInfo;
import io.gitlab.jfronny.inceptum.util.account.MicrosoftAccount;
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 java.io.IOException;
import java.nio.file.Files;
@ -27,25 +29,9 @@ import java.util.List;
public class MainWindow extends Window {
private final ImBoolean darkTheme = new ImBoolean(Inceptum.CONFIG.darkTheme);
private final ImBoolean debugTools = new ImBoolean(false);
private final List<InstanceMeta> instances; //TODO custom ordering
private final ImInt accountIndex = new ImInt(0);
public MainWindow() {
super("Inceptum");
List<InstanceMeta> instances = new ArrayList<>();
try {
for (Path path : Files.list(Inceptum.INSTANCE_DIR).filter(Files::isDirectory).toList()) {
if (Files.exists(path.resolve("instance.json"))) {
InstanceMeta im = Utils.loadObject(path.resolve("instance.json"), InstanceMeta.class);
im.instancePath = path;
instances.add(im);
} else {
Inceptum.LOGGER.error("Invalid instance (doesn't contain instance.json): " + path);
}
}
} catch (IOException e) {
Inceptum.LOGGER.error("Could not list present instances", e);
}
this.instances = List.copyOf(instances);
}
@Override
@ -96,56 +82,94 @@ public class MainWindow extends Window {
ImGui.showDemoWindow();
}
if (instances.isEmpty()) {
List<Path> paths;
try {
paths = Files.list(Inceptum.INSTANCE_DIR).filter(Files::isDirectory).toList();
} catch (IOException e) {
Inceptum.LOGGER.error("Could not list instances");
return;
}
if (paths.isEmpty()) {
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.Resizable | ImGuiTableFlags.Borders)) {
for (InstanceMeta instance : instances) {
else if (ImGui.beginTable("Instances", 2, ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.Borders)) {
for (Path path : paths) {
if (Files.exists(path.resolve("inceptum.setup.lock"))) {
ImGui.tableNextColumn();
if (ImGui.button(instance.instancePath.getFileName().toString())) {
//TODO implement fabric support
//TODO extract launch logic to separate class
for (VersionsListInfo version : McApi.getVersions().versions) {
if (version.id.equals(instance.version)) {
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);
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());
Inceptum.LOGGER.info(classPath.toString());
//TODO -Xms{lowMem} -Xmx{maxMem}
args.addAll(parse(info.arguments.jvm, info, instance, classPath.toString()));
args.add(info.mainClass);
args.addAll(parse(info.arguments.game, info, instance, classPath.toString()));
ProcessBuilder pb = new ProcessBuilder(args.toArray(new String[0]));
pb.directory(instance.instancePath.toFile());
pb.redirectOutput(ProcessBuilder.Redirect.INHERIT);
pb.redirectError(ProcessBuilder.Redirect.INHERIT);
pb.start();
} catch (IOException e) {
e.printStackTrace();
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
}
}
ImGui.endTable();
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) {
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()) {
@ -154,8 +178,8 @@ public class MainWindow extends Window {
res.add(s
// game args
.replace("${auth_player_name}", authInfo.name())
.replace("${version_name}", info.id) //TODO fabric support
.replace("${game_directory}", instance.instancePath.toAbsolutePath().toString())
.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())

View File

@ -3,9 +3,9 @@ package io.gitlab.jfronny.inceptum.windows;
import imgui.ImGui;
import io.gitlab.jfronny.inceptum.Inceptum;
import io.gitlab.jfronny.inceptum.model.microsoft.*;
import io.gitlab.jfronny.inceptum.util.account.AccountManager;
import io.gitlab.jfronny.inceptum.util.account.MicrosoftAccount;
import io.gitlab.jfronny.inceptum.util.account.MicrosoftAuthAPI;
import io.gitlab.jfronny.inceptum.util.api.account.AccountManager;
import io.gitlab.jfronny.inceptum.util.api.account.MicrosoftAccount;
import io.gitlab.jfronny.inceptum.util.api.account.MicrosoftAuthAPI;
import io.gitlab.jfronny.inceptum.util.Utils;
import net.freeutils.httpserver.HTTPServer;

View File

@ -6,21 +6,30 @@ 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.model.inceptum.LoaderInfo;
import io.gitlab.jfronny.inceptum.model.fabric.FabricVersionLoaderInfo;
import io.gitlab.jfronny.inceptum.model.mojang.VersionInfo;
import io.gitlab.jfronny.inceptum.model.mojang.VersionsList;
import io.gitlab.jfronny.inceptum.model.mojang.VersionsListInfo;
import io.gitlab.jfronny.inceptum.util.McApi;
import io.gitlab.jfronny.inceptum.util.api.FabricMetaApi;
import io.gitlab.jfronny.inceptum.util.api.McApi;
import io.gitlab.jfronny.inceptum.util.Utils;
import java.io.IOException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class NewInstanceWindow extends Window {
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);
ImInt fabricVersion = new ImInt(0);
ImBoolean snapshots = new ImBoolean(Inceptum.CONFIG.snapshots);
ImBoolean fabric = new ImBoolean(true);
public NewInstanceWindow() {
@ -29,6 +38,15 @@ public class NewInstanceWindow extends Window {
if (Inceptum.CONFIG.snapshots)
version.set(manifest.versions.indexOf(selected));
name.set(getDefaultName(selected, fabric.get()));
List<FabricVersionLoaderInfo> versions = getFabricLoaderInfo();
for (int i = 0, fabricLoaderInfoSize = versions.size(); i < fabricLoaderInfoSize; i++) {
FabricVersionLoaderInfo version = versions.get(i);
if (version.loader.stable) {
selectedFabric = version;
fabricVersion.set(i);
break;
}
}
}
@Override
@ -53,8 +71,14 @@ public class NewInstanceWindow extends Window {
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
//TODO implement fabric support
ImGui.inputTextWithHint("Name", "Select a name", name);
if (!Utils.VALID_FILENAME.matcher(name.get()).matches())
ImGui.text("Invalid name");
@ -63,7 +87,11 @@ public class NewInstanceWindow extends Window {
else if (ImGui.button("OK")) {
close();
try {
Inceptum.open(new InstanceCreateProcessWindow(new SetupStepInfo(McApi.getVersionInfo(selected), fabric.get() ? LoaderType.Fabric : LoaderType.None, name.get())));
VersionInfo vi = McApi.getVersionInfo(selected);
if (fabric.get()) FabricMetaApi.addFabric(vi, selectedFabric.loader.version);
Inceptum.open(new InstanceCreateProcessWindow(new SetupStepInfo(vi,
fabric.get() ? new LoaderInfo(selectedFabric.loader) : LoaderInfo.NONE,
name.get())));
} catch (IOException e) {
Inceptum.LOGGER.error("Could not initialize instance creation", e);
}
@ -76,12 +104,13 @@ public class NewInstanceWindow extends Window {
return res;
}
private List<FabricVersionLoaderInfo> getFabricLoaderInfo() {
if (!loaderInfoCache.containsKey(selected))
loaderInfoCache.put(selected, FabricMetaApi.getLoaderVersions(selected));
return loaderInfoCache.get(selected);
}
private String getDefaultName(VersionsListInfo info, boolean fabric) {
return fabric ? "Fabric " + info.id : info.id;
}
public enum LoaderType {
None,
Fabric
}
}