update VersionList

This commit is contained in:
Glavo 2025-08-01 16:01:36 +08:00
parent bcf66c8996
commit 4eab456687
20 changed files with 141 additions and 135 deletions

View File

@ -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<RemoteVersion> items = loadVersions();
@ -348,8 +349,9 @@ public final class VersionsPage extends BorderPane implements WizardPage, Refres
@Override
public void cleanup(Map<String, Object> settings) {
settings.remove(libraryId);
if (executor != null)
executor.cancel(true);
// fixme
// if (executor != null)
// executor.cancel(true);
}
private void onRefresh() {

View File

@ -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));

View File

@ -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<RemoteVersion> {
}
@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<Void> 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.<CompletableFuture<?>>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);
}

View File

@ -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 <T> The subclass of {@code RemoteVersion}, the type of RemoteVersion.
*
* @author huangyuhui
*/
public abstract class VersionList<T extends RemoteVersion> {
@ -48,6 +47,7 @@ public abstract class VersionList<T extends RemoteVersion> {
/**
* 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,19 +61,18 @@ public abstract class VersionList<T extends RemoteVersion> {
/**
* @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 -> {
public Task<?> loadAsync() {
return Task.composeAsync(() -> {
lock.readLock().lock();
boolean loaded;
@ -82,13 +81,12 @@ public abstract class VersionList<T extends RemoteVersion> {
} finally {
lock.readLock().unlock();
}
return loaded ? CompletableFuture.completedFuture(null) : refreshAsync();
return loaded ? null : refreshAsync();
});
}
public CompletableFuture<?> loadAsync(String gameVersion) {
return CompletableFuture.completedFuture(null)
.thenComposeAsync(unused -> {
public Task<?> loadAsync(String gameVersion) {
return Task.composeAsync(() -> {
lock.readLock().lock();
boolean loaded;
@ -97,7 +95,7 @@ public abstract class VersionList<T extends RemoteVersion> {
} finally {
lock.readLock().unlock();
}
return loaded ? CompletableFuture.completedFuture(null) : refreshAsync(gameVersion);
return loaded ? Task.completed(null) : refreshAsync(gameVersion);
});
}

View File

@ -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<FabricAPIRemoteVersion> {
@ -42,14 +40,14 @@ public class FabricAPIVersionList extends VersionList<FabricAPIRemoteVersion> {
}
@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())));
}
}
}));
});
}
}

View File

@ -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<FabricRemoteVersion> {
@ -45,8 +44,8 @@ public final class FabricVersionList extends VersionList<FabricRemoteVersion> {
}
@Override
public CompletableFuture<?> refreshAsync() {
return CompletableFuture.runAsync(wrap(() -> {
public Task<?> refreshAsync() {
return Task.runAsync(() -> {
List<String> gameVersions = getGameVersions(GAME_META_URL);
List<String> loaderVersions = getGameVersions(LOADER_META_URL);
@ -60,7 +59,7 @@ public final class FabricVersionList extends VersionList<FabricRemoteVersion> {
} finally {
lock.writeLock().unlock();
}
}));
});
}
private static final String LOADER_META_URL = "https://meta.fabricmc.net/v2/versions/loader";

View File

@ -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<ForgeRemoteVersion>
}
@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<ForgeRemoteVersion>
}
@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 {

View File

@ -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<ForgeRemoteVersion> {
}
@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<ForgeRemoteVersion> {
});
}
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/");
}

View File

@ -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<GameRemoteVersion> {
}
@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;

View File

@ -44,7 +44,7 @@ public final class VersionJsonDownloadTask extends Task<String> {
this.dependencyManager = dependencyManager;
this.gameVersionList = dependencyManager.getVersionList("game");
dependents.add(Task.fromCompletableFuture(gameVersionList.loadAsync(gameVersion)));
dependents.add(gameVersionList.loadAsync(gameVersion));
setSignificance(TaskSignificance.MODERATE);
}

View File

@ -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<LiteLoaderRemot
}
@Override
public CompletableFuture<?> 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();

View File

@ -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<LiteLoaderRemoteVer
public static final String LITELOADER_LIST = "https://dl.liteloader.com/versions/versions.json";
@Override
public CompletableFuture<?> 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<LiteLoaderRemoteVer
}
@Override
public CompletableFuture<?> refreshAsync() {
public Task<?> refreshAsync() {
throw new UnsupportedOperationException();
}

View File

@ -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<NeoForgeRemoteVersion> {
@ -47,12 +46,12 @@ public final class NeoForgeBMCLVersionList extends VersionList<NeoForgeRemoteVer
}
@Override
public CompletableFuture<?> 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<NeoForgeRemoteVer
}
@Override
public CompletableFuture<?> 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();

View File

@ -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<NeoForgeRemoteVersion> {
@ -37,17 +37,17 @@ public final class NeoForgeOfficialVersionList extends VersionList<NeoForgeRemot
}
@Override
public CompletableFuture<?> 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<NeoForgeRemot
));
}
for (String version : results[1].versions) {
for (String version : results.get(1).versions) {
String mcVersion;
try {

View File

@ -19,14 +19,15 @@ package org.jackhuang.hmcl.download.optifine;
import com.google.gson.annotations.SerializedName;
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.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import static org.jackhuang.hmcl.util.gson.JsonUtils.listTypeOf;
@ -71,8 +72,8 @@ public final class OptiFineBMCLVersionList extends VersionList<OptiFineRemoteVer
}
@Override
public CompletableFuture<?> 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 {

View File

@ -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<QuiltAPIRemoteVersion> {
@ -42,14 +40,14 @@ public class QuiltAPIVersionList extends VersionList<QuiltAPIRemoteVersion> {
}
@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())));
}
}
}));
});
}
}

View File

@ -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<QuiltRemoteVersion> {
@ -45,8 +44,8 @@ public final class QuiltVersionList extends VersionList<QuiltRemoteVersion> {
}
@Override
public CompletableFuture<?> refreshAsync() {
return CompletableFuture.runAsync(wrap(() -> {
public Task<?> refreshAsync() {
return Task.runAsync(() -> {
List<String> gameVersions = getGameVersions(GAME_META_URL);
List<String> loaderVersions = getGameVersions(LOADER_META_URL);
@ -60,7 +59,7 @@ public final class QuiltVersionList extends VersionList<QuiltRemoteVersion> {
} finally {
lock.writeLock().unlock();
}
}));
});
}
private static final String LOADER_META_URL = "https://meta.quiltmc.org/v3/versions/loader";

View File

@ -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<String> {
@ -95,4 +97,11 @@ public final class GetTask extends FetchTask<String> {
};
}
public <T> Task<T> thenGetJsonAsync(Class<T> type) {
return thenGetJsonAsync(TypeToken.get(type));
}
public <T> Task<T> thenGetJsonAsync(TypeToken<T> type) {
return thenApplyAsync(jsonString -> JsonUtils.fromNonNullJson(jsonString, type));
}
}

View File

@ -917,7 +917,8 @@ public abstract class Task<T> {
* @param tasks the Tasks
* @return a new Task that is completed when all of the given Tasks complete
*/
public static Task<List<Object>> allOf(Task<?>... tasks) {
@SafeVarargs
public static <T> Task<List<T>> allOf(Task<? extends T>... tasks) {
return allOf(Arrays.asList(tasks));
}
@ -932,8 +933,8 @@ public abstract class Task<T> {
* @param tasks the Tasks
* @return a new Task that is completed when all of the given Tasks complete
*/
public static Task<List<Object>> allOf(Collection<Task<?>> tasks) {
return new Task<List<Object>>() {
public static <T> Task<List<T>> allOf(Collection<? extends Task<? extends T>> tasks) {
return new Task<>() {
{
setSignificance(TaskSignificance.MINOR);
}
@ -944,7 +945,7 @@ public abstract class Task<T> {
}
@Override
public Collection<Task<?>> getDependents() {
public Collection<? extends Task<?>> getDependents() {
return tasks;
}
};

View File

@ -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<URI> withQuery(List<URI> list, Map<String, String> params) {
return list.stream().map(uri -> URI.create(withQuery(uri.toString(), params))).collect(Collectors.toList());
}
public static List<Pair<String, String>> parseQuery(URI uri) {
return parseQuery(uri.getRawQuery());
}