From d2a9024fc88e96dce8fd4c3bbb4aa254134a47eb Mon Sep 17 00:00:00 2001 From: CiiLu <109708109+CiiLu@users.noreply.github.com> Date: Tue, 17 Feb 2026 23:04:22 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=90=AF=E5=8A=A8=E6=B8=B8?= =?UTF-8?q?=E6=88=8F=E8=A1=A5=E5=85=A8=E6=96=87=E4=BB=B6=E6=97=B6=EF=BC=8C?= =?UTF-8?q?=E4=BB=BB=E5=8A=A1=E6=B2=A1=E6=9C=89=E6=AD=A3=E7=A1=AE=E5=BD=92?= =?UTF-8?q?=E7=B1=BB=E7=9A=84=E9=97=AE=E9=A2=98=20(#5430)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Glavo --- .../jackhuang/hmcl/game/LauncherHelper.java | 10 ++--- .../jackhuang/hmcl/game/ModpackHelper.java | 10 ++--- .../hmcl/ui/construct/TaskListPane.java | 39 ++++++++++++------- .../UpdateInstallerWizardProvider.java | 11 +++--- .../hmcl/ui/versions/ModListPage.java | 2 +- .../hmcl/download/DefaultGameBuilder.java | 15 ++++--- .../java/org/jackhuang/hmcl/task/Task.java | 28 +++++++++---- .../org/jackhuang/hmcl/task/TaskExecutor.java | 10 +++-- 8 files changed, 76 insertions(+), 49 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java index 62f435842..3e38774b2 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java @@ -249,11 +249,11 @@ public final class LauncherHelper { i18n("message.doing"), () -> launchingLatch.getCount() == 0, 6.95 ).withStage("launch.state.waiting_launching")) - .withStagesHint(Lang.immutableListOf( - "launch.state.java", - "launch.state.dependencies", - "launch.state.logging_in", - "launch.state.waiting_launching")) + .withStagesHints( + new Task.StagesHint("launch.state.java"), + new Task.StagesHint("launch.state.dependencies", List.of("hmcl.install.assets", "hmcl.install.libraries", "hmcl.modpack.download")), + new Task.StagesHint("launch.state.logging_in"), + new Task.StagesHint("launch.state.waiting_launching")) .executor(); launchingStepsPane.setExecutor(executor, false); executor.addTaskListener(new TaskListener() { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/ModpackHelper.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/ModpackHelper.java index 9acd849d5..9e7f4cfe7 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/ModpackHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/ModpackHelper.java @@ -167,7 +167,7 @@ public final class ModpackHelper { return new ServerModpackRemoteInstallTask(profile.getDependency(), manifest, name) .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) { @@ -211,16 +211,16 @@ public final class ModpackHelper { return modpack.getInstallTask(profile.getDependency(), zipFile, name, iconUrl) .whenComplete(Schedulers.defaultScheduler(), success, failure) .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) return modpack.getInstallTask(profile.getDependency(), zipFile, name, iconUrl) .whenComplete(Schedulers.defaultScheduler(), success, failure) .thenComposeAsync(createMcbbsPostInstallTask(profile, (McbbsModpackManifest) modpack.getManifest(), name)) - .withStagesHint(List.of("hmcl.modpack", "hmcl.modpack.download")); + .withStagesHints("hmcl.modpack", "hmcl.modpack.download"); else return modpack.getInstallTask(profile.getDependency(), zipFile, name, iconUrl) .whenComplete(Schedulers.javafx(), success, failure) - .withStagesHint(List.of("hmcl.modpack", "hmcl.modpack.download")); + .withStagesHints("hmcl.modpack", "hmcl.modpack.download"); } public static Task 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: return new ModpackUpdateTask(profile.getRepository(), name, new ServerModpackRemoteInstallTask(profile.getDependency(), manifest, name)) .thenComposeAsync(profile.getRepository().refreshVersionsAsync()) - .withStagesHint(Arrays.asList("hmcl.modpack", "hmcl.modpack.download")); + .withStagesHints("hmcl.modpack", "hmcl.modpack.download"); default: throw new UnsupportedModpackException(); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskListPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskListPane.java index 0f5fd1be4..f5f7e52e1 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskListPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskListPane.java @@ -106,13 +106,18 @@ public final class TaskListPane extends StackPane { } @FXThread - private void addStages(@NotNull Collection stages) { - for (String stage : stages) { - stageNodes.computeIfAbsent(stage, s -> { - StageNode node = new StageNode(stage); + private void addStagesHints(@NotNull Collection hints) { + for (Task.StagesHint hint : hints) { + StageNode node = stageNodes.get(hint.stage()); + + if (node == null) { + node = new StageNode(hint.stage()); + stageNodes.put(hint.stage(), 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(() -> { stageNodes.clear(); listView.getItems().clear(); - addStages(executor.getStages()); + addStagesHints(executor.getHints()); updateProgressNodePadding(); }); } @@ -138,7 +143,7 @@ public final class TaskListPane extends StackPane { public void onReady(Task task) { if (task instanceof Task.StagesHintTask) { Platform.runLater(() -> { - addStages(((Task.StagesHintTask) task).getStages()); + addStagesHints(((Task.StagesHintTask) task).getHints()); updateProgressNodePadding(); }); } @@ -394,6 +399,8 @@ public final class TaskListPane extends StackPane { } private static final class StageNode extends Node { + private int runningTasksCount = 0; + private enum Status { WAITING(SVG.MORE_HORIZ), RUNNING(SVG.ARROW_FORWARD), @@ -454,17 +461,23 @@ public final class TaskListPane extends StackPane { } private void begin() { - if (status.get() == Status.WAITING) { + runningTasksCount++; + if (status.get() == Status.WAITING || status.get() == Status.SUCCESS) { status.set(Status.RUNNING); } } - public void fail() { - status.set(Status.FAILED); + public void succeed() { + runningTasksCount = Math.max(0, runningTasksCount - 1); + + if (runningTasksCount == 0) { + status.set(Status.SUCCESS); + } } - public void succeed() { - status.set(Status.SUCCESS); + public void fail() { + runningTasksCount = Math.max(0, runningTasksCount - 1); + status.set(Status.FAILED); } public void count() { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/UpdateInstallerWizardProvider.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/UpdateInstallerWizardProvider.java index 0b4f8dbf7..578cb2434 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/UpdateInstallerWizardProvider.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/UpdateInstallerWizardProvider.java @@ -40,7 +40,6 @@ import org.jetbrains.annotations.Nullable; import java.net.SocketTimeoutException; import java.net.URI; import java.util.ArrayList; -import java.util.List; import java.util.concurrent.CancellationException; import java.util.zip.ZipException; @@ -78,21 +77,21 @@ public final class UpdateInstallerWizardProvider implements WizardProvider { // We remove library but not save it, // so if installation failed will not break down current version. Task ret = Task.supplyAsync(() -> version); - List stages = new ArrayList<>(); + var hints = new ArrayList(); for (Object value : settings.asStringMap().values()) { if (value instanceof RemoteVersion 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())) { - stages.add("hmcl.install.libraries"); - stages.add("hmcl.install.assets"); + hints.add(new Task.StagesHint("hmcl.install.libraries")); + hints.add(new Task.StagesHint("hmcl.install.assets")); } } else if (value instanceof RemoveVersionAction removeVersionAction) { 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 diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java index c681a8e23..998e3b526 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java @@ -252,7 +252,7 @@ public final class ModListPage extends ListPageBase buildAsync() { - List stages = new ArrayList<>(); + var hints = new ArrayList(); Task libraryTask = Task.supplyAsync(() -> new Version(name)); libraryTask = libraryTask.thenComposeAsync(libraryTaskHelper(gameVersion, "game", gameVersion)); - stages.add("hmcl.install.game:" + gameVersion); - stages.add("hmcl.install.libraries"); - stages.add("hmcl.install.assets"); + hints.add(new Task.StagesHint("hmcl.install.game:" + gameVersion)); + hints.add(new Task.StagesHint("hmcl.install.libraries")); + hints.add(new Task.StagesHint("hmcl.install.assets")); for (Map.Entry entry : toolVersions.entrySet()) { 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) { 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 -> { if (exception != null) dependencyManager.getGameRepository().removeVersionFromDisk(name); - }).withStagesHint(stages); + }).withStagesHints(hints); } private ExceptionalFunction, ?> libraryTaskHelper(String gameVersion, String libraryId, String libraryVersion) { 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 e2eb9a788..7ccd79581 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java @@ -871,15 +871,29 @@ public abstract class Task { return new FakeProgressTask(done, k).setExecutor(Schedulers.defaultScheduler()).setName(name).setSignificance(TaskSignificance.MAJOR); } - public Task withStagesHint(List stages) { - return new StagesHintTask(stages); + public record StagesHint(String stage, List aliases) { + public StagesHint(String stage) { + this(stage, List.of()); + } + } + + public Task withStagesHints(String... hints) { + return withStagesHints(Arrays.stream(hints).map(StagesHint::new).toList()); + } + + public Task withStagesHints(StagesHint... hints) { + return new StagesHintTask(List.of(hints)); + } + + public Task withStagesHints(List hints) { + return new StagesHintTask(hints); } public class StagesHintTask extends Task { - private final List stages; + private final List hints; - public StagesHintTask(List stages) { - this.stages = stages; + public StagesHintTask(List hints) { + this.hints = hints; } @Override @@ -892,8 +906,8 @@ public abstract class Task { setResult(Task.this.getResult()); } - public List getStages() { - return stages; + public List getHints() { + return hints; } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskExecutor.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskExecutor.java index 0655c342d..5fcdf4011 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskExecutor.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskExecutor.java @@ -26,11 +26,13 @@ public abstract class TaskExecutor { protected final List taskListeners = new ArrayList<>(0); protected volatile boolean cancelled = false; protected Exception exception; - private final List stages; + private final List hints; public TaskExecutor(Task 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) { @@ -59,7 +61,7 @@ public abstract class TaskExecutor { return cancelled; } - public List getStages() { - return stages; + public List getHints() { + return hints; } }