From 4eab456687858d62fe7fbfe6eb23032a1a8d3d33 Mon Sep 17 00:00:00 2001 From: Glavo Date: Fri, 1 Aug 2025 16:01:36 +0800 Subject: [PATCH] update VersionList --- .../hmcl/ui/download/VersionsPage.java | 12 ++-- .../download/DefaultDependencyManager.java | 2 +- .../download/MultipleSourceVersionList.java | 39 ++++++------- .../jackhuang/hmcl/download/VersionList.java | 56 +++++++++---------- .../download/fabric/FabricAPIVersionList.java | 10 ++-- .../download/fabric/FabricVersionList.java | 9 ++- .../download/forge/ForgeBMCLVersionList.java | 12 ++-- .../hmcl/download/forge/ForgeVersionList.java | 11 ++-- .../hmcl/download/game/GameVersionList.java | 9 +-- .../game/VersionJsonDownloadTask.java | 2 +- .../liteloader/LiteLoaderBMCLVersionList.java | 18 +++--- .../liteloader/LiteLoaderVersionList.java | 11 ++-- .../neoforge/NeoForgeBMCLVersionList.java | 12 ++-- .../neoforge/NeoForgeOfficialVersionList.java | 20 +++---- .../optifine/OptiFineBMCLVersionList.java | 9 +-- .../download/quilt/QuiltAPIVersionList.java | 10 ++-- .../hmcl/download/quilt/QuiltVersionList.java | 9 ++- .../java/org/jackhuang/hmcl/task/GetTask.java | 11 +++- .../java/org/jackhuang/hmcl/task/Task.java | 9 +-- .../jackhuang/hmcl/util/io/NetworkUtils.java | 5 ++ 20 files changed, 141 insertions(+), 135 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java index 5ec976168..4221dca9d 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java @@ -49,6 +49,8 @@ import org.jackhuang.hmcl.download.quilt.QuiltAPIRemoteVersion; import org.jackhuang.hmcl.download.quilt.QuiltRemoteVersion; import org.jackhuang.hmcl.setting.Theme; import org.jackhuang.hmcl.setting.VersionIconType; +import org.jackhuang.hmcl.task.Schedulers; +import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.ui.SVG; import org.jackhuang.hmcl.ui.animation.ContainerAnimations; @@ -67,7 +69,6 @@ import org.jackhuang.hmcl.util.i18n.I18n; import java.util.List; import java.util.Locale; import java.util.Map; -import java.util.concurrent.CompletableFuture; import java.util.function.Predicate; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -96,7 +97,7 @@ public final class VersionsPage extends BorderPane implements WizardPage, Refres private final StackPane center; private final VersionList versionList; - private CompletableFuture executor; + private Task executor; private final HBox searchBar; private final StringProperty queryString = new SimpleStringProperty(); @@ -308,7 +309,7 @@ public final class VersionsPage extends BorderPane implements WizardPage, Refres public void refresh() { VersionList currentVersionList = versionList; root.setContent(spinner, ContainerAnimations.FADE); - executor = currentVersionList.refreshAsync(gameVersion).whenComplete((result, exception) -> { + executor = currentVersionList.refreshAsync(gameVersion).whenComplete(Schedulers.io(), (result, exception) -> { if (exception == null) { List items = loadVersions(); @@ -348,8 +349,9 @@ public final class VersionsPage extends BorderPane implements WizardPage, Refres @Override public void cleanup(Map settings) { settings.remove(libraryId); - if (executor != null) - executor.cancel(true); + // fixme +// if (executor != null) +// executor.cancel(true); } private void onRefresh() { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java index 8b665aec9..995189c1b 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java @@ -148,7 +148,7 @@ public class DefaultDependencyManager extends AbstractDependencyManager { if (baseVersion.isResolved()) throw new IllegalArgumentException("Version should not be resolved"); VersionList versionList = getVersionList(libraryId); - return Task.fromCompletableFuture(versionList.loadAsync(gameVersion)) + return versionList.loadAsync(gameVersion) .thenComposeAsync(() -> installLibraryAsync(baseVersion, versionList.getVersion(gameVersion, libraryVersion) .orElseThrow(() -> new IOException("Remote library " + libraryId + " has no version " + libraryVersion)))) .withStage(String.format("hmcl.install.%s:%s", libraryId, libraryVersion)); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/MultipleSourceVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/MultipleSourceVersionList.java index cde656bf3..703e2ff53 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/MultipleSourceVersionList.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/MultipleSourceVersionList.java @@ -17,8 +17,9 @@ */ package org.jackhuang.hmcl.download; +import org.jackhuang.hmcl.task.Task; + import java.util.Arrays; -import java.util.concurrent.CompletableFuture; import static org.jackhuang.hmcl.util.logging.Logger.LOG; @@ -40,44 +41,40 @@ public class MultipleSourceVersionList extends VersionList { } @Override - public CompletableFuture loadAsync() { + public Task loadAsync() { throw new UnsupportedOperationException("MultipleSourceVersionList does not support loading the entire remote version list."); } @Override - public CompletableFuture refreshAsync() { + public Task refreshAsync() { throw new UnsupportedOperationException("MultipleSourceVersionList does not support loading the entire remote version list."); } - private CompletableFuture refreshAsync(String gameVersion, int sourceIndex) { + private Task refreshAsync(String gameVersion, int sourceIndex) { VersionList versionList = backends[sourceIndex]; - CompletableFuture future = versionList.refreshAsync(gameVersion) - .thenRunAsync(() -> { + return versionList.refreshAsync(gameVersion) + .thenComposeAsync(() -> { lock.writeLock().lock(); - try { versions.putAll(gameVersion, versionList.getVersions(gameVersion)); + } catch (Exception e) { + if (sourceIndex == backends.length - 1) { + LOG.warning("Failed to fetch versions list from all sources", e); + return null; + } else { + LOG.warning("Failed to fetch versions list and try to fetch from other source", e); + return refreshAsync(gameVersion, sourceIndex + 1); + } } finally { lock.writeLock().unlock(); } + + return null; }); - - if (sourceIndex == backends.length - 1) { - return future; - } else { - return future.>handle((ignore, e) -> { - if (e == null) { - return future; - } - - LOG.warning("Failed to fetch versions list and try to fetch from other source", e); - return refreshAsync(gameVersion, sourceIndex + 1); - }).thenCompose(it -> it); - } } @Override - public CompletableFuture refreshAsync(String gameVersion) { + public Task refreshAsync(String gameVersion) { versions.clear(gameVersion); return refreshAsync(gameVersion, 0); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/VersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/VersionList.java index b41e835cc..67b52864c 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/VersionList.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/VersionList.java @@ -17,17 +17,16 @@ */ package org.jackhuang.hmcl.download; +import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.util.SimpleMultimap; import java.util.*; -import java.util.concurrent.CompletableFuture; import java.util.concurrent.locks.ReentrantReadWriteLock; /** * The remote version list. * * @param The subclass of {@code RemoteVersion}, the type of RemoteVersion. - * * @author huangyuhui */ public abstract class VersionList { @@ -48,6 +47,7 @@ public abstract class VersionList { /** * True if the version list that contains the remote versions which depends on the specific game version has been loaded. + * * @param gameVersion the remote version depends on */ public boolean isLoaded(String gameVersion) { @@ -61,44 +61,42 @@ public abstract class VersionList { /** * @return the task to reload the remote version list. */ - public abstract CompletableFuture refreshAsync(); + public abstract Task refreshAsync(); /** * @param gameVersion the remote version depends on * @return the task to reload the remote version list. */ - public CompletableFuture refreshAsync(String gameVersion) { + public Task refreshAsync(String gameVersion) { return refreshAsync(); } - public CompletableFuture loadAsync() { - return CompletableFuture.completedFuture(null) - .thenComposeAsync(unused -> { - lock.readLock().lock(); - boolean loaded; + public Task loadAsync() { + return Task.composeAsync(() -> { + lock.readLock().lock(); + boolean loaded; - try { - loaded = isLoaded(); - } finally { - lock.readLock().unlock(); - } - return loaded ? CompletableFuture.completedFuture(null) : refreshAsync(); - }); + try { + loaded = isLoaded(); + } finally { + lock.readLock().unlock(); + } + return loaded ? null : refreshAsync(); + }); } - public CompletableFuture loadAsync(String gameVersion) { - return CompletableFuture.completedFuture(null) - .thenComposeAsync(unused -> { - lock.readLock().lock(); - boolean loaded; + public Task loadAsync(String gameVersion) { + return Task.composeAsync(() -> { + lock.readLock().lock(); + boolean loaded; - try { - loaded = isLoaded(gameVersion); - } finally { - lock.readLock().unlock(); - } - return loaded ? CompletableFuture.completedFuture(null) : refreshAsync(gameVersion); - }); + try { + loaded = isLoaded(gameVersion); + } finally { + lock.readLock().unlock(); + } + return loaded ? Task.completed(null) : refreshAsync(gameVersion); + }); } protected Collection getVersionsImpl(String gameVersion) { @@ -123,7 +121,7 @@ public abstract class VersionList { /** * Get the specific remote version. * - * @param gameVersion the Minecraft version that remote versions belong to + * @param gameVersion the Minecraft version that remote versions belong to * @param remoteVersion the version of the remote version. * @return the specific remote version, null if it is not found. */ diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/fabric/FabricAPIVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/fabric/FabricAPIVersionList.java index 74c862874..8c092822e 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/fabric/FabricAPIVersionList.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/fabric/FabricAPIVersionList.java @@ -21,12 +21,10 @@ import org.jackhuang.hmcl.download.DownloadProvider; import org.jackhuang.hmcl.download.VersionList; import org.jackhuang.hmcl.mod.RemoteMod; import org.jackhuang.hmcl.mod.modrinth.ModrinthRemoteModRepository; +import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.util.Lang; import java.util.Collections; -import java.util.concurrent.CompletableFuture; - -import static org.jackhuang.hmcl.util.Lang.wrap; public class FabricAPIVersionList extends VersionList { @@ -42,14 +40,14 @@ public class FabricAPIVersionList extends VersionList { } @Override - public CompletableFuture refreshAsync() { - return CompletableFuture.runAsync(wrap(() -> { + public Task refreshAsync() { + return Task.runAsync(() -> { for (RemoteMod.Version modVersion : Lang.toIterable(ModrinthRemoteModRepository.MODS.getRemoteVersionsById("P7dR8mSH"))) { for (String gameVersion : modVersion.getGameVersions()) { versions.put(gameVersion, new FabricAPIRemoteVersion(gameVersion, modVersion.getVersion(), modVersion.getName(), modVersion.getDatePublished(), modVersion, Collections.singletonList(modVersion.getFile().getUrl()))); } } - })); + }); } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/fabric/FabricVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/fabric/FabricVersionList.java index 8440f70b7..b71a7fb30 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/fabric/FabricVersionList.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/fabric/FabricVersionList.java @@ -19,6 +19,7 @@ package org.jackhuang.hmcl.download.fabric; import org.jackhuang.hmcl.download.DownloadProvider; import org.jackhuang.hmcl.download.VersionList; +import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.util.gson.JsonUtils; import org.jackhuang.hmcl.util.io.NetworkUtils; import org.jetbrains.annotations.Nullable; @@ -26,10 +27,8 @@ import org.jetbrains.annotations.Nullable; import java.io.IOException; import java.util.Collections; import java.util.List; -import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; -import static org.jackhuang.hmcl.util.Lang.wrap; import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf; public final class FabricVersionList extends VersionList { @@ -45,8 +44,8 @@ public final class FabricVersionList extends VersionList { } @Override - public CompletableFuture refreshAsync() { - return CompletableFuture.runAsync(wrap(() -> { + public Task refreshAsync() { + return Task.runAsync(() -> { List gameVersions = getGameVersions(GAME_META_URL); List loaderVersions = getGameVersions(LOADER_META_URL); @@ -60,7 +59,7 @@ public final class FabricVersionList extends VersionList { } finally { lock.writeLock().unlock(); } - })); + }); } private static final String LOADER_META_URL = "https://meta.fabricmc.net/v2/versions/loader"; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeBMCLVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeBMCLVersionList.java index c0d0fdc8b..5e3a3374c 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeBMCLVersionList.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeBMCLVersionList.java @@ -19,6 +19,7 @@ package org.jackhuang.hmcl.download.forge; import com.google.gson.JsonParseException; import org.jackhuang.hmcl.download.VersionList; +import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.util.Immutable; import org.jackhuang.hmcl.util.Lang; import org.jackhuang.hmcl.util.StringUtils; @@ -34,10 +35,8 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Optional; -import java.util.concurrent.CompletableFuture; import static org.jackhuang.hmcl.util.Lang.mapOf; -import static org.jackhuang.hmcl.util.Lang.wrap; 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; @@ -58,12 +57,12 @@ public final class ForgeBMCLVersionList extends VersionList } @Override - public CompletableFuture loadAsync() { + public Task loadAsync() { throw new UnsupportedOperationException("ForgeBMCLVersionList does not support loading the entire Forge remote version list."); } @Override - public CompletableFuture refreshAsync() { + public Task refreshAsync() { throw new UnsupportedOperationException("ForgeBMCLVersionList does not support loading the entire Forge remote version list."); } @@ -83,11 +82,10 @@ public final class ForgeBMCLVersionList extends VersionList } @Override - public CompletableFuture refreshAsync(String gameVersion) { + public Task refreshAsync(String gameVersion) { String lookupVersion = toLookupVersion(gameVersion); - return CompletableFuture.completedFuture(null) - .thenApplyAsync(wrap(unused -> HttpRequest.GET(apiRoot + "/forge/minecraft/" + lookupVersion).getJson(listTypeOf(ForgeVersion.class)))) + return Task.supplyAsync(() -> HttpRequest.GET(apiRoot + "/forge/minecraft/" + lookupVersion).getJson(listTypeOf(ForgeVersion.class))) .thenAcceptAsync(forgeVersions -> { lock.writeLock().lock(); try { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeVersionList.java index acb97fef3..cf58b60cf 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeVersionList.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeVersionList.java @@ -19,14 +19,15 @@ package org.jackhuang.hmcl.download.forge; import org.jackhuang.hmcl.download.DownloadProvider; import org.jackhuang.hmcl.download.VersionList; +import org.jackhuang.hmcl.task.GetTask; +import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.util.StringUtils; -import org.jackhuang.hmcl.util.io.HttpRequest; import org.jackhuang.hmcl.util.versioning.VersionNumber; +import java.net.URI; import java.time.Instant; import java.util.Collections; import java.util.Map; -import java.util.concurrent.CompletableFuture; /** * @@ -53,8 +54,8 @@ public final class ForgeVersionList extends VersionList { } @Override - public CompletableFuture refreshAsync() { - return HttpRequest.GET(FORGE_LIST).getJsonAsync(ForgeVersionRoot.class) + public Task refreshAsync() { + return new GetTask(FORGE_LIST).thenGetJsonAsync(ForgeVersionRoot.class) .thenAcceptAsync(root -> { lock.writeLock().lock(); @@ -95,5 +96,5 @@ public final class ForgeVersionList extends VersionList { }); } - public static final String FORGE_LIST = "https://hmcl-dev.github.io/metadata/forge/"; + public static final URI FORGE_LIST = URI.create("https://hmcl-dev.github.io/metadata/forge/"); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameVersionList.java index bfcb0bfa3..30ff1bdb1 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameVersionList.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameVersionList.java @@ -19,14 +19,15 @@ package org.jackhuang.hmcl.download.game; import org.jackhuang.hmcl.download.DownloadProvider; import org.jackhuang.hmcl.download.VersionList; +import org.jackhuang.hmcl.task.GetTask; +import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.util.gson.JsonUtils; -import org.jackhuang.hmcl.util.io.HttpRequest; import java.io.InputStreamReader; import java.io.Reader; +import java.net.URI; import java.util.Collection; import java.util.Collections; -import java.util.concurrent.CompletableFuture; import static org.jackhuang.hmcl.util.logging.Logger.LOG; @@ -52,8 +53,8 @@ public final class GameVersionList extends VersionList { } @Override - public CompletableFuture refreshAsync() { - return HttpRequest.GET(downloadProvider.getVersionListURL()).getJsonAsync(GameRemoteVersions.class) + public Task refreshAsync() { + return new GetTask(URI.create(downloadProvider.getVersionListURL())).thenGetJsonAsync(GameRemoteVersions.class) .thenAcceptAsync(root -> { GameRemoteVersions unlistedVersions = null; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/VersionJsonDownloadTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/VersionJsonDownloadTask.java index f91b6e426..112295a15 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/VersionJsonDownloadTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/VersionJsonDownloadTask.java @@ -44,7 +44,7 @@ public final class VersionJsonDownloadTask extends Task { this.dependencyManager = dependencyManager; this.gameVersionList = dependencyManager.getVersionList("game"); - dependents.add(Task.fromCompletableFuture(gameVersionList.loadAsync(gameVersion))); + dependents.add(gameVersionList.loadAsync(gameVersion)); setSignificance(TaskSignificance.MODERATE); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/liteloader/LiteLoaderBMCLVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/liteloader/LiteLoaderBMCLVersionList.java index 8ede1acce..d8d5d04b7 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/liteloader/LiteLoaderBMCLVersionList.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/liteloader/LiteLoaderBMCLVersionList.java @@ -20,12 +20,12 @@ package org.jackhuang.hmcl.download.liteloader; import org.jackhuang.hmcl.download.BMCLAPIDownloadProvider; import org.jackhuang.hmcl.download.RemoteVersion; import org.jackhuang.hmcl.download.VersionList; -import org.jackhuang.hmcl.util.Pair; -import org.jackhuang.hmcl.util.io.HttpRequest; +import org.jackhuang.hmcl.task.GetTask; +import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.util.io.NetworkUtils; import java.util.Collections; -import java.util.concurrent.CompletableFuture; +import java.util.Map; /** * @author huangyuhui @@ -54,17 +54,15 @@ public final class LiteLoaderBMCLVersionList extends VersionList refreshAsync() { + public Task refreshAsync() { throw new UnsupportedOperationException(); } @Override - public CompletableFuture refreshAsync(String gameVersion) { - return HttpRequest.GET( - downloadProvider.injectURL("https://bmclapi2.bangbang93.com/liteloader/list"), Pair.pair("mcversion", gameVersion) - ) - .getJsonAsync(LiteLoaderBMCLVersion.class) - .thenAccept(v -> { + public Task refreshAsync(String gameVersion) { + return new GetTask(NetworkUtils.withQuery(downloadProvider.injectURLWithCandidates("https://bmclapi2.bangbang93.com/liteloader/list"), Map.of("mcversion", gameVersion))) + .thenGetJsonAsync(LiteLoaderBMCLVersion.class) + .thenAcceptAsync(v -> { lock.writeLock().lock(); try { versions.clear(); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/liteloader/LiteLoaderVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/liteloader/LiteLoaderVersionList.java index 3f95c06d5..2310a238a 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/liteloader/LiteLoaderVersionList.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/liteloader/LiteLoaderVersionList.java @@ -20,16 +20,18 @@ package org.jackhuang.hmcl.download.liteloader; import org.jackhuang.hmcl.download.DownloadProvider; import org.jackhuang.hmcl.download.RemoteVersion; import org.jackhuang.hmcl.download.VersionList; +import org.jackhuang.hmcl.task.GetTask; +import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.util.io.HttpRequest; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import java.io.IOException; import java.io.UncheckedIOException; +import java.net.URI; import java.util.Collections; import java.util.Map; import java.util.Objects; -import java.util.concurrent.CompletableFuture; /** * @author huangyuhui @@ -50,8 +52,9 @@ public final class LiteLoaderVersionList extends VersionList refreshAsync(String gameVersion) { - return HttpRequest.GET(downloadProvider.injectURL(LITELOADER_LIST)).getJsonAsync(LiteLoaderVersionsRoot.class) + public Task refreshAsync(String gameVersion) { + return new GetTask(URI.create(downloadProvider.injectURL(LITELOADER_LIST))) + .thenGetJsonAsync(LiteLoaderVersionsRoot.class) .thenAcceptAsync(root -> { LiteLoaderGameVersions versions = root.getVersions().get(gameVersion); if (versions == null) { @@ -85,7 +88,7 @@ public final class LiteLoaderVersionList extends VersionList refreshAsync() { + public Task refreshAsync() { throw new UnsupportedOperationException(); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/neoforge/NeoForgeBMCLVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/neoforge/NeoForgeBMCLVersionList.java index a00f2eaeb..a472abee4 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/neoforge/NeoForgeBMCLVersionList.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/neoforge/NeoForgeBMCLVersionList.java @@ -20,15 +20,14 @@ package org.jackhuang.hmcl.download.neoforge; import com.google.gson.JsonParseException; import com.google.gson.annotations.SerializedName; import org.jackhuang.hmcl.download.VersionList; +import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.util.Immutable; import org.jackhuang.hmcl.util.gson.Validation; import org.jackhuang.hmcl.util.io.HttpRequest; import java.util.Collections; import java.util.Optional; -import java.util.concurrent.CompletableFuture; -import static org.jackhuang.hmcl.util.Lang.wrap; import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf; public final class NeoForgeBMCLVersionList extends VersionList { @@ -47,12 +46,12 @@ public final class NeoForgeBMCLVersionList extends VersionList loadAsync() { + public Task loadAsync() { throw new UnsupportedOperationException("NeoForgeBMCLVersionList does not support loading the entire NeoForge remote version list."); } @Override - public CompletableFuture refreshAsync() { + public Task refreshAsync() { throw new UnsupportedOperationException("NeoForgeBMCLVersionList does not support loading the entire NeoForge remote version list."); } @@ -65,9 +64,8 @@ public final class NeoForgeBMCLVersionList extends VersionList refreshAsync(String gameVersion) { - return CompletableFuture.completedFuture((Void) null) - .thenApplyAsync(wrap(unused -> HttpRequest.GET(apiRoot + "/neoforge/list/" + gameVersion).getJson(listTypeOf(NeoForgeVersion.class)))) + public Task refreshAsync(String gameVersion) { + return Task.supplyAsync(() -> HttpRequest.GET(apiRoot + "/neoforge/list/" + gameVersion).getJson(listTypeOf(NeoForgeVersion.class))) .thenAcceptAsync(neoForgeVersions -> { lock.writeLock().lock(); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/neoforge/NeoForgeOfficialVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/neoforge/NeoForgeOfficialVersionList.java index d853b9d3e..3a20320a6 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/neoforge/NeoForgeOfficialVersionList.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/neoforge/NeoForgeOfficialVersionList.java @@ -2,14 +2,14 @@ package org.jackhuang.hmcl.download.neoforge; import org.jackhuang.hmcl.download.DownloadProvider; import org.jackhuang.hmcl.download.VersionList; -import org.jackhuang.hmcl.util.io.HttpRequest; +import org.jackhuang.hmcl.task.GetTask; +import org.jackhuang.hmcl.task.Task; +import java.net.URI; import java.util.Collections; import java.util.List; import java.util.Optional; -import java.util.concurrent.CompletableFuture; -import static org.jackhuang.hmcl.util.Lang.wrap; import static org.jackhuang.hmcl.util.logging.Logger.LOG; public final class NeoForgeOfficialVersionList extends VersionList { @@ -37,17 +37,17 @@ public final class NeoForgeOfficialVersionList extends VersionList refreshAsync() { - return CompletableFuture.supplyAsync(wrap(() -> new OfficialAPIResult[]{ - HttpRequest.GET(downloadProvider.injectURL(OLD_URL)).getJson(OfficialAPIResult.class), - HttpRequest.GET(downloadProvider.injectURL(META_URL)).getJson(OfficialAPIResult.class) - })).thenAccept(results -> { + public Task refreshAsync() { + return Task.allOf( + new GetTask(URI.create(downloadProvider.injectURL(OLD_URL))).thenGetJsonAsync(OfficialAPIResult.class), + new GetTask(URI.create(downloadProvider.injectURL(META_URL))).thenGetJsonAsync(OfficialAPIResult.class) + ).thenAcceptAsync(results -> { lock.writeLock().lock(); try { versions.clear(); - for (String version : results[0].versions) { + for (String version : results.get(0).versions) { versions.put("1.20.1", new NeoForgeRemoteVersion( "1.20.1", NeoForgeRemoteVersion.normalize(version), Collections.singletonList( @@ -56,7 +56,7 @@ public final class NeoForgeOfficialVersionList extends VersionList refreshAsync() { - return HttpRequest.GET(apiRoot + "/optifine/versionlist").getJsonAsync(listTypeOf(OptiFineVersion.class)).thenAcceptAsync(root -> { + public Task refreshAsync() { + return new GetTask(URI.create(apiRoot + "/optifine/versionlist")).thenGetJsonAsync(listTypeOf(OptiFineVersion.class)).thenAcceptAsync(root -> { lock.writeLock().lock(); try { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/quilt/QuiltAPIVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/quilt/QuiltAPIVersionList.java index 9435f5c86..04fc0327a 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/quilt/QuiltAPIVersionList.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/quilt/QuiltAPIVersionList.java @@ -21,12 +21,10 @@ import org.jackhuang.hmcl.download.DownloadProvider; import org.jackhuang.hmcl.download.VersionList; import org.jackhuang.hmcl.mod.RemoteMod; import org.jackhuang.hmcl.mod.modrinth.ModrinthRemoteModRepository; +import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.util.Lang; import java.util.Collections; -import java.util.concurrent.CompletableFuture; - -import static org.jackhuang.hmcl.util.Lang.wrap; public class QuiltAPIVersionList extends VersionList { @@ -42,14 +40,14 @@ public class QuiltAPIVersionList extends VersionList { } @Override - public CompletableFuture refreshAsync() { - return CompletableFuture.runAsync(wrap(() -> { + public Task refreshAsync() { + return Task.runAsync(() -> { for (RemoteMod.Version modVersion : Lang.toIterable(ModrinthRemoteModRepository.MODS.getRemoteVersionsById("qsl"))) { for (String gameVersion : modVersion.getGameVersions()) { versions.put(gameVersion, new QuiltAPIRemoteVersion(gameVersion, modVersion.getVersion(), modVersion.getName(), modVersion.getDatePublished(), modVersion, Collections.singletonList(modVersion.getFile().getUrl()))); } } - })); + }); } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/quilt/QuiltVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/quilt/QuiltVersionList.java index f7d6a2e6b..c33d0acf0 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/quilt/QuiltVersionList.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/quilt/QuiltVersionList.java @@ -19,6 +19,7 @@ package org.jackhuang.hmcl.download.quilt; import org.jackhuang.hmcl.download.DownloadProvider; import org.jackhuang.hmcl.download.VersionList; +import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.util.gson.JsonUtils; import org.jackhuang.hmcl.util.io.NetworkUtils; import org.jetbrains.annotations.Nullable; @@ -26,10 +27,8 @@ import org.jetbrains.annotations.Nullable; import java.io.IOException; import java.util.Collections; import java.util.List; -import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; -import static org.jackhuang.hmcl.util.Lang.wrap; import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf; public final class QuiltVersionList extends VersionList { @@ -45,8 +44,8 @@ public final class QuiltVersionList extends VersionList { } @Override - public CompletableFuture refreshAsync() { - return CompletableFuture.runAsync(wrap(() -> { + public Task refreshAsync() { + return Task.runAsync(() -> { List gameVersions = getGameVersions(GAME_META_URL); List loaderVersions = getGameVersions(LOADER_META_URL); @@ -60,7 +59,7 @@ public final class QuiltVersionList extends VersionList { } finally { lock.writeLock().unlock(); } - })); + }); } private static final String LOADER_META_URL = "https://meta.quiltmc.org/v3/versions/loader"; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/GetTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/GetTask.java index d5505420f..c0fab32db 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/GetTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/GetTask.java @@ -17,6 +17,9 @@ */ package org.jackhuang.hmcl.task; +import com.google.gson.reflect.TypeToken; +import org.jackhuang.hmcl.util.gson.JsonUtils; + import java.io.ByteArrayOutputStream; import java.io.IOException; import java.net.URI; @@ -29,7 +32,6 @@ import java.util.List; import static java.nio.charset.StandardCharsets.UTF_8; /** - * * @author huangyuhui */ public final class GetTask extends FetchTask { @@ -95,4 +97,11 @@ public final class GetTask extends FetchTask { }; } + public Task thenGetJsonAsync(Class type) { + return thenGetJsonAsync(TypeToken.get(type)); + } + + public Task thenGetJsonAsync(TypeToken type) { + return thenApplyAsync(jsonString -> JsonUtils.fromNonNullJson(jsonString, type)); + } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java index 4f4d793b3..422308d80 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java @@ -917,7 +917,8 @@ public abstract class Task { * @param tasks the Tasks * @return a new Task that is completed when all of the given Tasks complete */ - public static Task> allOf(Task... tasks) { + @SafeVarargs + public static Task> allOf(Task... tasks) { return allOf(Arrays.asList(tasks)); } @@ -932,8 +933,8 @@ public abstract class Task { * @param tasks the Tasks * @return a new Task that is completed when all of the given Tasks complete */ - public static Task> allOf(Collection> tasks) { - return new Task>() { + public static Task> allOf(Collection> tasks) { + return new Task<>() { { setSignificance(TaskSignificance.MINOR); } @@ -944,7 +945,7 @@ public abstract class Task { } @Override - public Collection> getDependents() { + public Collection> getDependents() { return tasks; } }; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/NetworkUtils.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/NetworkUtils.java index d1a7f9a11..034508ad4 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/NetworkUtils.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/NetworkUtils.java @@ -26,6 +26,7 @@ import java.util.*; import java.util.Map.Entry; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; import static java.nio.charset.StandardCharsets.UTF_8; import static org.jackhuang.hmcl.util.Pair.pair; @@ -68,6 +69,10 @@ public final class NetworkUtils { return sb.toString(); } + public static List withQuery(List list, Map params) { + return list.stream().map(uri -> URI.create(withQuery(uri.toString(), params))).collect(Collectors.toList()); + } + public static List> parseQuery(URI uri) { return parseQuery(uri.getRawQuery()); }