修复启动游戏补全文件时,任务没有正确归类的问题 (#5430)

Co-authored-by: Glavo <zjx001202@gmail.com>
This commit is contained in:
CiiLu
2026-02-17 23:04:22 +08:00
committed by GitHub
parent 5e5d777dae
commit d2a9024fc8
8 changed files with 76 additions and 49 deletions

View File

@@ -249,11 +249,11 @@ public final class LauncherHelper {
i18n("message.doing"), i18n("message.doing"),
() -> launchingLatch.getCount() == 0, 6.95 () -> launchingLatch.getCount() == 0, 6.95
).withStage("launch.state.waiting_launching")) ).withStage("launch.state.waiting_launching"))
.withStagesHint(Lang.immutableListOf( .withStagesHints(
"launch.state.java", new Task.StagesHint("launch.state.java"),
"launch.state.dependencies", new Task.StagesHint("launch.state.dependencies", List.of("hmcl.install.assets", "hmcl.install.libraries", "hmcl.modpack.download")),
"launch.state.logging_in", new Task.StagesHint("launch.state.logging_in"),
"launch.state.waiting_launching")) new Task.StagesHint("launch.state.waiting_launching"))
.executor(); .executor();
launchingStepsPane.setExecutor(executor, false); launchingStepsPane.setExecutor(executor, false);
executor.addTaskListener(new TaskListener() { executor.addTaskListener(new TaskListener() {

View File

@@ -167,7 +167,7 @@ public final class ModpackHelper {
return new ServerModpackRemoteInstallTask(profile.getDependency(), manifest, name) return new ServerModpackRemoteInstallTask(profile.getDependency(), manifest, name)
.whenComplete(Schedulers.defaultScheduler(), success, failure) .whenComplete(Schedulers.defaultScheduler(), success, failure)
.withStagesHint(Arrays.asList("hmcl.modpack", "hmcl.modpack.download")); .withStagesHints("hmcl.modpack", "hmcl.modpack.download");
} }
public static boolean isExternalGameNameConflicts(String name) { public static boolean isExternalGameNameConflicts(String name) {
@@ -211,16 +211,16 @@ public final class ModpackHelper {
return modpack.getInstallTask(profile.getDependency(), zipFile, name, iconUrl) return modpack.getInstallTask(profile.getDependency(), zipFile, name, iconUrl)
.whenComplete(Schedulers.defaultScheduler(), success, failure) .whenComplete(Schedulers.defaultScheduler(), success, failure)
.thenComposeAsync(createMultiMCPostInstallTask(profile, (MultiMCInstanceConfiguration) modpack.getManifest(), name)) .thenComposeAsync(createMultiMCPostInstallTask(profile, (MultiMCInstanceConfiguration) modpack.getManifest(), name))
.withStagesHint(List.of("hmcl.modpack", "hmcl.modpack.download")); .withStagesHints("hmcl.modpack", "hmcl.modpack.download");
else if (modpack.getManifest() instanceof McbbsModpackManifest) else if (modpack.getManifest() instanceof McbbsModpackManifest)
return modpack.getInstallTask(profile.getDependency(), zipFile, name, iconUrl) return modpack.getInstallTask(profile.getDependency(), zipFile, name, iconUrl)
.whenComplete(Schedulers.defaultScheduler(), success, failure) .whenComplete(Schedulers.defaultScheduler(), success, failure)
.thenComposeAsync(createMcbbsPostInstallTask(profile, (McbbsModpackManifest) modpack.getManifest(), name)) .thenComposeAsync(createMcbbsPostInstallTask(profile, (McbbsModpackManifest) modpack.getManifest(), name))
.withStagesHint(List.of("hmcl.modpack", "hmcl.modpack.download")); .withStagesHints("hmcl.modpack", "hmcl.modpack.download");
else else
return modpack.getInstallTask(profile.getDependency(), zipFile, name, iconUrl) return modpack.getInstallTask(profile.getDependency(), zipFile, name, iconUrl)
.whenComplete(Schedulers.javafx(), success, failure) .whenComplete(Schedulers.javafx(), success, failure)
.withStagesHint(List.of("hmcl.modpack", "hmcl.modpack.download")); .withStagesHints("hmcl.modpack", "hmcl.modpack.download");
} }
public static Task<Void> getUpdateTask(Profile profile, ServerModpackManifest manifest, Charset charset, String name, ModpackConfiguration<?> configuration) throws UnsupportedModpackException { public static Task<Void> getUpdateTask(Profile profile, ServerModpackManifest manifest, Charset charset, String name, ModpackConfiguration<?> configuration) throws UnsupportedModpackException {
@@ -228,7 +228,7 @@ public final class ModpackHelper {
case ServerModpackRemoteInstallTask.MODPACK_TYPE: case ServerModpackRemoteInstallTask.MODPACK_TYPE:
return new ModpackUpdateTask(profile.getRepository(), name, new ServerModpackRemoteInstallTask(profile.getDependency(), manifest, name)) return new ModpackUpdateTask(profile.getRepository(), name, new ServerModpackRemoteInstallTask(profile.getDependency(), manifest, name))
.thenComposeAsync(profile.getRepository().refreshVersionsAsync()) .thenComposeAsync(profile.getRepository().refreshVersionsAsync())
.withStagesHint(Arrays.asList("hmcl.modpack", "hmcl.modpack.download")); .withStagesHints("hmcl.modpack", "hmcl.modpack.download");
default: default:
throw new UnsupportedModpackException(); throw new UnsupportedModpackException();
} }

View File

@@ -106,13 +106,18 @@ public final class TaskListPane extends StackPane {
} }
@FXThread @FXThread
private void addStages(@NotNull Collection<String> stages) { private void addStagesHints(@NotNull Collection<Task.StagesHint> hints) {
for (String stage : stages) { for (Task.StagesHint hint : hints) {
stageNodes.computeIfAbsent(stage, s -> { StageNode node = stageNodes.get(hint.stage());
StageNode node = new StageNode(stage);
if (node == null) {
node = new StageNode(hint.stage());
stageNodes.put(hint.stage(), node);
listView.getItems().add(node); listView.getItems().add(node);
return node; }
}); for (String stage : hint.aliases()) {
stageNodes.put(stage, node);
}
} }
} }
@@ -129,7 +134,7 @@ public final class TaskListPane extends StackPane {
Platform.runLater(() -> { Platform.runLater(() -> {
stageNodes.clear(); stageNodes.clear();
listView.getItems().clear(); listView.getItems().clear();
addStages(executor.getStages()); addStagesHints(executor.getHints());
updateProgressNodePadding(); updateProgressNodePadding();
}); });
} }
@@ -138,7 +143,7 @@ public final class TaskListPane extends StackPane {
public void onReady(Task<?> task) { public void onReady(Task<?> task) {
if (task instanceof Task.StagesHintTask) { if (task instanceof Task.StagesHintTask) {
Platform.runLater(() -> { Platform.runLater(() -> {
addStages(((Task<?>.StagesHintTask) task).getStages()); addStagesHints(((Task<?>.StagesHintTask) task).getHints());
updateProgressNodePadding(); updateProgressNodePadding();
}); });
} }
@@ -394,6 +399,8 @@ public final class TaskListPane extends StackPane {
} }
private static final class StageNode extends Node { private static final class StageNode extends Node {
private int runningTasksCount = 0;
private enum Status { private enum Status {
WAITING(SVG.MORE_HORIZ), WAITING(SVG.MORE_HORIZ),
RUNNING(SVG.ARROW_FORWARD), RUNNING(SVG.ARROW_FORWARD),
@@ -454,17 +461,23 @@ public final class TaskListPane extends StackPane {
} }
private void begin() { private void begin() {
if (status.get() == Status.WAITING) { runningTasksCount++;
if (status.get() == Status.WAITING || status.get() == Status.SUCCESS) {
status.set(Status.RUNNING); status.set(Status.RUNNING);
} }
} }
public void fail() { public void succeed() {
status.set(Status.FAILED); runningTasksCount = Math.max(0, runningTasksCount - 1);
if (runningTasksCount == 0) {
status.set(Status.SUCCESS);
}
} }
public void succeed() { public void fail() {
status.set(Status.SUCCESS); runningTasksCount = Math.max(0, runningTasksCount - 1);
status.set(Status.FAILED);
} }
public void count() { public void count() {

View File

@@ -40,7 +40,6 @@ import org.jetbrains.annotations.Nullable;
import java.net.SocketTimeoutException; import java.net.SocketTimeoutException;
import java.net.URI; import java.net.URI;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CancellationException; import java.util.concurrent.CancellationException;
import java.util.zip.ZipException; import java.util.zip.ZipException;
@@ -78,21 +77,21 @@ public final class UpdateInstallerWizardProvider implements WizardProvider {
// We remove library but not save it, // We remove library but not save it,
// so if installation failed will not break down current version. // so if installation failed will not break down current version.
Task<Version> ret = Task.supplyAsync(() -> version); Task<Version> ret = Task.supplyAsync(() -> version);
List<String> stages = new ArrayList<>(); var hints = new ArrayList<Task.StagesHint>();
for (Object value : settings.asStringMap().values()) { for (Object value : settings.asStringMap().values()) {
if (value instanceof RemoteVersion remoteVersion) { if (value instanceof RemoteVersion remoteVersion) {
ret = ret.thenComposeAsync(version -> dependencyManager.installLibraryAsync(version, remoteVersion)); ret = ret.thenComposeAsync(version -> dependencyManager.installLibraryAsync(version, remoteVersion));
stages.add(String.format("hmcl.install.%s:%s", remoteVersion.getLibraryId(), remoteVersion.getSelfVersion())); hints.add(new Task.StagesHint(String.format("hmcl.install.%s:%s", remoteVersion.getLibraryId(), remoteVersion.getSelfVersion())));
if ("game".equals(remoteVersion.getLibraryId())) { if ("game".equals(remoteVersion.getLibraryId())) {
stages.add("hmcl.install.libraries"); hints.add(new Task.StagesHint("hmcl.install.libraries"));
stages.add("hmcl.install.assets"); hints.add(new Task.StagesHint("hmcl.install.assets"));
} }
} else if (value instanceof RemoveVersionAction removeVersionAction) { } else if (value instanceof RemoveVersionAction removeVersionAction) {
ret = ret.thenComposeAsync(version -> dependencyManager.removeLibraryAsync(version, removeVersionAction.libraryId)); ret = ret.thenComposeAsync(version -> dependencyManager.removeLibraryAsync(version, removeVersionAction.libraryId));
} }
} }
return ret.thenComposeAsync(profile.getRepository()::saveAsync).thenComposeAsync(profile.getRepository().refreshVersionsAsync()).withStagesHint(stages); return ret.thenComposeAsync(profile.getRepository()::saveAsync).thenComposeAsync(profile.getRepository().refreshVersionsAsync()).withStagesHints(hints);
} }
@Override @Override

View File

@@ -252,7 +252,7 @@ public final class ModListPage extends ListPageBase<ModListPageSkin.ModInfoObjec
Controllers.navigateForward(new ModUpdatesPage(modManager, result)); Controllers.navigateForward(new ModUpdatesPage(modManager, result));
} }
}) })
.withStagesHint(Collections.singletonList("update.checking")), .withStagesHints("update.checking"),
i18n("mods.check_updates"), TaskCancellationAction.NORMAL); i18n("mods.check_updates"), TaskCancellationAction.NORMAL);
if (profile.getRepository().isModpack(instanceId)) { if (profile.getRepository().isModpack(instanceId)) {

View File

@@ -22,7 +22,6 @@ import org.jackhuang.hmcl.task.Task;
import org.jackhuang.hmcl.util.function.ExceptionalFunction; import org.jackhuang.hmcl.util.function.ExceptionalFunction;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List;
import java.util.Map; import java.util.Map;
/** /**
@@ -43,28 +42,28 @@ public class DefaultGameBuilder extends GameBuilder {
@Override @Override
public Task<?> buildAsync() { public Task<?> buildAsync() {
List<String> stages = new ArrayList<>(); var hints = new ArrayList<Task.StagesHint>();
Task<Version> libraryTask = Task.supplyAsync(() -> new Version(name)); Task<Version> libraryTask = Task.supplyAsync(() -> new Version(name));
libraryTask = libraryTask.thenComposeAsync(libraryTaskHelper(gameVersion, "game", gameVersion)); libraryTask = libraryTask.thenComposeAsync(libraryTaskHelper(gameVersion, "game", gameVersion));
stages.add("hmcl.install.game:" + gameVersion); hints.add(new Task.StagesHint("hmcl.install.game:" + gameVersion));
stages.add("hmcl.install.libraries"); hints.add(new Task.StagesHint("hmcl.install.libraries"));
stages.add("hmcl.install.assets"); hints.add(new Task.StagesHint("hmcl.install.assets"));
for (Map.Entry<String, String> entry : toolVersions.entrySet()) { for (Map.Entry<String, String> entry : toolVersions.entrySet()) {
libraryTask = libraryTask.thenComposeAsync(libraryTaskHelper(gameVersion, entry.getKey(), entry.getValue())); libraryTask = libraryTask.thenComposeAsync(libraryTaskHelper(gameVersion, entry.getKey(), entry.getValue()));
stages.add(String.format("hmcl.install.%s:%s", entry.getKey(), entry.getValue())); hints.add(new Task.StagesHint(String.format("hmcl.install.%s:%s", entry.getKey(), entry.getValue())));
} }
for (RemoteVersion remoteVersion : remoteVersions) { for (RemoteVersion remoteVersion : remoteVersions) {
libraryTask = libraryTask.thenComposeAsync(version -> dependencyManager.installLibraryAsync(version, remoteVersion)); libraryTask = libraryTask.thenComposeAsync(version -> dependencyManager.installLibraryAsync(version, remoteVersion));
stages.add(String.format("hmcl.install.%s:%s", remoteVersion.getLibraryId(), remoteVersion.getSelfVersion())); hints.add(new Task.StagesHint(String.format("hmcl.install.%s:%s", remoteVersion.getLibraryId(), remoteVersion.getSelfVersion())));
} }
return libraryTask.thenComposeAsync(dependencyManager.getGameRepository()::saveAsync).whenComplete(exception -> { return libraryTask.thenComposeAsync(dependencyManager.getGameRepository()::saveAsync).whenComplete(exception -> {
if (exception != null) if (exception != null)
dependencyManager.getGameRepository().removeVersionFromDisk(name); dependencyManager.getGameRepository().removeVersionFromDisk(name);
}).withStagesHint(stages); }).withStagesHints(hints);
} }
private ExceptionalFunction<Version, Task<Version>, ?> libraryTaskHelper(String gameVersion, String libraryId, String libraryVersion) { private ExceptionalFunction<Version, Task<Version>, ?> libraryTaskHelper(String gameVersion, String libraryId, String libraryVersion) {

View File

@@ -871,15 +871,29 @@ public abstract class Task<T> {
return new FakeProgressTask(done, k).setExecutor(Schedulers.defaultScheduler()).setName(name).setSignificance(TaskSignificance.MAJOR); return new FakeProgressTask(done, k).setExecutor(Schedulers.defaultScheduler()).setName(name).setSignificance(TaskSignificance.MAJOR);
} }
public Task<T> withStagesHint(List<String> stages) { public record StagesHint(String stage, List<String> aliases) {
return new StagesHintTask(stages); public StagesHint(String stage) {
this(stage, List.of());
}
}
public Task<T> withStagesHints(String... hints) {
return withStagesHints(Arrays.stream(hints).map(StagesHint::new).toList());
}
public Task<T> withStagesHints(StagesHint... hints) {
return new StagesHintTask(List.of(hints));
}
public Task<T> withStagesHints(List<StagesHint> hints) {
return new StagesHintTask(hints);
} }
public class StagesHintTask extends Task<T> { public class StagesHintTask extends Task<T> {
private final List<String> stages; private final List<StagesHint> hints;
public StagesHintTask(List<String> stages) { public StagesHintTask(List<StagesHint> hints) {
this.stages = stages; this.hints = hints;
} }
@Override @Override
@@ -892,8 +906,8 @@ public abstract class Task<T> {
setResult(Task.this.getResult()); setResult(Task.this.getResult());
} }
public List<String> getStages() { public List<StagesHint> getHints() {
return stages; return hints;
} }
} }

View File

@@ -26,11 +26,13 @@ public abstract class TaskExecutor {
protected final List<TaskListener> taskListeners = new ArrayList<>(0); protected final List<TaskListener> taskListeners = new ArrayList<>(0);
protected volatile boolean cancelled = false; protected volatile boolean cancelled = false;
protected Exception exception; protected Exception exception;
private final List<String> stages; private final List<Task.StagesHint> hints;
public TaskExecutor(Task<?> task) { public TaskExecutor(Task<?> task) {
this.firstTask = task; this.firstTask = task;
this.stages = task instanceof Task<?>.StagesHintTask hintTask ? hintTask.getStages() : Collections.emptyList(); this.hints = task instanceof Task<?>.StagesHintTask hintTask
? hintTask.getHints()
: List.of();
} }
public void addTaskListener(TaskListener taskListener) { public void addTaskListener(TaskListener taskListener) {
@@ -59,7 +61,7 @@ public abstract class TaskExecutor {
return cancelled; return cancelled;
} }
public List<String> getStages() { public List<Task.StagesHint> getHints() {
return stages; return hints;
} }
} }