Switch to gson-compile
This commit is contained in:
parent
841fa6b3d4
commit
7ce6a764ec
|
@ -12,7 +12,8 @@ allprojects {
|
|||
|
||||
val lwjglVersion by extra("3.3.1")
|
||||
val imguiVersion by extra("1.86.4")
|
||||
val jfCommonsVersion by extra("2022.9.18+16-50-22")
|
||||
val jfCommonsVersion by extra("2022.11.1+18-31-34")
|
||||
val gsonCompileVersion by extra("1.0-SNAPSHOT")
|
||||
val jlhttpVersion by extra("2.6")
|
||||
val flavorProp: String by extra(prop("flavor", "custom"))
|
||||
if (!setOf("custom", "maven", "fat", "windows", "linux", "macos").contains(flavorProp)) throw IllegalStateException("Unsupported flavor: $flavorProp")
|
||||
|
@ -34,7 +35,7 @@ tasks.register("exportMetadata") {
|
|||
"jvm": ${project(":common").extra["javaVersion"]},
|
||||
"repositories": [
|
||||
"https://repo.maven.apache.org/maven2/",
|
||||
"https://gitlab.com/api/v4/projects/35745143/packages/maven"
|
||||
"https://maven.frohnmeyer-wds.de/artifacts/"
|
||||
],
|
||||
"natives": {
|
||||
"windows": [
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
import org.gradle.kotlin.dsl.extra
|
||||
|
||||
plugins {
|
||||
id("inceptum.library-conventions")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api("io.gitlab.jfronny.gson:gson-compile-core:${rootProject.extra["gsonCompileVersion"]}")
|
||||
compileOnly("io.gitlab.jfronny.gson:gson-compile-annotations:${rootProject.extra["gsonCompileVersion"]}")
|
||||
annotationProcessor("io.gitlab.jfronny.gson:gson-compile-processor:${rootProject.extra["gsonCompileVersion"]}")
|
||||
}
|
||||
|
||||
tasks.withType<JavaCompile> {
|
||||
options.compilerArgs.add("-AgsonCompileNoReflect")
|
||||
}
|
|
@ -3,6 +3,7 @@ import io.gitlab.jfronny.scripts.*
|
|||
plugins {
|
||||
id("inceptum.library-conventions")
|
||||
id("jf.codegen")
|
||||
id("inceptum.gson-compile")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
package io.gitlab.jfronny.inceptum.common;
|
||||
|
||||
import io.gitlab.jfronny.commons.serialize.gson.api.GsonHolder;
|
||||
import io.gitlab.jfronny.gson.stream.*;
|
||||
import io.gitlab.jfronny.inceptum.common.model.inceptum.UpdateChannel;
|
||||
|
||||
import java.io.*;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
|
@ -32,8 +31,8 @@ public class InceptumConfig {
|
|||
saveConfig();
|
||||
}
|
||||
}
|
||||
try (Reader reader = Files.newBufferedReader(MetaHolder.CONFIG_PATH);
|
||||
JsonReader jr = GsonHolder.getGson().newJsonReader(reader)) {
|
||||
try (JsonReader jr = new JsonReader(Files.newBufferedReader(MetaHolder.CONFIG_PATH))) {
|
||||
jr.setLenient(true);
|
||||
jr.beginObject();
|
||||
while (jr.peek() != JsonToken.END_OBJECT) {
|
||||
String name = null;
|
||||
|
@ -70,8 +69,10 @@ public class InceptumConfig {
|
|||
}
|
||||
|
||||
public static void saveConfig() {
|
||||
try (Writer writer = Files.newBufferedWriter(MetaHolder.CONFIG_PATH);
|
||||
JsonWriter jw = GsonHolder.getGson().newJsonWriter(writer)) {
|
||||
try (JsonWriter jw = new JsonWriter(Files.newBufferedWriter(MetaHolder.CONFIG_PATH))) {
|
||||
jw.setLenient(true);
|
||||
jw.setOmitQuotes(true);
|
||||
jw.setIndent(" ");
|
||||
jw.beginObject()
|
||||
.comment("Whether to show snapshots in the version selector for new instances")
|
||||
.name("snapshots").value(snapshots)
|
||||
|
|
|
@ -3,7 +3,6 @@ package io.gitlab.jfronny.inceptum.common;
|
|||
import io.gitlab.jfronny.commons.HttpUtils;
|
||||
import io.gitlab.jfronny.commons.log.Logger;
|
||||
import io.gitlab.jfronny.commons.log.StdoutLogger;
|
||||
import io.gitlab.jfronny.commons.serialize.gson.api.GsonHolder;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
|
@ -11,7 +10,6 @@ public class InceptumEnvironmentInitializer {
|
|||
public static void initialize() throws IOException {
|
||||
Logger.registerFactory(InceptumEnvironmentInitializer::defaultFactory);
|
||||
HttpUtils.setUserAgent("jfmods/inceptum/" + BuildMetadata.VERSION);
|
||||
GsonHolder.register();
|
||||
InceptumConfig.load();
|
||||
}
|
||||
|
||||
|
|
|
@ -2,13 +2,11 @@ package io.gitlab.jfronny.inceptum.common;
|
|||
|
||||
import io.gitlab.jfronny.commons.HashUtils;
|
||||
import io.gitlab.jfronny.commons.HttpUtils;
|
||||
import io.gitlab.jfronny.commons.cache.FileBackedOperationResultCache;
|
||||
import io.gitlab.jfronny.commons.serialize.gson.api.GsonHolder;
|
||||
import io.gitlab.jfronny.commons.throwable.ThrowingFunction;
|
||||
import io.gitlab.jfronny.commons.throwable.ThrowingSupplier;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Type;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
@ -17,7 +15,7 @@ import java.nio.file.Path;
|
|||
import java.util.Map;
|
||||
|
||||
public class Net {
|
||||
private static final FileBackedOperationResultCache OBJECT_CACHE = new FileBackedOperationResultCache(MetaHolder.CACHE_DIR);
|
||||
private static final ObjectCache OBJECT_CACHE = new ObjectCache(MetaHolder.CACHE_DIR);
|
||||
|
||||
public static byte[] downloadData(String url) throws IOException, URISyntaxException {
|
||||
try (InputStream is = HttpUtils.get(url).sendInputStream()) {
|
||||
|
@ -32,38 +30,30 @@ public class Net {
|
|||
return buf;
|
||||
}
|
||||
|
||||
public static <T> T downloadObject(String url, Class<T> type) throws IOException {
|
||||
return downloadObject(url, type, true);
|
||||
public static <T> T downloadObject(String url, ThrowingFunction<String, T, IOException> func) throws IOException {
|
||||
return downloadObject(url, func, true);
|
||||
}
|
||||
|
||||
public static <T> T downloadObject(String url, Class<T> type, boolean cache) throws IOException {
|
||||
return downloadObject(url, () -> HttpUtils.get(url).sendString(), type, cache);
|
||||
public static <T> T downloadObject(String url, ThrowingFunction<String, T, IOException> func, boolean cache) throws IOException {
|
||||
return downloadObject(url, () -> HttpUtils.get(url).sendString(), func, cache);
|
||||
}
|
||||
|
||||
public static <T> T downloadObject(String url, Type type) throws IOException {
|
||||
return downloadObject(url, type, true);
|
||||
public static <T> T downloadObject(String url, ThrowingFunction<String, T, IOException> func, String apiKey) throws IOException {
|
||||
return downloadObject(url, () -> HttpUtils.get(url).header("x-api-key", apiKey).sendString(), func, true);
|
||||
}
|
||||
|
||||
public static <T> T downloadObject(String url, Type type, String apiKey) throws IOException {
|
||||
return downloadObject(url, () -> HttpUtils.get(url).header("x-api-key", apiKey).sendString(), type, true);
|
||||
public static <T> T downloadObject(String url, String sha1, ThrowingFunction<String, T, IOException> func) throws IOException {
|
||||
return downloadObject(url, sha1, func, true);
|
||||
}
|
||||
|
||||
public static <T> T downloadObject(String url, Type type, boolean cache) throws IOException {
|
||||
return downloadObject(url, () -> HttpUtils.get(url).sendString(), type, cache);
|
||||
public static <T> T downloadObject(String url, String sha1, ThrowingFunction<String, T, IOException> func, boolean cache) throws IOException {
|
||||
return downloadObject(url, () -> downloadString(url, sha1), func, cache);
|
||||
}
|
||||
|
||||
public static <T> T downloadObject(String url, String sha1, Class<T> type) throws IOException {
|
||||
return downloadObject(url, sha1, type, true);
|
||||
}
|
||||
|
||||
public static <T> T downloadObject(String url, String sha1, Class<T> type, boolean cache) throws IOException {
|
||||
return downloadObject(url, () -> downloadString(url, sha1), type, cache);
|
||||
}
|
||||
|
||||
private static <T> T downloadObject(String url, ThrowingSupplier<String, Exception> sourceString, Type type, boolean cache) throws IOException {
|
||||
private static <T> T downloadObject(String url, ThrowingSupplier<String, Exception> sourceString, ThrowingFunction<String, T, IOException> func, boolean cache) throws IOException {
|
||||
try {
|
||||
ThrowingSupplier<T, Exception> builder = () -> GsonHolder.getGson().fromJson(sourceString.get(), type);
|
||||
return cache ? OBJECT_CACHE.get(HashUtils.sha1(url.getBytes(StandardCharsets.UTF_8)), builder, type) : builder.get();
|
||||
ThrowingSupplier<T, Exception> builder = () -> func.apply(sourceString.get());
|
||||
return cache ? OBJECT_CACHE.get(HashUtils.sha1(url.getBytes(StandardCharsets.UTF_8)), sourceString, func) : builder.get();
|
||||
} catch (Exception e) {
|
||||
throw new IOException("Could not download object and no cache exists", e);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
package io.gitlab.jfronny.inceptum.common;
|
||||
|
||||
import io.gitlab.jfronny.commons.io.JFiles;
|
||||
import io.gitlab.jfronny.commons.throwable.ThrowingFunction;
|
||||
import io.gitlab.jfronny.commons.throwable.ThrowingSupplier;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class ObjectCache {
|
||||
private final ConcurrentHashMap<String, Object> container = new ConcurrentHashMap<>();
|
||||
private final Path cacheDir;
|
||||
|
||||
public ObjectCache(Path cacheDir) {
|
||||
this.cacheDir = cacheDir;
|
||||
}
|
||||
|
||||
public void remove(String key) throws IOException {
|
||||
container.remove(key);
|
||||
Files.delete(cacheDir.resolve(key));
|
||||
}
|
||||
|
||||
public void clear() throws IOException {
|
||||
container.clear();
|
||||
JFiles.clearDirectory(cacheDir);
|
||||
}
|
||||
|
||||
public <T, TEx extends Throwable> T get(String key, ThrowingSupplier<String, ? extends TEx> download, ThrowingFunction<String, T, ? extends TEx> builder) throws IOException, TEx {
|
||||
if (!container.containsKey(key)) {
|
||||
Path cd = cacheDir.resolve(key);
|
||||
if (Files.exists(cd)) container.put(key, builder.apply(Files.readString(cd)));
|
||||
else container.put(key, builder.apply(download.get()));
|
||||
}
|
||||
//noinspection unchecked
|
||||
return (T) container.get(key);
|
||||
}
|
||||
}
|
|
@ -2,7 +2,6 @@ package io.gitlab.jfronny.inceptum.common;
|
|||
|
||||
import io.gitlab.jfronny.commons.ComparableVersion;
|
||||
import io.gitlab.jfronny.commons.OSUtils;
|
||||
import io.gitlab.jfronny.commons.io.JFiles;
|
||||
import io.gitlab.jfronny.inceptum.common.api.GitlabApi;
|
||||
import io.gitlab.jfronny.inceptum.common.api.MavenApi;
|
||||
import io.gitlab.jfronny.inceptum.common.model.gitlab.*;
|
||||
|
@ -62,7 +61,7 @@ public class Updater {
|
|||
config.natives.put(Utils.getCurrentFlavor(), natives);
|
||||
}
|
||||
|
||||
JFiles.writeObject(MetaHolder.WRAPPER_CONFIG_PATH, config);
|
||||
GC_WrapperConfig.write(MetaHolder.WRAPPER_CONFIG_PATH, config);
|
||||
|
||||
if (relaunch) {
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
|
||||
|
@ -103,7 +102,7 @@ public class Updater {
|
|||
}
|
||||
}
|
||||
|
||||
if (configChanged) JFiles.writeObject(MetaHolder.WRAPPER_CONFIG_PATH, wrapperConfig);
|
||||
if (configChanged) GC_WrapperConfig.write(MetaHolder.WRAPPER_CONFIG_PATH, wrapperConfig);
|
||||
|
||||
return buildClasspath(Stream.concat(libs.stream(), natives.stream())).toList();
|
||||
}
|
||||
|
@ -152,16 +151,16 @@ public class Updater {
|
|||
UpdateMetadata stable = null;
|
||||
packageLoop:for (GitlabPackage info : GitlabApi.getPackages(project)) {
|
||||
if (info.status.equals("default") && info.name.equals("io/gitlab/jfronny/inceptum/Inceptum")) {
|
||||
pipelineLoop:for (GitlabPipeline pipeline : info.pipelines) {
|
||||
if (!pipeline.ref.equals("master")) continue pipelineLoop;
|
||||
for (GitlabPipeline pipeline : info.pipelines) {
|
||||
if (!pipeline.ref.equals("master")) continue;
|
||||
if (!pipeline.status.equals("success")) {
|
||||
Utils.LOGGER.warn("Skipping failed CI build");
|
||||
continue pipelineLoop;
|
||||
continue;
|
||||
}
|
||||
for (GitlabJob job : GitlabApi.getJobs(project, pipeline.id)) {
|
||||
if (!job.name.equals("build_test")) continue;
|
||||
try {
|
||||
UpdateMetadata update = Net.downloadObject(GitlabApi.PROJECTS + project.id + "/jobs/" + job.id + "/artifacts/version.json", UpdateMetadata.class);
|
||||
UpdateMetadata update = Net.downloadObject(GitlabApi.PROJECTS + project.id + "/jobs/" + job.id + "/artifacts/version.json", GC_UpdateMetadata::read);
|
||||
if (update.jvm > jvm) {
|
||||
Utils.LOGGER.error("A newer JVM is required to use the latest inceptum version. Please update!");
|
||||
continue packageLoop;
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
package io.gitlab.jfronny.inceptum.common.api;
|
||||
|
||||
import io.gitlab.jfronny.commons.HttpUtils;
|
||||
import io.gitlab.jfronny.gson.reflect.TypeToken;
|
||||
import io.gitlab.jfronny.gson.compile.util.GList;
|
||||
import io.gitlab.jfronny.gson.stream.JsonReader;
|
||||
import io.gitlab.jfronny.inceptum.common.model.gitlab.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Type;
|
||||
import java.io.Reader;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
|
@ -16,32 +17,36 @@ public class GitlabApi {
|
|||
public static final long PROJECT_ID = 30862253L;
|
||||
public static final String PROJECT_MAVEN = "https://gitlab.com/api/v4/projects/" + PROJECT_ID + "/packages/maven/";
|
||||
|
||||
private static final Type packageInfoListType = new TypeToken<List<GitlabPackage>>() {}.getType();
|
||||
private static final Type jobListType = new TypeToken<List<GitlabJob>>() {}.getType();
|
||||
private static final Type packageFileInfoListType = new TypeToken<List<GitlabPackageFile>>() {}.getType();
|
||||
|
||||
public static GitlabProject getProject(Long projectId) throws IOException, URISyntaxException {
|
||||
return HttpUtils.get(PROJECTS + projectId).sendSerialized(GitlabProject.class);
|
||||
try (Reader r = HttpUtils.get(PROJECTS + projectId).sendReader()) {
|
||||
return GC_GitlabProject.read(r);
|
||||
}
|
||||
}
|
||||
|
||||
public static List<GitlabPackage> getPackages(GitlabProject project) throws IOException, URISyntaxException {
|
||||
return HttpUtils.get(PROJECTS + project.id + "/packages?order_by=created_at&sort=desc").sendSerialized(packageInfoListType);
|
||||
try (JsonReader r = new JsonReader(HttpUtils.get(PROJECTS + project.id + "/packages?order_by=created_at&sort=desc").sendReader())) {
|
||||
return GList.read(r, GC_GitlabPackage::read);
|
||||
}
|
||||
}
|
||||
|
||||
public static List<GitlabJob> getJobs(GitlabProject project, Long pipelineId) throws IOException, URISyntaxException {
|
||||
List<GitlabJob> list = HttpUtils.get(PROJECTS + project.id + "/pipelines/" + pipelineId + "/jobs").sendSerialized(jobListType);
|
||||
list.sort((left, right) -> right.created_at.compareTo(left.created_at));
|
||||
return list;
|
||||
try (JsonReader r = new JsonReader(HttpUtils.get(PROJECTS + project.id + "/pipelines/" + pipelineId + "/jobs").sendReader())) {
|
||||
List<GitlabJob> list = GList.read(r, GC_GitlabJob::read);
|
||||
list.sort((left, right) -> right.created_at.compareTo(left.created_at));
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
public static GitlabPackageFile getFile(GitlabProject project, GitlabPackage packageInfo, Predicate<GitlabPackageFile> isValid) throws IOException, URISyntaxException {
|
||||
int page = 0;
|
||||
while (true) {
|
||||
List<GitlabPackageFile> files = HttpUtils.get(PROJECTS + project.id + "/packages/" + packageInfo.id + "/package_files?per_page=100&page=" + ++page).sendSerialized(packageFileInfoListType);
|
||||
if (files.isEmpty()) return null;
|
||||
for (GitlabPackageFile file : files) {
|
||||
if (isValid.test(file))
|
||||
return file;
|
||||
try (JsonReader r = new JsonReader(HttpUtils.get(PROJECTS + project.id + "/packages/" + packageInfo.id + "/package_files?per_page=100&page=" + ++page).sendReader())) {
|
||||
List<GitlabPackageFile> files = GList.read(r, GC_GitlabPackageFile::read);
|
||||
if (files.isEmpty()) return null;
|
||||
for (GitlabPackageFile file : files) {
|
||||
if (isValid.test(file))
|
||||
return file;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package io.gitlab.jfronny.inceptum.common.model.gitlab;
|
||||
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
|
||||
@GSerializable
|
||||
public class GitlabArtifact {
|
||||
public String file_type;
|
||||
public Long size;
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
package io.gitlab.jfronny.inceptum.common.model.gitlab;
|
||||
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@GSerializable
|
||||
public class GitlabCommit {
|
||||
public String id;
|
||||
public String short_id;
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
package io.gitlab.jfronny.inceptum.common.model.gitlab;
|
||||
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@GSerializable
|
||||
public class GitlabJob {
|
||||
public Long id;
|
||||
public String status;
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
package io.gitlab.jfronny.inceptum.common.model.gitlab;
|
||||
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@GSerializable
|
||||
public class GitlabPackage {
|
||||
public Long id;
|
||||
public String name;
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
package io.gitlab.jfronny.inceptum.common.model.gitlab;
|
||||
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@GSerializable
|
||||
public class GitlabPackageFile {
|
||||
public Long id;
|
||||
public Long package_id;
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
package io.gitlab.jfronny.inceptum.common.model.gitlab;
|
||||
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@GSerializable
|
||||
public class GitlabPipeline {
|
||||
public long id;
|
||||
public long project_id;
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
package io.gitlab.jfronny.inceptum.common.model.gitlab;
|
||||
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@GSerializable
|
||||
public class GitlabProject {
|
||||
public Long id;
|
||||
public String description;
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package io.gitlab.jfronny.inceptum.common.model.gitlab;
|
||||
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
|
||||
@GSerializable
|
||||
public class GitlabRunner {
|
||||
public Long id;
|
||||
public String description;
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package io.gitlab.jfronny.inceptum.common.model.gitlab;
|
||||
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
|
||||
@GSerializable
|
||||
public class GitlabUser {
|
||||
public long id;
|
||||
public String name;
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
package io.gitlab.jfronny.inceptum.common.model.inceptum;
|
||||
|
||||
import io.gitlab.jfronny.commons.ComparableVersion;
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@GSerializable
|
||||
public class UpdateMetadata {
|
||||
public Integer wrapperVersion;
|
||||
public ComparableVersion version;
|
||||
|
@ -12,4 +14,12 @@ public class UpdateMetadata {
|
|||
public Integer jvm;
|
||||
public Set<String> repositories;
|
||||
public Map<String, Set<String>> natives;
|
||||
|
||||
// For serialization
|
||||
public String getVersion() {
|
||||
return version == null ? null : version.toString();
|
||||
}
|
||||
public void setVersion(String version) {
|
||||
this.version = new ComparableVersion(version);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
package io.gitlab.jfronny.inceptum.common.model.inceptum;
|
||||
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@GSerializable
|
||||
public class WrapperConfig {
|
||||
public Set<String> libraries;
|
||||
public Set<String> repositories;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
plugins {
|
||||
id("inceptum.library-conventions")
|
||||
id("inceptum.gson-compile")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
|
|
@ -1,16 +1,10 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher;
|
||||
|
||||
import io.gitlab.jfronny.commons.io.JFiles;
|
||||
import io.gitlab.jfronny.commons.serialize.gson.api.GsonHolder;
|
||||
import io.gitlab.jfronny.inceptum.common.*;
|
||||
import io.gitlab.jfronny.inceptum.launcher.api.McApi;
|
||||
import io.gitlab.jfronny.inceptum.launcher.api.account.MicrosoftAccount;
|
||||
import io.gitlab.jfronny.inceptum.launcher.gson.*;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.microsoft.OauthTokenResponse;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.mojang.MinecraftArgument;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.mojang.Rules;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.mds.ModsDirScanner;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.source.ModSource;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
|
@ -27,12 +21,6 @@ public class LauncherEnv {
|
|||
|
||||
updateBackend(backend);
|
||||
|
||||
GsonHolder.registerTypeAdapter(MinecraftArgument.class, new MinecraftArgumentDeserializer());
|
||||
GsonHolder.registerTypeAdapter(Rules.class, new RulesDeserializer());
|
||||
GsonHolder.registerTypeAdapter(OauthTokenResponse.class, new OauthTokenResponseDeserializer());
|
||||
GsonHolder.registerTypeAdapter(ModSource.class, new ModSourceTypeAdapter());
|
||||
GsonHolder.registerTypeAdapter(ModSourceMapDeserializer.modSourceMapType, new ModSourceMapDeserializer());
|
||||
|
||||
InceptumEnvironmentInitializer.initialize();
|
||||
|
||||
if (!Files.exists(MetaHolder.CACHE_DIR)) Files.createDirectories(MetaHolder.CACHE_DIR);
|
||||
|
|
|
@ -6,8 +6,7 @@ import io.gitlab.jfronny.inceptum.launcher.model.curseforge.CurseforgeFile;
|
|||
import io.gitlab.jfronny.inceptum.launcher.model.curseforge.CurseforgeMod;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.curseforge.response.*;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.*;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.*;
|
||||
|
||||
|
@ -39,7 +38,7 @@ public class CurseforgeApi {
|
|||
"gameVersion", gameVersion,
|
||||
"pageSize", Integer.toString(pageSize),
|
||||
"index", Integer.toString(page * pageSize)
|
||||
)), SearchResponse.class, API_KEY);
|
||||
)), GC_SearchResponse::read, API_KEY).data;
|
||||
}
|
||||
|
||||
public static CurseforgeMod getMod(String slug) throws IOException {
|
||||
|
@ -47,7 +46,7 @@ public class CurseforgeApi {
|
|||
"gameId", "432",
|
||||
"classId", "6",
|
||||
"slug", slug
|
||||
)), SearchResponse.class, API_KEY);
|
||||
)), GC_SearchResponse::read, API_KEY);
|
||||
if (response.pagination.totalCount != 1) {
|
||||
throw new FileNotFoundException("Could not find mod with slug \"" + slug + "\"");
|
||||
}
|
||||
|
@ -55,8 +54,7 @@ public class CurseforgeApi {
|
|||
}
|
||||
|
||||
public static CurseforgeMod getMod(int id) throws IOException {
|
||||
GetModResponse response = Net.downloadObject(API_URL + "mods/" + id, GetModResponse.class, API_KEY);
|
||||
return checkDistribution(response.data);
|
||||
return checkDistribution(Net.downloadObject(API_URL + "mods/" + id, GC_GetModResponse::read, API_KEY).data);
|
||||
}
|
||||
|
||||
private static CurseforgeMod checkDistribution(CurseforgeMod mod) {
|
||||
|
@ -68,13 +66,13 @@ public class CurseforgeApi {
|
|||
}
|
||||
|
||||
public static CurseforgeFile getFile(int modId, int fileId) throws IOException {
|
||||
GetModFileResponse response = Net.downloadObject(API_URL + "mods/" + modId + "/files/" + fileId, GetModFileResponse.class, API_KEY);
|
||||
return response.data;
|
||||
return Net.downloadObject(API_URL + "mods/" + modId + "/files/" + fileId, GC_GetModFileResponse::read, API_KEY).data;
|
||||
}
|
||||
|
||||
public static FingerprintMatchesResponse.Result checkFingerprint(long hash) throws IOException, URISyntaxException {
|
||||
FingerprintMatchesResponse response = HttpUtils.post(API_URL + "fingerprints").bodyJson("{\"fingerprints\":[" + hash + "]}").sendSerialized(FingerprintMatchesResponse.class);
|
||||
return response.data;
|
||||
try (Reader r = HttpUtils.post(API_URL + "fingerprints").bodyJson("{\"fingerprints\":[" + hash + "]}").sendReader()) {
|
||||
return GC_FingerprintMatchesResponse.read(r).data;
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] unsalt(byte[] data, int salt) {
|
||||
|
|
|
@ -1,30 +1,34 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.api;
|
||||
|
||||
import io.gitlab.jfronny.gson.reflect.TypeToken;
|
||||
import io.gitlab.jfronny.gson.compile.util.GList;
|
||||
import io.gitlab.jfronny.gson.stream.JsonReader;
|
||||
import io.gitlab.jfronny.inceptum.common.Net;
|
||||
import io.gitlab.jfronny.inceptum.common.api.MavenApi;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.fabric.FabricVersionLoaderInfo;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.fabric.*;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.mojang.*;
|
||||
import io.gitlab.jfronny.inceptum.launcher.util.GameVersionParser;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Type;
|
||||
import java.io.StringReader;
|
||||
import java.util.*;
|
||||
|
||||
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 Net.downloadObject(META_URL + "v2/versions/loader/" + version.id, fabricLoaderVersionListType);
|
||||
return Net.downloadObject(META_URL + "v2/versions/loader/" + version.id, s -> {
|
||||
try (JsonReader r = new JsonReader(new StringReader(s))) {
|
||||
return GList.read(r, GC_FabricVersionLoaderInfo::read);
|
||||
}
|
||||
});
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Could not get fabric loader versions", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static FabricVersionLoaderInfo getLoaderVersion(String gameVersion, String fabricVersion) throws IOException {
|
||||
return Net.downloadObject(META_URL + "v2/versions/loader/" + gameVersion + "/" + fabricVersion, FabricVersionLoaderInfo.WithMeta.class);
|
||||
return Net.downloadObject(META_URL + "v2/versions/loader/" + gameVersion + "/" + fabricVersion, GC_FabricVersionLoaderInfo_WithMeta::read);
|
||||
}
|
||||
|
||||
public static VersionInfo addFabric(VersionInfo version, String fabricVersion, FabricVersionInfoType type) throws IOException {
|
||||
|
|
|
@ -18,14 +18,14 @@ import static io.gitlab.jfronny.inceptum.common.Net.downloadObject;
|
|||
public class McApi {
|
||||
public static VersionsList getVersions() {
|
||||
try {
|
||||
return downloadObject("https://launchermeta.mojang.com/mc/game/version_manifest_v2.json", VersionsList.class);
|
||||
return downloadObject("https://launchermeta.mojang.com/mc/game/version_manifest_v2.json", GC_VersionsList::read);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Could not load version manifest", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static VersionInfo getVersionInfo(VersionsListInfo listInfo) throws IOException {
|
||||
return downloadObject(listInfo.url, listInfo.sha1, VersionInfo.class);
|
||||
return downloadObject(listInfo.url, listInfo.sha1, GC_VersionInfo::read);
|
||||
}
|
||||
|
||||
public static AssetIndex getAssetIndex(VersionInfo info) throws IOException, URISyntaxException {
|
||||
|
@ -37,12 +37,12 @@ public class McApi {
|
|||
} catch (IOException | URISyntaxException e) {
|
||||
if (!Files.exists(file)) throw e;
|
||||
}
|
||||
return JFiles.readObject(file, AssetIndex.class);
|
||||
return GC_AssetIndex.read(file);
|
||||
}
|
||||
|
||||
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#L123
|
||||
JvmInfo info = Net.downloadObject("https://launchermeta.mojang.com/v1/products/java-runtime/2ec0cc96c44e5a76b9c8b7c39df7210883d12871/all.json", JvmInfo.class);
|
||||
JvmInfo info = Net.downloadObject("https://launchermeta.mojang.com/v1/products/java-runtime/2ec0cc96c44e5a76b9c8b7c39df7210883d12871/all.json", GC_JvmInfo::read);
|
||||
Map<String, List<JvmInfo.Jvm>> vms = switch (OSUtils.TYPE) {
|
||||
case WINDOWS -> info.windowsX64;
|
||||
case LINUX -> info.linux;
|
||||
|
@ -53,14 +53,13 @@ public class McApi {
|
|||
throw new IOException("Invalid component: " + component + " (available: " + String.join(", ", vms.keySet()));
|
||||
for (JvmInfo.Jvm jvm : vmList) {
|
||||
if (jvm.version.name.startsWith(Integer.toString(majorVersion))) {
|
||||
return downloadObject(jvm.manifest.url, jvm.manifest.sha1, JvmFileInfo.class).files;
|
||||
return downloadObject(jvm.manifest.url, jvm.manifest.sha1, GC_JvmFileInfo::read).files;
|
||||
}
|
||||
}
|
||||
throw new IOException("JVM not found");
|
||||
}
|
||||
|
||||
public static void downloadAsset(AssetIndex.Asset asset, Path path) throws IOException, URISyntaxException {
|
||||
String url = "http://resources.download.minecraft.net/" + asset.hash.substring(0, 2) + "/" + asset.hash;
|
||||
Net.downloadFile(url, asset.hash, path);
|
||||
Net.downloadFile("http://resources.download.minecraft.net/" + asset.hash.substring(0, 2) + "/" + asset.hash, asset.hash, path);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.api;
|
||||
|
||||
import io.gitlab.jfronny.gson.compile.util.GList;
|
||||
import io.gitlab.jfronny.gson.reflect.TypeToken;
|
||||
import io.gitlab.jfronny.gson.stream.JsonReader;
|
||||
import io.gitlab.jfronny.inceptum.common.Net;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.modrinth.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.*;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.*;
|
||||
|
||||
public class ModrinthApi {
|
||||
private static final String API_HOST = "https://api.modrinth.com/";
|
||||
private static final int ITEMS_PER_PAGE = 20;
|
||||
private static final Type modrinthVersionListType = new TypeToken<List<ModrinthVersion>>() {}.getType();
|
||||
|
||||
//TODO search by categories: facets:[["versions:$ver","versions:$ver"],["categories:$cat","categories:$cat"]]
|
||||
//TODO filter server/client-only mods
|
||||
|
@ -22,24 +23,28 @@ public class ModrinthApi {
|
|||
"index", "relevance",
|
||||
"offset", Integer.toString(page * ITEMS_PER_PAGE),
|
||||
"limit", Integer.toString(ITEMS_PER_PAGE)
|
||||
)), ModrinthSearchResult.class);
|
||||
)), GC_ModrinthSearchResult::read);
|
||||
}
|
||||
|
||||
public static ModrinthProject getMod(String id) throws IOException {
|
||||
return Net.downloadObject(API_HOST + "v2/project/" + id, ModrinthProject.class);
|
||||
return Net.downloadObject(API_HOST + "v2/project/" + id, GC_ModrinthProject::read);
|
||||
}
|
||||
|
||||
public static List<ModrinthVersion> getVersions(String mod) throws IOException {
|
||||
List<ModrinthVersion> versions = Net.downloadObject(API_HOST + "v2/project/" + mod + "/version", modrinthVersionListType);
|
||||
List<ModrinthVersion> versions = Net.downloadObject(API_HOST + "v2/project/" + mod + "/version", s -> {
|
||||
try (JsonReader r = new JsonReader(new StringReader(s))) {
|
||||
return GList.read(r, GC_ModrinthVersion::read);
|
||||
}
|
||||
});
|
||||
versions.sort(Comparator.comparing(version -> version.date_published));
|
||||
return versions;
|
||||
}
|
||||
|
||||
public static ModrinthVersion getVersion(String id) throws IOException {
|
||||
return Net.downloadObject(API_HOST + "v2/version/" + id, ModrinthVersion.class);
|
||||
return Net.downloadObject(API_HOST + "v2/version/" + id, GC_ModrinthVersion::read);
|
||||
}
|
||||
|
||||
public static ModrinthVersion getVersionByHash(String sha1) throws IOException {
|
||||
return Net.downloadObject(API_HOST + "v2/version_file/" + sha1 + "?algorithm=sha1", ModrinthVersion.class);
|
||||
return Net.downloadObject(API_HOST + "v2/version_file/" + sha1 + "?algorithm=sha1", GC_ModrinthVersion::read);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +1,17 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.api.account;
|
||||
|
||||
import io.gitlab.jfronny.commons.io.JFiles;
|
||||
import io.gitlab.jfronny.commons.serialize.gson.api.GsonHolder;
|
||||
import io.gitlab.jfronny.gson.reflect.TypeToken;
|
||||
import io.gitlab.jfronny.inceptum.launcher.LauncherEnv;
|
||||
import io.gitlab.jfronny.gson.compile.util.GList;
|
||||
import io.gitlab.jfronny.gson.stream.JsonReader;
|
||||
import io.gitlab.jfronny.gson.stream.JsonWriter;
|
||||
import io.gitlab.jfronny.inceptum.common.*;
|
||||
import io.gitlab.jfronny.inceptum.launcher.LauncherEnv;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Type;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
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<>();
|
||||
public static final AuthInfo NULL_AUTH = new AuthInfo("Joe", "2536abce90e8476a871679918164abc5", "99abe417230342cb8e9e2168ab46297a", "legacy");
|
||||
|
@ -42,8 +39,8 @@ public class AccountManager {
|
|||
}
|
||||
|
||||
public static void saveAccounts() {
|
||||
try {
|
||||
JFiles.writeObject(MetaHolder.ACCOUNTS_PATH, ACCOUNTS);
|
||||
try (JsonWriter w = new JsonWriter(Files.newBufferedWriter(MetaHolder.ACCOUNTS_PATH))) {
|
||||
GList.write(w, ACCOUNTS, GC_MicrosoftAccount::write);
|
||||
} catch (IOException e) {
|
||||
Utils.LOGGER.error("Could not save accounts", e);
|
||||
}
|
||||
|
@ -52,8 +49,8 @@ public class AccountManager {
|
|||
public static void loadAccounts() {
|
||||
Utils.LOGGER.info("Loading accounts");
|
||||
if (Files.exists(MetaHolder.ACCOUNTS_PATH)) {
|
||||
try {
|
||||
ACCOUNTS.addAll(JFiles.readObject(MetaHolder.ACCOUNTS_PATH, abstractAccountListType));
|
||||
try (JsonReader r = new JsonReader(Files.newBufferedReader(MetaHolder.ACCOUNTS_PATH))) {
|
||||
ACCOUNTS.addAll(GList.read(r, GC_MicrosoftAccount::read));
|
||||
} catch (IOException e) {
|
||||
Utils.LOGGER.error("Could not load accounts", e);
|
||||
}
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.api.account;
|
||||
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
import io.gitlab.jfronny.inceptum.common.R;
|
||||
import io.gitlab.jfronny.inceptum.common.Utils;
|
||||
import io.gitlab.jfronny.inceptum.launcher.LauncherEnv;
|
||||
import io.gitlab.jfronny.inceptum.launcher.gson.MicrosoftAccountMeta;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.microsoft.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.*;
|
||||
|
||||
@GSerializable(with = MicrosoftAccountMeta.class)
|
||||
public class MicrosoftAccount {
|
||||
/**
|
||||
* Auto generated serial.
|
||||
|
@ -56,6 +59,30 @@ public class MicrosoftAccount {
|
|||
*/
|
||||
public boolean mustLogin;
|
||||
|
||||
public MicrosoftAccount(MicrosoftAccountMeta meta) {
|
||||
this.accountId = meta.accountId();
|
||||
this.minecraftUsername = meta.minecraftUsername();
|
||||
this.uuid = meta.uuid();
|
||||
this.accessToken = meta.accessToken();
|
||||
this.oauthToken = meta.oauthToken();
|
||||
this.xstsAuth = meta.xstsAuth();
|
||||
this.accessTokenExpiresAt = meta.accessTokenExpiresAt();
|
||||
this.mustLogin = meta.mustLogin();
|
||||
}
|
||||
|
||||
public MicrosoftAccountMeta toMeta() {
|
||||
return new MicrosoftAccountMeta(
|
||||
accountId,
|
||||
minecraftUsername,
|
||||
uuid,
|
||||
accessToken,
|
||||
oauthToken,
|
||||
xstsAuth,
|
||||
accessTokenExpiresAt,
|
||||
mustLogin
|
||||
);
|
||||
}
|
||||
|
||||
public MicrosoftAccount(OauthTokenResponse oauthTokenResponse, XboxLiveAuthResponse xstsAuthResponse,
|
||||
LoginResponse loginResponse, Profile profile) {
|
||||
update(oauthTokenResponse, xstsAuthResponse, loginResponse, profile);
|
||||
|
@ -65,14 +92,14 @@ public class MicrosoftAccount {
|
|||
LoginResponse loginResponse, Profile profile) {
|
||||
this.oauthToken = oauthTokenResponse;
|
||||
this.xstsAuth = xstsAuthResponse;
|
||||
this.accessToken = loginResponse.accessToken;
|
||||
this.accessToken = loginResponse.accessToken();
|
||||
this.minecraftUsername = profile.name;
|
||||
this.uuid = profile.id;
|
||||
this.accountId = loginResponse.username;
|
||||
this.accountId = loginResponse.username();
|
||||
this.mustLogin = false;
|
||||
|
||||
this.accessTokenExpiresAt = new Date();
|
||||
this.accessTokenExpiresAt.setTime(this.accessTokenExpiresAt.getTime() + (loginResponse.expiresIn * 1000));
|
||||
this.accessTokenExpiresAt.setTime(this.accessTokenExpiresAt.getTime() + (loginResponse.expiresIn() * 1000));
|
||||
}
|
||||
|
||||
public String getAccessToken() {
|
||||
|
@ -125,10 +152,10 @@ public class MicrosoftAccount {
|
|||
AccountManager.saveAccounts();
|
||||
}
|
||||
|
||||
if (force || new Date().after(this.xstsAuth.notAfter)) {
|
||||
if (force || new Date().after(this.xstsAuth.notAfter())) {
|
||||
Utils.LOGGER.info("xsts auth expired. Attempting to get new auth");
|
||||
XboxLiveAuthResponse xboxLiveAuthResponse = MicrosoftAuthAPI.getXBLToken(this.oauthToken.accessToken);
|
||||
this.xstsAuth = MicrosoftAuthAPI.getXstsToken(xboxLiveAuthResponse.token);
|
||||
this.xstsAuth = MicrosoftAuthAPI.getXstsToken(xboxLiveAuthResponse.token());
|
||||
|
||||
if (xstsAuth == null) {
|
||||
mustLogin = true;
|
||||
|
@ -150,12 +177,12 @@ public class MicrosoftAccount {
|
|||
return false;
|
||||
}
|
||||
|
||||
this.accessToken = loginResponse.accessToken;
|
||||
this.accountId = loginResponse.username;
|
||||
this.accessToken = loginResponse.accessToken();
|
||||
this.accountId = loginResponse.username();
|
||||
|
||||
this.accessTokenExpiresAt = new Date();
|
||||
this.accessTokenExpiresAt
|
||||
.setTime(this.accessTokenExpiresAt.getTime() + (loginResponse.expiresIn * 1000));
|
||||
.setTime(this.accessTokenExpiresAt.getTime() + (loginResponse.expiresIn() * 1000));
|
||||
|
||||
AccountManager.saveAccounts();
|
||||
}
|
||||
|
@ -171,7 +198,7 @@ public class MicrosoftAccount {
|
|||
}
|
||||
|
||||
private String getIdentityToken() {
|
||||
return "XBL3.0 x=" + xstsAuth.displayClaims.xui.get(0).uhs + ";" + xstsAuth.token;
|
||||
return "XBL3.0 x=" + xstsAuth.displayClaims().xui().get(0).uhs() + ";" + xstsAuth.token();
|
||||
}
|
||||
|
||||
public boolean ensureAccessTokenValid() {
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.api.account;
|
||||
|
||||
import io.gitlab.jfronny.commons.HttpUtils;
|
||||
import io.gitlab.jfronny.inceptum.launcher.api.account.request.*;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.microsoft.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.*;
|
||||
|
||||
|
@ -28,75 +30,81 @@ public class MicrosoftAuthAPI {
|
|||
public static final String MICROSOFT_MINECRAFT_ENTITLEMENTS_URL = "https://api.minecraftservices.com/entitlements/license?requestId=";
|
||||
|
||||
public static OauthTokenResponse tradeCodeForAccessToken(String code) throws IOException, URISyntaxException {
|
||||
return HttpUtils.post(MICROSOFT_AUTH_TOKEN_URL)
|
||||
try (Reader r = HttpUtils.post(MICROSOFT_AUTH_TOKEN_URL)
|
||||
.bodyForm(Map.of("client_id", MICROSOFT_LOGIN_CLIENT_ID,
|
||||
"code", code,
|
||||
"grant_type", "authorization_code",
|
||||
"redirect_uri", MICROSOFT_LOGIN_REDIRECT_URL,
|
||||
"scope", String.join(" ", MICROSOFT_LOGIN_SCOPES)))
|
||||
.sendSerialized(OauthTokenResponse.class);
|
||||
.sendReader()) {
|
||||
return GC_OauthTokenResponse.read(r);
|
||||
}
|
||||
}
|
||||
|
||||
public static OauthTokenResponse refreshAccessToken(String refreshToken) throws IOException, URISyntaxException {
|
||||
return HttpUtils.post(MICROSOFT_AUTH_TOKEN_URL)
|
||||
try (Reader r = HttpUtils.post(MICROSOFT_AUTH_TOKEN_URL)
|
||||
.bodyForm(Map.of("client_id", MICROSOFT_LOGIN_CLIENT_ID,
|
||||
"refresh_token", refreshToken,
|
||||
"grant_type", "refresh_token",
|
||||
"redirect_uri", MICROSOFT_LOGIN_REDIRECT_URL))
|
||||
.sendSerialized(OauthTokenResponse.class);
|
||||
.sendReader()) {
|
||||
return GC_OauthTokenResponse.read(r);
|
||||
}
|
||||
}
|
||||
|
||||
public static XboxLiveAuthResponse getXBLToken(String accessToken) throws IOException, URISyntaxException {
|
||||
Map<Object, Object> properties = new HashMap<>();
|
||||
properties.put("AuthMethod", "RPS");
|
||||
properties.put("SiteName", "user.auth.xboxlive.com");
|
||||
properties.put("RpsTicket", "d=" + accessToken);
|
||||
|
||||
Map<Object, Object> data = new HashMap<>();
|
||||
data.put("Properties", properties);
|
||||
data.put("RelyingParty", "http://auth.xboxlive.com");
|
||||
data.put("TokenType", "JWT");
|
||||
|
||||
return HttpUtils.post(MICROSOFT_XBL_AUTH_TOKEN_URL)
|
||||
try (Reader r = HttpUtils.post(MICROSOFT_XBL_AUTH_TOKEN_URL)
|
||||
.header("x-xbl-contract-version", "1")
|
||||
.bodySerialized(data)
|
||||
.sendSerialized(XboxLiveAuthResponse.class);
|
||||
.bodyJson(GC_XblTokenRequest.toJson(new XblTokenRequest(
|
||||
new XblTokenRequest.Properties(
|
||||
"RPS",
|
||||
"user.auth.xboxlive.com",
|
||||
"d=" + accessToken
|
||||
),
|
||||
"http://auth.xboxlive.com",
|
||||
"JWT"
|
||||
)))
|
||||
.sendReader()) {
|
||||
return GC_XboxLiveAuthResponse.read(r);
|
||||
}
|
||||
}
|
||||
|
||||
public static XboxLiveAuthResponse getXstsToken(String xblToken) throws IOException, URISyntaxException {
|
||||
Map<Object, Object> properties = new HashMap<>();
|
||||
properties.put("SandboxId", "RETAIL");
|
||||
|
||||
List<String> userTokens = new ArrayList<>();
|
||||
userTokens.add(xblToken);
|
||||
properties.put("UserTokens", userTokens);
|
||||
|
||||
Map<Object, Object> data = new HashMap<>();
|
||||
data.put("Properties", properties);
|
||||
data.put("RelyingParty", "rp://api.minecraftservices.com/");
|
||||
data.put("TokenType", "JWT");
|
||||
|
||||
return HttpUtils.post(MICROSOFT_XSTS_AUTH_TOKEN_URL)
|
||||
try (Reader r = HttpUtils.post(MICROSOFT_XSTS_AUTH_TOKEN_URL)
|
||||
.header("x-xbl-contract-version", "1")
|
||||
.bodySerialized(data)
|
||||
.sendSerialized(XboxLiveAuthResponse.class);
|
||||
.bodyJson(GC_XstsTokenRequest.toJson(new XstsTokenRequest(
|
||||
new XstsTokenRequest.Properties(
|
||||
"RETAIL",
|
||||
List.of(xblToken)
|
||||
),
|
||||
"rp://api.minecraftservices.com/",
|
||||
"JWT"
|
||||
)))
|
||||
.sendReader()) {
|
||||
return GC_XboxLiveAuthResponse.read(r);
|
||||
}
|
||||
}
|
||||
|
||||
public static LoginResponse loginToMinecraft(String xstsToken) throws IOException, URISyntaxException {
|
||||
Map<Object, Object> data = new HashMap<>();
|
||||
data.put("xtoken", xstsToken);
|
||||
data.put("platform", "PC_LAUNCHER");
|
||||
|
||||
return HttpUtils.post(MICROSOFT_MINECRAFT_LOGIN_URL)
|
||||
.bodySerialized(data)
|
||||
.sendSerialized(LoginResponse.class);
|
||||
try (Reader r = HttpUtils.post(MICROSOFT_MINECRAFT_LOGIN_URL)
|
||||
.bodyJson(GC_LoginRequest.toJson(new LoginRequest(
|
||||
xstsToken,
|
||||
"PC_LAUNCHER"
|
||||
)))
|
||||
.sendReader()) {
|
||||
return GC_LoginResponse.read(r);
|
||||
}
|
||||
}
|
||||
|
||||
public static Entitlements getEntitlements(String accessToken) throws IOException, URISyntaxException {
|
||||
return HttpUtils.get(MICROSOFT_MINECRAFT_ENTITLEMENTS_URL + UUID.randomUUID()).bearer(accessToken).sendSerialized(Entitlements.class);
|
||||
try (Reader r = HttpUtils.get(MICROSOFT_MINECRAFT_ENTITLEMENTS_URL + UUID.randomUUID()).bearer(accessToken).sendReader()) {
|
||||
return GC_Entitlements.read(r);
|
||||
}
|
||||
}
|
||||
|
||||
public static Profile getMcProfile(String accessToken) throws IOException, URISyntaxException {
|
||||
return HttpUtils.get(MICROSOFT_MINECRAFT_PROFILE_URL).bearer(accessToken).sendSerialized(Profile.class);
|
||||
try (Reader r = HttpUtils.get(MICROSOFT_MINECRAFT_PROFILE_URL).bearer(accessToken).sendReader()) {
|
||||
return GC_Profile.read(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,8 +61,8 @@ public class MicrosoftAuthServer implements Closeable {
|
|||
}
|
||||
|
||||
private void addAccount(OauthTokenResponse oauthTokenResponse, XboxLiveAuthResponse xstsAuthResponse, LoginResponse loginResponse, Profile profile) {
|
||||
if (this.previous != null || AccountManager.isAccountByName(loginResponse.username)) {
|
||||
MicrosoftAccount account = (MicrosoftAccount) AccountManager.getAccountByName(loginResponse.username);
|
||||
if (this.previous != null || AccountManager.isAccountByName(loginResponse.username())) {
|
||||
MicrosoftAccount account = (MicrosoftAccount) AccountManager.getAccountByName(loginResponse.username());
|
||||
|
||||
if (account == null) {
|
||||
return;
|
||||
|
@ -91,7 +91,7 @@ public class MicrosoftAuthServer implements Closeable {
|
|||
private void acquireXBLToken(OauthTokenResponse oauthTokenResponse) throws Exception {
|
||||
XboxLiveAuthResponse xblAuthResponse = MicrosoftAuthAPI.getXBLToken(oauthTokenResponse.accessToken);
|
||||
|
||||
acquireXsts(oauthTokenResponse, xblAuthResponse.token);
|
||||
acquireXsts(oauthTokenResponse, xblAuthResponse.token());
|
||||
}
|
||||
|
||||
private void acquireXsts(OauthTokenResponse oauthTokenResponse, String xblToken) throws Exception {
|
||||
|
@ -103,8 +103,8 @@ public class MicrosoftAuthServer implements Closeable {
|
|||
}
|
||||
|
||||
private void acquireMinecraftToken(OauthTokenResponse oauthTokenResponse, XboxLiveAuthResponse xstsAuthResponse) throws Exception {
|
||||
String xblUhs = xstsAuthResponse.displayClaims.xui.get(0).uhs;
|
||||
String xblXsts = xstsAuthResponse.token;
|
||||
String xblUhs = xstsAuthResponse.displayClaims().xui().get(0).uhs();
|
||||
String xblXsts = xstsAuthResponse.token();
|
||||
|
||||
LoginResponse loginResponse = MicrosoftAuthAPI.loginToMinecraft("XBL3.0 x=" + xblUhs + ";" + xblXsts);
|
||||
|
||||
|
@ -112,7 +112,7 @@ public class MicrosoftAuthServer implements Closeable {
|
|||
throw new Exception("Failed to login to Minecraft");
|
||||
}
|
||||
|
||||
Entitlements entitlements = MicrosoftAuthAPI.getEntitlements(loginResponse.accessToken);
|
||||
Entitlements entitlements = MicrosoftAuthAPI.getEntitlements(loginResponse.accessToken());
|
||||
|
||||
if (!(entitlements.items.stream().anyMatch(i -> i.name.equalsIgnoreCase("product_minecraft"))
|
||||
&& entitlements.items.stream().anyMatch(i -> i.name.equalsIgnoreCase("game_minecraft")))) {
|
||||
|
@ -123,7 +123,7 @@ public class MicrosoftAuthServer implements Closeable {
|
|||
Profile profile = null;
|
||||
|
||||
try {
|
||||
profile = MicrosoftAuthAPI.getMcProfile(loginResponse.accessToken);
|
||||
profile = MicrosoftAuthAPI.getMcProfile(loginResponse.accessToken());
|
||||
} catch (Exception e) {
|
||||
LauncherEnv.showError("""
|
||||
No Minecraft profiles were found for this account. Have you purchased Minecraft?
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.api.account.request;
|
||||
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
|
||||
@GSerializable
|
||||
public record LoginRequest(String xtoken, String platform) {
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.api.account.request;
|
||||
|
||||
import io.gitlab.jfronny.gson.annotations.SerializedName;
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
|
||||
@GSerializable
|
||||
public record XblTokenRequest(@SerializedName("Properties") Properties properties,
|
||||
@SerializedName("RelyingParty") String relyingParty,
|
||||
@SerializedName("TokenType") String tokenType) {
|
||||
@GSerializable
|
||||
public record Properties(@SerializedName("AuthMethod") String authMethod,
|
||||
@SerializedName("SiteName") String siteName,
|
||||
@SerializedName("RpsTicket") String rpsTicket) {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.api.account.request;
|
||||
|
||||
import io.gitlab.jfronny.gson.annotations.SerializedName;
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@GSerializable
|
||||
public record XstsTokenRequest(@SerializedName("Properties") Properties properties,
|
||||
@SerializedName("RelyingParty") String relyingParty,
|
||||
@SerializedName("TokenType") String tokenType) {
|
||||
@GSerializable
|
||||
public record Properties(@SerializedName("SandboxId") String sandboxId, @SerializedName("UserTokens") List<String> userTokens) {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.gson;
|
||||
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
import io.gitlab.jfronny.gson.stream.JsonReader;
|
||||
import io.gitlab.jfronny.gson.stream.JsonWriter;
|
||||
import io.gitlab.jfronny.inceptum.launcher.api.account.MicrosoftAccount;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.microsoft.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
|
||||
@GSerializable
|
||||
public record MicrosoftAccountMeta(String accountId, String minecraftUsername, String uuid, String accessToken, OauthTokenResponse oauthToken, XboxLiveAuthResponse xstsAuth, Date accessTokenExpiresAt, boolean mustLogin) {
|
||||
public static final long SERIAL_VERSION_UID = 5483749902584257559L;
|
||||
|
||||
public static void write(JsonWriter writer, MicrosoftAccount value) throws IOException {
|
||||
GC_MicrosoftAccountMeta.write(writer, value == null ? null : value.toMeta());
|
||||
}
|
||||
|
||||
public static MicrosoftAccount read(JsonReader reader) throws IOException {
|
||||
MicrosoftAccountMeta meta = GC_MicrosoftAccountMeta.read(reader);
|
||||
return meta == null ? null : new MicrosoftAccount(meta);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.gson;
|
||||
|
||||
import io.gitlab.jfronny.gson.*;
|
||||
import io.gitlab.jfronny.gson.compile.util.GList;
|
||||
import io.gitlab.jfronny.gson.stream.*;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.mojang.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
public class MinecraftArgumentAdapter {
|
||||
public static void write(JsonWriter writer, MinecraftArgument rules) throws IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public static MinecraftArgument read(JsonReader reader) throws IOException {
|
||||
if (reader.peek() == JsonToken.STRING) return new MinecraftArgument(Set.of(reader.nextString()));
|
||||
Rules rules = null;
|
||||
List<String> value = null;
|
||||
reader.beginObject();
|
||||
while (reader.hasNext()) {
|
||||
switch (reader.nextName()) {
|
||||
case "rules" -> rules = GC_Rules.read(reader);
|
||||
case "value" -> value = GList.read(reader, JsonReader::nextString);
|
||||
}
|
||||
}
|
||||
reader.endObject();
|
||||
if (rules == null || value == null) throw new JsonParseException("Not a valid minecraft argument");
|
||||
if (!rules.allow()) return new MinecraftArgument(Set.of());
|
||||
return new MinecraftArgument(Set.copyOf(value));
|
||||
}
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.gson;
|
||||
|
||||
import io.gitlab.jfronny.gson.*;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.mojang.MinecraftArgument;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.mojang.Rules;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class MinecraftArgumentDeserializer implements JsonDeserializer<MinecraftArgument> {
|
||||
@Override
|
||||
public MinecraftArgument deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
|
||||
if (json.isJsonPrimitive() && json.getAsJsonPrimitive().isString()) {
|
||||
return new MinecraftArgument(Set.of(json.getAsString()));
|
||||
} else if (json.isJsonObject()) {
|
||||
JsonObject jo = json.getAsJsonObject();
|
||||
if (jo.size() != 2 || !jo.has("rules") || !jo.has("value"))
|
||||
throw new JsonParseException("Not a valid minecraft argument");
|
||||
Rules r = context.deserialize(jo.get("rules"), Rules.class);
|
||||
if (!r.allow()) return new MinecraftArgument(Set.of());
|
||||
Set<String> sel = new LinkedHashSet<>();
|
||||
JsonElement value = jo.get("value");
|
||||
if (value.isJsonArray()) {
|
||||
for (JsonElement val : value.getAsJsonArray()) {
|
||||
sel.add(val.getAsString());
|
||||
}
|
||||
} else if (value.isJsonPrimitive())
|
||||
sel.add(value.getAsString());
|
||||
else throw new JsonParseException("Unexpected value type");
|
||||
return new MinecraftArgument(Set.copyOf(sel));
|
||||
} else throw new JsonParseException("Not a valid minecraft argument");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.gson;
|
||||
|
||||
import io.gitlab.jfronny.gson.stream.JsonReader;
|
||||
import io.gitlab.jfronny.gson.stream.JsonWriter;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.ModMeta$Sources;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.source.GC_ModSource;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.source.ModSource;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Optional;
|
||||
|
||||
public class ModMetaSourcesAdapter {
|
||||
public static void write(JsonWriter writer, ModMeta$Sources value) throws IOException {
|
||||
writer.beginArray();
|
||||
for (ModSource source : value.keySet()) GC_ModSource.write(writer, source);
|
||||
writer.endArray();
|
||||
}
|
||||
|
||||
public static ModMeta$Sources read(JsonReader reader) throws IOException {
|
||||
reader.beginArray();
|
||||
ModMeta$Sources sources = new ModMeta$Sources();
|
||||
while (reader.hasNext()) {
|
||||
sources.put(GC_ModSource.read(reader), Optional.empty());
|
||||
}
|
||||
reader.endArray();
|
||||
return sources;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.gson;
|
||||
|
||||
import io.gitlab.jfronny.gson.JsonParseException;
|
||||
import io.gitlab.jfronny.gson.stream.JsonReader;
|
||||
import io.gitlab.jfronny.gson.stream.JsonWriter;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.source.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class ModSourceAdapter {
|
||||
public static void write(JsonWriter writer, ModSource src) throws IOException {
|
||||
writer.beginObject();
|
||||
if (src instanceof ModrinthModSource mo) {
|
||||
writer.name("type").value("modrinth")
|
||||
.name("id").value(mo.getVersionId());
|
||||
} else if (src instanceof DirectModSource di) {
|
||||
writer.name("type").value("direct")
|
||||
.name("fileName").value(di.fileName())
|
||||
.name("url").value(di.url())
|
||||
.name("dependencies");
|
||||
writer.beginArray();
|
||||
for (ModSource dependency : di.dependencies()) {
|
||||
write(writer, dependency);
|
||||
}
|
||||
writer.endArray();
|
||||
} else if (src instanceof CurseforgeModSource cu) {
|
||||
writer.name("type").value("curseforge");
|
||||
if (cu.getShortName().matches("\\d+")) {
|
||||
writer.name("projectId").value(cu.getProjectId());
|
||||
} else {
|
||||
writer.name("project").value(cu.getShortName());
|
||||
}
|
||||
writer.name("fileId").value(cu.getFileId());
|
||||
} else throw new RuntimeException("ModSources with the type " + src.getClass() + " are not supported");
|
||||
writer.endObject();
|
||||
}
|
||||
|
||||
public static ModSource read(JsonReader reader) throws IOException {
|
||||
String type = null;
|
||||
|
||||
String mr$id = null;
|
||||
|
||||
Integer cf$projectId = null;
|
||||
String cf$project = null;
|
||||
Integer cf$fileId = null;
|
||||
|
||||
String direct$fileName = null;
|
||||
String direct$url = null;
|
||||
Set<ModSource> direct$dependencies = null;
|
||||
|
||||
reader.beginObject();
|
||||
while (reader.hasNext()) {
|
||||
switch (reader.nextName()) {
|
||||
case "type" -> type = reader.nextString();
|
||||
case "id" -> mr$id = reader.nextString();
|
||||
case "projectId" -> cf$projectId = reader.nextInt();
|
||||
case "project" -> cf$project = reader.nextString();
|
||||
case "fileId" -> cf$fileId = reader.nextInt();
|
||||
case "fileName" -> direct$fileName = reader.nextString();
|
||||
case "url" -> direct$url = reader.nextString();
|
||||
case "dependencies" -> {
|
||||
direct$dependencies = new LinkedHashSet<>();
|
||||
reader.beginArray();
|
||||
while (reader.hasNext()) direct$dependencies.add(read(reader));
|
||||
reader.endArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
reader.endObject();
|
||||
if (type == null) throw new JsonParseException("Expected ModSource to contain a type");
|
||||
return switch (type) {
|
||||
case "modrinth" -> {
|
||||
if (mr$id == null) throw new JsonParseException("Expected ModrinthModSource to contain a version ID");
|
||||
yield new ModrinthModSource(mr$id);
|
||||
}
|
||||
case "curseforge" -> {
|
||||
if (cf$fileId == null)
|
||||
throw new JsonParseException("Expected a fileId in this curseforge project");
|
||||
if (cf$projectId != null) yield new CurseforgeModSource(cf$projectId, cf$fileId);
|
||||
else if (cf$project != null) yield new CurseforgeModSource(cf$project, cf$fileId);
|
||||
else throw new JsonParseException("Expected a projectId in this curseforge project");
|
||||
}
|
||||
case "direct" -> {
|
||||
if (direct$fileName == null) throw new JsonParseException("Expected direct download to have a fileName");
|
||||
if (direct$url == null) throw new JsonParseException("Expected direct download to have a url");
|
||||
if (direct$dependencies == null) yield new DirectModSource(direct$fileName, direct$url, Set.of());
|
||||
else {
|
||||
yield new DirectModSource(direct$fileName, direct$url, direct$dependencies);
|
||||
}
|
||||
}
|
||||
default -> throw new JsonParseException("Unexpected ModSource type: " + type);
|
||||
};
|
||||
}
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.gson;
|
||||
|
||||
import io.gitlab.jfronny.gson.*;
|
||||
import io.gitlab.jfronny.gson.reflect.TypeToken;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.source.ModSource;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.*;
|
||||
|
||||
public class ModSourceMapDeserializer implements JsonSerializer<Map<ModSource, Optional<ModSource>>>, JsonDeserializer<Map<ModSource, Optional<ModSource>>> {
|
||||
public static final Type modSourceMapType = new TypeToken<Map<ModSource, Optional<ModSource>>>() {}.getType();
|
||||
|
||||
@Override
|
||||
public Map<ModSource, Optional<ModSource>> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
|
||||
if (!json.isJsonArray()) throw new JsonParseException("Not an array");
|
||||
Map<ModSource, Optional<ModSource>> res = new LinkedHashMap<>();
|
||||
for (JsonElement element : json.getAsJsonArray()) {
|
||||
res.put(context.deserialize(element, ModSource.class), Optional.empty());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonElement serialize(Map<ModSource, Optional<ModSource>> src, Type typeOfSrc, JsonSerializationContext context) {
|
||||
JsonArray res = new JsonArray();
|
||||
for (ModSource source : src.keySet()) {
|
||||
res.add(context.serialize(source, ModSource.class));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
|
@ -1,79 +0,0 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.gson;
|
||||
|
||||
import io.gitlab.jfronny.gson.*;
|
||||
import io.gitlab.jfronny.gson.reflect.TypeToken;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.source.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Set;
|
||||
|
||||
public class ModSourceTypeAdapter implements JsonSerializer<ModSource>, JsonDeserializer<ModSource> {
|
||||
private static final Type modSourceSetType = new TypeToken<Set<ModSource>>() {}.getType();
|
||||
|
||||
@Override
|
||||
public ModSource deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
|
||||
if (!(json instanceof JsonObject jo))
|
||||
throw new JsonParseException("Expected ModSource to be an object");
|
||||
if (!jo.has("type"))
|
||||
throw new JsonParseException("Expected ModSource to contain a type");
|
||||
return switch (jo.get("type").getAsString()) {
|
||||
case "modrinth" -> {
|
||||
if (!jo.has("id"))
|
||||
throw new JsonParseException("Expected ModrinthModSource to contain a version ID");
|
||||
try {
|
||||
yield new ModrinthModSource(jo.get("id").getAsString());
|
||||
} catch (IOException e) {
|
||||
throw new JsonParseException("Could not fetch Modrinth source", e);
|
||||
}
|
||||
}
|
||||
case "curseforge" -> {
|
||||
if (!jo.has("fileId"))
|
||||
throw new JsonParseException("Expected a fileId in this curseforge project");
|
||||
try {
|
||||
if (jo.has("projectId")) {
|
||||
yield new CurseforgeModSource(jo.get("projectId").getAsInt(), jo.get("fileId").getAsInt());
|
||||
} else if (jo.has("project")) {
|
||||
yield new CurseforgeModSource(jo.get("project").getAsString(), jo.get("fileId").getAsInt());
|
||||
} else throw new JsonParseException("Expected a projectId in this curseforge project");
|
||||
} catch (IOException e) {
|
||||
throw new JsonParseException("Could not fetch Curseforge source", e);
|
||||
}
|
||||
}
|
||||
case "direct" -> {
|
||||
if (!jo.has("fileName"))
|
||||
throw new JsonParseException("Expected direct download to have a fileName");
|
||||
if (!jo.has("url"))
|
||||
throw new JsonParseException("Expected direct download to have a url");
|
||||
if (jo.has("dependencies"))
|
||||
yield new DirectModSource(jo.get("fileName").getAsString(), jo.get("url").getAsString(), context.deserialize(jo.get("dependencies"), modSourceSetType));
|
||||
else
|
||||
yield new DirectModSource(jo.get("fileName").getAsString(), jo.get("url").getAsString(), Set.of());
|
||||
}
|
||||
default -> throw new JsonParseException("Unexpected ModSource type: " + jo.get("type").getAsString());
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonElement serialize(ModSource src, Type typeOfSrc, JsonSerializationContext context) {
|
||||
JsonObject jo = new JsonObject();
|
||||
if (src instanceof ModrinthModSource mo) {
|
||||
jo.add("type", new JsonPrimitive("modrinth"));
|
||||
jo.add("id", new JsonPrimitive(mo.getVersionId()));
|
||||
} else if (src instanceof DirectModSource di) {
|
||||
jo.add("type", new JsonPrimitive("direct"));
|
||||
jo.add("fileName", new JsonPrimitive(di.fileName()));
|
||||
jo.add("url", new JsonPrimitive(di.url()));
|
||||
jo.add("dependencies", context.serialize(di.dependencies()));
|
||||
} else if (src instanceof CurseforgeModSource cu) {
|
||||
jo.add("type", new JsonPrimitive("curseforge"));
|
||||
if (cu.getShortName().matches("\\d+")) {
|
||||
jo.add("projectId", new JsonPrimitive(cu.getProjectId()));
|
||||
} else {
|
||||
jo.add("project", new JsonPrimitive(cu.getShortName()));
|
||||
}
|
||||
jo.add("fileId", new JsonPrimitive(cu.getFileId()));
|
||||
} else throw new RuntimeException("ModSources with the type " + src.getClass() + " are not supported");
|
||||
return jo;
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.gson;
|
||||
|
||||
import io.gitlab.jfronny.gson.*;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.microsoft.OauthTokenResponse;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Date;
|
||||
|
||||
public class OauthTokenResponseDeserializer implements JsonDeserializer<OauthTokenResponse> {
|
||||
@Override
|
||||
public OauthTokenResponse deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
|
||||
OauthTokenResponse oauthTokenResponse = new OauthTokenResponse();
|
||||
JsonObject rootObject = json.getAsJsonObject();
|
||||
|
||||
oauthTokenResponse.tokenType = rootObject.get("token_type").getAsString();
|
||||
oauthTokenResponse.expiresIn = rootObject.get("expires_in").getAsInt();
|
||||
oauthTokenResponse.scope = rootObject.get("scope").getAsString();
|
||||
oauthTokenResponse.accessToken = rootObject.get("access_token").getAsString();
|
||||
oauthTokenResponse.refreshToken = rootObject.get("refresh_token").getAsString();
|
||||
oauthTokenResponse.userId = rootObject.get("user_id").getAsString();
|
||||
|
||||
if (rootObject.has("foci")) {
|
||||
oauthTokenResponse.foci = rootObject.get("foci").isJsonNull() ? null : rootObject.get("foci").getAsString();
|
||||
}
|
||||
|
||||
if (rootObject.has("expires_at")) {
|
||||
oauthTokenResponse.expiresAt = context.deserialize(rootObject.get("expires_at"), Date.class);
|
||||
} else {
|
||||
oauthTokenResponse.expiresAt = new Date();
|
||||
oauthTokenResponse.expiresAt
|
||||
.setTime(oauthTokenResponse.expiresAt.getTime() + (oauthTokenResponse.expiresIn * 1000));
|
||||
}
|
||||
|
||||
return oauthTokenResponse;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.gson;
|
||||
|
||||
import io.gitlab.jfronny.commons.OSUtils;
|
||||
import io.gitlab.jfronny.gson.*;
|
||||
import io.gitlab.jfronny.gson.stream.JsonReader;
|
||||
import io.gitlab.jfronny.gson.stream.JsonWriter;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.mojang.Rules;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class RulesAdapter {
|
||||
public static void write(JsonWriter writer, Rules rules) throws IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public static Rules read(JsonReader reader) throws IOException {
|
||||
boolean valid = true;
|
||||
reader.beginArray();
|
||||
while (reader.hasNext()) {
|
||||
if (!valid) {
|
||||
reader.skipValue();
|
||||
continue;
|
||||
}
|
||||
reader.beginObject();
|
||||
String actionType = null;
|
||||
boolean hasFeatures = false;
|
||||
String osName = null;
|
||||
String osVersion = null;
|
||||
while (reader.hasNext()) {
|
||||
switch (reader.nextName()) {
|
||||
case "action" -> actionType = reader.nextString();
|
||||
case "features" -> {
|
||||
reader.skipValue();
|
||||
hasFeatures = true;
|
||||
}
|
||||
case "os" -> {
|
||||
reader.beginObject();
|
||||
while (reader.hasNext()) {
|
||||
switch (reader.nextName()) {
|
||||
case "name" -> osName = reader.nextString();
|
||||
case "version" -> osVersion = reader.nextString();
|
||||
}
|
||||
}
|
||||
reader.endObject();
|
||||
}
|
||||
}
|
||||
}
|
||||
reader.endObject();
|
||||
if (actionType == null || !actionType.equals("allow") && !actionType.equals("disallow")) {
|
||||
throw new JsonParseException("Unexpected action in argument: " + actionType);
|
||||
}
|
||||
if (!hasFeatures) valid = false;
|
||||
if (osName != null && !OSUtils.TYPE.getMojName().equals(osName)) valid = false;
|
||||
if (osVersion != null && !System.getProperty("os.version").matches(osVersion)) valid = false;
|
||||
if (actionType.equals("disallow")) valid = !valid;
|
||||
}
|
||||
reader.endArray();
|
||||
return new Rules(valid);
|
||||
}
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.gson;
|
||||
|
||||
import io.gitlab.jfronny.commons.OSUtils;
|
||||
import io.gitlab.jfronny.gson.*;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.mojang.Rules;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
public class RulesDeserializer implements JsonDeserializer<Rules> {
|
||||
@Override
|
||||
public Rules deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
|
||||
boolean valid = true;
|
||||
for (JsonElement rule : json.getAsJsonArray()) {
|
||||
JsonObject ro = rule.getAsJsonObject();
|
||||
String actionType = ro.get("action").getAsJsonPrimitive().getAsString();
|
||||
if (!actionType.equals("allow") && !actionType.equals("disallow")) {
|
||||
throw new JsonParseException("Unexpected action in argument: " + actionType);
|
||||
}
|
||||
boolean matched = true;
|
||||
if (ro.has("features")) {
|
||||
matched = false;
|
||||
}
|
||||
if (ro.has("os")) {
|
||||
JsonObject osObject = ro.get("os").getAsJsonObject();
|
||||
if (osObject.has("name")) {
|
||||
if (!OSUtils.TYPE.getMojName().equals(osObject.get("name").getAsString())) {
|
||||
matched = false;
|
||||
}
|
||||
}
|
||||
if (osObject.has("version")) {
|
||||
if (!System.getProperty("os.version").matches(osObject.get("version").getAsString())) {
|
||||
matched = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (actionType.equals("disallow")) matched = !matched;
|
||||
if (!matched) {
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return new Rules(valid);
|
||||
}
|
||||
}
|
|
@ -1,8 +1,11 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.model.curseforge;
|
||||
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@GSerializable
|
||||
public class CurseforgeFile {
|
||||
public Integer id;
|
||||
public Integer gameId;
|
||||
|
@ -45,6 +48,7 @@ public class CurseforgeFile {
|
|||
public Long fileFingerprint; // murmur5 hash
|
||||
public List<Module> modules;
|
||||
|
||||
@GSerializable
|
||||
public static class Hash {
|
||||
public String value;
|
||||
/* Possible values:
|
||||
|
@ -53,6 +57,7 @@ public class CurseforgeFile {
|
|||
public Integer algo;
|
||||
}
|
||||
|
||||
@GSerializable
|
||||
public static class GameVersion {
|
||||
public String gameVersionName;
|
||||
public String gameVersionPadded;
|
||||
|
@ -61,6 +66,7 @@ public class CurseforgeFile {
|
|||
public Integer gameVersionTypeId;
|
||||
}
|
||||
|
||||
@GSerializable
|
||||
public static class Dependency {
|
||||
public Integer modId;
|
||||
/* Possible values:
|
||||
|
@ -73,6 +79,7 @@ public class CurseforgeFile {
|
|||
public Integer relationType;
|
||||
}
|
||||
|
||||
@GSerializable
|
||||
public static class Module {
|
||||
public String name;
|
||||
public Long fingerprint;
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.model.curseforge;
|
||||
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@GSerializable
|
||||
public class CurseforgeMod {
|
||||
public Integer id;
|
||||
public Integer gameId;
|
||||
|
@ -41,6 +44,7 @@ public class CurseforgeMod {
|
|||
public Boolean isAvailable;
|
||||
public Integer thumbsUpCount;
|
||||
|
||||
@GSerializable
|
||||
public static class Links {
|
||||
public String websiteUrl;
|
||||
public String wikiUrl;
|
||||
|
@ -48,6 +52,7 @@ public class CurseforgeMod {
|
|||
public String sourcesUrl;
|
||||
}
|
||||
|
||||
@GSerializable
|
||||
public static class Category {
|
||||
public Integer id;
|
||||
public Integer gameId;
|
||||
|
@ -61,12 +66,14 @@ public class CurseforgeMod {
|
|||
public Integer primaryCategoryId;
|
||||
}
|
||||
|
||||
@GSerializable
|
||||
public static class Author {
|
||||
public Integer id;
|
||||
public String name;
|
||||
public String url;
|
||||
}
|
||||
|
||||
@GSerializable
|
||||
public static class Logo {
|
||||
public Integer id;
|
||||
public Integer modId;
|
||||
|
@ -76,6 +83,7 @@ public class CurseforgeMod {
|
|||
public String url;
|
||||
}
|
||||
|
||||
@GSerializable
|
||||
public static class Screenshot {
|
||||
public Integer id;
|
||||
public Integer modId;
|
||||
|
@ -85,6 +93,7 @@ public class CurseforgeMod {
|
|||
public String url;
|
||||
}
|
||||
|
||||
@GSerializable
|
||||
public static class LatestFileIndex {
|
||||
public String gameVersion;
|
||||
public Integer fileId;
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.model.curseforge;
|
||||
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
@GSerializable
|
||||
public class CurseforgeModpackManifest {
|
||||
public Minecraft minecraft;
|
||||
public String manifestType;
|
||||
|
@ -12,16 +15,19 @@ public class CurseforgeModpackManifest {
|
|||
public Set<File> files;
|
||||
public String overrides;
|
||||
|
||||
@GSerializable
|
||||
public static class Minecraft {
|
||||
public String version;
|
||||
public Set<ModLoader> modLoaders;
|
||||
|
||||
@GSerializable
|
||||
public static class ModLoader {
|
||||
public String id;
|
||||
public Boolean primary;
|
||||
}
|
||||
}
|
||||
|
||||
@GSerializable
|
||||
public static class File {
|
||||
public Integer projectID;
|
||||
public Integer fileID;
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.model.curseforge.response;
|
||||
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.curseforge.CurseforgeFile;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@GSerializable
|
||||
public class FingerprintMatchesResponse {
|
||||
public Result data;
|
||||
|
||||
@GSerializable
|
||||
public static class Result {
|
||||
public Boolean isCacheBuilt;
|
||||
public List<Match> exactMatches;
|
||||
|
@ -15,6 +18,7 @@ public class FingerprintMatchesResponse {
|
|||
public List<Integer> installedFingerprints;
|
||||
public List<Integer> unmatchedFingerprints;
|
||||
|
||||
@GSerializable
|
||||
public static class Match {
|
||||
public Integer id;
|
||||
public CurseforgeFile file;
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.model.curseforge.response;
|
||||
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.curseforge.CurseforgeFile;
|
||||
|
||||
@GSerializable
|
||||
public class GetModFileResponse {
|
||||
public CurseforgeFile data;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.model.curseforge.response;
|
||||
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.curseforge.CurseforgeMod;
|
||||
|
||||
@GSerializable
|
||||
public class GetModResponse {
|
||||
public CurseforgeMod data;
|
||||
}
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.model.curseforge.response;
|
||||
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.curseforge.CurseforgeMod;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@GSerializable
|
||||
public class SearchResponse {
|
||||
public List<CurseforgeMod> data;
|
||||
public Pagination pagination;
|
||||
|
||||
@GSerializable
|
||||
public static class Pagination {
|
||||
public Integer index;
|
||||
public Integer pageSite;
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.model.fabric;
|
||||
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
|
||||
@GSerializable
|
||||
public class FabricLoaderVersion {
|
||||
public String separator;
|
||||
public Integer build;
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.model.fabric;
|
||||
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
|
||||
@GSerializable
|
||||
public class FabricModJson {
|
||||
public String id;
|
||||
public String name;
|
||||
|
|
|
@ -1,30 +1,38 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.model.fabric;
|
||||
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@GSerializable
|
||||
public class FabricVersionLoaderInfo {
|
||||
public FabricLoaderVersion loader;
|
||||
public IntermediaryVersion intermediary;
|
||||
|
||||
@GSerializable
|
||||
public static class WithMeta extends FabricVersionLoaderInfo {
|
||||
public LauncherMeta launcherMeta;
|
||||
|
||||
@GSerializable
|
||||
public static class LauncherMeta {
|
||||
public int version;
|
||||
public Libraries libraries;
|
||||
public MainClass mainClass;
|
||||
|
||||
@GSerializable
|
||||
public static class Libraries {
|
||||
public List<Library> client;
|
||||
public List<Library> common;
|
||||
public List<Library> server;
|
||||
|
||||
@GSerializable
|
||||
public static class Library {
|
||||
public String name;
|
||||
public String url;
|
||||
}
|
||||
}
|
||||
|
||||
@GSerializable
|
||||
public static class MainClass {
|
||||
public String client;
|
||||
public String server;
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.model.fabric;
|
||||
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
|
||||
@GSerializable
|
||||
public class IntermediaryVersion {
|
||||
public String maven;
|
||||
public String version;
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.model.inceptum;
|
||||
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@GSerializable
|
||||
public class InstanceMeta {
|
||||
public String version;
|
||||
public String java;
|
||||
|
@ -11,6 +14,7 @@ public class InstanceMeta {
|
|||
public Long lastLaunched;
|
||||
public Arguments arguments;
|
||||
|
||||
@GSerializable
|
||||
public static class Arguments {
|
||||
public List<String> jvm;
|
||||
public List<String> client;
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.model.inceptum;
|
||||
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
import io.gitlab.jfronny.inceptum.launcher.gson.ModMetaSourcesAdapter;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.source.ModSource;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@GSerializable(with = ModMetaSourcesAdapter.class)
|
||||
public class ModMeta$Sources implements Map<ModSource, Optional<ModSource>> {
|
||||
private Map<ModSource, Optional<ModSource>> delegate = new LinkedHashMap<>();
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return delegate.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return delegate.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsKey(Object o) {
|
||||
return delegate.containsKey(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsValue(Object o) {
|
||||
return delegate.containsValue(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<ModSource> get(Object o) {
|
||||
return delegate.get(o);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Optional<ModSource> put(ModSource modSource, Optional<ModSource> modSource2) {
|
||||
return delegate.put(modSource, modSource2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<ModSource> remove(Object o) {
|
||||
return delegate.remove(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putAll(@NotNull Map<? extends ModSource, ? extends Optional<ModSource>> map) {
|
||||
delegate.putAll(map);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
delegate.clear();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Set<ModSource> keySet() {
|
||||
return delegate.keySet();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<Optional<ModSource>> values() {
|
||||
return delegate.values();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Set<Entry<ModSource, Optional<ModSource>>> entrySet() {
|
||||
return delegate.entrySet();
|
||||
}
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.model.inceptum;
|
||||
|
||||
import io.gitlab.jfronny.commons.HashUtils;
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GPrefer;
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
import io.gitlab.jfronny.inceptum.common.Utils;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.curseforge.response.FingerprintMatchesResponse;
|
||||
import io.gitlab.jfronny.inceptum.launcher.api.CurseforgeApi;
|
||||
|
@ -14,14 +16,19 @@ import java.nio.file.Files;
|
|||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
|
||||
@GSerializable
|
||||
public class ModMeta {
|
||||
public Map<ModSource, Optional<ModSource>> sources; //key: source, value: update
|
||||
public ModMeta$Sources sources; //key: source, value: update
|
||||
public String sha1;
|
||||
public Long murmur2;
|
||||
public List<String> dependents; // by file name
|
||||
public List<String> dependencies; // by file name
|
||||
public boolean explicit = true;
|
||||
|
||||
@GPrefer
|
||||
public ModMeta() {
|
||||
}
|
||||
|
||||
public boolean initialize(String gameVersion) {
|
||||
boolean modrinth = false;
|
||||
boolean curseforge = false;
|
||||
|
@ -56,7 +63,7 @@ public class ModMeta {
|
|||
|
||||
public static ModMeta of(Path mod) {
|
||||
ModMeta res = new ModMeta();
|
||||
res.sources = new LinkedHashMap<>();
|
||||
res.sources = new ModMeta$Sources();
|
||||
if (!Files.isDirectory(mod)) {
|
||||
try {
|
||||
byte[] data = Files.readAllBytes(mod);
|
||||
|
@ -73,7 +80,7 @@ public class ModMeta {
|
|||
|
||||
public static ModMeta of(String sha1, Long murmur2, @Nullable ModSource knownSource, String gameVersion) {
|
||||
ModMeta res = new ModMeta();
|
||||
res.sources = new LinkedHashMap<>();
|
||||
res.sources = new ModMeta$Sources();
|
||||
res.sha1 = sha1;
|
||||
res.murmur2 = murmur2;
|
||||
res.dependents = new ArrayList<>();
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.model.microsoft;
|
||||
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@GSerializable
|
||||
public class Entitlements {
|
||||
public List<StoreItem> items;
|
||||
public String signature;
|
||||
|
||||
@GSerializable
|
||||
public static class StoreItem {
|
||||
public String name;
|
||||
public String signature;
|
||||
|
|
|
@ -1,16 +1,12 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.model.microsoft;
|
||||
|
||||
import io.gitlab.jfronny.gson.annotations.SerializedName;
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
|
||||
public class LoginResponse {
|
||||
public String username;
|
||||
|
||||
@SerializedName("access_token")
|
||||
public String accessToken;
|
||||
|
||||
@SerializedName("token_type")
|
||||
public String tokenType;
|
||||
|
||||
@SerializedName("expires_in")
|
||||
public Integer expiresIn;
|
||||
//TODO test SerializedName
|
||||
@GSerializable
|
||||
public record LoginResponse(String username,
|
||||
@SerializedName("access_token") String accessToken,
|
||||
@SerializedName("token_type") String tokenType,
|
||||
@SerializedName("expires_in") Integer expiresIn) {
|
||||
}
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.model.microsoft;
|
||||
|
||||
import io.gitlab.jfronny.gson.annotations.SerializedName;
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GPrefer;
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@GSerializable
|
||||
public class OauthTokenResponse {
|
||||
@SerializedName("token_type")
|
||||
public String tokenType;
|
||||
|
@ -26,4 +29,20 @@ public class OauthTokenResponse {
|
|||
public String userId;
|
||||
|
||||
public String foci;
|
||||
|
||||
@GPrefer
|
||||
public OauthTokenResponse(String tokenType, Integer expiresIn, Date expiresAt, String scope, String accessToken, String refreshToken, String userId, String foci) {
|
||||
this.tokenType = tokenType;
|
||||
this.expiresIn = expiresIn;
|
||||
this.expiresAt = expiresAt;
|
||||
this.scope = scope;
|
||||
this.accessToken = accessToken;
|
||||
this.refreshToken = refreshToken;
|
||||
this.userId = userId;
|
||||
this.foci = foci;
|
||||
if (this.expiresAt == null) {
|
||||
this.expiresAt = new Date();
|
||||
this.expiresAt.setTime(this.expiresAt.getTime() + this.expiresIn * 1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,17 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.model.microsoft;
|
||||
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@GSerializable
|
||||
public class Profile {
|
||||
public String id;
|
||||
public String name;
|
||||
public List<Skin> skins;
|
||||
public List<Cape> capes;
|
||||
|
||||
@GSerializable
|
||||
public static class Skin {
|
||||
public String id;
|
||||
public String state;
|
||||
|
@ -16,6 +20,7 @@ public class Profile {
|
|||
public String alias;
|
||||
}
|
||||
|
||||
@GSerializable
|
||||
public static class Cape {
|
||||
public String id;
|
||||
}
|
||||
|
|
|
@ -1,28 +1,21 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.model.microsoft;
|
||||
|
||||
import io.gitlab.jfronny.gson.annotations.SerializedName;
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
public class XboxLiveAuthResponse {
|
||||
@SerializedName("IssueInstant")
|
||||
public Date issueInstant;
|
||||
|
||||
@SerializedName("NotAfter")
|
||||
public Date notAfter;
|
||||
|
||||
@SerializedName("Token")
|
||||
public String token;
|
||||
|
||||
@SerializedName("DisplayClaims")
|
||||
public DisplayClaims displayClaims;
|
||||
|
||||
public static class DisplayClaims {
|
||||
public List<XUIClaim> xui;
|
||||
|
||||
public static class XUIClaim {
|
||||
public String uhs;
|
||||
//TODO test SerializedName
|
||||
@GSerializable
|
||||
public record XboxLiveAuthResponse(@SerializedName("IssueInstant") Date issueInstant,
|
||||
@SerializedName("NotAfter") Date notAfter,
|
||||
@SerializedName("Token") String token,
|
||||
@SerializedName("DisplayClaims") DisplayClaims displayClaims) {
|
||||
@GSerializable
|
||||
public record DisplayClaims(List<XUIClaim> xui) {
|
||||
@GSerializable
|
||||
public record XUIClaim(String uhs) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.model.modrinth;
|
||||
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
|
||||
@GSerializable
|
||||
public class ModrinthHashes { //TODO ensure this can parse with additional hashes
|
||||
public String sha1;
|
||||
public String sha512;
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.model.modrinth;
|
||||
|
||||
import io.gitlab.jfronny.gson.annotations.SerializedName;
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@GSerializable
|
||||
public class ModrinthModpackManifest {
|
||||
public Integer formatVersion; // 1
|
||||
public String game; // "minecraft"
|
||||
|
@ -13,6 +15,7 @@ public class ModrinthModpackManifest {
|
|||
public List<File> files;
|
||||
public Dependencies dependencies;
|
||||
|
||||
@GSerializable
|
||||
public static class File {
|
||||
public String path;
|
||||
public ModrinthHashes hashes;
|
||||
|
@ -20,12 +23,14 @@ public class ModrinthModpackManifest {
|
|||
public List<String> downloads;
|
||||
public Long fileSize;
|
||||
|
||||
@GSerializable
|
||||
public static class Env {
|
||||
public ModrinthDependencyType client;
|
||||
public ModrinthDependencyType server;
|
||||
}
|
||||
}
|
||||
|
||||
@GSerializable
|
||||
public static class Dependencies { // All are nullable
|
||||
public String minecraft;
|
||||
public String forge;
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.model.modrinth;
|
||||
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@GSerializable
|
||||
public class ModrinthProject {
|
||||
public String id;
|
||||
public String slug;
|
||||
|
@ -30,18 +33,21 @@ public class ModrinthProject {
|
|||
public List<DonationUrl> donation_urls;
|
||||
public List<GalleryItem> gallery;
|
||||
|
||||
@GSerializable
|
||||
public static class DonationUrl {
|
||||
public String id;
|
||||
public String platform;
|
||||
public String url;
|
||||
}
|
||||
|
||||
@GSerializable
|
||||
public static class License {
|
||||
public String id;
|
||||
public String name;
|
||||
public String url;
|
||||
}
|
||||
|
||||
@GSerializable
|
||||
public static class GalleryItem {
|
||||
public String url;
|
||||
public Boolean featured;
|
||||
|
|
|
@ -1,14 +1,18 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.model.modrinth;
|
||||
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@GSerializable
|
||||
public class ModrinthSearchResult {
|
||||
public List<ModResult> hits;
|
||||
public Integer offset;
|
||||
public Integer limit;
|
||||
public Integer total_hits;
|
||||
|
||||
@GSerializable
|
||||
public static class ModResult {
|
||||
public String project_id;
|
||||
public ModrinthProjectType project_type;
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.model.modrinth;
|
||||
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@GSerializable
|
||||
public class ModrinthVersion {
|
||||
public String id;
|
||||
public String project_id;
|
||||
|
@ -24,6 +27,7 @@ public class ModrinthVersion {
|
|||
alpha, beta, release
|
||||
}
|
||||
|
||||
@GSerializable
|
||||
public static class File {
|
||||
public ModrinthHashes hashes;
|
||||
public String url;
|
||||
|
@ -31,6 +35,7 @@ public class ModrinthVersion {
|
|||
public Boolean primary;
|
||||
}
|
||||
|
||||
@GSerializable
|
||||
public static class Dependency {
|
||||
public String version_id;
|
||||
public String project_id;
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.model.mojang;
|
||||
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@GSerializable
|
||||
public class AssetIndex {
|
||||
public Map<String, Asset> objects;
|
||||
|
||||
@GSerializable
|
||||
public static class Asset {
|
||||
public String hash;
|
||||
public int size;
|
||||
|
|
|
@ -1,15 +1,20 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.model.mojang;
|
||||
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@GSerializable
|
||||
public class JvmFileInfo {
|
||||
public Map<String, File> files;
|
||||
|
||||
@GSerializable
|
||||
public static class File {
|
||||
public Downloads downloads;
|
||||
public boolean executable;
|
||||
public String type;
|
||||
|
||||
@GSerializable
|
||||
public static class Downloads {
|
||||
public MojangFileDownload lzma;
|
||||
public MojangFileDownload raw;
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.model.mojang;
|
||||
|
||||
import io.gitlab.jfronny.gson.annotations.SerializedName;
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@GSerializable
|
||||
public class JvmInfo {
|
||||
public Map<String, List<Jvm>> linux;
|
||||
@SerializedName("mac-os")
|
||||
|
@ -12,16 +14,19 @@ public class JvmInfo {
|
|||
@SerializedName("windows-x64")
|
||||
public Map<String, List<Jvm>> windowsX64;
|
||||
|
||||
@GSerializable
|
||||
public static class Jvm {
|
||||
public Availability availability;
|
||||
public MojangFileDownload manifest;
|
||||
public Version version;
|
||||
|
||||
@GSerializable
|
||||
public static class Availability {
|
||||
public int group;
|
||||
public int progress;
|
||||
}
|
||||
|
||||
@GSerializable
|
||||
public static class Version {
|
||||
public String name;
|
||||
public String released;
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.model.mojang;
|
||||
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
import io.gitlab.jfronny.inceptum.launcher.gson.MinecraftArgumentAdapter;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
@GSerializable(with = MinecraftArgumentAdapter.class)
|
||||
public record MinecraftArgument(Set<String> arg) implements Cloneable {
|
||||
@Override
|
||||
protected MinecraftArgument clone() {
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.model.mojang;
|
||||
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
|
||||
@GSerializable
|
||||
public class MojangFileDownload implements Cloneable {
|
||||
public String sha1;
|
||||
public int size;
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.model.mojang;
|
||||
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
import io.gitlab.jfronny.inceptum.launcher.gson.RulesAdapter;
|
||||
|
||||
@GSerializable(with = RulesAdapter.class)
|
||||
public record Rules(boolean allow) implements Cloneable {
|
||||
@Override
|
||||
protected Rules clone() {
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.model.mojang;
|
||||
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@SuppressWarnings("MethodDoesntCallSuperMethod")
|
||||
@GSerializable
|
||||
public class VersionInfo extends VersionsListInfo implements Cloneable {
|
||||
public Arguments arguments;
|
||||
public AssetIndex assetIndex;
|
||||
|
@ -31,6 +34,7 @@ public class VersionInfo extends VersionsListInfo implements Cloneable {
|
|||
return clone;
|
||||
}
|
||||
|
||||
@GSerializable
|
||||
public static class Arguments implements Cloneable {
|
||||
public List<MinecraftArgument> game;
|
||||
public List<MinecraftArgument> jvm;
|
||||
|
@ -46,6 +50,7 @@ public class VersionInfo extends VersionsListInfo implements Cloneable {
|
|||
}
|
||||
}
|
||||
|
||||
@GSerializable
|
||||
public static class AssetIndex extends MojangFileDownload {
|
||||
public String id;
|
||||
public int totalSize;
|
||||
|
@ -60,6 +65,7 @@ public class VersionInfo extends VersionsListInfo implements Cloneable {
|
|||
}
|
||||
}
|
||||
|
||||
@GSerializable
|
||||
public static class Downloads implements Cloneable {
|
||||
public MojangFileDownload client;
|
||||
public MojangFileDownload client_mappings;
|
||||
|
@ -77,6 +83,7 @@ public class VersionInfo extends VersionsListInfo implements Cloneable {
|
|||
}
|
||||
}
|
||||
|
||||
@GSerializable
|
||||
public static class JavaVersion implements Cloneable {
|
||||
public String component;
|
||||
public int majorVersion;
|
||||
|
@ -90,6 +97,7 @@ public class VersionInfo extends VersionsListInfo implements Cloneable {
|
|||
}
|
||||
}
|
||||
|
||||
@GSerializable
|
||||
public static class Library implements Cloneable {
|
||||
public Downloads downloads;
|
||||
public String name;
|
||||
|
@ -107,6 +115,7 @@ public class VersionInfo extends VersionsListInfo implements Cloneable {
|
|||
return clone;
|
||||
}
|
||||
|
||||
@GSerializable
|
||||
public static class Downloads implements Cloneable {
|
||||
public Artifact artifact;
|
||||
public Map<String, Artifact> classifiers;
|
||||
|
@ -120,6 +129,7 @@ public class VersionInfo extends VersionsListInfo implements Cloneable {
|
|||
return clone;
|
||||
}
|
||||
|
||||
@GSerializable
|
||||
public static class Artifact extends MojangFileDownload implements Cloneable {
|
||||
public String path;
|
||||
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.model.mojang;
|
||||
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@GSerializable
|
||||
public class VersionsList {
|
||||
public Latest latest;
|
||||
public List<VersionsListInfo> versions;
|
||||
|
||||
@GSerializable
|
||||
public static class Latest {
|
||||
public String release;
|
||||
public String snapshot;
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.model.mojang;
|
||||
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@GSerializable
|
||||
public class VersionsListInfo {
|
||||
public String id;
|
||||
public String type;
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.model.multimc;
|
||||
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@GSerializable
|
||||
public class MMCPackMeta {
|
||||
public List<Component> components;
|
||||
public Integer formatVersion;
|
||||
|
||||
@GSerializable
|
||||
public static class Component {
|
||||
public Boolean dependencyOnly;
|
||||
public Boolean important;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.system.exporter;
|
||||
|
||||
import io.gitlab.jfronny.commons.io.JFiles;
|
||||
import io.gitlab.jfronny.inceptum.common.InceptumConfig;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.curseforge.CurseforgeModpackManifest;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.curseforge.GC_CurseforgeModpackManifest;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.instance.Mod;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.source.CurseforgeModSource;
|
||||
|
@ -38,7 +38,7 @@ public class CurseForgeExporter extends Exporter<CurseforgeModpackManifest> {
|
|||
loader.primary = true;
|
||||
manifest.minecraft.modLoaders.add(loader);
|
||||
}
|
||||
JFiles.writeObject(root.resolve("manifest.json"), manifest);
|
||||
GC_CurseforgeModpackManifest.write(root.resolve("manifest.json"), manifest);
|
||||
return manifest;
|
||||
}
|
||||
|
||||
|
@ -58,6 +58,6 @@ public class CurseForgeExporter extends Exporter<CurseforgeModpackManifest> {
|
|||
Files.createDirectories(modsOverrides);
|
||||
Files.copy(mod.getJarPath(), modsOverrides.resolve(mod.getJarPath().getFileName().toString()));
|
||||
}
|
||||
JFiles.writeObject(root.resolve("manifest.json"), manifest);
|
||||
GC_CurseforgeModpackManifest.write(root.resolve("manifest.json"), manifest);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.system.exporter;
|
||||
|
||||
import io.gitlab.jfronny.commons.io.JFiles;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.modrinth.GC_ModrinthModpackManifest;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.modrinth.ModrinthModpackManifest;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.instance.Mod;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.source.ModSource;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.source.ModrinthModSource;
|
||||
|
@ -31,7 +31,7 @@ public class ModrinthExporter extends Exporter<ModrinthModpackManifest> {
|
|||
if (instance.isFabric()) {
|
||||
manifest.dependencies.fabricLoader = instance.getLoaderVersion();
|
||||
}
|
||||
JFiles.writeObject(root.resolve("modrinth.index.json"), manifest);
|
||||
GC_ModrinthModpackManifest.write(root.resolve("modrinth.index.json"), manifest);
|
||||
return manifest;
|
||||
}
|
||||
|
||||
|
@ -51,6 +51,6 @@ public class ModrinthExporter extends Exporter<ModrinthModpackManifest> {
|
|||
Files.createDirectories(modsOverrides);
|
||||
Files.copy(mod.getJarPath(), modsOverrides.resolve(mod.getJarPath().getFileName().toString()));
|
||||
}
|
||||
JFiles.writeObject(root.resolve("modrinth.index.json"), manifest);
|
||||
GC_ModrinthModpackManifest.write(root.resolve("modrinth.index.json"), manifest);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.system.exporter;
|
||||
|
||||
import io.gitlab.jfronny.commons.io.JFiles;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.multimc.GC_MMCPackMeta;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.multimc.MMCPackMeta;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.instance.Mod;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -70,7 +70,7 @@ public class MultiMCExporter extends Exporter<MMCPackMeta> {
|
|||
fabric.version = instance.getLoaderVersion();
|
||||
manifest.components.add(fabric);
|
||||
}
|
||||
JFiles.writeObject(root.resolve("mmc-pack.json"), manifest);
|
||||
GC_MMCPackMeta.write(root.resolve("mmc-pack.json"), manifest);
|
||||
return manifest;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.system.importer;
|
||||
|
||||
import io.gitlab.jfronny.commons.io.JFiles;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.curseforge.CurseforgeModpackManifest;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.curseforge.GC_CurseforgeModpackManifest;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.GC_ModMeta;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.ModMeta;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.instance.ModPath;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.source.*;
|
||||
import io.gitlab.jfronny.inceptum.launcher.util.*;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.source.CurseforgeModSource;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.source.ModDownload;
|
||||
import io.gitlab.jfronny.inceptum.launcher.util.ProcessState;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
|
@ -14,7 +16,7 @@ import java.util.Set;
|
|||
|
||||
public class CurseForgeImporter extends Importer<CurseforgeModpackManifest> {
|
||||
public CurseForgeImporter() {
|
||||
super("CurseForge", "manifest.json", CurseforgeModpackManifest.class);
|
||||
super("CurseForge", "manifest.json", GC_CurseforgeModpackManifest::read);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -45,7 +47,7 @@ public class CurseForgeImporter extends Importer<CurseforgeModpackManifest> {
|
|||
ModDownload download = source.download();
|
||||
ModMeta imod = ModMeta.of(download.sha1(), download.murmur2(), source, manifest.minecraft.version);
|
||||
Files.createDirectories(modsPath);
|
||||
JFiles.writeObject(modsPath.resolve(source.getShortName() + ModPath.EXT_IMOD), imod);
|
||||
GC_ModMeta.write(modsPath.resolve(source.getShortName() + ModPath.EXT_IMOD), imod);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.system.importer;
|
||||
|
||||
import io.gitlab.jfronny.commons.io.JFiles;
|
||||
import io.gitlab.jfronny.commons.throwable.ThrowingFunction;
|
||||
import io.gitlab.jfronny.inceptum.common.MetaHolder;
|
||||
import io.gitlab.jfronny.inceptum.common.Utils;
|
||||
import io.gitlab.jfronny.inceptum.launcher.api.FabricMetaApi;
|
||||
import io.gitlab.jfronny.inceptum.launcher.api.McApi;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.GC_InstanceMeta;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.instance.*;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.setup.Steps;
|
||||
|
@ -18,9 +20,9 @@ import java.nio.file.Path;
|
|||
public abstract class Importer<T> {
|
||||
private final String name;
|
||||
private final String manifestFile;
|
||||
private final Class<T> manifestClass;
|
||||
private final ThrowingFunction<Path, T, IOException> manifestClass;
|
||||
|
||||
public Importer(String name, String manifestFile, Class<T> manifestClass) {
|
||||
public Importer(String name, String manifestFile, ThrowingFunction<Path, T, IOException> manifestClass) {
|
||||
this.name = name;
|
||||
this.manifestFile = manifestFile;
|
||||
this.manifestClass = manifestClass;
|
||||
|
@ -47,7 +49,7 @@ public abstract class Importer<T> {
|
|||
|
||||
public Path importPack(Path sourceRoot, ProcessState state) throws IOException {
|
||||
state.incrementStep("Generating skeleton");
|
||||
T manifest = JFiles.readObject(sourceRoot.resolve(manifestFile), manifestClass);
|
||||
T manifest = manifestClass.apply(sourceRoot.resolve(manifestFile));
|
||||
IntermediaryManifest man = validateManifest(manifest, sourceRoot);
|
||||
String name = man.name();
|
||||
if (name == null || !Utils.VALID_FILENAME.matcher(name).matches()) name = "New Pack";
|
||||
|
@ -56,7 +58,7 @@ public abstract class Importer<T> {
|
|||
Instance.setSetupLock(iDir, true);
|
||||
InstanceMeta meta = new InstanceMeta();
|
||||
meta.version = createVersionString(man.gameVersion(), man.fabricVersion());
|
||||
JFiles.writeObject(iDir.resolve("instance.json"), meta);
|
||||
GC_InstanceMeta.write(iDir.resolve("instance.json"), meta);
|
||||
|
||||
state.incrementStep("Downloading mods");
|
||||
downloadMods(manifest, iDir, state);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.system.importer;
|
||||
|
||||
import io.gitlab.jfronny.inceptum.common.Net;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.modrinth.GC_ModrinthModpackManifest;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.modrinth.ModrinthModpackManifest;
|
||||
import io.gitlab.jfronny.inceptum.launcher.util.ProcessState;
|
||||
|
||||
|
@ -11,7 +12,7 @@ import java.util.ArrayList;
|
|||
|
||||
public class ModrinthImporter extends Importer<ModrinthModpackManifest> {
|
||||
public ModrinthImporter() {
|
||||
super("Modrinth", "modrinth.index.json", ModrinthModpackManifest.class);
|
||||
super("Modrinth", "modrinth.index.json", GC_ModrinthModpackManifest::read);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.system.importer;
|
||||
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.multimc.GC_MMCPackMeta;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.multimc.MMCPackMeta;
|
||||
import io.gitlab.jfronny.inceptum.launcher.util.ProcessState;
|
||||
|
||||
|
@ -10,7 +11,7 @@ import java.util.stream.Stream;
|
|||
|
||||
public class MultiMCImporter extends Importer<MMCPackMeta> {
|
||||
public MultiMCImporter() {
|
||||
super("MultiMC", "mmc-pack.json", MMCPackMeta.class);
|
||||
super("MultiMC", "mmc-pack.json", GC_MMCPackMeta::read);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -3,6 +3,7 @@ package io.gitlab.jfronny.inceptum.launcher.system.instance;
|
|||
import io.gitlab.jfronny.commons.io.JFiles;
|
||||
import io.gitlab.jfronny.inceptum.common.R;
|
||||
import io.gitlab.jfronny.inceptum.common.Utils;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.GC_InstanceMeta;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.mds.ModsDirScanner;
|
||||
import io.gitlab.jfronny.inceptum.launcher.util.GameVersionParser;
|
||||
|
@ -131,7 +132,7 @@ public record Instance(String id, Path path, InstanceMeta meta, ModsDirScanner m
|
|||
|
||||
public void writeMeta() {
|
||||
try {
|
||||
JFiles.writeObject(path.resolve("instance.json"), meta);
|
||||
GC_InstanceMeta.write(path.resolve("instance.json"), meta);
|
||||
} catch (IOException e) {
|
||||
Utils.LOGGER.error("Could not write instance config", e);
|
||||
}
|
||||
|
|
|
@ -1,17 +1,16 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.system.instance;
|
||||
|
||||
import io.gitlab.jfronny.commons.cache.FileBackedRef;
|
||||
import io.gitlab.jfronny.commons.io.JFiles;
|
||||
import io.gitlab.jfronny.commons.throwable.ThrowingConsumer;
|
||||
import io.gitlab.jfronny.commons.throwable.*;
|
||||
import io.gitlab.jfronny.inceptum.common.MetaHolder;
|
||||
import io.gitlab.jfronny.inceptum.common.Utils;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.GC_InstanceMeta;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance;
|
||||
import io.gitlab.jfronny.inceptum.launcher.util.FileBackedRef;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.*;
|
||||
import java.util.*;
|
||||
|
||||
public class InstanceList {
|
||||
|
@ -55,7 +54,7 @@ public class InstanceList {
|
|||
if (!metas.containsKey(instancePath)) {
|
||||
metas.put(instancePath, new IEntry(
|
||||
instancePath,
|
||||
new FileBackedRef<>(instancePath.resolve("instance.json"), InstanceMeta.class)
|
||||
new FileBackedRef<>(instancePath.resolve("instance.json"), GC_InstanceMeta::read)
|
||||
));
|
||||
}
|
||||
return metas.get(instancePath).toPub();
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.system.instance;
|
||||
|
||||
import io.gitlab.jfronny.commons.io.JFiles;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.GC_ModMeta;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.ModMeta;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.mds.ModsDirScanner;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.source.ModDownload;
|
||||
|
@ -31,7 +31,7 @@ public class ModManager {
|
|||
|
||||
public record DownloadMeta(ModDownload download, ModMeta meta, ModSource source, Path metaFile) {
|
||||
public void write() throws IOException {
|
||||
JFiles.writeObject(metaFile, meta);
|
||||
GC_ModMeta.write(metaFile, meta);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,14 +6,13 @@ import io.gitlab.jfronny.inceptum.common.api.MavenApi;
|
|||
import io.gitlab.jfronny.inceptum.launcher.LauncherEnv;
|
||||
import io.gitlab.jfronny.inceptum.common.*;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.*;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.instance.*;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.mojang.*;
|
||||
import io.gitlab.jfronny.inceptum.launcher.api.FabricMetaApi;
|
||||
import io.gitlab.jfronny.inceptum.launcher.api.McApi;
|
||||
import io.gitlab.jfronny.inceptum.launcher.api.account.AccountManager;
|
||||
import io.gitlab.jfronny.inceptum.launcher.api.account.AuthInfo;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.setup.steps.DownloadLibrariesStep;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.instance.ModPath;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.source.ModSource;
|
||||
import io.gitlab.jfronny.inceptum.launcher.util.*;
|
||||
|
||||
|
@ -101,17 +100,9 @@ public class InstanceLauncher {
|
|||
// Fabric imods
|
||||
if (instance.isFabric()) {
|
||||
StringBuilder fabricAddMods = new StringBuilder("-Dfabric.addMods=");
|
||||
if (Files.exists(instance.modsDir())) {
|
||||
for (Path imod : JFiles.list(instance.modsDir(), path -> ModPath.isImod(path) && ModPath.isEnabled(path))) {
|
||||
String fn = imod.getFileName().toString();
|
||||
if (Files.exists(imod.getParent().resolve(fn.substring(0, fn.length() - 5))))
|
||||
continue;
|
||||
Map<ModSource, Optional<ModSource>> sources = JFiles.readObject(imod, ModMeta.class).sources;
|
||||
if (sources.isEmpty()) throw new LaunchException(".imod without attached jar contains no sources");
|
||||
ModSource ms = List.copyOf(sources.keySet()).get(0);
|
||||
Path p = ms.getJarPath().toAbsolutePath();
|
||||
if (!Files.exists(p)) ms.download();
|
||||
fabricAddMods.append(p);
|
||||
for (Mod mod : instance.getMods()) {
|
||||
if (mod.isEnabled() && mod.needsInject()) {
|
||||
fabricAddMods.append(mod.getJarPath());
|
||||
fabricAddMods.append(File.pathSeparatorChar);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@ import io.gitlab.jfronny.commons.io.JFiles;
|
|||
import io.gitlab.jfronny.gson.JsonParseException;
|
||||
import io.gitlab.jfronny.inceptum.common.Utils;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.fabric.FabricModJson;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.fabric.GC_FabricModJson;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.GC_ModMeta;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.ModMeta;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.instance.Mod;
|
||||
|
@ -45,7 +47,7 @@ public record FileScanTask(ProtoInstance instance, Path file, BiConsumer<Path, M
|
|||
private <TEx extends Throwable> void evaluateSources(Path modFile, MetadataRef ref) throws IOException, TEx {
|
||||
boolean modified = false;
|
||||
if (ref.meta.initialize(gameVersion)) {
|
||||
JFiles.writeObject(ref.imodPath, ref.meta);
|
||||
GC_ModMeta.write(ref.imodPath, ref.meta);
|
||||
modified = true;
|
||||
}
|
||||
ModSource selectedSource = null;
|
||||
|
@ -77,14 +79,14 @@ public record FileScanTask(ProtoInstance instance, Path file, BiConsumer<Path, M
|
|||
try (FileSystem fs = Utils.openZipFile(modJarDefault, false)) {
|
||||
Path fmjPath = fs.getPath("fabric.mod.json");
|
||||
if (!Files.exists(fmjPath)) return null;
|
||||
return JFiles.readObject(fmjPath, FabricModJson.class);
|
||||
return GC_FabricModJson.read(fmjPath);
|
||||
}
|
||||
}
|
||||
|
||||
private static class MetadataRef {
|
||||
public MetadataRef(Path imodPath, @Nullable Function<Path, ModMeta> defaultMeta) throws IOException {
|
||||
this.imodPath = imodPath;
|
||||
if (!Files.exists(imodPath) && defaultMeta != null) JFiles.writeObject(imodPath, defaultMeta.apply(imodPath));
|
||||
if (!Files.exists(imodPath) && defaultMeta != null) GC_ModMeta.write(imodPath, defaultMeta.apply(imodPath));
|
||||
if (Files.exists(imodPath)) update();
|
||||
}
|
||||
|
||||
|
@ -93,7 +95,7 @@ public record FileScanTask(ProtoInstance instance, Path file, BiConsumer<Path, M
|
|||
public ModMeta meta;
|
||||
|
||||
public void update() throws IOException {
|
||||
this.meta = JFiles.readObject(imodPath, ModMeta.class);
|
||||
this.meta = GC_ModMeta.read(imodPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.system.mds;
|
||||
|
||||
import io.gitlab.jfronny.commons.io.JFiles;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.fabric.FabricModJson;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.GC_ModMeta;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.ModMeta;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.instance.*;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.source.ModSource;
|
||||
|
@ -131,6 +131,6 @@ public class MdsMod extends Mod {
|
|||
}
|
||||
|
||||
private void write() throws IOException {
|
||||
JFiles.writeObject(imodPath, meta);
|
||||
GC_ModMeta.write(imodPath, meta);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,8 +36,7 @@ class ModsDirScannerImpl implements ModsDirScanner {
|
|||
protected static ModsDirScannerImpl get(Path modsDir, InstanceMeta instance) throws IOException {
|
||||
if (SCANNERS.containsKey(modsDir)) {
|
||||
ModsDirScannerImpl mds = SCANNERS.get(modsDir);
|
||||
if (mds.instance.equals(instance))
|
||||
return mds;
|
||||
if (mds.instance.meta.equals(instance)) return mds;
|
||||
mds.close();
|
||||
}
|
||||
ModsDirScannerImpl mds = new ModsDirScannerImpl(modsDir, instance);
|
||||
|
@ -153,14 +152,19 @@ class ModsDirScannerImpl implements ModsDirScanner {
|
|||
|
||||
public static void closeAll() {
|
||||
for (ModsDirScannerImpl value : SCANNERS.values().toArray(ModsDirScannerImpl[]::new)) {
|
||||
value.close();
|
||||
try {
|
||||
value.close();
|
||||
} catch (IOException e) {
|
||||
Utils.LOGGER.error("Could not close MDS", e);
|
||||
}
|
||||
}
|
||||
POOL.shutdown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
public void close() throws IOException {
|
||||
disposed = true;
|
||||
service.close();
|
||||
SCANNERS.remove(instance.modsDir);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package io.gitlab.jfronny.inceptum.launcher.system.mds;
|
|||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Objects;
|
||||
|
||||
public class ProtoInstance {
|
||||
public final Path modsDir;
|
||||
|
@ -14,4 +15,9 @@ public class ProtoInstance {
|
|||
this.mds = mds;
|
||||
this.meta = meta;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(modsDir, mds, meta);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.system.setup.steps;
|
||||
|
||||
import io.gitlab.jfronny.commons.io.JFiles;
|
||||
import io.gitlab.jfronny.inceptum.common.MetaHolder;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.setup.Step;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.GC_InstanceMeta;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.mds.ModsDirScanner;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.setup.SetupStepInfo;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.setup.Step;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
|
@ -16,7 +15,7 @@ public class RunMdsStep implements Step {
|
|||
public void execute(SetupStepInfo info, AtomicBoolean stopThread) throws IOException {
|
||||
info.setState("Running MDS");
|
||||
Path instance = MetaHolder.INSTANCE_DIR.resolve(info.name());
|
||||
ModsDirScanner.get(instance.resolve("mods"), JFiles.readObject(instance.resolve("instance.json"), InstanceMeta.class))
|
||||
ModsDirScanner.get(instance.resolve("mods"), GC_InstanceMeta.read(instance.resolve("instance.json")))
|
||||
.runOnce((path, iwModDescription) -> info.setState("Scanned " + path));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.system.setup.steps;
|
||||
|
||||
import io.gitlab.jfronny.commons.io.JFiles;
|
||||
import io.gitlab.jfronny.inceptum.common.MetaHolder;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.GC_InstanceMeta;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.setup.Step;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.setup.SetupStepInfo;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.setup.Step;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
|
@ -21,7 +21,7 @@ public class WriteMetadataStep implements Step {
|
|||
if (!Files.exists(metaPath)) {
|
||||
InstanceMeta meta = new InstanceMeta();
|
||||
meta.version = info.version().id;
|
||||
JFiles.writeObject(metaPath, meta);
|
||||
GC_InstanceMeta.write(metaPath, meta);
|
||||
}
|
||||
Instance.setSetupLock(instance, false);
|
||||
if (!Files.exists(instance.resolve(".gitignore"))) {
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.system.source;
|
||||
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
import io.gitlab.jfronny.inceptum.common.MetaHolder;
|
||||
import io.gitlab.jfronny.inceptum.launcher.gson.ModSourceAdapter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
@GSerializable(with = ModSourceAdapter.class)
|
||||
public interface ModSource {
|
||||
ModDownload download() throws IOException;
|
||||
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.util;
|
||||
|
||||
import io.gitlab.jfronny.commons.throwable.ThrowingFunction;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.*;
|
||||
|
||||
public class FileBackedRef<T> implements Closeable {
|
||||
private final Path filePath;
|
||||
private final ThrowingFunction<Path, T, IOException> read;
|
||||
private final WatchService service;
|
||||
private T cache = null;
|
||||
|
||||
public FileBackedRef(Path filePath, ThrowingFunction<Path, T, IOException> read) throws IOException {
|
||||
this.filePath = filePath;
|
||||
this.read = read;
|
||||
this.service = FileSystems.getDefault().newWatchService();
|
||||
filePath.getParent().register(service, StandardWatchEventKinds.ENTRY_MODIFY);
|
||||
}
|
||||
|
||||
public T get() throws IOException {
|
||||
WatchKey key = service.poll();
|
||||
boolean update = cache == null;
|
||||
if (key != null) {
|
||||
for (WatchEvent<?> event : key.pollEvents()) {
|
||||
update |= event.context().equals(filePath);
|
||||
}
|
||||
key.reset();
|
||||
}
|
||||
if (update) cache = read.apply(filePath);
|
||||
return cache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
service.close();
|
||||
}
|
||||
}
|
|
@ -27,7 +27,7 @@ public class Wrapper {
|
|||
throw new FileNotFoundException("Something went wrong while downloading the latest version.");
|
||||
}
|
||||
}
|
||||
List<Path> classpath = Updater.getLaunchClasspath(JFiles.readObject(MetaHolder.WRAPPER_CONFIG_PATH, WrapperConfig.class));
|
||||
List<Path> classpath = Updater.getLaunchClasspath(GC_WrapperConfig.read(MetaHolder.WRAPPER_CONFIG_PATH));
|
||||
if (!BuildMetadata.IS_RELEASE) {
|
||||
System.out.println("Using classpath: " + classpath.stream().map(Path::toString).collect(Collectors.joining("" + File.pathSeparator)));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue