Use Mojang JVM, switch to SLF4J, ini

This commit is contained in:
JFronny 2021-10-30 19:26:59 +02:00
parent 2adf5cac1b
commit d73aefd99e
No known key found for this signature in database
GPG Key ID: BEC5ACBBD4EE17E5
28 changed files with 514 additions and 230 deletions

View File

@ -41,9 +41,10 @@ if (flavor == 'auto') {
dependencies {
implementation 'com.google.code.gson:gson:2.8.8'
implementation "org.apache.logging.log4j:log4j-api:$log4jVersion"
implementation "org.apache.logging.log4j:log4j-core:$log4jVersion"
implementation 'org.slf4j:slf4j-api:1.7.32'
implementation 'ch.qos.logback:logback-classic:1.2.6'
implementation 'net.freeutils:jlhttp:2.6'
implementation 'org.eclipse.jgit:org.eclipse.jgit:5.13.0.202109080827-r'
implementation platform("org.lwjgl:lwjgl-bom:$lwjglVersion")

View File

@ -19,13 +19,16 @@ import io.gitlab.jfronny.inceptum.util.Utils;
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;
import org.apache.logging.log4j.Logger;
import org.lwjgl.glfw.*;
import org.lwjgl.glfw.Callbacks;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.glfw.GLFWVidMode;
import org.lwjgl.opengl.GL;
import org.lwjgl.opengl.GL32;
import org.lwjgl.system.MemoryStack;
import org.lwjgl.system.MemoryUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.InputStream;
@ -44,7 +47,7 @@ import java.util.Set;
//TODO update checker
public class Inceptum {
public static final Set<Window> WINDOWS = new LinkedHashSet<>();
public static final Logger LOGGER = LogManager.getFormatterLogger("Inceptum");
public static final Logger LOGGER = LoggerFactory.getLogger("Inceptum");
public static final Gson GSON = new GsonBuilder()
.registerTypeAdapter(MinecraftArgument.class, new MinecraftArgumentDeserializer())
.registerTypeAdapter(Rules.class, new RulesDeserializer())
@ -218,9 +221,12 @@ public class Inceptum {
//render
if (Inceptum.WINDOWS.isEmpty()) exit();
else {
for (Window window : Inceptum.WINDOWS.toArray(new Window[0])) {
Window[] array = Inceptum.WINDOWS.toArray(new Window[0]);
for (int i = 0, arrayLength = array.length; i < arrayLength; i++) {
Window window = array[i];
if (window.isNew()) window.preFirstDraw();
if (ImGui.begin(window.getName(), window.getOpenState(), window.getFlags())) window.draw();
if (ImGui.begin(window.getName() + "##" + i, window.getOpenState(), window.getFlags()))
window.draw();
ImGui.end();
if (!window.getOpenState().get()) window.close();
}

View File

@ -1,9 +1,17 @@
package io.gitlab.jfronny.inceptum.install;
import io.gitlab.jfronny.inceptum.Inceptum;
import io.gitlab.jfronny.inceptum.model.inceptum.LoaderInfo;
import io.gitlab.jfronny.inceptum.model.mojang.VersionInfo;
import java.util.concurrent.atomic.AtomicReference;
public record SetupStepInfo(VersionInfo version,
LoaderInfo loader,
String name) {
String name,
AtomicReference<String> currentState) {
public void setState(String state) {
currentState.set(state);
Inceptum.LOGGER.info(state);
}
}

View File

@ -9,6 +9,7 @@ import java.util.Set;
public class Steps {
public static Set<Step> STEPS = new LinkedHashSet<>(List.of(
new SetupDirsStep(),
new DownloadJavaStep(),
new DownloadClientStep(),
new DownloadAssetsStep(),
new DownloadLibrariesStep(),

View File

@ -21,8 +21,8 @@ public class DownloadAssetsStep implements Step {
Path fPath = o.resolve(entry.getValue().hash.substring(0, 2));
if (!Files.exists(fPath)) Files.createDirectories(fPath);
fPath = fPath.resolve(entry.getValue().hash);
if (Files.exists(fPath)) return;
Inceptum.LOGGER.info("Downloading asset: " + entry.getKey());
if (Files.exists(fPath)) continue;
info.setState("Downloading asset: " + entry.getKey());
McApi.downloadAsset(entry.getValue(), fPath);
}
}

View File

@ -4,6 +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.inceptum.InstanceMeta;
import io.gitlab.jfronny.inceptum.model.mojang.MojangFileDownload;
import io.gitlab.jfronny.inceptum.model.mojang.VersionInfo;
import io.gitlab.jfronny.inceptum.util.Utils;
@ -19,8 +20,8 @@ public class DownloadClientStep implements Step {
if (!Files.exists(path)) Files.createDirectories(path);
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");
MojangFileDownload client = info.version().downloads.client;
info.setState("Downloading Client");
Utils.downloadFile(client.url, client.sha1, path);
}
}

View File

@ -0,0 +1,42 @@
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.JvmFileInfo;
import io.gitlab.jfronny.inceptum.model.mojang.MojangFileDownload;
import io.gitlab.jfronny.inceptum.model.mojang.VersionInfo;
import io.gitlab.jfronny.inceptum.util.Utils;
import io.gitlab.jfronny.inceptum.util.api.McApi;
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 DownloadJavaStep implements Step {
@Override
public void execute(SetupStepInfo info, AtomicBoolean stopThread) throws IOException {
VersionInfo.JavaVersion ver = info.version().javaVersion;
Path jvmDir = Inceptum.NATIVES_DIR.resolve(ver.component).resolve(Integer.toString(ver.majorVersion));
if (Files.exists(jvmDir)) return;
info.setState("Downloading JVM");
Files.createDirectories(jvmDir);
for (Map.Entry<String, JvmFileInfo.File> entry : McApi.getJvm(ver.component, ver.majorVersion).entrySet()) {
Path tPath = jvmDir.resolve(entry.getKey());
switch (entry.getValue().type) {
case "file" -> {
MojangFileDownload mf = entry.getValue().downloads.raw;
info.setState("jvm: Downloading " + tPath);
Utils.downloadFile(mf.url, mf.sha1, tPath);
if (entry.getValue().executable) {
if (!tPath.toFile().setExecutable(true))
info.setState("Could not set executable bit for " + tPath);
}
}
case "directory" -> Files.createDirectories(tPath);
}
}
}
}

View File

@ -5,6 +5,7 @@ import io.gitlab.jfronny.inceptum.install.SetupStepInfo;
import io.gitlab.jfronny.inceptum.install.Step;
import io.gitlab.jfronny.inceptum.model.inceptum.ArtifactInfo;
import io.gitlab.jfronny.inceptum.model.inceptum.InstanceMeta;
import io.gitlab.jfronny.inceptum.model.mojang.VersionInfo;
import io.gitlab.jfronny.inceptum.util.Utils;
import io.gitlab.jfronny.inceptum.util.VersionInfoLibraryResolver;
@ -16,15 +17,21 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
public class DownloadLibrariesStep implements Step {
@Override
public void execute(SetupStepInfo info, AtomicBoolean stopThread) throws IOException {
for (ArtifactInfo artifact : VersionInfoLibraryResolver.getRelevant(info.version())) {
execute(info.version(), stopThread, info.currentState());
}
public static void execute(VersionInfo version, AtomicBoolean stopThread, AtomicReference<String> currentState) throws IOException {
for (ArtifactInfo artifact : VersionInfoLibraryResolver.getRelevant(version)) {
if (stopThread.get()) return;
Path path = Inceptum.LIBRARIES_DIR.resolve(artifact.path);
if (!Files.exists(path)) {
Inceptum.LOGGER.info("Downloading library: " + artifact.path);
currentState.set("Downloading library: " + artifact.path);
Inceptum.LOGGER.info(currentState.get());
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);
@ -33,10 +40,11 @@ public class DownloadLibrariesStep implements Step {
Utils.downloadFile(artifact.url, artifact.sha1, path);
}
if (artifact.isNative) {
Inceptum.LOGGER.info("Extracting natives");
currentState.set("Extracting natives");
Inceptum.LOGGER.info(currentState.get());
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)));
Utils.copyRecursive(path1, Inceptum.NATIVES_DIR.resolve(InstanceMeta.getMinecraftVersion(version.id)));
}
}
catch (Throwable t) {

View File

@ -14,7 +14,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
public class SetupDirsStep implements Step {
@Override
public void execute(SetupStepInfo info, AtomicBoolean stopThread) throws IOException {
Inceptum.LOGGER.info("Setting up instance dirs");
info.setState("Setting up instance dirs");
Path iDir = Inceptum.INSTANCE_DIR.resolve(info.name());
if (!Files.exists(iDir)) {
Files.createDirectories(iDir.resolve("inceptum.setup.lock"));

View File

@ -5,6 +5,9 @@ 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.util.Utils;
import io.gitlab.jfronny.inceptum.windows.AlertWindow;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import java.io.IOException;
import java.nio.file.Files;
@ -14,12 +17,39 @@ import java.util.concurrent.atomic.AtomicBoolean;
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");
info.setState("Writing metadata");
Path instance = Inceptum.INSTANCE_DIR.resolve(info.name());
Path metaDir = instance.resolve("instance.json");
InstanceMeta meta = new InstanceMeta();
meta.version = info.version().id;
Utils.writeObject(metaDir, meta);
Path lock = Inceptum.INSTANCE_DIR.resolve(info.name()).resolve("inceptum.setup.lock");
Path lock = instance.resolve("inceptum.setup.lock");
if (Files.exists(lock)) Files.delete(lock);
if (!Files.exists(instance.resolve(".gitignore"))) {
Files.writeString(instance.resolve(".gitignore"), """
realms_persistence.json
saves/
screenshots/
logs/
.mixin.out/
.fabric/
mods/*.jar""");
}
Path gitDir = instance.resolve(".git");
if (!Files.exists(gitDir)) {
try (Git git = Git.init()
.setDirectory(instance.toFile())
.setGitDir(gitDir.toFile())
.call()) {
//TODO use proper git identity
git.add().addFilepattern(".").call();
git.commit().setMessage("Initial commit")
.setSign(false)
.setAuthor("Inceptum", "inceptum@jfronny.gitlab.io").call();
} catch (GitAPIException e) {
Inceptum.LOGGER.error("Could not initialize git", e);
Inceptum.open(new AlertWindow("Could not initialize git", e.toString()));
}
}
}
}

View File

@ -2,9 +2,6 @@ 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 {
@GsonIgnore public static final String floaderPrefix = "fabric-loader-";
public String version;
@ -27,16 +24,4 @@ public class InstanceMeta {
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;
}
}

View File

@ -0,0 +1,18 @@
package io.gitlab.jfronny.inceptum.model.mojang;
import java.util.Map;
public class JvmFileInfo {
public Map<String, File> files;
public static class File {
public Downloads downloads;
public boolean executable;
public String type;
public static class Downloads {
public MojangFileDownload lzma;
public MojangFileDownload raw;
}
}
}

View File

@ -0,0 +1,36 @@
package io.gitlab.jfronny.inceptum.model.mojang;
import com.google.gson.annotations.SerializedName;
import java.util.List;
public class JvmInfo {
public Jvms linux;
@SerializedName("mac-os")
public Jvms macOs;
@SerializedName("windows-x64")
public Jvms windowsX64;
public static class Jvms {
@SerializedName("java-runtime-alpha")
public List<Jvm> javaRuntimeAlpha;
@SerializedName("jre-legacy")
public List<Jvm> jreLegacy;
public static class Jvm {
public Availability availability;
public MojangFileDownload manifest;
public Version version;
public static class Availability {
public int group;
public int progress;
}
public static class Version {
public String name;
public String released;
}
}
}
}

View File

@ -0,0 +1,7 @@
package io.gitlab.jfronny.inceptum.model.mojang;
public class MojangFileDownload {
public String sha1;
public int size;
public String url;
}

View File

@ -20,25 +20,16 @@ public class VersionInfo extends VersionsListInfo {
public List<MinecraftArgument> jvm;
}
public static class AssetIndex {
public static class AssetIndex extends MojangFileDownload {
public String id;
public String sha1;
public int size;
public int totalSize;
public String url;
}
public static class Downloads {
public Download client;
public Download client_mappings;
public Download server;
public Download server_mappings;
public static class Download {
public String sha1;
public int size;
public String url;
}
public MojangFileDownload client;
public MojangFileDownload client_mappings;
public MojangFileDownload server;
public MojangFileDownload server_mappings;
}
public static class JavaVersion {
@ -56,11 +47,8 @@ public class VersionInfo extends VersionsListInfo {
public Artifact artifact;
public Map<String, Artifact> classifiers;
public static class Artifact {
public static class Artifact extends MojangFileDownload {
public String path;
public String sha1;
public int size;
public String url;
}
}
}

View File

@ -1,15 +1,7 @@
package io.gitlab.jfronny.inceptum.util;
import org.apache.logging.log4j.core.Appender;
import org.apache.logging.log4j.core.Core;
import org.apache.logging.log4j.core.Filter;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.appender.AbstractAppender;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
import org.apache.logging.log4j.core.config.plugins.PluginElement;
import org.apache.logging.log4j.core.config.plugins.PluginFactory;
import org.apache.logging.log4j.util.StringBuilderFormattable;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.AppenderBase;
import java.time.Instant;
import java.util.LinkedHashSet;
@ -17,43 +9,19 @@ import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@Plugin(name = "MapAppender", category = Core.CATEGORY_NAME, elementType = Appender.ELEMENT_TYPE)
public class MapAppender extends AbstractAppender {
public static final ConcurrentMap<String, LogEvent> EVENT_MAP = new ConcurrentHashMap<>();
public class MapAppender extends AppenderBase<ILoggingEvent> {
public static final ConcurrentMap<String, ILoggingEvent> 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);
super(name, filter, null, false, null);
}
@PluginFactory
public static MapAppender createAppender(
@PluginAttribute("name") String name,
@PluginElement("Filter") Filter filter) {
return new MapAppender(name, filter);
}
@Override
public void append(LogEvent event) {
protected void append(ILoggingEvent event) {
EVENT_MAP.put(Instant.now().toString(), event);
StringBuilder msg = new StringBuilder(event.getLevel().name())
.append(" | ")
.append(Instant.now().toString())
.append(" | [")
.append(event.getThreadName())
.append("] ")
.append(event.getSource().getClassName())
.append(" - ");
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);
LOG.add(event.getLevel().toString() +
" | " +
Instant.now().toString() +
" | [" +
event.getThreadName() +
"] " +
event.getFormattedMessage());
}
}

View File

@ -110,6 +110,30 @@ public class Utils {
Files.write(path, downloadData(url, sha1));
}
public static void clearDirectory(Path path) throws IOException {
if (!Files.exists(path)) return;
try {
Files.list(path).forEach(p -> {
if (Files.isDirectory(p)) {
try {
deleteRecursive(p);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
else {
try {
Files.delete(p);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
});
} catch (Throwable t) {
throw new IOException("Could not clear directory", t);
}
}
public static void deleteRecursive(Path path) throws IOException {
Files.walkFileTree(path, new SimpleFileVisitor<>() {
@Override
@ -188,4 +212,13 @@ public class Utils {
return false;
}
}
public static Path getJvmMain(Path jvmDir) {
Path f = jvmDir.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;
}
}

View File

@ -1,15 +1,14 @@
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.model.mojang.*;
import io.gitlab.jfronny.inceptum.util.Utils;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import static io.gitlab.jfronny.inceptum.util.Utils.downloadObject;
@ -39,6 +38,28 @@ public class McApi {
return Utils.loadObject(file, AssetIndex.class);
}
public static Map<String, JvmFileInfo.File> getJvm(String component, int majorVersion) throws IOException {
// https://github.com/ATLauncher/ATLauncher/blob/master/src/main/java/com/atlauncher/constants/Constants.java#L116
JvmInfo info = Utils.downloadObject("https://launchermeta.mojang.com/v1/products/java-runtime/2ec0cc96c44e5a76b9c8b7c39df7210883d12871/all.json", JvmInfo.class);
JvmInfo.Jvms vms = switch (Utils.OS) {
case "windows" -> info.windowsX64;
case "linux" -> info.linux;
case "macos" -> info.macOs;
default -> throw new IOException("Invalid OS");
};
List<JvmInfo.Jvms.Jvm> vmList = switch (component) {
case "java-runtime-alpha" -> vms.javaRuntimeAlpha;
case "jre-legacy" -> vms.jreLegacy;
default -> throw new IOException("Invalid JVM component: " + component);
};
for (JvmInfo.Jvms.Jvm jvm : vmList) {
if (jvm.version.name.startsWith(Integer.toString(majorVersion))) {
return downloadObject(jvm.manifest.url, jvm.manifest.sha1, JvmFileInfo.class).files;
}
}
throw new IOException("JVM not found");
}
public static void downloadAsset(AssetIndex.Asset asset, Path path) throws IOException {
String url = "http://resources.download.minecraft.net/" + asset.hash.substring(0, 2) + "/" + asset.hash;
Utils.downloadFile(url, asset.hash, path);

View File

@ -10,15 +10,25 @@ import java.lang.reflect.Type;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
public class AccountManager {
private static final Type abstractAccountListType = new TypeToken<List<MicrosoftAccount>>() {}.getType();
private static MicrosoftAccount SELECTED_ACCOUNT;
private static final List<MicrosoftAccount> ACCOUNTS = new ArrayList<>();
private static final AuthInfo NULL_AUTH = new AuthInfo("Joe", "2536abce90e8476a871679918164abc5", "99abe417230342cb8e9e2168ab46297a", "legacy");
public static AuthInfo getSelectedAccount() {
if (SELECTED_ACCOUNT == null) return new AuthInfo("Joe", "2536abce90e8476a871679918164abc5", "99abe417230342cb8e9e2168ab46297a", "legacy");
return new AuthInfo(SELECTED_ACCOUNT);
if (SELECTED_ACCOUNT == null) {
return NULL_AUTH;
}
if (SELECTED_ACCOUNT.ensureAccessTokenValid(a -> {})) {
return new AuthInfo(SELECTED_ACCOUNT);
}
else {
Inceptum.LOGGER.error("Couldn't login properly, using offline mode");
return NULL_AUTH;
}
}
public static List<MicrosoftAccount> getAccounts() {
@ -43,6 +53,7 @@ public class AccountManager {
}
}
for (MicrosoftAccount account : ACCOUNTS) {
account.refreshAccessToken();
if (account.accountId.equalsIgnoreCase(Inceptum.CONFIG.lastAccount)) {
SELECTED_ACCOUNT = account;
}

View File

@ -185,8 +185,7 @@ public class MicrosoftAccount {
return "XBL3.0 x=" + xstsAuth.displayClaims.xui.get(0).uhs + ";" + xstsAuth.token;
}
public void ensureAccessTokenValid(Consumer<Boolean> isValid) {
boolean hasCancelled = false;
public boolean ensureAccessTokenValid(Consumer<Boolean> isValid) {
if (mustLogin) {
Inceptum.open(new AlertWindow("Login expired", "You must login again in order to continue", () -> {
Inceptum.open(new MicrosoftLoginWindow(this));
@ -207,10 +206,9 @@ public class MicrosoftAccount {
}
isValid.accept(false);
}, () -> {
isValid.accept(false);
}));
}
}, () -> isValid.accept(false)));
return false;
} else return true;
}
@Override

View File

@ -11,6 +11,7 @@ import io.gitlab.jfronny.inceptum.util.Utils;
import java.io.IOException;
import java.nio.file.Files;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
public class InstanceCreateProcessWindow extends Window {
private final SetupStepInfo stepInfo;
@ -28,9 +29,7 @@ public class InstanceCreateProcessWindow extends Window {
close();
return;
}
String last = "Initializing";
for (String s : MapAppender.LOG_MESSAGES) last = s;
ImGui.textUnformatted(last);
ImGui.textUnformatted(stepInfo.currentState().get());
if (ImGui.button("Cancel")) finalize.set(true);
}

View File

@ -1,45 +1,50 @@
package io.gitlab.jfronny.inceptum.windows;
import imgui.ImGui;
import imgui.type.ImBoolean;
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 io.gitlab.jfronny.inceptum.windows.control.InstanceManageControls;
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;
private final InstanceManageControls imc = new InstanceManageControls();
private final ImBoolean customJava;
private final ImString customJavaPath = new ImString(128);
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);
customJava = new ImBoolean(instance.java != null);
}
@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")) {
imc.nameBox("Rename", name -> {
try {
Path newPath = Inceptum.INSTANCE_DIR.resolve(name.get());
Path newPath = Inceptum.INSTANCE_DIR.resolve(name);
Files.move(path, newPath);
close();
Inceptum.open(new InstanceEditWindow(newPath, instance));
} catch (IOException e) {
e.printStackTrace();
}
}
});
imc.snapshotsBox();
imc.versionBox(ver -> {
instance.version = ver;
save();
});
if (ImGui.button("Delete")) Inceptum.open(new AlertWindow("Are you sure?", "This instance will be removed forever (a long time)", () -> {
close();
try {
@ -49,9 +54,24 @@ public class InstanceEditWindow extends Window {
Inceptum.open(new AlertWindow("Could not delete", e.toString()));
}
}, () -> {}));
if (ImGui.checkbox("Custom Java", customJava)) {
if (customJava.get()) {
instance.java = Utils.getJvmMain(Path.of(System.getProperty("java.home"))).toAbsolutePath().toString();
customJavaPath.set(instance.java);
} else {
instance.java = null;
}
save();
}
if (customJava.get() && ImGui.inputText("Path", customJavaPath)) {
instance.java = customJavaPath.get();;
save();
}
ImGui.text("Did you know that every instance in Inceptum is a git repository?");
ImGui.endTabItem();
}
if (instance.isFabric() && ImGui.beginTabItem("Mods")) {
//TODO implement
ImGui.text("Mod editing is not currently implemented");
ImGui.text("Please be patient");
ImGui.endTabItem();
@ -59,4 +79,12 @@ public class InstanceEditWindow extends Window {
ImGui.endTabBar();
}
}
private void save() {
try {
Utils.writeObject(path.resolve("instance.json"), instance);
} catch (IOException e) {
Inceptum.LOGGER.error("Could not write instance config", e);
}
}
}

View File

@ -26,6 +26,7 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
public class MainWindow extends Window {
private final ImBoolean darkTheme = new ImBoolean(Inceptum.CONFIG.darkTheme);
@ -47,6 +48,10 @@ public class MainWindow extends Window {
if (ImGui.menuItem("New Instance")) Inceptum.open(new NewInstanceWindow());
if (ImGui.menuItem("Re-download resources")) {
try {
Utils.clearDirectory(Inceptum.ASSETS_DIR);
Utils.clearDirectory(Inceptum.LIBRARIES_DIR);
Utils.clearDirectory(Inceptum.NATIVES_DIR);
Utils.clearDirectory(Inceptum.CACHE_DIR);
Files.list(Inceptum.INSTANCE_DIR).forEach(p -> {
try {
if (Files.exists(p.resolve("inceptum.setup.lock"))) return;
@ -59,7 +64,7 @@ public class MainWindow extends Window {
LoaderInfo li = im.isFabric()
? new LoaderInfo(LoaderInfo.Type.Fabric, im.getLoaderVersion())
: LoaderInfo.NONE;
SetupStepInfo info = new SetupStepInfo(vi, li, p.getFileName().toString());
SetupStepInfo info = new SetupStepInfo(vi, li, p.getFileName().toString(), new AtomicReference<>("Reloading"));
for (Step step : Steps.STEPS) {
step.execute(info, new AtomicBoolean(false));
}
@ -115,6 +120,7 @@ public class MainWindow extends Window {
List<Path> paths;
try {
if (!Files.exists(Inceptum.INSTANCE_DIR)) Files.createDirectories(Inceptum.INSTANCE_DIR);
paths = Files.list(Inceptum.INSTANCE_DIR).filter(Files::isDirectory).toList();
} catch (IOException e) {
Inceptum.LOGGER.error("Could not list instances");

View File

@ -1,123 +1,33 @@
package io.gitlab.jfronny.inceptum.windows;
import imgui.ImGui;
import imgui.type.ImBoolean;
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.api.FabricMetaApi;
import io.gitlab.jfronny.inceptum.util.api.McApi;
import io.gitlab.jfronny.inceptum.util.Utils;
import io.gitlab.jfronny.inceptum.windows.control.InstanceManageControls;
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;
import java.util.concurrent.atomic.AtomicReference;
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("", MAX_NAME_LENGTH);
ImInt fabricVersion = new ImInt(0);
ImBoolean snapshots = new ImBoolean(Inceptum.CONFIG.snapshots);
ImBoolean fabric = new ImBoolean(true);
InstanceManageControls imc = new InstanceManageControls();
public NewInstanceWindow() {
super("New Instance");
selected = getVersions(false).get(0);
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
public void draw() {
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 (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());
}
}
}
imc.snapshotsBox();
imc.versionBox(ver -> {});
//TODO forge
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")) {
imc.nameBox("OK", name -> {
close();
try {
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())));
Inceptum.open(new InstanceCreateProcessWindow(new SetupStepInfo(imc.getVersionInfo(),
imc.getLoaderInfo(),
name,
new AtomicReference<>("Initializing"))));
} catch (IOException e) {
Inceptum.LOGGER.error("Could not initialize instance creation", e);
}
}
}
private List<VersionsListInfo> getVersions(boolean snapshots) {
ArrayList<VersionsListInfo> res = new ArrayList<>(manifest.versions);
res.removeIf(info -> !snapshots && !info.type.equals("release"));
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;
});
}
}

View File

@ -4,10 +4,12 @@ import imgui.flag.ImGuiWindowFlags;
import imgui.type.ImBoolean;
import io.gitlab.jfronny.inceptum.Inceptum;
public abstract class Window {
import java.io.Closeable;
public abstract class Window implements Closeable {
private final String name;
private final ImBoolean openState = new ImBoolean(true);
private boolean isNew = true;
private ImBoolean openState = new ImBoolean(true);
public Window(String name) {
this.name = name;
@ -21,6 +23,7 @@ public abstract class Window {
return name;
}
@Override
public void close() {
openState.set(false);
Inceptum.WINDOWS.remove(this);

View File

@ -0,0 +1,147 @@
package io.gitlab.jfronny.inceptum.windows.control;
import imgui.ImGui;
import imgui.type.ImBoolean;
import imgui.type.ImInt;
import imgui.type.ImString;
import io.gitlab.jfronny.inceptum.Inceptum;
import io.gitlab.jfronny.inceptum.model.fabric.FabricVersionLoaderInfo;
import io.gitlab.jfronny.inceptum.model.inceptum.LoaderInfo;
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 io.gitlab.jfronny.inceptum.util.api.FabricMetaApi;
import io.gitlab.jfronny.inceptum.util.api.McApi;
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;
import java.util.function.Consumer;
public class InstanceManageControls {
public static final int MAX_NAME_LENGTH = 128;
private final VersionsList manifest = McApi.getVersions();
private final Map<VersionsListInfo, List<FabricVersionLoaderInfo>> loaderInfoCache = new HashMap<>();
private final Map<VersionsListInfo, VersionInfo> versionInfoCache = new HashMap<>();
private final ImInt version = new ImInt(0);
private final ImString name = new ImString("", MAX_NAME_LENGTH);
private final ImInt fabricVersion = new ImInt(0);
private final ImBoolean snapshots = new ImBoolean(Inceptum.CONFIG.snapshots);
private final ImBoolean fabric = new ImBoolean(true);
private VersionsListInfo selected;
private FabricVersionLoaderInfo selectedFabric;
public InstanceManageControls() {
selected = getVersions(false).get(0);
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;
}
}
}
public void nameBox(String okText, Consumer<String> ok) {
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(okText)) {
ok.accept(name.get());
}
}
public void snapshotsBox() {
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);
}
}
public void versionBox(Consumer<String> modifiedVersion) {
List<VersionsListInfo> vil = getVersions(Inceptum.CONFIG.snapshots);
String originalStr = null;
try {
originalStr = getVersionInfo().id;
} catch (IOException e) {
Inceptum.LOGGER.error("Could not get version string", e);
}
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()));
}
}
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());
}
}
}
try {
if (originalStr != null && !originalStr.equals(getVersionInfo().id))
modifiedVersion.accept(getVersionInfo().id);
} catch (IOException e) {
Inceptum.LOGGER.error("Could not compare version string", e);
}
}
public VersionInfo getVersionInfo() throws IOException {
if (!versionInfoCache.containsKey(selected)) {
VersionInfo vi = McApi.getVersionInfo(selected);
if (fabric.get()) FabricMetaApi.addFabric(vi, selectedFabric.loader.version);
versionInfoCache.put(selected, vi);
}
return versionInfoCache.get(selected);
}
public LoaderInfo getLoaderInfo() {
return fabric.get() ? new LoaderInfo(selectedFabric.loader) : LoaderInfo.NONE;
}
private List<VersionsListInfo> getVersions(boolean snapshots) {
ArrayList<VersionsListInfo> res = new ArrayList<>(manifest.versions);
res.removeIf(info -> !snapshots && !info.type.equals("release"));
return res;
}
private String getDefaultName(VersionsListInfo info, boolean fabric) {
return fabric ? "Fabric " + info.id : info.id;
}
private List<FabricVersionLoaderInfo> getFabricLoaderInfo() {
if (!loaderInfoCache.containsKey(selected))
loaderInfoCache.put(selected, FabricMetaApi.getLoaderVersions(selected));
return loaderInfoCache.get(selected);
}
}

View File

@ -3,6 +3,7 @@ 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.install.steps.DownloadLibrariesStep;
import io.gitlab.jfronny.inceptum.model.inceptum.ArtifactInfo;
import io.gitlab.jfronny.inceptum.model.inceptum.InstanceMeta;
import io.gitlab.jfronny.inceptum.model.mojang.MinecraftArgument;
@ -22,6 +23,9 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
public class InstanceView {
public static void draw(List<Path> paths) {
@ -59,7 +63,7 @@ public class InstanceView {
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 (ImGui.button("Edit##" + path)) Inceptum.open(new InstanceEditWindow(path, instance));
if (disabled) ImGui.endDisabled();
}
ImGui.endTable();
@ -71,12 +75,16 @@ public class InstanceView {
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());
}
args.add(Objects.requireNonNullElseGet(instance.java, () ->
Utils.getJvmMain(Inceptum.NATIVES_DIR
.resolve(info.javaVersion.component)
.resolve(Integer.toString(info.javaVersion.majorVersion)))
.toAbsolutePath().toString()));
DownloadLibrariesStep.execute(info, new AtomicBoolean(false), new AtomicReference<>());
StringBuilder classPath = new StringBuilder();
for (ArtifactInfo artifact : VersionInfoLibraryResolver.getRelevant(info)) {
classPath.append(Inceptum.LIBRARIES_DIR.resolve(artifact.path).toAbsolutePath());
@ -94,11 +102,15 @@ public class InstanceView {
}
args.add(info.mainClass);
if (info.arguments != null) args.addAll(parse(info.arguments.game, info, instance, classPath.toString(), path.toAbsolutePath().toString()));
else {
else if (info.minecraftArguments != null) {
for (String s : info.minecraftArguments.split(" ")) {
args.add(expandArg(s, info, instance, classPath.toString(), path.toAbsolutePath().toString()));
}
}
else {
Inceptum.LOGGER.error("Could not launch: No valid argument source found");
return;
}
Inceptum.LOGGER.info(String.join(" ", args));
ProcessBuilder pb = new ProcessBuilder(args.toArray(new String[0]));
pb.directory(path.toFile());

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} %boldCyan(%-34.-34thread) %red(%10.10X{jda.shard}) %boldGreen(%-15.-15logger{0}) %highlight(%-6level) %msg%n</pattern>
</encoder>
</appender>
<appender name="MapAppender" class="io.gitlab.jfronny.inceptum.util.MapAppender">
</appender>
<root level="info">
<appender-ref ref="STDOUT" />
<appender-ref ref="MapAppender" />
</root>
</configuration>