Actually launch minecraft
This commit is contained in:
parent
c9f824d673
commit
f159efbc05
|
@ -2,4 +2,5 @@
|
|||
.idea/
|
||||
build/
|
||||
run/
|
||||
imgui.ini
|
||||
imgui.ini
|
||||
hs_err_pid*
|
|
@ -7,6 +7,7 @@ import imgui.ImGuiIO;
|
|||
import imgui.flag.ImGuiConfigFlags;
|
||||
import imgui.gl3.ImGuiImplGl3;
|
||||
import imgui.glfw.ImGuiImplGlfw;
|
||||
import io.gitlab.jfronny.glaunch.gson.GsonIgnoreExclusionStrategy;
|
||||
import io.gitlab.jfronny.glaunch.gson.MinecraftArgumentDeserializer;
|
||||
import io.gitlab.jfronny.glaunch.gson.RulesDeserializer;
|
||||
import io.gitlab.jfronny.glaunch.model.MinecraftArgument;
|
||||
|
@ -24,6 +25,7 @@ import org.lwjgl.system.MemoryUtil;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.nio.IntBuffer;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
@ -42,6 +44,10 @@ public class GLaunch {
|
|||
public static final Gson GSON = new GsonBuilder()
|
||||
.registerTypeAdapter(MinecraftArgument.class, new MinecraftArgumentDeserializer())
|
||||
.registerTypeAdapter(Rules.class, new RulesDeserializer())
|
||||
.excludeFieldsWithModifiers(Modifier.TRANSIENT)
|
||||
.excludeFieldsWithModifiers(Modifier.PRIVATE)
|
||||
.addSerializationExclusionStrategy(new GsonIgnoreExclusionStrategy())
|
||||
.setPrettyPrinting()
|
||||
.create();
|
||||
//TODO allow moving to .config or elsewhere
|
||||
public static final Path CACHE_DIR = Path.of("run/cache");
|
||||
|
@ -229,7 +235,7 @@ public class GLaunch {
|
|||
}
|
||||
|
||||
public static void exit() {
|
||||
GLFW.glfwSetWindowShouldClose(handle, true); //TODO fix hs_error_pid
|
||||
GLFW.glfwSetWindowShouldClose(handle, true);
|
||||
}
|
||||
public static void applyTheme() {
|
||||
if (CONFIG.darkTheme) ImGui.styleColorsDark();
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
package io.gitlab.jfronny.glaunch.gson;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
public @interface GsonIgnore {
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package io.gitlab.jfronny.glaunch.gson;
|
||||
|
||||
import com.google.gson.ExclusionStrategy;
|
||||
import com.google.gson.FieldAttributes;
|
||||
|
||||
public class GsonIgnoreExclusionStrategy implements ExclusionStrategy {
|
||||
@Override
|
||||
public boolean shouldSkipClass(Class<?> clazz) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldSkipField(FieldAttributes f) {
|
||||
return f.getAnnotation(GsonIgnore.class) != null;
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@ import io.gitlab.jfronny.glaunch.install.SetupStepInfo;
|
|||
import io.gitlab.jfronny.glaunch.install.Step;
|
||||
import io.gitlab.jfronny.glaunch.model.VersionInfo;
|
||||
import io.gitlab.jfronny.glaunch.util.Utils;
|
||||
import io.gitlab.jfronny.glaunch.util.VersionInfoLibraryResolver;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
|
@ -13,25 +14,13 @@ import java.nio.file.Path;
|
|||
public class DownloadLibrariesStep implements Step {
|
||||
@Override
|
||||
public void execute(SetupStepInfo info) throws IOException {
|
||||
for (VersionInfo.Library library : info.version().libraries) {
|
||||
if (library.rules != null && !library.rules.allow()) continue;
|
||||
if (library.downloads.classifiers != null && library.natives != null && library.natives.containsKey(Utils.OS)) {
|
||||
downloadLib(library.downloads.classifiers.get(library.natives.get(Utils.OS)));
|
||||
}
|
||||
if (library.downloads.artifact == null) {
|
||||
GLaunch.LOGGER.info("Null library artifact @ " + library.name);
|
||||
continue;
|
||||
}
|
||||
downloadLib(library.downloads.artifact);
|
||||
for (VersionInfo.Library.Downloads.Artifact artifact : VersionInfoLibraryResolver.getRelevant(info.version())) {
|
||||
Path path = GLaunch.LIBRARIES_DIR.resolve(artifact.path);
|
||||
if (Files.exists(path)) return;
|
||||
//TODO allow maven-like download for fabric
|
||||
GLaunch.LOGGER.info("Downloading library: " + artifact.path);
|
||||
if (!Files.exists(path.getParent())) Files.createDirectories(path.getParent());
|
||||
Utils.downloadFile(artifact.url, artifact.sha1, path);
|
||||
}
|
||||
}
|
||||
|
||||
private void downloadLib(VersionInfo.Library.Downloads.Artifact artifact) throws IOException {
|
||||
Path path = GLaunch.LIBRARIES_DIR.resolve(artifact.path);
|
||||
if (Files.exists(path)) return;
|
||||
//TODO allow maven-like download for fabric
|
||||
GLaunch.LOGGER.info("Downloading library: " + artifact.path);
|
||||
if (!Files.exists(path.getParent())) Files.createDirectories(path.getParent());
|
||||
Utils.downloadFile(artifact.url, artifact.sha1, path);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
package io.gitlab.jfronny.glaunch.model;
|
||||
|
||||
import io.gitlab.jfronny.glaunch.gson.GsonIgnore;
|
||||
import io.gitlab.jfronny.glaunch.windows.NewInstanceWindow;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class InstanceMeta {
|
||||
public NewInstanceWindow.LoaderType loaderType;
|
||||
public String version;
|
||||
@GsonIgnore public Path instancePath;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
package io.gitlab.jfronny.glaunch.util;
|
||||
|
||||
import io.gitlab.jfronny.glaunch.GLaunch;
|
||||
import io.gitlab.jfronny.glaunch.model.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<>();
|
||||
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)));
|
||||
}
|
||||
if (library.downloads.artifact == null) {
|
||||
GLaunch.LOGGER.info("Null library artifact @ " + library.name);
|
||||
continue;
|
||||
}
|
||||
artifacts.add(library.downloads.artifact);
|
||||
}
|
||||
return artifacts;
|
||||
}
|
||||
}
|
|
@ -10,6 +10,7 @@ public class LogWindow extends Window {
|
|||
|
||||
@Override
|
||||
public void draw() {
|
||||
//TODO autoscroll
|
||||
MapAppender.LOG.forEach(ImGui::textUnformatted);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,15 +1,45 @@
|
|||
package io.gitlab.jfronny.glaunch.windows;
|
||||
|
||||
import imgui.ImGui;
|
||||
import imgui.flag.ImGuiTableFlags;
|
||||
import imgui.flag.ImGuiWindowFlags;
|
||||
import imgui.type.ImBoolean;
|
||||
import io.gitlab.jfronny.glaunch.GLaunch;
|
||||
import io.gitlab.jfronny.glaunch.model.InstanceMeta;
|
||||
import io.gitlab.jfronny.glaunch.model.MinecraftArgument;
|
||||
import io.gitlab.jfronny.glaunch.model.VersionInfo;
|
||||
import io.gitlab.jfronny.glaunch.model.VersionsListInfo;
|
||||
import io.gitlab.jfronny.glaunch.util.Utils;
|
||||
import io.gitlab.jfronny.glaunch.util.VersionInfoLibraryResolver;
|
||||
import io.gitlab.jfronny.glaunch.util.mojang.McApi;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class MainWindow extends Window {
|
||||
private final ImBoolean darkTheme = new ImBoolean(GLaunch.CONFIG.darkTheme);
|
||||
private final ImBoolean debugTools = new ImBoolean(false);
|
||||
private final List<InstanceMeta> instances; //TODO custom ordering
|
||||
public MainWindow() {
|
||||
super("GLaunch");
|
||||
List<InstanceMeta> instances = new ArrayList<>();
|
||||
try {
|
||||
for (Path path : Files.list(GLaunch.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 {
|
||||
GLaunch.LOGGER.error("Invalid instance (doesn't contain instance.json): " + path);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
GLaunch.LOGGER.error("Could not list present instances", e);
|
||||
}
|
||||
this.instances = List.copyOf(instances);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -45,8 +75,82 @@ public class MainWindow extends Window {
|
|||
ImGui.showDemoWindow();
|
||||
}
|
||||
|
||||
//TODO if no instance
|
||||
ImGui.text("You have not yet created an instance");
|
||||
ImGui.text("Use File->New Instance to do so");
|
||||
if (instances.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) {
|
||||
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(GLaunch.LIBRARIES_DIR.resolve(artifact.path).toAbsolutePath());
|
||||
classPath.append(':');
|
||||
}
|
||||
classPath.append(GLaunch.LIBRARIES_DIR.resolve("net/minecraft/minecraft").resolve(version.id + ".jar").toAbsolutePath());
|
||||
GLaunch.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()));
|
||||
//Process p = Runtime.getRuntime().exec(args.toArray(new String[0]), new String[0], instance.instancePath.toFile());
|
||||
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.tableNextColumn();
|
||||
if (ImGui.button("Edit")) {
|
||||
GLaunch.LOGGER.error("Editing not yet implemented"); //TODO allow changing name (moving), changing version, managing mods etc
|
||||
}
|
||||
}
|
||||
ImGui.endTable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> parse(List<MinecraftArgument> arguments, VersionInfo info, InstanceMeta instance, String classPath) {
|
||||
List<String> res = new ArrayList<>();
|
||||
for (MinecraftArgument argument : arguments) {
|
||||
for (String s : argument.arg()) {
|
||||
//TODO support old versions
|
||||
res.add(s
|
||||
// game args
|
||||
.replace("${auth_player_name}", "Joe") //TODO auth support
|
||||
.replace("${version_name}", info.id) //TODO fabric support
|
||||
.replace("${game_directory}", instance.instancePath.toAbsolutePath().toString())
|
||||
.replace("${assets_root}", GLaunch.ASSETS_DIR.toAbsolutePath().toString())
|
||||
.replace("${assets_index_name}", info.assets)
|
||||
.replace("${auth_uuid}", "2536abce90e8476a871679918164abc5") //TODO auth support
|
||||
.replace("${auth_access_token}", "99abe417230342cb8e9e2168ab46297a") //TODO auth support
|
||||
.replace("${user_type}", "legacy") //TODO auth support
|
||||
.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}", GLaunch.INSTANCE_DIR.toAbsolutePath().toString())
|
||||
.replace("${launcher_name}", "GLaunch")
|
||||
.replace("${launcher_version}", "1.0") //TODO automatically fill in
|
||||
.replace("${classpath}", classPath)
|
||||
);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue