From 5d57052ea287cec3de13f9a57857ea5d6131d58f Mon Sep 17 00:00:00 2001 From: Burning_TNT Date: Fri, 6 Feb 2026 22:56:44 +0800 Subject: [PATCH] =?UTF-8?q?Fix=20#4977=20Modrinth=20=E4=BE=9D=E8=B5=96?= =?UTF-8?q?=E5=8F=AF=E4=BB=A5=E6=8C=87=E5=90=91=E5=B7=B2=E7=BB=8F=E8=A2=AB?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E7=9A=84=E9=A1=B9=E7=9B=AE=20(#5012)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hmcl/ui/versions/DownloadPage.java | 49 ++++++++++++++++--- .../org/jackhuang/hmcl/mod/RemoteMod.java | 2 +- .../hmcl/mod/RemoteModRepository.java | 4 ++ .../modrinth/ModrinthRemoteModRepository.java | 15 ++++++ 4 files changed, 61 insertions(+), 9 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DownloadPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DownloadPage.java index cb0513b64..278223a37 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DownloadPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/DownloadPage.java @@ -27,9 +27,18 @@ import javafx.beans.property.SimpleBooleanProperty; import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.Node; -import javafx.scene.control.*; +import javafx.scene.control.Control; +import javafx.scene.control.Label; +import javafx.scene.control.ScrollPane; +import javafx.scene.control.Skin; +import javafx.scene.control.SkinBase; import javafx.scene.image.ImageView; -import javafx.scene.layout.*; +import javafx.scene.layout.BorderPane; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Priority; +import javafx.scene.layout.Region; +import javafx.scene.layout.StackPane; +import javafx.scene.layout.VBox; import javafx.stage.FileChooser; import org.jackhuang.hmcl.download.LibraryAnalyzer; import org.jackhuang.hmcl.game.HMCLGameRepository; @@ -46,7 +55,11 @@ import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.ui.SVG; import org.jackhuang.hmcl.ui.construct.*; import org.jackhuang.hmcl.ui.decorator.DecoratorPage; -import org.jackhuang.hmcl.util.*; +import org.jackhuang.hmcl.util.Lang; +import org.jackhuang.hmcl.util.Pair; +import org.jackhuang.hmcl.util.SimpleMultimap; +import org.jackhuang.hmcl.util.StringUtils; +import org.jackhuang.hmcl.util.TaskCancellationAction; import org.jackhuang.hmcl.util.i18n.I18n; import org.jackhuang.hmcl.util.io.FileUtils; import org.jackhuang.hmcl.util.javafx.BindingMapping; @@ -54,7 +67,14 @@ import org.jackhuang.hmcl.util.versioning.GameVersionNumber; import org.jetbrains.annotations.Nullable; import java.nio.file.Path; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.EnumMap; +import java.util.HashMap; +import java.util.List; +import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -518,8 +538,10 @@ public class DownloadPage extends Control implements DecoratorPage { private void loadDependencies(RemoteMod.Version version, DownloadPage selfPage, SpinnerPane spinnerPane, ComponentList dependenciesList) { spinnerPane.setLoading(true); - Task.supplyAsync(() -> { + Task.composeAsync(() -> { + // TODO: Massive tasks may cause OOM. EnumMap> dependencies = new EnumMap<>(RemoteMod.DependencyType.class); + List> queue = new ArrayList<>(version.getDependencies().size()); for (RemoteMod.Dependency dependency : version.getDependencies()) { if (dependency.getType() == RemoteMod.DependencyType.INCOMPATIBLE || dependency.getType() == RemoteMod.DependencyType.BROKEN) { continue; @@ -532,11 +554,22 @@ public class DownloadPage extends Control implements DecoratorPage { list.add(title); dependencies.put(dependency.getType(), list); } - DependencyModItem dependencyModItem = new DependencyModItem(selfPage.page, dependency.load(), selfPage.version, selfPage.callback); - dependencies.get(dependency.getType()).add(dependencyModItem); + + queue.add(Task.supplyAsync(Schedulers.io(), dependency::load) + .setSignificance(Task.TaskSignificance.MINOR) + .thenAcceptAsync(Schedulers.javafx(), dep -> { + if (dep == RemoteMod.BROKEN) { + return; + } + DependencyModItem dependencyModItem = new DependencyModItem(selfPage.page, dep, selfPage.version, selfPage.callback); + dependencies.get(dependency.getType()).add(dependencyModItem); + }) + .setSignificance(Task.TaskSignificance.MINOR)); } - return dependencies.values().stream().flatMap(Collection::stream).collect(Collectors.toList()); + return Task.allOf(queue).thenSupplyAsync(() -> + dependencies.values().stream().flatMap(Collection::stream).collect(Collectors.toList()) + ); }).whenComplete(Schedulers.javafx(), (result, exception) -> { spinnerPane.setLoading(false); if (exception == null) { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/RemoteMod.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/RemoteMod.java index a936f887b..ce7c56e23 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/RemoteMod.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/RemoteMod.java @@ -159,7 +159,7 @@ public final class RemoteMod { if (this.type == DependencyType.BROKEN) { this.remoteMod = RemoteMod.BROKEN; } else { - this.remoteMod = this.remoteModRepository.getModById(this.id); + this.remoteMod = this.remoteModRepository.resolveDependency(this.id); } } return this.remoteMod; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/RemoteModRepository.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/RemoteModRepository.java index 4dcd467fe..8325375eb 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/RemoteModRepository.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/RemoteModRepository.java @@ -92,6 +92,10 @@ public interface RemoteModRepository { RemoteMod getModById(String id) throws IOException; + default RemoteMod resolveDependency(String id) throws IOException { + return getModById(id); + } + RemoteMod.File getModFile(String modId, String fileId) throws IOException; Stream getRemoteVersionsById(String id) throws IOException; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/modrinth/ModrinthRemoteModRepository.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/modrinth/ModrinthRemoteModRepository.java index 3cfa7c255..a0dde282f 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/modrinth/ModrinthRemoteModRepository.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/mod/modrinth/ModrinthRemoteModRepository.java @@ -35,6 +35,7 @@ import org.jackhuang.hmcl.util.io.NetworkUtils; import org.jackhuang.hmcl.util.io.ResponseCodeException; import org.jetbrains.annotations.Nullable; +import java.io.FileNotFoundException; import java.io.IOException; import java.nio.file.NoSuchFileException; import java.nio.file.Path; @@ -154,6 +155,20 @@ public final class ModrinthRemoteModRepository implements RemoteModRepository { } } + @Override + public RemoteMod resolveDependency(String id) throws IOException { + try { + return getModById(id); + } catch (ResponseCodeException e) { + if (e.getResponseCode() == 502 || e.getResponseCode() == 404) { + return RemoteMod.BROKEN; + } + throw e; + } catch (FileNotFoundException e) { + return RemoteMod.BROKEN; + } + } + @Override public RemoteMod.File getModFile(String modId, String fileId) throws IOException { throw new UnsupportedOperationException();