@@ -27,9 +27,18 @@ import javafx.beans.property.SimpleBooleanProperty;
|
|||||||
import javafx.geometry.Insets;
|
import javafx.geometry.Insets;
|
||||||
import javafx.geometry.Pos;
|
import javafx.geometry.Pos;
|
||||||
import javafx.scene.Node;
|
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.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 javafx.stage.FileChooser;
|
||||||
import org.jackhuang.hmcl.download.LibraryAnalyzer;
|
import org.jackhuang.hmcl.download.LibraryAnalyzer;
|
||||||
import org.jackhuang.hmcl.game.HMCLGameRepository;
|
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.SVG;
|
||||||
import org.jackhuang.hmcl.ui.construct.*;
|
import org.jackhuang.hmcl.ui.construct.*;
|
||||||
import org.jackhuang.hmcl.ui.decorator.DecoratorPage;
|
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.i18n.I18n;
|
||||||
import org.jackhuang.hmcl.util.io.FileUtils;
|
import org.jackhuang.hmcl.util.io.FileUtils;
|
||||||
import org.jackhuang.hmcl.util.javafx.BindingMapping;
|
import org.jackhuang.hmcl.util.javafx.BindingMapping;
|
||||||
@@ -54,7 +67,14 @@ import org.jackhuang.hmcl.util.versioning.GameVersionNumber;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.nio.file.Path;
|
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.Collectors;
|
||||||
import java.util.stream.Stream;
|
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) {
|
private void loadDependencies(RemoteMod.Version version, DownloadPage selfPage, SpinnerPane spinnerPane, ComponentList dependenciesList) {
|
||||||
spinnerPane.setLoading(true);
|
spinnerPane.setLoading(true);
|
||||||
Task.supplyAsync(() -> {
|
Task.composeAsync(() -> {
|
||||||
|
// TODO: Massive tasks may cause OOM.
|
||||||
EnumMap<RemoteMod.DependencyType, List<Node>> dependencies = new EnumMap<>(RemoteMod.DependencyType.class);
|
EnumMap<RemoteMod.DependencyType, List<Node>> dependencies = new EnumMap<>(RemoteMod.DependencyType.class);
|
||||||
|
List<Task<?>> queue = new ArrayList<>(version.getDependencies().size());
|
||||||
for (RemoteMod.Dependency dependency : version.getDependencies()) {
|
for (RemoteMod.Dependency dependency : version.getDependencies()) {
|
||||||
if (dependency.getType() == RemoteMod.DependencyType.INCOMPATIBLE || dependency.getType() == RemoteMod.DependencyType.BROKEN) {
|
if (dependency.getType() == RemoteMod.DependencyType.INCOMPATIBLE || dependency.getType() == RemoteMod.DependencyType.BROKEN) {
|
||||||
continue;
|
continue;
|
||||||
@@ -532,11 +554,22 @@ public class DownloadPage extends Control implements DecoratorPage {
|
|||||||
list.add(title);
|
list.add(title);
|
||||||
dependencies.put(dependency.getType(), list);
|
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) -> {
|
}).whenComplete(Schedulers.javafx(), (result, exception) -> {
|
||||||
spinnerPane.setLoading(false);
|
spinnerPane.setLoading(false);
|
||||||
if (exception == null) {
|
if (exception == null) {
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ public final class RemoteMod {
|
|||||||
if (this.type == DependencyType.BROKEN) {
|
if (this.type == DependencyType.BROKEN) {
|
||||||
this.remoteMod = RemoteMod.BROKEN;
|
this.remoteMod = RemoteMod.BROKEN;
|
||||||
} else {
|
} else {
|
||||||
this.remoteMod = this.remoteModRepository.getModById(this.id);
|
this.remoteMod = this.remoteModRepository.resolveDependency(this.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this.remoteMod;
|
return this.remoteMod;
|
||||||
|
|||||||
@@ -92,6 +92,10 @@ public interface RemoteModRepository {
|
|||||||
|
|
||||||
RemoteMod getModById(String id) throws IOException;
|
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;
|
RemoteMod.File getModFile(String modId, String fileId) throws IOException;
|
||||||
|
|
||||||
Stream<RemoteMod.Version> getRemoteVersionsById(String id) throws IOException;
|
Stream<RemoteMod.Version> getRemoteVersionsById(String id) throws IOException;
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import org.jackhuang.hmcl.util.io.NetworkUtils;
|
|||||||
import org.jackhuang.hmcl.util.io.ResponseCodeException;
|
import org.jackhuang.hmcl.util.io.ResponseCodeException;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.NoSuchFileException;
|
import java.nio.file.NoSuchFileException;
|
||||||
import java.nio.file.Path;
|
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
|
@Override
|
||||||
public RemoteMod.File getModFile(String modId, String fileId) throws IOException {
|
public RemoteMod.File getModFile(String modId, String fileId) throws IOException {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
|
|||||||
Reference in New Issue
Block a user