使用 TypeToken 替代 Type (#3320)
This commit is contained in:
@@ -18,7 +18,6 @@
|
|||||||
package org.jackhuang.hmcl.game;
|
package org.jackhuang.hmcl.game;
|
||||||
|
|
||||||
import com.google.gson.JsonParseException;
|
import com.google.gson.JsonParseException;
|
||||||
import com.google.gson.reflect.TypeToken;
|
|
||||||
import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
||||||
import org.jackhuang.hmcl.download.LibraryAnalyzer;
|
import org.jackhuang.hmcl.download.LibraryAnalyzer;
|
||||||
import org.jackhuang.hmcl.mod.MinecraftInstanceTask;
|
import org.jackhuang.hmcl.mod.MinecraftInstanceTask;
|
||||||
@@ -67,8 +66,7 @@ public final class HMCLModpackInstallTask extends Task<Void> {
|
|||||||
ModpackConfiguration<Modpack> config = null;
|
ModpackConfiguration<Modpack> config = null;
|
||||||
try {
|
try {
|
||||||
if (json.exists()) {
|
if (json.exists()) {
|
||||||
config = JsonUtils.GSON.fromJson(FileUtils.readText(json), new TypeToken<ModpackConfiguration<Modpack>>() {
|
config = JsonUtils.GSON.fromJson(FileUtils.readText(json), ModpackConfiguration.typeOf(Modpack.class));
|
||||||
}.getType());
|
|
||||||
|
|
||||||
if (!HMCLModpackProvider.INSTANCE.getName().equals(config.getType()))
|
if (!HMCLModpackProvider.INSTANCE.getName().equals(config.getType()))
|
||||||
throw new IllegalArgumentException("Version " + name + " is not a HMCL modpack. Cannot update this version.");
|
throw new IllegalArgumentException("Version " + name + " is not a HMCL modpack. Cannot update this version.");
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
package org.jackhuang.hmcl.game;
|
package org.jackhuang.hmcl.game;
|
||||||
|
|
||||||
import com.google.gson.JsonParseException;
|
import com.google.gson.JsonParseException;
|
||||||
import com.google.gson.reflect.TypeToken;
|
|
||||||
import org.apache.commons.compress.archivers.zip.ZipFile;
|
import org.apache.commons.compress.archivers.zip.ZipFile;
|
||||||
import org.jackhuang.hmcl.mod.*;
|
import org.jackhuang.hmcl.mod.*;
|
||||||
import org.jackhuang.hmcl.mod.curse.CurseModpackProvider;
|
import org.jackhuang.hmcl.mod.curse.CurseModpackProvider;
|
||||||
@@ -141,8 +140,7 @@ public final class ModpackHelper {
|
|||||||
throw new FileNotFoundException(file.getPath());
|
throw new FileNotFoundException(file.getPath());
|
||||||
else
|
else
|
||||||
try {
|
try {
|
||||||
return JsonUtils.GSON.fromJson(FileUtils.readText(file), new TypeToken<ModpackConfiguration<?>>() {
|
return JsonUtils.GSON.fromJson(FileUtils.readText(file), ModpackConfiguration.class);
|
||||||
}.getType());
|
|
||||||
} catch (JsonParseException e) {
|
} catch (JsonParseException e) {
|
||||||
throw new IOException("Malformed modpack configuration");
|
throw new IOException("Malformed modpack configuration");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ package org.jackhuang.hmcl.java;
|
|||||||
|
|
||||||
import com.google.gson.*;
|
import com.google.gson.*;
|
||||||
import com.google.gson.annotations.JsonAdapter;
|
import com.google.gson.annotations.JsonAdapter;
|
||||||
import com.google.gson.reflect.TypeToken;
|
|
||||||
import org.jackhuang.hmcl.util.platform.Architecture;
|
import org.jackhuang.hmcl.util.platform.Architecture;
|
||||||
import org.jackhuang.hmcl.util.platform.OperatingSystem;
|
import org.jackhuang.hmcl.util.platform.OperatingSystem;
|
||||||
import org.jackhuang.hmcl.util.platform.Platform;
|
import org.jackhuang.hmcl.util.platform.Platform;
|
||||||
@@ -29,6 +28,8 @@ import java.lang.reflect.Type;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import static org.jackhuang.hmcl.util.gson.JsonUtils.mapTypeOf;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Glavo
|
* @author Glavo
|
||||||
*/
|
*/
|
||||||
@@ -63,8 +64,7 @@ public final class JavaManifest {
|
|||||||
|
|
||||||
public static final class Serializer implements JsonSerializer<JavaManifest>, JsonDeserializer<JavaManifest> {
|
public static final class Serializer implements JsonSerializer<JavaManifest>, JsonDeserializer<JavaManifest> {
|
||||||
|
|
||||||
private static final Type LOCAL_FILES_TYPE = new TypeToken<Map<String, JavaLocalFiles.Local>>() {
|
private static final Type LOCAL_FILES_TYPE = mapTypeOf(String.class, JavaLocalFiles.Local.class).getType();
|
||||||
}.getType();
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JsonElement serialize(JavaManifest src, Type typeOfSrc, JsonSerializationContext context) {
|
public JsonElement serialize(JavaManifest src, Type typeOfSrc, JsonSerializationContext context) {
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.jackhuang.hmcl.setting;
|
package org.jackhuang.hmcl.setting;
|
||||||
|
|
||||||
import com.google.gson.reflect.TypeToken;
|
|
||||||
import javafx.beans.InvalidationListener;
|
import javafx.beans.InvalidationListener;
|
||||||
import javafx.beans.Observable;
|
import javafx.beans.Observable;
|
||||||
import javafx.beans.property.ObjectProperty;
|
import javafx.beans.property.ObjectProperty;
|
||||||
@@ -55,6 +54,8 @@ import static org.jackhuang.hmcl.ui.FXUtils.onInvalidating;
|
|||||||
import static org.jackhuang.hmcl.util.Lang.immutableListOf;
|
import static org.jackhuang.hmcl.util.Lang.immutableListOf;
|
||||||
import static org.jackhuang.hmcl.util.Lang.mapOf;
|
import static org.jackhuang.hmcl.util.Lang.mapOf;
|
||||||
import static org.jackhuang.hmcl.util.Pair.pair;
|
import static org.jackhuang.hmcl.util.Pair.pair;
|
||||||
|
import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf;
|
||||||
|
import static org.jackhuang.hmcl.util.gson.JsonUtils.mapTypeOf;
|
||||||
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||||
import static org.jackhuang.hmcl.util.logging.Logger.LOG;
|
import static org.jackhuang.hmcl.util.logging.Logger.LOG;
|
||||||
|
|
||||||
@@ -171,14 +172,11 @@ public final class Accounts {
|
|||||||
config().getAccountStorages().setAll(portable);
|
config().getAccountStorages().setAll(portable);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private static void loadGlobalAccountStorages() {
|
private static void loadGlobalAccountStorages() {
|
||||||
Path globalAccountsFile = Metadata.HMCL_DIRECTORY.resolve("accounts.json");
|
Path globalAccountsFile = Metadata.HMCL_DIRECTORY.resolve("accounts.json");
|
||||||
if (Files.exists(globalAccountsFile)) {
|
if (Files.exists(globalAccountsFile)) {
|
||||||
try (Reader reader = Files.newBufferedReader(globalAccountsFile)) {
|
try (Reader reader = Files.newBufferedReader(globalAccountsFile)) {
|
||||||
globalAccountStorages.setAll((List<Map<Object, Object>>)
|
globalAccountStorages.setAll(Config.CONFIG_GSON.fromJson(reader, listTypeOf(mapTypeOf(Object.class, Object.class))));
|
||||||
Config.CONFIG_GSON.fromJson(reader, new TypeToken<List<Map<Object, Object>>>() {
|
|
||||||
}.getType()));
|
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
LOG.warning("Failed to load global accounts", e);
|
LOG.warning("Failed to load global accounts", e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
package org.jackhuang.hmcl.ui.main;
|
package org.jackhuang.hmcl.ui.main;
|
||||||
|
|
||||||
import com.google.gson.annotations.SerializedName;
|
import com.google.gson.annotations.SerializedName;
|
||||||
import com.google.gson.reflect.TypeToken;
|
|
||||||
import javafx.geometry.Insets;
|
import javafx.geometry.Insets;
|
||||||
import javafx.scene.control.ScrollPane;
|
import javafx.scene.control.ScrollPane;
|
||||||
import javafx.scene.layout.VBox;
|
import javafx.scene.layout.VBox;
|
||||||
@@ -34,6 +33,7 @@ import org.jackhuang.hmcl.util.io.HttpRequest;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf;
|
||||||
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||||
|
|
||||||
public class HelpPage extends SpinnerPane {
|
public class HelpPage extends SpinnerPane {
|
||||||
@@ -63,8 +63,7 @@ public class HelpPage extends SpinnerPane {
|
|||||||
|
|
||||||
private void loadHelp() {
|
private void loadHelp() {
|
||||||
showSpinner();
|
showSpinner();
|
||||||
Task.<List<HelpCategory>>supplyAsync(() -> HttpRequest.GET("https://docs.hmcl.net/index.json").getJson(new TypeToken<List<HelpCategory>>() {
|
Task.supplyAsync(() -> HttpRequest.GET("https://docs.hmcl.net/index.json").getJson(listTypeOf(HelpCategory.class)))
|
||||||
}.getType()))
|
|
||||||
.thenAcceptAsync(Schedulers.javafx(), helpCategories -> {
|
.thenAcceptAsync(Schedulers.javafx(), helpCategories -> {
|
||||||
for (HelpCategory category : helpCategories) {
|
for (HelpCategory category : helpCategories) {
|
||||||
ComponentList categoryPane = new ComponentList();
|
ComponentList categoryPane = new ComponentList();
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.jackhuang.hmcl.util;
|
package org.jackhuang.hmcl.util;
|
||||||
|
|
||||||
import com.google.gson.reflect.TypeToken;
|
|
||||||
import org.jackhuang.hmcl.game.*;
|
import org.jackhuang.hmcl.game.*;
|
||||||
import org.jackhuang.hmcl.setting.VersionSetting;
|
import org.jackhuang.hmcl.setting.VersionSetting;
|
||||||
import org.jackhuang.hmcl.util.gson.JsonUtils;
|
import org.jackhuang.hmcl.util.gson.JsonUtils;
|
||||||
@@ -34,6 +33,7 @@ import java.nio.charset.StandardCharsets;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static org.jackhuang.hmcl.util.gson.JsonUtils.mapTypeOf;
|
||||||
import static org.jackhuang.hmcl.util.logging.Logger.LOG;
|
import static org.jackhuang.hmcl.util.logging.Logger.LOG;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -51,9 +51,7 @@ public final class NativePatcher {
|
|||||||
return natives.computeIfAbsent(platform, p -> {
|
return natives.computeIfAbsent(platform, p -> {
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
try (Reader reader = new InputStreamReader(NativePatcher.class.getResourceAsStream("/assets/natives.json"), StandardCharsets.UTF_8)) {
|
try (Reader reader = new InputStreamReader(NativePatcher.class.getResourceAsStream("/assets/natives.json"), StandardCharsets.UTF_8)) {
|
||||||
Map<String, Map<String, Library>> natives = JsonUtils.GSON.fromJson(reader, new TypeToken<Map<String, Map<String, Library>>>() {
|
Map<String, Map<String, Library>> natives = JsonUtils.GSON.fromJson(reader, mapTypeOf(String.class, mapTypeOf(String.class, Library.class)));
|
||||||
}.getType());
|
|
||||||
|
|
||||||
return natives.getOrDefault(p.toString(), Collections.emptyMap());
|
return natives.getOrDefault(p.toString(), Collections.emptyMap());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.warning("Failed to load native library list", e);
|
LOG.warning("Failed to load native library list", e);
|
||||||
|
|||||||
@@ -41,10 +41,9 @@
|
|||||||
*/
|
*/
|
||||||
package org.jackhuang.hmcl.util;
|
package org.jackhuang.hmcl.util;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
import com.google.gson.reflect.TypeToken;
|
|
||||||
import org.jackhuang.hmcl.Main;
|
import org.jackhuang.hmcl.Main;
|
||||||
import org.jackhuang.hmcl.ui.SwingUtils;
|
import org.jackhuang.hmcl.ui.SwingUtils;
|
||||||
|
import org.jackhuang.hmcl.util.gson.JsonUtils;
|
||||||
import org.jackhuang.hmcl.util.io.ChecksumMismatchException;
|
import org.jackhuang.hmcl.util.io.ChecksumMismatchException;
|
||||||
import org.jackhuang.hmcl.util.io.IOUtils;
|
import org.jackhuang.hmcl.util.io.IOUtils;
|
||||||
import org.jackhuang.hmcl.util.io.JarUtils;
|
import org.jackhuang.hmcl.util.io.JarUtils;
|
||||||
@@ -68,6 +67,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
import static java.util.stream.Collectors.toSet;
|
import static java.util.stream.Collectors.toSet;
|
||||||
import static org.jackhuang.hmcl.Metadata.HMCL_DIRECTORY;
|
import static org.jackhuang.hmcl.Metadata.HMCL_DIRECTORY;
|
||||||
|
import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf;
|
||||||
|
import static org.jackhuang.hmcl.util.gson.JsonUtils.mapTypeOf;
|
||||||
import static org.jackhuang.hmcl.util.logging.Logger.LOG;
|
import static org.jackhuang.hmcl.util.logging.Logger.LOG;
|
||||||
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||||
|
|
||||||
@@ -104,11 +105,11 @@ public final class SelfDependencyPatcher {
|
|||||||
private static final Path DEPENDENCIES_DIR_PATH = HMCL_DIRECTORY.resolve("dependencies").resolve(Platform.getPlatform().toString()).resolve("openjfx");
|
private static final Path DEPENDENCIES_DIR_PATH = HMCL_DIRECTORY.resolve("dependencies").resolve(Platform.getPlatform().toString()).resolve("openjfx");
|
||||||
|
|
||||||
static List<DependencyDescriptor> readDependencies() {
|
static List<DependencyDescriptor> readDependencies() {
|
||||||
ArrayList<DependencyDescriptor> dependencies;
|
List<DependencyDescriptor> dependencies;
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
try (Reader reader = new InputStreamReader(SelfDependencyPatcher.class.getResourceAsStream(DEPENDENCIES_LIST_FILE), UTF_8)) {
|
try (Reader reader = new InputStreamReader(SelfDependencyPatcher.class.getResourceAsStream(DEPENDENCIES_LIST_FILE), UTF_8)) {
|
||||||
Map<String, ArrayList<DependencyDescriptor>> allDependencies =
|
Map<String, List<DependencyDescriptor>> allDependencies =
|
||||||
new Gson().fromJson(reader, new TypeToken<Map<String, ArrayList<DependencyDescriptor>>>(){}.getType());
|
JsonUtils.GSON.fromJson(reader, mapTypeOf(String.class, listTypeOf(DependencyDescriptor.class)));
|
||||||
dependencies = allDependencies.get(Platform.getPlatform().toString());
|
dependencies = allDependencies.get(Platform.getPlatform().toString());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new UncheckedIOException(e);
|
throw new UncheckedIOException(e);
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.jackhuang.hmcl.auth.offline;
|
package org.jackhuang.hmcl.auth.offline;
|
||||||
|
|
||||||
import com.google.gson.reflect.TypeToken;
|
|
||||||
import org.glavo.png.javafx.PNGJavaFXUtils;
|
import org.glavo.png.javafx.PNGJavaFXUtils;
|
||||||
import org.jackhuang.hmcl.auth.yggdrasil.GameProfile;
|
import org.jackhuang.hmcl.auth.yggdrasil.GameProfile;
|
||||||
import org.jackhuang.hmcl.auth.yggdrasil.TextureModel;
|
import org.jackhuang.hmcl.auth.yggdrasil.TextureModel;
|
||||||
@@ -38,6 +37,7 @@ import java.util.stream.Stream;
|
|||||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
import static org.jackhuang.hmcl.util.Lang.mapOf;
|
import static org.jackhuang.hmcl.util.Lang.mapOf;
|
||||||
import static org.jackhuang.hmcl.util.Pair.pair;
|
import static org.jackhuang.hmcl.util.Pair.pair;
|
||||||
|
import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf;
|
||||||
|
|
||||||
public class YggdrasilServer extends HttpServer {
|
public class YggdrasilServer extends HttpServer {
|
||||||
|
|
||||||
@@ -81,8 +81,7 @@ public class YggdrasilServer extends HttpServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Response profiles(Request request) throws IOException {
|
private Response profiles(Request request) throws IOException {
|
||||||
List<String> names = JsonUtils.fromNonNullJsonFully(request.getSession().getInputStream(), new TypeToken<List<String>>() {
|
List<String> names = JsonUtils.fromNonNullJsonFully(request.getSession().getInputStream(), listTypeOf(String.class));
|
||||||
}.getType());
|
|
||||||
return ok(names.stream().distinct()
|
return ok(names.stream().distinct()
|
||||||
.map(this::findCharacterByName)
|
.map(this::findCharacterByName)
|
||||||
.flatMap(Lang::toStream)
|
.flatMap(Lang::toStream)
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.jackhuang.hmcl.download.fabric;
|
package org.jackhuang.hmcl.download.fabric;
|
||||||
|
|
||||||
import com.google.gson.reflect.TypeToken;
|
|
||||||
import org.jackhuang.hmcl.download.DownloadProvider;
|
import org.jackhuang.hmcl.download.DownloadProvider;
|
||||||
import org.jackhuang.hmcl.download.VersionList;
|
import org.jackhuang.hmcl.download.VersionList;
|
||||||
import org.jackhuang.hmcl.util.gson.JsonUtils;
|
import org.jackhuang.hmcl.util.gson.JsonUtils;
|
||||||
@@ -25,13 +24,13 @@ import org.jackhuang.hmcl.util.io.NetworkUtils;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static org.jackhuang.hmcl.util.Lang.wrap;
|
import static org.jackhuang.hmcl.util.Lang.wrap;
|
||||||
|
import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf;
|
||||||
|
|
||||||
public final class FabricVersionList extends VersionList<FabricRemoteVersion> {
|
public final class FabricVersionList extends VersionList<FabricRemoteVersion> {
|
||||||
private final DownloadProvider downloadProvider;
|
private final DownloadProvider downloadProvider;
|
||||||
@@ -69,8 +68,8 @@ public final class FabricVersionList extends VersionList<FabricRemoteVersion> {
|
|||||||
|
|
||||||
private List<String> getGameVersions(String metaUrl) throws IOException {
|
private List<String> getGameVersions(String metaUrl) throws IOException {
|
||||||
String json = NetworkUtils.doGet(downloadProvider.injectURLWithCandidates(metaUrl));
|
String json = NetworkUtils.doGet(downloadProvider.injectURLWithCandidates(metaUrl));
|
||||||
return JsonUtils.GSON.<ArrayList<GameVersion>>fromJson(json, new TypeToken<ArrayList<GameVersion>>() {
|
return JsonUtils.GSON.fromJson(json, listTypeOf(GameVersion.class))
|
||||||
}.getType()).stream().map(GameVersion::getVersion).collect(Collectors.toList());
|
.stream().map(GameVersion::getVersion).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getLaunchMetaUrl(String gameVersion, String loaderVersion) {
|
private static String getLaunchMetaUrl(String gameVersion, String loaderVersion) {
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
package org.jackhuang.hmcl.download.forge;
|
package org.jackhuang.hmcl.download.forge;
|
||||||
|
|
||||||
import com.google.gson.JsonParseException;
|
import com.google.gson.JsonParseException;
|
||||||
import com.google.gson.reflect.TypeToken;
|
|
||||||
import org.jackhuang.hmcl.download.VersionList;
|
import org.jackhuang.hmcl.download.VersionList;
|
||||||
import org.jackhuang.hmcl.util.Immutable;
|
import org.jackhuang.hmcl.util.Immutable;
|
||||||
import org.jackhuang.hmcl.util.Lang;
|
import org.jackhuang.hmcl.util.Lang;
|
||||||
@@ -40,6 +39,7 @@ import java.util.concurrent.CompletableFuture;
|
|||||||
import static org.jackhuang.hmcl.util.Lang.mapOf;
|
import static org.jackhuang.hmcl.util.Lang.mapOf;
|
||||||
import static org.jackhuang.hmcl.util.Lang.wrap;
|
import static org.jackhuang.hmcl.util.Lang.wrap;
|
||||||
import static org.jackhuang.hmcl.util.Pair.pair;
|
import static org.jackhuang.hmcl.util.Pair.pair;
|
||||||
|
import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf;
|
||||||
import static org.jackhuang.hmcl.util.logging.Logger.LOG;
|
import static org.jackhuang.hmcl.util.logging.Logger.LOG;
|
||||||
|
|
||||||
public final class ForgeBMCLVersionList extends VersionList<ForgeRemoteVersion> {
|
public final class ForgeBMCLVersionList extends VersionList<ForgeRemoteVersion> {
|
||||||
@@ -87,11 +87,9 @@ public final class ForgeBMCLVersionList extends VersionList<ForgeRemoteVersion>
|
|||||||
String lookupVersion = toLookupVersion(gameVersion);
|
String lookupVersion = toLookupVersion(gameVersion);
|
||||||
|
|
||||||
return CompletableFuture.completedFuture(null)
|
return CompletableFuture.completedFuture(null)
|
||||||
.thenApplyAsync(wrap(unused -> HttpRequest.GET(apiRoot + "/forge/minecraft/" + lookupVersion).<List<ForgeVersion>>getJson(new TypeToken<List<ForgeVersion>>() {
|
.thenApplyAsync(wrap(unused -> HttpRequest.GET(apiRoot + "/forge/minecraft/" + lookupVersion).getJson(listTypeOf(ForgeVersion.class))))
|
||||||
}.getType())))
|
|
||||||
.thenAcceptAsync(forgeVersions -> {
|
.thenAcceptAsync(forgeVersions -> {
|
||||||
lock.writeLock().lock();
|
lock.writeLock().lock();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
versions.clear(gameVersion);
|
versions.clear(gameVersion);
|
||||||
if (forgeVersions == null) return;
|
if (forgeVersions == null) return;
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ package org.jackhuang.hmcl.download.java.mojang;
|
|||||||
|
|
||||||
import com.google.gson.*;
|
import com.google.gson.*;
|
||||||
import com.google.gson.annotations.JsonAdapter;
|
import com.google.gson.annotations.JsonAdapter;
|
||||||
import com.google.gson.reflect.TypeToken;
|
|
||||||
import org.jackhuang.hmcl.game.DownloadInfo;
|
import org.jackhuang.hmcl.game.DownloadInfo;
|
||||||
import org.jackhuang.hmcl.util.Immutable;
|
import org.jackhuang.hmcl.util.Immutable;
|
||||||
|
|
||||||
@@ -27,6 +26,9 @@ import java.lang.reflect.Type;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf;
|
||||||
|
import static org.jackhuang.hmcl.util.gson.JsonUtils.mapTypeOf;
|
||||||
|
|
||||||
@JsonAdapter(MojangJavaDownloads.Adapter.class)
|
@JsonAdapter(MojangJavaDownloads.Adapter.class)
|
||||||
public class MojangJavaDownloads {
|
public class MojangJavaDownloads {
|
||||||
|
|
||||||
@@ -49,8 +51,7 @@ public class MojangJavaDownloads {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MojangJavaDownloads deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
|
public MojangJavaDownloads deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
|
||||||
return new MojangJavaDownloads(context.deserialize(json, new TypeToken<Map<String, Map<String, List<JavaDownload>>>>() {
|
return new MojangJavaDownloads(context.deserialize(json, mapTypeOf(String.class, mapTypeOf(String.class, listTypeOf(JavaDownload.class))).getType()));
|
||||||
}.getType()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,18 +19,17 @@ package org.jackhuang.hmcl.download.neoforge;
|
|||||||
|
|
||||||
import com.google.gson.JsonParseException;
|
import com.google.gson.JsonParseException;
|
||||||
import com.google.gson.annotations.SerializedName;
|
import com.google.gson.annotations.SerializedName;
|
||||||
import com.google.gson.reflect.TypeToken;
|
|
||||||
import org.jackhuang.hmcl.download.VersionList;
|
import org.jackhuang.hmcl.download.VersionList;
|
||||||
import org.jackhuang.hmcl.util.Immutable;
|
import org.jackhuang.hmcl.util.Immutable;
|
||||||
import org.jackhuang.hmcl.util.gson.Validation;
|
import org.jackhuang.hmcl.util.gson.Validation;
|
||||||
import org.jackhuang.hmcl.util.io.HttpRequest;
|
import org.jackhuang.hmcl.util.io.HttpRequest;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
import static org.jackhuang.hmcl.util.Lang.wrap;
|
import static org.jackhuang.hmcl.util.Lang.wrap;
|
||||||
|
import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf;
|
||||||
|
|
||||||
public final class NeoForgeBMCLVersionList extends VersionList<NeoForgeRemoteVersion> {
|
public final class NeoForgeBMCLVersionList extends VersionList<NeoForgeRemoteVersion> {
|
||||||
private final String apiRoot;
|
private final String apiRoot;
|
||||||
@@ -68,8 +67,7 @@ public final class NeoForgeBMCLVersionList extends VersionList<NeoForgeRemoteVer
|
|||||||
@Override
|
@Override
|
||||||
public CompletableFuture<?> refreshAsync(String gameVersion) {
|
public CompletableFuture<?> refreshAsync(String gameVersion) {
|
||||||
return CompletableFuture.completedFuture((Void) null)
|
return CompletableFuture.completedFuture((Void) null)
|
||||||
.thenApplyAsync(wrap(unused -> HttpRequest.GET(apiRoot + "/neoforge/list/" + gameVersion).<List<NeoForgeVersion>>getJson(new TypeToken<List<NeoForgeVersion>>() {
|
.thenApplyAsync(wrap(unused -> HttpRequest.GET(apiRoot + "/neoforge/list/" + gameVersion).getJson(listTypeOf(NeoForgeVersion.class))))
|
||||||
}.getType())))
|
|
||||||
.thenAcceptAsync(neoForgeVersions -> {
|
.thenAcceptAsync(neoForgeVersions -> {
|
||||||
lock.writeLock().lock();
|
lock.writeLock().lock();
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
package org.jackhuang.hmcl.download.optifine;
|
package org.jackhuang.hmcl.download.optifine;
|
||||||
|
|
||||||
import com.google.gson.annotations.SerializedName;
|
import com.google.gson.annotations.SerializedName;
|
||||||
import com.google.gson.reflect.TypeToken;
|
|
||||||
import org.jackhuang.hmcl.download.VersionList;
|
import org.jackhuang.hmcl.download.VersionList;
|
||||||
import org.jackhuang.hmcl.util.StringUtils;
|
import org.jackhuang.hmcl.util.StringUtils;
|
||||||
import org.jackhuang.hmcl.util.io.HttpRequest;
|
import org.jackhuang.hmcl.util.io.HttpRequest;
|
||||||
@@ -26,10 +25,11 @@ import org.jackhuang.hmcl.util.versioning.VersionNumber;
|
|||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author huangyuhui
|
* @author huangyuhui
|
||||||
*/
|
*/
|
||||||
@@ -72,8 +72,7 @@ public final class OptiFineBMCLVersionList extends VersionList<OptiFineRemoteVer
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<?> refreshAsync() {
|
public CompletableFuture<?> refreshAsync() {
|
||||||
return HttpRequest.GET(apiRoot + "/optifine/versionlist").<List<OptiFineVersion>>getJsonAsync(new TypeToken<List<OptiFineVersion>>() {
|
return HttpRequest.GET(apiRoot + "/optifine/versionlist").getJsonAsync(listTypeOf(OptiFineVersion.class)).thenAcceptAsync(root -> {
|
||||||
}.getType()).thenAcceptAsync(root -> {
|
|
||||||
lock.writeLock().lock();
|
lock.writeLock().lock();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.jackhuang.hmcl.download.quilt;
|
package org.jackhuang.hmcl.download.quilt;
|
||||||
|
|
||||||
import com.google.gson.reflect.TypeToken;
|
|
||||||
import org.jackhuang.hmcl.download.DownloadProvider;
|
import org.jackhuang.hmcl.download.DownloadProvider;
|
||||||
import org.jackhuang.hmcl.download.VersionList;
|
import org.jackhuang.hmcl.download.VersionList;
|
||||||
import org.jackhuang.hmcl.util.gson.JsonUtils;
|
import org.jackhuang.hmcl.util.gson.JsonUtils;
|
||||||
@@ -25,13 +24,13 @@ import org.jackhuang.hmcl.util.io.NetworkUtils;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static org.jackhuang.hmcl.util.Lang.wrap;
|
import static org.jackhuang.hmcl.util.Lang.wrap;
|
||||||
|
import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf;
|
||||||
|
|
||||||
public final class QuiltVersionList extends VersionList<QuiltRemoteVersion> {
|
public final class QuiltVersionList extends VersionList<QuiltRemoteVersion> {
|
||||||
private final DownloadProvider downloadProvider;
|
private final DownloadProvider downloadProvider;
|
||||||
@@ -69,8 +68,8 @@ public final class QuiltVersionList extends VersionList<QuiltRemoteVersion> {
|
|||||||
|
|
||||||
private List<String> getGameVersions(String metaUrl) throws IOException {
|
private List<String> getGameVersions(String metaUrl) throws IOException {
|
||||||
String json = NetworkUtils.doGet(downloadProvider.injectURLWithCandidates(metaUrl));
|
String json = NetworkUtils.doGet(downloadProvider.injectURLWithCandidates(metaUrl));
|
||||||
return JsonUtils.GSON.<ArrayList<GameVersion>>fromJson(json, new TypeToken<ArrayList<GameVersion>>() {
|
return JsonUtils.GSON.fromJson(json, listTypeOf(GameVersion.class))
|
||||||
}.getType()).stream().map(GameVersion::getVersion).collect(Collectors.toList());
|
.stream().map(GameVersion::getVersion).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getLaunchMetaUrl(String gameVersion, String loaderVersion) {
|
private static String getLaunchMetaUrl(String gameVersion, String loaderVersion) {
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
package org.jackhuang.hmcl.game;
|
package org.jackhuang.hmcl.game;
|
||||||
|
|
||||||
import com.google.gson.JsonParseException;
|
import com.google.gson.JsonParseException;
|
||||||
import com.google.gson.reflect.TypeToken;
|
|
||||||
import org.jackhuang.hmcl.download.MaintainTask;
|
import org.jackhuang.hmcl.download.MaintainTask;
|
||||||
import org.jackhuang.hmcl.download.game.VersionJsonSaveTask;
|
import org.jackhuang.hmcl.download.game.VersionJsonSaveTask;
|
||||||
import org.jackhuang.hmcl.event.*;
|
import org.jackhuang.hmcl.event.*;
|
||||||
@@ -499,18 +498,16 @@ public class DefaultGameRepository implements GameRepository {
|
|||||||
* read modpack configuration for a version.
|
* read modpack configuration for a version.
|
||||||
*
|
*
|
||||||
* @param version version installed as modpack
|
* @param version version installed as modpack
|
||||||
* @param <M> manifest type of ModpackConfiguration
|
|
||||||
* @return modpack configuration object, or null if this version is not a modpack.
|
* @return modpack configuration object, or null if this version is not a modpack.
|
||||||
* @throws VersionNotFoundException if version does not exist.
|
* @throws VersionNotFoundException if version does not exist.
|
||||||
* @throws IOException if an i/o error occurs.
|
* @throws IOException if an i/o error occurs.
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public <M> ModpackConfiguration<M> readModpackConfiguration(String version) throws IOException, VersionNotFoundException {
|
public ModpackConfiguration<?> readModpackConfiguration(String version) throws IOException, VersionNotFoundException {
|
||||||
if (!hasVersion(version)) throw new VersionNotFoundException(version);
|
if (!hasVersion(version)) throw new VersionNotFoundException(version);
|
||||||
File file = getModpackConfiguration(version);
|
File file = getModpackConfiguration(version);
|
||||||
if (!file.exists()) return null;
|
if (!file.exists()) return null;
|
||||||
return JsonUtils.GSON.fromJson(FileUtils.readText(file), new TypeToken<ModpackConfiguration<M>>() {
|
return JsonUtils.GSON.fromJson(FileUtils.readText(file), ModpackConfiguration.class);
|
||||||
}.getType());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isModpack(String version) {
|
public boolean isModpack(String version) {
|
||||||
|
|||||||
@@ -19,13 +19,14 @@ package org.jackhuang.hmcl.game;
|
|||||||
|
|
||||||
import com.google.gson.*;
|
import com.google.gson.*;
|
||||||
import com.google.gson.annotations.JsonAdapter;
|
import com.google.gson.annotations.JsonAdapter;
|
||||||
import com.google.gson.reflect.TypeToken;
|
|
||||||
import org.jackhuang.hmcl.util.Immutable;
|
import org.jackhuang.hmcl.util.Immutable;
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author huangyuhui
|
* @author huangyuhui
|
||||||
@@ -86,8 +87,7 @@ public class RuledArgument implements Argument {
|
|||||||
public RuledArgument deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
|
public RuledArgument deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
|
||||||
JsonObject obj = json.getAsJsonObject();
|
JsonObject obj = json.getAsJsonObject();
|
||||||
|
|
||||||
List<CompatibilityRule> rules = context.deserialize(obj.get("rules"), new TypeToken<List<CompatibilityRule>>() {
|
List<CompatibilityRule> rules = context.deserialize(obj.get("rules"), listTypeOf(CompatibilityRule.class).getType());
|
||||||
}.getType());
|
|
||||||
|
|
||||||
JsonElement valuesElement;
|
JsonElement valuesElement;
|
||||||
if (obj.has("values")) {
|
if (obj.has("values")) {
|
||||||
@@ -102,8 +102,7 @@ public class RuledArgument implements Argument {
|
|||||||
if (valuesElement.isJsonPrimitive()) {
|
if (valuesElement.isJsonPrimitive()) {
|
||||||
values = Collections.singletonList(valuesElement.getAsString());
|
values = Collections.singletonList(valuesElement.getAsString());
|
||||||
} else {
|
} else {
|
||||||
values = context.deserialize(valuesElement, new TypeToken<List<String>>() {
|
values = context.deserialize(valuesElement, listTypeOf(String.class).getType());
|
||||||
}.getType());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new RuledArgument(rules, values);
|
return new RuledArgument(rules, values);
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
package org.jackhuang.hmcl.mod;
|
package org.jackhuang.hmcl.mod;
|
||||||
|
|
||||||
import com.google.gson.JsonParseException;
|
import com.google.gson.JsonParseException;
|
||||||
|
import com.google.gson.reflect.TypeToken;
|
||||||
import org.jackhuang.hmcl.util.Immutable;
|
import org.jackhuang.hmcl.util.Immutable;
|
||||||
import org.jackhuang.hmcl.util.gson.Validation;
|
import org.jackhuang.hmcl.util.gson.Validation;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@@ -29,6 +30,11 @@ import java.util.List;
|
|||||||
@Immutable
|
@Immutable
|
||||||
public final class ModpackConfiguration<T> implements Validation {
|
public final class ModpackConfiguration<T> implements Validation {
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static <T> TypeToken<ModpackConfiguration<T>> typeOf(Class<T> clazz) {
|
||||||
|
return (TypeToken<ModpackConfiguration<T>>) TypeToken.getParameterized(ModpackConfiguration.class, clazz);
|
||||||
|
}
|
||||||
|
|
||||||
private final T manifest;
|
private final T manifest;
|
||||||
private final String type;
|
private final String type;
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import java.util.stream.Stream;
|
|||||||
|
|
||||||
import static org.jackhuang.hmcl.util.Lang.mapOf;
|
import static org.jackhuang.hmcl.util.Lang.mapOf;
|
||||||
import static org.jackhuang.hmcl.util.Pair.pair;
|
import static org.jackhuang.hmcl.util.Pair.pair;
|
||||||
|
import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf;
|
||||||
|
|
||||||
public final class CurseForgeRemoteModRepository implements RemoteModRepository {
|
public final class CurseForgeRemoteModRepository implements RemoteModRepository {
|
||||||
|
|
||||||
@@ -113,8 +114,7 @@ public final class CurseForgeRemoteModRepository implements RemoteModRepository
|
|||||||
pair("index", Integer.toString(pageOffset * pageSize)),
|
pair("index", Integer.toString(pageOffset * pageSize)),
|
||||||
pair("pageSize", Integer.toString(pageSize)))
|
pair("pageSize", Integer.toString(pageSize)))
|
||||||
.header("X-API-KEY", apiKey)
|
.header("X-API-KEY", apiKey)
|
||||||
.getJson(new TypeToken<Response<List<CurseAddon>>>() {
|
.getJson(Response.typeOf(listTypeOf(CurseAddon.class)));
|
||||||
}.getType());
|
|
||||||
if (searchFilter.isEmpty()) {
|
if (searchFilter.isEmpty()) {
|
||||||
return new SearchResult(response.getData().stream().map(CurseAddon::toMod), calculateTotalPages(response, pageSize));
|
return new SearchResult(response.getData().stream().map(CurseAddon::toMod), calculateTotalPages(response, pageSize));
|
||||||
}
|
}
|
||||||
@@ -163,8 +163,7 @@ public final class CurseForgeRemoteModRepository implements RemoteModRepository
|
|||||||
Response<FingerprintMatchesResult> response = HttpRequest.POST(PREFIX + "/v1/fingerprints/432")
|
Response<FingerprintMatchesResult> response = HttpRequest.POST(PREFIX + "/v1/fingerprints/432")
|
||||||
.json(mapOf(pair("fingerprints", Collections.singletonList(hash))))
|
.json(mapOf(pair("fingerprints", Collections.singletonList(hash))))
|
||||||
.header("X-API-KEY", apiKey)
|
.header("X-API-KEY", apiKey)
|
||||||
.getJson(new TypeToken<Response<FingerprintMatchesResult>>() {
|
.getJson(Response.typeOf(FingerprintMatchesResult.class));
|
||||||
}.getType());
|
|
||||||
|
|
||||||
if (response.getData().getExactMatches() == null || response.getData().getExactMatches().isEmpty()) {
|
if (response.getData().getExactMatches() == null || response.getData().getExactMatches().isEmpty()) {
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
@@ -177,8 +176,7 @@ public final class CurseForgeRemoteModRepository implements RemoteModRepository
|
|||||||
public RemoteMod getModById(String id) throws IOException {
|
public RemoteMod getModById(String id) throws IOException {
|
||||||
Response<CurseAddon> response = HttpRequest.GET(PREFIX + "/v1/mods/" + id)
|
Response<CurseAddon> response = HttpRequest.GET(PREFIX + "/v1/mods/" + id)
|
||||||
.header("X-API-KEY", apiKey)
|
.header("X-API-KEY", apiKey)
|
||||||
.getJson(new TypeToken<Response<CurseAddon>>() {
|
.getJson(Response.typeOf(CurseAddon.class));
|
||||||
}.getType());
|
|
||||||
return response.data.toMod();
|
return response.data.toMod();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,8 +184,7 @@ public final class CurseForgeRemoteModRepository implements RemoteModRepository
|
|||||||
public RemoteMod.File getModFile(String modId, String fileId) throws IOException {
|
public RemoteMod.File getModFile(String modId, String fileId) throws IOException {
|
||||||
Response<CurseAddon.LatestFile> response = HttpRequest.GET(String.format("%s/v1/mods/%s/files/%s", PREFIX, modId, fileId))
|
Response<CurseAddon.LatestFile> response = HttpRequest.GET(String.format("%s/v1/mods/%s/files/%s", PREFIX, modId, fileId))
|
||||||
.header("X-API-KEY", apiKey)
|
.header("X-API-KEY", apiKey)
|
||||||
.getJson(new TypeToken<Response<CurseAddon.LatestFile>>() {
|
.getJson(Response.typeOf(CurseAddon.LatestFile.class));
|
||||||
}.getType());
|
|
||||||
return response.getData().toVersion().getFile();
|
return response.getData().toVersion().getFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,16 +193,14 @@ public final class CurseForgeRemoteModRepository implements RemoteModRepository
|
|||||||
Response<List<CurseAddon.LatestFile>> response = HttpRequest.GET(PREFIX + "/v1/mods/" + id + "/files",
|
Response<List<CurseAddon.LatestFile>> response = HttpRequest.GET(PREFIX + "/v1/mods/" + id + "/files",
|
||||||
pair("pageSize", "10000"))
|
pair("pageSize", "10000"))
|
||||||
.header("X-API-KEY", apiKey)
|
.header("X-API-KEY", apiKey)
|
||||||
.getJson(new TypeToken<Response<List<CurseAddon.LatestFile>>>() {
|
.getJson(Response.typeOf(listTypeOf(CurseAddon.LatestFile.class)));
|
||||||
}.getType());
|
|
||||||
return response.getData().stream().map(CurseAddon.LatestFile::toVersion);
|
return response.getData().stream().map(CurseAddon.LatestFile::toVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<CurseAddon.Category> getCategoriesImpl() throws IOException {
|
public List<CurseAddon.Category> getCategoriesImpl() throws IOException {
|
||||||
Response<List<CurseAddon.Category>> categories = HttpRequest.GET(PREFIX + "/v1/categories", pair("gameId", "432"))
|
Response<List<CurseAddon.Category>> categories = HttpRequest.GET(PREFIX + "/v1/categories", pair("gameId", "432"))
|
||||||
.header("X-API-KEY", apiKey)
|
.header("X-API-KEY", apiKey)
|
||||||
.getJson(new TypeToken<Response<List<CurseAddon.Category>>>() {
|
.getJson(Response.typeOf(listTypeOf(CurseAddon.Category.class)));
|
||||||
}.getType());
|
|
||||||
return reorganizeCategories(categories.getData(), section);
|
return reorganizeCategories(categories.getData(), section);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,6 +279,17 @@ public final class CurseForgeRemoteModRepository implements RemoteModRepository
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static class Response<T> {
|
public static class Response<T> {
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static <T> TypeToken<Response<T>> typeOf(Class<T> responseType) {
|
||||||
|
return (TypeToken<Response<T>>) TypeToken.getParameterized(Response.class, responseType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static <T> TypeToken<Response<T>> typeOf(TypeToken<T> responseType) {
|
||||||
|
return (TypeToken<Response<T>>) TypeToken.getParameterized(Response.class, responseType.getType());
|
||||||
|
}
|
||||||
|
|
||||||
private final T data;
|
private final T data;
|
||||||
private final Pagination pagination;
|
private final Pagination pagination;
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
package org.jackhuang.hmcl.mod.curse;
|
package org.jackhuang.hmcl.mod.curse;
|
||||||
|
|
||||||
import com.google.gson.JsonParseException;
|
import com.google.gson.JsonParseException;
|
||||||
import com.google.gson.reflect.TypeToken;
|
|
||||||
import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
||||||
import org.jackhuang.hmcl.download.GameBuilder;
|
import org.jackhuang.hmcl.download.GameBuilder;
|
||||||
import org.jackhuang.hmcl.game.DefaultGameRepository;
|
import org.jackhuang.hmcl.game.DefaultGameRepository;
|
||||||
@@ -99,8 +98,7 @@ public final class CurseInstallTask extends Task<Void> {
|
|||||||
ModpackConfiguration<CurseManifest> config = null;
|
ModpackConfiguration<CurseManifest> config = null;
|
||||||
try {
|
try {
|
||||||
if (json.exists()) {
|
if (json.exists()) {
|
||||||
config = JsonUtils.GSON.fromJson(FileUtils.readText(json), new TypeToken<ModpackConfiguration<CurseManifest>>() {
|
config = JsonUtils.GSON.fromJson(FileUtils.readText(json), ModpackConfiguration.typeOf(CurseManifest.class));
|
||||||
}.getType());
|
|
||||||
|
|
||||||
if (!CurseModpackProvider.INSTANCE.getName().equals(config.getType()))
|
if (!CurseModpackProvider.INSTANCE.getName().equals(config.getType()))
|
||||||
throw new IllegalArgumentException("Version " + name + " is not a Curse modpack. Cannot update this version.");
|
throw new IllegalArgumentException("Version " + name + " is not a Curse modpack. Cannot update this version.");
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
package org.jackhuang.hmcl.mod.mcbbs;
|
package org.jackhuang.hmcl.mod.mcbbs;
|
||||||
|
|
||||||
import com.google.gson.JsonParseException;
|
import com.google.gson.JsonParseException;
|
||||||
import com.google.gson.reflect.TypeToken;
|
|
||||||
import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
||||||
import org.jackhuang.hmcl.game.DefaultGameRepository;
|
import org.jackhuang.hmcl.game.DefaultGameRepository;
|
||||||
import org.jackhuang.hmcl.mod.ModManager;
|
import org.jackhuang.hmcl.mod.ModManager;
|
||||||
@@ -88,8 +87,7 @@ public class McbbsModpackCompletionTask extends CompletableFutureTask<Void> {
|
|||||||
if (configuration == null) {
|
if (configuration == null) {
|
||||||
// Load configuration from disk
|
// Load configuration from disk
|
||||||
try {
|
try {
|
||||||
configuration = JsonUtils.fromNonNullJson(FileUtils.readText(configurationFile), new TypeToken<ModpackConfiguration<McbbsModpackManifest>>() {
|
configuration = JsonUtils.fromNonNullJson(FileUtils.readText(configurationFile), ModpackConfiguration.typeOf(McbbsModpackManifest.class));
|
||||||
}.getType());
|
|
||||||
} catch (IOException | JsonParseException e) {
|
} catch (IOException | JsonParseException e) {
|
||||||
throw new IOException("Malformed modpack configuration");
|
throw new IOException("Malformed modpack configuration");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
package org.jackhuang.hmcl.mod.mcbbs;
|
package org.jackhuang.hmcl.mod.mcbbs;
|
||||||
|
|
||||||
import com.google.gson.JsonParseException;
|
import com.google.gson.JsonParseException;
|
||||||
import com.google.gson.reflect.TypeToken;
|
|
||||||
import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
||||||
import org.jackhuang.hmcl.download.GameBuilder;
|
import org.jackhuang.hmcl.download.GameBuilder;
|
||||||
import org.jackhuang.hmcl.game.DefaultGameRepository;
|
import org.jackhuang.hmcl.game.DefaultGameRepository;
|
||||||
@@ -80,8 +79,7 @@ public class McbbsModpackLocalInstallTask extends Task<Void> {
|
|||||||
ModpackConfiguration<McbbsModpackManifest> config = null;
|
ModpackConfiguration<McbbsModpackManifest> config = null;
|
||||||
try {
|
try {
|
||||||
if (json.exists()) {
|
if (json.exists()) {
|
||||||
config = JsonUtils.GSON.fromJson(FileUtils.readText(json), new TypeToken<ModpackConfiguration<McbbsModpackManifest>>() {
|
config = JsonUtils.GSON.fromJson(FileUtils.readText(json), ModpackConfiguration.typeOf(McbbsModpackManifest.class));
|
||||||
}.getType());
|
|
||||||
|
|
||||||
if (!McbbsModpackProvider.INSTANCE.getName().equals(config.getType()))
|
if (!McbbsModpackProvider.INSTANCE.getName().equals(config.getType()))
|
||||||
throw new IllegalArgumentException("Version " + name + " is not a Mcbbs modpack. Cannot update this version.");
|
throw new IllegalArgumentException("Version " + name + " is not a Mcbbs modpack. Cannot update this version.");
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
package org.jackhuang.hmcl.mod.mcbbs;
|
package org.jackhuang.hmcl.mod.mcbbs;
|
||||||
|
|
||||||
import com.google.gson.JsonParseException;
|
import com.google.gson.JsonParseException;
|
||||||
import com.google.gson.reflect.TypeToken;
|
|
||||||
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
|
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
|
||||||
import org.apache.commons.compress.archivers.zip.ZipFile;
|
import org.apache.commons.compress.archivers.zip.ZipFile;
|
||||||
import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
||||||
@@ -56,8 +55,7 @@ public final class McbbsModpackProvider implements ModpackProvider {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void injectLaunchOptions(String modpackConfigurationJson, LaunchOptions.Builder builder) {
|
public void injectLaunchOptions(String modpackConfigurationJson, LaunchOptions.Builder builder) {
|
||||||
ModpackConfiguration<McbbsModpackManifest> config = JsonUtils.GSON.fromJson(modpackConfigurationJson, new TypeToken<ModpackConfiguration<McbbsModpackManifest>>() {
|
ModpackConfiguration<McbbsModpackManifest> config = JsonUtils.GSON.fromJson(modpackConfigurationJson, ModpackConfiguration.typeOf(McbbsModpackManifest.class));
|
||||||
}.getType());
|
|
||||||
|
|
||||||
if (!getName().equals(config.getType())) {
|
if (!getName().equals(config.getType())) {
|
||||||
throw new IllegalArgumentException("Incorrect manifest type, actual=" + config.getType() + ", expected=" + getName());
|
throw new IllegalArgumentException("Incorrect manifest type, actual=" + config.getType() + ", expected=" + getName());
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
package org.jackhuang.hmcl.mod.mcbbs;
|
package org.jackhuang.hmcl.mod.mcbbs;
|
||||||
|
|
||||||
import com.google.gson.JsonParseException;
|
import com.google.gson.JsonParseException;
|
||||||
import com.google.gson.reflect.TypeToken;
|
|
||||||
import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
||||||
import org.jackhuang.hmcl.download.GameBuilder;
|
import org.jackhuang.hmcl.download.GameBuilder;
|
||||||
import org.jackhuang.hmcl.game.DefaultGameRepository;
|
import org.jackhuang.hmcl.game.DefaultGameRepository;
|
||||||
@@ -66,8 +65,7 @@ public class McbbsModpackRemoteInstallTask extends Task<Void> {
|
|||||||
ModpackConfiguration<McbbsModpackManifest> config = null;
|
ModpackConfiguration<McbbsModpackManifest> config = null;
|
||||||
try {
|
try {
|
||||||
if (json.exists()) {
|
if (json.exists()) {
|
||||||
config = JsonUtils.GSON.fromJson(FileUtils.readText(json), new TypeToken<ModpackConfiguration<McbbsModpackManifest>>() {
|
config = JsonUtils.GSON.fromJson(FileUtils.readText(json), ModpackConfiguration.typeOf(McbbsModpackManifest.class));
|
||||||
}.getType());
|
|
||||||
|
|
||||||
if (!MODPACK_TYPE.equals(config.getType()))
|
if (!MODPACK_TYPE.equals(config.getType()))
|
||||||
throw new IllegalArgumentException("Version " + name + " is not a Mcbbs modpack. Cannot update this version.");
|
throw new IllegalArgumentException("Version " + name + " is not a Mcbbs modpack. Cannot update this version.");
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ package org.jackhuang.hmcl.mod.modinfo;
|
|||||||
|
|
||||||
import com.google.gson.JsonParseException;
|
import com.google.gson.JsonParseException;
|
||||||
import com.google.gson.annotations.SerializedName;
|
import com.google.gson.annotations.SerializedName;
|
||||||
import com.google.gson.reflect.TypeToken;
|
|
||||||
import org.jackhuang.hmcl.mod.LocalModFile;
|
import org.jackhuang.hmcl.mod.LocalModFile;
|
||||||
import org.jackhuang.hmcl.mod.ModLoaderType;
|
import org.jackhuang.hmcl.mod.ModLoaderType;
|
||||||
import org.jackhuang.hmcl.mod.ModManager;
|
import org.jackhuang.hmcl.mod.ModManager;
|
||||||
@@ -34,6 +33,8 @@ import java.nio.file.Files;
|
|||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author huangyuhui
|
* @author huangyuhui
|
||||||
@@ -125,9 +126,7 @@ public final class ForgeOldModMetadata {
|
|||||||
Path mcmod = fs.getPath("mcmod.info");
|
Path mcmod = fs.getPath("mcmod.info");
|
||||||
if (Files.notExists(mcmod))
|
if (Files.notExists(mcmod))
|
||||||
throw new IOException("File " + modFile + " is not a Forge mod.");
|
throw new IOException("File " + modFile + " is not a Forge mod.");
|
||||||
List<ForgeOldModMetadata> modList = JsonUtils.GSON.fromJson(FileUtils.readText(mcmod),
|
List<ForgeOldModMetadata> modList = JsonUtils.GSON.fromJson(FileUtils.readText(mcmod), listTypeOf(ForgeOldModMetadata.class));
|
||||||
new TypeToken<List<ForgeOldModMetadata>>() {
|
|
||||||
}.getType());
|
|
||||||
if (modList == null || modList.isEmpty())
|
if (modList == null || modList.isEmpty())
|
||||||
throw new IOException("Mod " + modFile + " `mcmod.info` is malformed..");
|
throw new IOException("Mod " + modFile + " `mcmod.info` is malformed..");
|
||||||
ForgeOldModMetadata metadata = modList.get(0);
|
ForgeOldModMetadata metadata = modList.get(0);
|
||||||
|
|||||||
@@ -18,12 +18,10 @@
|
|||||||
package org.jackhuang.hmcl.mod.modrinth;
|
package org.jackhuang.hmcl.mod.modrinth;
|
||||||
|
|
||||||
import com.google.gson.JsonParseException;
|
import com.google.gson.JsonParseException;
|
||||||
import com.google.gson.reflect.TypeToken;
|
|
||||||
import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
||||||
import org.jackhuang.hmcl.download.GameBuilder;
|
import org.jackhuang.hmcl.download.GameBuilder;
|
||||||
import org.jackhuang.hmcl.game.DefaultGameRepository;
|
import org.jackhuang.hmcl.game.DefaultGameRepository;
|
||||||
import org.jackhuang.hmcl.mod.*;
|
import org.jackhuang.hmcl.mod.*;
|
||||||
import org.jackhuang.hmcl.mod.curse.CurseManifest;
|
|
||||||
import org.jackhuang.hmcl.task.Task;
|
import org.jackhuang.hmcl.task.Task;
|
||||||
import org.jackhuang.hmcl.util.gson.JsonUtils;
|
import org.jackhuang.hmcl.util.gson.JsonUtils;
|
||||||
import org.jackhuang.hmcl.util.io.FileUtils;
|
import org.jackhuang.hmcl.util.io.FileUtils;
|
||||||
@@ -95,8 +93,7 @@ public class ModrinthInstallTask extends Task<Void> {
|
|||||||
ModpackConfiguration<ModrinthManifest> config = null;
|
ModpackConfiguration<ModrinthManifest> config = null;
|
||||||
try {
|
try {
|
||||||
if (json.exists()) {
|
if (json.exists()) {
|
||||||
config = JsonUtils.GSON.fromJson(FileUtils.readText(json), new TypeToken<ModpackConfiguration<CurseManifest>>() {
|
config = JsonUtils.GSON.fromJson(FileUtils.readText(json), ModpackConfiguration.typeOf(ModrinthManifest.class));
|
||||||
}.getType());
|
|
||||||
|
|
||||||
if (!ModrinthModpackProvider.INSTANCE.getName().equals(config.getType()))
|
if (!ModrinthModpackProvider.INSTANCE.getName().equals(config.getType()))
|
||||||
throw new IllegalArgumentException("Version " + name + " is not a Modrinth modpack. Cannot update this version.");
|
throw new IllegalArgumentException("Version " + name + " is not a Modrinth modpack. Cannot update this version.");
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ import java.util.stream.Stream;
|
|||||||
|
|
||||||
import static org.jackhuang.hmcl.util.Lang.mapOf;
|
import static org.jackhuang.hmcl.util.Lang.mapOf;
|
||||||
import static org.jackhuang.hmcl.util.Pair.pair;
|
import static org.jackhuang.hmcl.util.Pair.pair;
|
||||||
|
import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf;
|
||||||
|
|
||||||
public final class ModrinthRemoteModRepository implements RemoteModRepository {
|
public final class ModrinthRemoteModRepository implements RemoteModRepository {
|
||||||
public static final ModrinthRemoteModRepository MODS = new ModrinthRemoteModRepository("mod");
|
public static final ModrinthRemoteModRepository MODS = new ModrinthRemoteModRepository("mod");
|
||||||
@@ -93,8 +94,7 @@ public final class ModrinthRemoteModRepository implements RemoteModRepository {
|
|||||||
pair("index", convertSortType(sort))
|
pair("index", convertSortType(sort))
|
||||||
);
|
);
|
||||||
Response<ProjectSearchResult> response = HttpRequest.GET(NetworkUtils.withQuery(PREFIX + "/v2/search", query))
|
Response<ProjectSearchResult> response = HttpRequest.GET(NetworkUtils.withQuery(PREFIX + "/v2/search", query))
|
||||||
.getJson(new TypeToken<Response<ProjectSearchResult>>() {
|
.getJson(Response.typeOf(ProjectSearchResult.class));
|
||||||
}.getType());
|
|
||||||
return new SearchResult(response.getHits().stream().map(ProjectSearchResult::toMod), (int) Math.ceil((double) response.totalHits / pageSize));
|
return new SearchResult(response.getHits().stream().map(ProjectSearchResult::toMod), (int) Math.ceil((double) response.totalHits / pageSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,13 +132,12 @@ public final class ModrinthRemoteModRepository implements RemoteModRepository {
|
|||||||
public Stream<RemoteMod.Version> getRemoteVersionsById(String id) throws IOException {
|
public Stream<RemoteMod.Version> getRemoteVersionsById(String id) throws IOException {
|
||||||
id = StringUtils.removePrefix(id, "local-");
|
id = StringUtils.removePrefix(id, "local-");
|
||||||
List<ProjectVersion> versions = HttpRequest.GET(PREFIX + "/v2/project/" + id + "/version")
|
List<ProjectVersion> versions = HttpRequest.GET(PREFIX + "/v2/project/" + id + "/version")
|
||||||
.getJson(new TypeToken<List<ProjectVersion>>() {
|
.getJson(listTypeOf(ProjectVersion.class));
|
||||||
}.getType());
|
|
||||||
return versions.stream().map(ProjectVersion::toVersion).flatMap(Lang::toStream);
|
return versions.stream().map(ProjectVersion::toVersion).flatMap(Lang::toStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Category> getCategoriesImpl() throws IOException {
|
public List<Category> getCategoriesImpl() throws IOException {
|
||||||
List<Category> categories = HttpRequest.GET(PREFIX + "/v2/tag/category").getJson(new TypeToken<List<Category>>() {}.getType());
|
List<Category> categories = HttpRequest.GET(PREFIX + "/v2/tag/category").getJson(listTypeOf(Category.class));
|
||||||
return categories.stream().filter(category -> category.getProjectType().equals(projectType)).collect(Collectors.toList());
|
return categories.stream().filter(category -> category.getProjectType().equals(projectType)).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -696,6 +695,12 @@ public final class ModrinthRemoteModRepository implements RemoteModRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static class Response<T> {
|
public static class Response<T> {
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static <T> TypeToken<Response<T>> typeOf(Class<T> responseType) {
|
||||||
|
return (TypeToken<Response<T>>) TypeToken.getParameterized(Response.class, responseType);
|
||||||
|
}
|
||||||
|
|
||||||
private final int offset;
|
private final int offset;
|
||||||
|
|
||||||
private final int limit;
|
private final int limit;
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
package org.jackhuang.hmcl.mod.multimc;
|
package org.jackhuang.hmcl.mod.multimc;
|
||||||
|
|
||||||
import com.google.gson.JsonParseException;
|
import com.google.gson.JsonParseException;
|
||||||
import com.google.gson.reflect.TypeToken;
|
|
||||||
import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
||||||
import org.jackhuang.hmcl.download.GameBuilder;
|
import org.jackhuang.hmcl.download.GameBuilder;
|
||||||
import org.jackhuang.hmcl.game.Arguments;
|
import org.jackhuang.hmcl.game.Arguments;
|
||||||
@@ -128,8 +127,7 @@ public final class MultiMCModpackInstallTask extends Task<Void> {
|
|||||||
ModpackConfiguration<MultiMCInstanceConfiguration> config = null;
|
ModpackConfiguration<MultiMCInstanceConfiguration> config = null;
|
||||||
try {
|
try {
|
||||||
if (json.exists()) {
|
if (json.exists()) {
|
||||||
config = JsonUtils.GSON.fromJson(FileUtils.readText(json), new TypeToken<ModpackConfiguration<MultiMCInstanceConfiguration>>() {
|
config = JsonUtils.GSON.fromJson(FileUtils.readText(json), ModpackConfiguration.typeOf(MultiMCInstanceConfiguration.class));
|
||||||
}.getType());
|
|
||||||
|
|
||||||
if (!MultiMCModpackProvider.INSTANCE.getName().equals(config.getType()))
|
if (!MultiMCModpackProvider.INSTANCE.getName().equals(config.getType()))
|
||||||
throw new IllegalArgumentException("Version " + name + " is not a MultiMC modpack. Cannot update this version.");
|
throw new IllegalArgumentException("Version " + name + " is not a MultiMC modpack. Cannot update this version.");
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
package org.jackhuang.hmcl.mod.server;
|
package org.jackhuang.hmcl.mod.server;
|
||||||
|
|
||||||
import com.google.gson.JsonParseException;
|
import com.google.gson.JsonParseException;
|
||||||
import com.google.gson.reflect.TypeToken;
|
|
||||||
import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
||||||
import org.jackhuang.hmcl.download.GameBuilder;
|
import org.jackhuang.hmcl.download.GameBuilder;
|
||||||
import org.jackhuang.hmcl.game.DefaultGameRepository;
|
import org.jackhuang.hmcl.game.DefaultGameRepository;
|
||||||
@@ -66,8 +65,7 @@ public class ServerModpackCompletionTask extends Task<Void> {
|
|||||||
try {
|
try {
|
||||||
File manifestFile = repository.getModpackConfiguration(version);
|
File manifestFile = repository.getModpackConfiguration(version);
|
||||||
if (manifestFile.exists()) {
|
if (manifestFile.exists()) {
|
||||||
this.manifest = JsonUtils.GSON.fromJson(FileUtils.readText(manifestFile), new TypeToken<ModpackConfiguration<ServerModpackManifest>>() {
|
this.manifest = JsonUtils.GSON.fromJson(FileUtils.readText(manifestFile), ModpackConfiguration.typeOf(ServerModpackManifest.class));
|
||||||
}.getType());
|
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.warning("Unable to read Server modpack manifest.json", e);
|
LOG.warning("Unable to read Server modpack manifest.json", e);
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
package org.jackhuang.hmcl.mod.server;
|
package org.jackhuang.hmcl.mod.server;
|
||||||
|
|
||||||
import com.google.gson.JsonParseException;
|
import com.google.gson.JsonParseException;
|
||||||
import com.google.gson.reflect.TypeToken;
|
|
||||||
import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
||||||
import org.jackhuang.hmcl.download.GameBuilder;
|
import org.jackhuang.hmcl.download.GameBuilder;
|
||||||
import org.jackhuang.hmcl.game.DefaultGameRepository;
|
import org.jackhuang.hmcl.game.DefaultGameRepository;
|
||||||
@@ -72,8 +71,7 @@ public class ServerModpackLocalInstallTask extends Task<Void> {
|
|||||||
ModpackConfiguration<ServerModpackManifest> config = null;
|
ModpackConfiguration<ServerModpackManifest> config = null;
|
||||||
try {
|
try {
|
||||||
if (json.exists()) {
|
if (json.exists()) {
|
||||||
config = JsonUtils.GSON.fromJson(FileUtils.readText(json), new TypeToken<ModpackConfiguration<ServerModpackManifest>>() {
|
config = JsonUtils.GSON.fromJson(FileUtils.readText(json), ModpackConfiguration.typeOf(ServerModpackManifest.class));
|
||||||
}.getType());
|
|
||||||
|
|
||||||
if (!ServerModpackProvider.INSTANCE.getName().equals(config.getType()))
|
if (!ServerModpackProvider.INSTANCE.getName().equals(config.getType()))
|
||||||
throw new IllegalArgumentException("Version " + name + " is not a Server modpack. Cannot update this version.");
|
throw new IllegalArgumentException("Version " + name + " is not a Server modpack. Cannot update this version.");
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
package org.jackhuang.hmcl.mod.server;
|
package org.jackhuang.hmcl.mod.server;
|
||||||
|
|
||||||
import com.google.gson.JsonParseException;
|
import com.google.gson.JsonParseException;
|
||||||
import com.google.gson.reflect.TypeToken;
|
|
||||||
import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
||||||
import org.jackhuang.hmcl.download.GameBuilder;
|
import org.jackhuang.hmcl.download.GameBuilder;
|
||||||
import org.jackhuang.hmcl.game.DefaultGameRepository;
|
import org.jackhuang.hmcl.game.DefaultGameRepository;
|
||||||
@@ -63,11 +62,10 @@ public class ServerModpackRemoteInstallTask extends Task<Void> {
|
|||||||
repository.removeVersionFromDisk(name);
|
repository.removeVersionFromDisk(name);
|
||||||
});
|
});
|
||||||
|
|
||||||
ModpackConfiguration<ServerModpackManifest> config = null;
|
ModpackConfiguration<ServerModpackManifest> config;
|
||||||
try {
|
try {
|
||||||
if (json.exists()) {
|
if (json.exists()) {
|
||||||
config = JsonUtils.GSON.fromJson(FileUtils.readText(json), new TypeToken<ModpackConfiguration<ServerModpackManifest>>() {
|
config = JsonUtils.GSON.fromJson(FileUtils.readText(json), ModpackConfiguration.typeOf(ServerModpackManifest.class));
|
||||||
}.getType());
|
|
||||||
|
|
||||||
if (!MODPACK_TYPE.equals(config.getType()))
|
if (!MODPACK_TYPE.equals(config.getType()))
|
||||||
throw new IllegalArgumentException("Version " + name + " is not a Server modpack. Cannot update this version.");
|
throw new IllegalArgumentException("Version " + name + " is not a Server modpack. Cannot update this version.");
|
||||||
|
|||||||
@@ -19,9 +19,7 @@ package org.jackhuang.hmcl.util;
|
|||||||
|
|
||||||
import com.google.gson.JsonParseException;
|
import com.google.gson.JsonParseException;
|
||||||
import com.google.gson.annotations.SerializedName;
|
import com.google.gson.annotations.SerializedName;
|
||||||
import com.google.gson.reflect.TypeToken;
|
|
||||||
import org.jackhuang.hmcl.util.function.ExceptionalSupplier;
|
import org.jackhuang.hmcl.util.function.ExceptionalSupplier;
|
||||||
import org.jackhuang.hmcl.util.gson.JsonUtils;
|
|
||||||
import org.jackhuang.hmcl.util.io.FileUtils;
|
import org.jackhuang.hmcl.util.io.FileUtils;
|
||||||
import org.jackhuang.hmcl.util.io.IOUtils;
|
import org.jackhuang.hmcl.util.io.IOUtils;
|
||||||
|
|
||||||
@@ -46,6 +44,7 @@ import java.util.function.BiFunction;
|
|||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
|
import static org.jackhuang.hmcl.util.gson.JsonUtils.*;
|
||||||
import static org.jackhuang.hmcl.util.logging.Logger.LOG;
|
import static org.jackhuang.hmcl.util.logging.Logger.LOG;
|
||||||
|
|
||||||
public class CacheRepository {
|
public class CacheRepository {
|
||||||
@@ -68,7 +67,7 @@ public class CacheRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (Files.isRegularFile(indexFile)) {
|
if (Files.isRegularFile(indexFile)) {
|
||||||
ETagIndex raw = JsonUtils.GSON.fromJson(FileUtils.readText(indexFile), ETagIndex.class);
|
ETagIndex raw = GSON.fromJson(FileUtils.readText(indexFile), ETagIndex.class);
|
||||||
if (raw == null)
|
if (raw == null)
|
||||||
index = new HashMap<>();
|
index = new HashMap<>();
|
||||||
else
|
else
|
||||||
@@ -289,10 +288,10 @@ public class CacheRepository {
|
|||||||
try (FileChannel channel = FileChannel.open(indexFile, StandardOpenOption.CREATE, StandardOpenOption.READ, StandardOpenOption.WRITE)) {
|
try (FileChannel channel = FileChannel.open(indexFile, StandardOpenOption.CREATE, StandardOpenOption.READ, StandardOpenOption.WRITE)) {
|
||||||
FileLock lock = channel.lock();
|
FileLock lock = channel.lock();
|
||||||
try {
|
try {
|
||||||
ETagIndex indexOnDisk = JsonUtils.fromMaybeMalformedJson(new String(IOUtils.readFullyWithoutClosing(Channels.newInputStream(channel)), UTF_8), ETagIndex.class);
|
ETagIndex indexOnDisk = fromMaybeMalformedJson(new String(IOUtils.readFullyWithoutClosing(Channels.newInputStream(channel)), UTF_8), ETagIndex.class);
|
||||||
Map<String, ETagItem> newIndex = joinETagIndexes(indexOnDisk == null ? null : indexOnDisk.eTag, index.values());
|
Map<String, ETagItem> newIndex = joinETagIndexes(indexOnDisk == null ? null : indexOnDisk.eTag, index.values());
|
||||||
channel.truncate(0);
|
channel.truncate(0);
|
||||||
ByteBuffer writeTo = ByteBuffer.wrap(JsonUtils.GSON.toJson(new ETagIndex(newIndex.values())).getBytes(UTF_8));
|
ByteBuffer writeTo = ByteBuffer.wrap(GSON.toJson(new ETagIndex(newIndex.values())).getBytes(UTF_8));
|
||||||
while (writeTo.hasRemaining()) {
|
while (writeTo.hasRemaining()) {
|
||||||
if (channel.write(writeTo) == 0) {
|
if (channel.write(writeTo) == 0) {
|
||||||
throw new IOException("No value is written");
|
throw new IOException("No value is written");
|
||||||
@@ -412,8 +411,7 @@ public class CacheRepository {
|
|||||||
try {
|
try {
|
||||||
indexFile = cacheDirectory.resolve(name + ".json");
|
indexFile = cacheDirectory.resolve(name + ".json");
|
||||||
if (Files.isRegularFile(indexFile)) {
|
if (Files.isRegularFile(indexFile)) {
|
||||||
joinEntries(JsonUtils.fromNonNullJson(FileUtils.readText(indexFile), new TypeToken<Map<String, Object>>() {
|
joinEntries(fromNonNullJson(FileUtils.readText(indexFile), mapTypeOf(String.class, Object.class)));
|
||||||
}.getType()));
|
|
||||||
}
|
}
|
||||||
} catch (IOException | JsonParseException e) {
|
} catch (IOException | JsonParseException e) {
|
||||||
LOG.warning("Unable to read storage {" + name + "} file");
|
LOG.warning("Unable to read storage {" + name + "} file");
|
||||||
@@ -426,12 +424,11 @@ public class CacheRepository {
|
|||||||
try (FileChannel channel = FileChannel.open(indexFile, StandardOpenOption.READ, StandardOpenOption.WRITE)) {
|
try (FileChannel channel = FileChannel.open(indexFile, StandardOpenOption.READ, StandardOpenOption.WRITE)) {
|
||||||
FileLock lock = channel.lock();
|
FileLock lock = channel.lock();
|
||||||
try {
|
try {
|
||||||
Map<String, Object> indexOnDisk = JsonUtils.fromMaybeMalformedJson(new String(IOUtils.readFullyWithoutClosing(Channels.newInputStream(channel)), UTF_8), new TypeToken<Map<String, Object>>() {
|
Map<String, Object> indexOnDisk = fromMaybeMalformedJson(new String(IOUtils.readFullyWithoutClosing(Channels.newInputStream(channel)), UTF_8), mapTypeOf(String.class, Object.class));
|
||||||
}.getType());
|
|
||||||
if (indexOnDisk == null) indexOnDisk = new HashMap<>();
|
if (indexOnDisk == null) indexOnDisk = new HashMap<>();
|
||||||
indexOnDisk.putAll(storage);
|
indexOnDisk.putAll(storage);
|
||||||
channel.truncate(0);
|
channel.truncate(0);
|
||||||
channel.write(ByteBuffer.wrap(JsonUtils.GSON.toJson(storage).getBytes(UTF_8)));
|
channel.write(ByteBuffer.wrap(GSON.toJson(storage).getBytes(UTF_8)));
|
||||||
this.storage = indexOnDisk;
|
this.storage = indexOnDisk;
|
||||||
} finally {
|
} finally {
|
||||||
lock.release();
|
lock.release();
|
||||||
|
|||||||
@@ -27,14 +27,16 @@ import java.io.File;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.lang.reflect.Type;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author yushijinhun
|
* @author yushijinhun
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public final class JsonUtils {
|
public final class JsonUtils {
|
||||||
|
|
||||||
public static final Gson GSON = defaultGsonBuilder().create();
|
public static final Gson GSON = defaultGsonBuilder().create();
|
||||||
@@ -48,13 +50,29 @@ public final class JsonUtils {
|
|||||||
private JsonUtils() {
|
private JsonUtils() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static <T> TypeToken<List<T>> listTypeOf(Class<T> elementType) {
|
||||||
|
return (TypeToken<List<T>>) TypeToken.getParameterized(List.class, elementType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> TypeToken<List<T>> listTypeOf(TypeToken<T> elementType) {
|
||||||
|
return (TypeToken<List<T>>) TypeToken.getParameterized(List.class, elementType.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <K, V> TypeToken<Map<K, V>> mapTypeOf(Class<K> keyType, Class<V> valueType) {
|
||||||
|
return (TypeToken<Map<K, V>>) TypeToken.getParameterized(Map.class, keyType, valueType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <K, V> TypeToken<Map<K, V>> mapTypeOf(Class<K> keyType, TypeToken<V> valueType) {
|
||||||
|
return (TypeToken<Map<K, V>>) TypeToken.getParameterized(Map.class, keyType, valueType.getType());
|
||||||
|
}
|
||||||
|
|
||||||
public static <T> T fromJsonFully(InputStream json, Class<T> classOfT) throws IOException, JsonParseException {
|
public static <T> T fromJsonFully(InputStream json, Class<T> classOfT) throws IOException, JsonParseException {
|
||||||
try (InputStreamReader reader = new InputStreamReader(json, StandardCharsets.UTF_8)) {
|
try (InputStreamReader reader = new InputStreamReader(json, StandardCharsets.UTF_8)) {
|
||||||
return GSON.fromJson(reader, classOfT);
|
return GSON.fromJson(reader, classOfT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> T fromJsonFully(InputStream json, Type type) throws IOException, JsonParseException {
|
public static <T> T fromJsonFully(InputStream json, TypeToken<T> type) throws IOException, JsonParseException {
|
||||||
try (InputStreamReader reader = new InputStreamReader(json, StandardCharsets.UTF_8)) {
|
try (InputStreamReader reader = new InputStreamReader(json, StandardCharsets.UTF_8)) {
|
||||||
return GSON.fromJson(reader, type);
|
return GSON.fromJson(reader, type);
|
||||||
}
|
}
|
||||||
@@ -67,13 +85,6 @@ public final class JsonUtils {
|
|||||||
return parsed;
|
return parsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> T fromNonNullJson(String json, Type type) throws JsonParseException {
|
|
||||||
T parsed = GSON.fromJson(json, type);
|
|
||||||
if (parsed == null)
|
|
||||||
throw new JsonParseException("Json object cannot be null.");
|
|
||||||
return parsed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> T fromNonNullJson(String json, TypeToken<T> type) throws JsonParseException {
|
public static <T> T fromNonNullJson(String json, TypeToken<T> type) throws JsonParseException {
|
||||||
T parsed = GSON.fromJson(json, type);
|
T parsed = GSON.fromJson(json, type);
|
||||||
if (parsed == null)
|
if (parsed == null)
|
||||||
@@ -90,7 +101,7 @@ public final class JsonUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> T fromNonNullJsonFully(InputStream json, Type type) throws IOException, JsonParseException {
|
public static <T> T fromNonNullJsonFully(InputStream json, TypeToken<T> type) throws IOException, JsonParseException {
|
||||||
try (InputStreamReader reader = new InputStreamReader(json, StandardCharsets.UTF_8)) {
|
try (InputStreamReader reader = new InputStreamReader(json, StandardCharsets.UTF_8)) {
|
||||||
T parsed = GSON.fromJson(reader, type);
|
T parsed = GSON.fromJson(reader, type);
|
||||||
if (parsed == null)
|
if (parsed == null)
|
||||||
@@ -107,7 +118,7 @@ public final class JsonUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> T fromMaybeMalformedJson(String json, Type type) throws JsonParseException {
|
public static <T> T fromMaybeMalformedJson(String json, TypeToken<T> type) throws JsonParseException {
|
||||||
try {
|
try {
|
||||||
return GSON.fromJson(json, type);
|
return GSON.fromJson(json, type);
|
||||||
} catch (JsonSyntaxException e) {
|
} catch (JsonSyntaxException e) {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
package org.jackhuang.hmcl.util.io;
|
package org.jackhuang.hmcl.util.io;
|
||||||
|
|
||||||
import com.google.gson.JsonParseException;
|
import com.google.gson.JsonParseException;
|
||||||
|
import com.google.gson.reflect.TypeToken;
|
||||||
import org.jackhuang.hmcl.task.Schedulers;
|
import org.jackhuang.hmcl.task.Schedulers;
|
||||||
import org.jackhuang.hmcl.util.Pair;
|
import org.jackhuang.hmcl.util.Pair;
|
||||||
import org.jackhuang.hmcl.util.function.ExceptionalBiConsumer;
|
import org.jackhuang.hmcl.util.function.ExceptionalBiConsumer;
|
||||||
@@ -26,7 +27,6 @@ import org.jackhuang.hmcl.util.gson.JsonUtils;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.lang.reflect.Type;
|
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
@@ -101,7 +101,7 @@ public abstract class HttpRequest {
|
|||||||
return JsonUtils.fromNonNullJson(getString(), typeOfT);
|
return JsonUtils.fromNonNullJson(getString(), typeOfT);
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> T getJson(Type type) throws IOException, JsonParseException {
|
public <T> T getJson(TypeToken<T> type) throws IOException, JsonParseException {
|
||||||
return JsonUtils.fromNonNullJson(getString(), type);
|
return JsonUtils.fromNonNullJson(getString(), type);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,7 +109,7 @@ public abstract class HttpRequest {
|
|||||||
return getStringAsync().thenApplyAsync(jsonString -> JsonUtils.fromNonNullJson(jsonString, typeOfT));
|
return getStringAsync().thenApplyAsync(jsonString -> JsonUtils.fromNonNullJson(jsonString, typeOfT));
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> CompletableFuture<T> getJsonAsync(Type type) {
|
public <T> CompletableFuture<T> getJsonAsync(TypeToken<T> type) {
|
||||||
return getStringAsync().thenApplyAsync(jsonString -> JsonUtils.fromNonNullJson(jsonString, type));
|
return getStringAsync().thenApplyAsync(jsonString -> JsonUtils.fromNonNullJson(jsonString, type));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Hello Minecraft! Launcher
|
||||||
|
* Copyright (C) 2024 huangyuhui <huanghongxun2008@126.com> and contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.jackhuang.hmcl.util.gson;
|
||||||
|
|
||||||
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf;
|
||||||
|
import static org.jackhuang.hmcl.util.gson.JsonUtils.mapTypeOf;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Glavo
|
||||||
|
*/
|
||||||
|
public class JsonUtilsTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetTypeToken() {
|
||||||
|
assertEquals(new TypeToken<List<Object>>(){}, listTypeOf(Object.class));
|
||||||
|
assertEquals(new TypeToken<List<String>>(){}, listTypeOf(String.class));
|
||||||
|
assertEquals(new TypeToken<List<Map<String, Integer>>>(){}, listTypeOf(mapTypeOf(String.class, Integer.class)));
|
||||||
|
assertEquals(new TypeToken<List<Map<String, List<Integer>>>>(){}, listTypeOf(mapTypeOf(String.class, listTypeOf(Integer.class))));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user