add: show stages of game installation
This commit is contained in:
@@ -49,6 +49,7 @@ import org.jackhuang.hmcl.ui.construct.MessageDialogPane.MessageType;
|
|||||||
import org.jackhuang.hmcl.ui.construct.TaskExecutorDialogPane;
|
import org.jackhuang.hmcl.ui.construct.TaskExecutorDialogPane;
|
||||||
import org.jackhuang.hmcl.util.*;
|
import org.jackhuang.hmcl.util.*;
|
||||||
import org.jackhuang.hmcl.util.gson.UUIDTypeAdapter;
|
import org.jackhuang.hmcl.util.gson.UUIDTypeAdapter;
|
||||||
|
import org.jackhuang.hmcl.util.i18n.LocalizedTaskStages;
|
||||||
import org.jackhuang.hmcl.util.io.ResponseCodeException;
|
import org.jackhuang.hmcl.util.io.ResponseCodeException;
|
||||||
import org.jackhuang.hmcl.util.platform.CommandBuilder;
|
import org.jackhuang.hmcl.util.platform.CommandBuilder;
|
||||||
import org.jackhuang.hmcl.util.platform.JavaVersion;
|
import org.jackhuang.hmcl.util.platform.JavaVersion;
|
||||||
@@ -199,12 +200,12 @@ public final class LauncherHelper {
|
|||||||
launchingLatch.await();
|
launchingLatch.await();
|
||||||
}).withStage("launch.state.waiting_launching"))
|
}).withStage("launch.state.waiting_launching"))
|
||||||
.cancellableExecutor();
|
.cancellableExecutor();
|
||||||
|
executor.setStages(new LocalizedTaskStages(Lang.immutableListOf(
|
||||||
launchingStepsPane.setExecutor(executor, Lang.immutableListOf(
|
|
||||||
"launch.state.dependencies",
|
"launch.state.dependencies",
|
||||||
"launch.state.modpack",
|
"launch.state.modpack",
|
||||||
"launch.state.logging_in",
|
"launch.state.logging_in",
|
||||||
"launch.state.waiting_launching"), false);
|
"launch.state.waiting_launching")));
|
||||||
|
launchingStepsPane.setExecutor(executor, false);
|
||||||
executor.addTaskListener(new TaskListener() {
|
executor.addTaskListener(new TaskListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -85,18 +85,10 @@ public class TaskExecutorDialogPane extends StackPane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setExecutor(TaskExecutor executor, boolean autoClose) {
|
public void setExecutor(TaskExecutor executor, boolean autoClose) {
|
||||||
setExecutor(executor, Collections.emptyList(), autoClose);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setExecutor(TaskExecutor executor, List<String> stages) {
|
|
||||||
setExecutor(executor, stages, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setExecutor(TaskExecutor executor, List<String> stages, boolean autoClose) {
|
|
||||||
this.executor = executor;
|
this.executor = executor;
|
||||||
|
|
||||||
if (executor != null) {
|
if (executor != null) {
|
||||||
taskListPane.setExecutor(executor, stages);
|
taskListPane.setExecutor(executor);
|
||||||
|
|
||||||
if (autoClose)
|
if (autoClose)
|
||||||
executor.addTaskListener(new TaskListener() {
|
executor.addTaskListener(new TaskListener() {
|
||||||
|
|||||||
@@ -19,13 +19,16 @@ package org.jackhuang.hmcl.ui.construct;
|
|||||||
|
|
||||||
import com.jfoenix.controls.JFXProgressBar;
|
import com.jfoenix.controls.JFXProgressBar;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.beans.property.ReadOnlyIntegerProperty;
|
import javafx.beans.binding.Bindings;
|
||||||
import javafx.beans.property.ReadOnlyIntegerWrapper;
|
import javafx.beans.binding.DoubleBinding;
|
||||||
|
import javafx.beans.property.ObjectProperty;
|
||||||
|
import javafx.beans.property.SimpleObjectProperty;
|
||||||
import javafx.geometry.Insets;
|
import javafx.geometry.Insets;
|
||||||
import javafx.geometry.Pos;
|
import javafx.geometry.Pos;
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.Label;
|
||||||
import javafx.scene.layout.BorderPane;
|
import javafx.scene.layout.BorderPane;
|
||||||
import javafx.scene.layout.StackPane;
|
import javafx.scene.layout.StackPane;
|
||||||
|
import org.jackhuang.hmcl.download.fabric.FabricInstallTask;
|
||||||
import org.jackhuang.hmcl.download.forge.ForgeInstallTask;
|
import org.jackhuang.hmcl.download.forge.ForgeInstallTask;
|
||||||
import org.jackhuang.hmcl.download.game.GameAssetDownloadTask;
|
import org.jackhuang.hmcl.download.game.GameAssetDownloadTask;
|
||||||
import org.jackhuang.hmcl.download.game.GameInstallTask;
|
import org.jackhuang.hmcl.download.game.GameInstallTask;
|
||||||
@@ -43,6 +46,7 @@ import org.jackhuang.hmcl.setting.Theme;
|
|||||||
import org.jackhuang.hmcl.task.Task;
|
import org.jackhuang.hmcl.task.Task;
|
||||||
import org.jackhuang.hmcl.task.TaskExecutor;
|
import org.jackhuang.hmcl.task.TaskExecutor;
|
||||||
import org.jackhuang.hmcl.task.TaskListener;
|
import org.jackhuang.hmcl.task.TaskListener;
|
||||||
|
import org.jackhuang.hmcl.task.TaskStages;
|
||||||
import org.jackhuang.hmcl.ui.FXUtils;
|
import org.jackhuang.hmcl.ui.FXUtils;
|
||||||
import org.jackhuang.hmcl.ui.SVG;
|
import org.jackhuang.hmcl.ui.SVG;
|
||||||
|
|
||||||
@@ -52,9 +56,11 @@ import java.util.stream.Collectors;
|
|||||||
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||||
|
|
||||||
public final class TaskListPane extends StackPane {
|
public final class TaskListPane extends StackPane {
|
||||||
|
private TaskExecutor executor;
|
||||||
private final AdvancedListBox listBox = new AdvancedListBox();
|
private final AdvancedListBox listBox = new AdvancedListBox();
|
||||||
private final Map<Task<?>, ProgressListNode> nodes = new HashMap<>();
|
private final Map<Task<?>, ProgressListNode> nodes = new HashMap<>();
|
||||||
private final List<StageNode> stageNodes = new ArrayList<>();
|
private final List<StageNode> stageNodes = new ArrayList<>();
|
||||||
|
private final ObjectProperty<Insets> progressNodePadding = new SimpleObjectProperty<>(Insets.EMPTY);
|
||||||
|
|
||||||
public TaskListPane() {
|
public TaskListPane() {
|
||||||
listBox.setSpacing(0);
|
listBox.setSpacing(0);
|
||||||
@@ -63,19 +69,19 @@ public final class TaskListPane extends StackPane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setExecutor(TaskExecutor executor) {
|
public void setExecutor(TaskExecutor executor) {
|
||||||
setExecutor(executor, Collections.emptyList());
|
TaskStages stages = executor.getStages();
|
||||||
}
|
this.executor = executor;
|
||||||
|
|
||||||
public void setExecutor(TaskExecutor executor, List<String> stages) {
|
|
||||||
|
|
||||||
executor.addTaskListener(new TaskListener() {
|
executor.addTaskListener(new TaskListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onStart() {
|
public void onStart() {
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
stageNodes.clear();
|
stageNodes.clear();
|
||||||
listBox.clear();
|
listBox.clear();
|
||||||
stageNodes.addAll(stages.stream().map(StageNode::new).collect(Collectors.toList()));
|
stageNodes.addAll(stages.getStages().stream().map(StageNode::new).collect(Collectors.toList()));
|
||||||
stageNodes.forEach(listBox::add);
|
stageNodes.forEach(listBox::add);
|
||||||
|
|
||||||
|
if (stages.getStages().isEmpty()) progressNodePadding.setValue(new Insets(0, 0, 8, 0));
|
||||||
|
else progressNodePadding.setValue(new Insets(0, 0, 8, 26));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,6 +109,8 @@ public final class TaskListPane extends StackPane {
|
|||||||
task.setName(i18n("install.installer.install", i18n("install.installer.liteloader")));
|
task.setName(i18n("install.installer.install", i18n("install.installer.liteloader")));
|
||||||
} else if (task instanceof OptiFineInstallTask) {
|
} else if (task instanceof OptiFineInstallTask) {
|
||||||
task.setName(i18n("install.installer.install", i18n("install.installer.optifine")));
|
task.setName(i18n("install.installer.install", i18n("install.installer.optifine")));
|
||||||
|
} else if (task instanceof FabricInstallTask) {
|
||||||
|
task.setName(i18n("install.installer.install", i18n("install.installer.fabric")));
|
||||||
} else if (task instanceof CurseCompletionTask) {
|
} else if (task instanceof CurseCompletionTask) {
|
||||||
task.setName(i18n("modpack.type.curse.completion"));
|
task.setName(i18n("modpack.type.curse.completion"));
|
||||||
} else if (task instanceof ModpackInstallTask) {
|
} else if (task instanceof ModpackInstallTask) {
|
||||||
@@ -163,7 +171,7 @@ public final class TaskListPane extends StackPane {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class StageNode extends BorderPane {
|
private class StageNode extends BorderPane {
|
||||||
private final String stage;
|
private final String stage;
|
||||||
private final Label title = new Label();
|
private final Label title = new Label();
|
||||||
private boolean started = false;
|
private boolean started = false;
|
||||||
@@ -171,12 +179,12 @@ public final class TaskListPane extends StackPane {
|
|||||||
public StageNode(String stage) {
|
public StageNode(String stage) {
|
||||||
this.stage = stage;
|
this.stage = stage;
|
||||||
|
|
||||||
title.setText(i18n(stage));
|
title.setText(executor.getStages().localize(stage));
|
||||||
BorderPane.setAlignment(title, Pos.CENTER_LEFT);
|
BorderPane.setAlignment(title, Pos.CENTER_LEFT);
|
||||||
BorderPane.setMargin(title, new Insets(0, 0, 0, 8));
|
BorderPane.setMargin(title, new Insets(0, 0, 0, 8));
|
||||||
setPadding(new Insets(0, 0, 8, 4));
|
setPadding(new Insets(0, 0, 8, 4));
|
||||||
setCenter(title);
|
setCenter(title);
|
||||||
setLeft(SVG.dotsHorizontal(Theme.blackFillBinding(), 14, 14));
|
setLeft(FXUtils.limitingSize(SVG.dotsHorizontal(Theme.blackFillBinding(), 14, 14), 14, 14));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void begin() {
|
public void begin() {
|
||||||
@@ -194,10 +202,13 @@ public final class TaskListPane extends StackPane {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class ProgressListNode extends BorderPane {
|
private class ProgressListNode extends BorderPane {
|
||||||
private final JFXProgressBar bar = new JFXProgressBar();
|
private final JFXProgressBar bar = new JFXProgressBar();
|
||||||
private final Label title = new Label();
|
private final Label title = new Label();
|
||||||
private final Label state = new Label();
|
private final Label state = new Label();
|
||||||
|
private final DoubleBinding binding = Bindings.createDoubleBinding(() ->
|
||||||
|
getWidth() - getPadding().getLeft() - getPadding().getRight(),
|
||||||
|
paddingProperty(), widthProperty());
|
||||||
|
|
||||||
public ProgressListNode(Task<?> task) {
|
public ProgressListNode(Task<?> task) {
|
||||||
bar.progressProperty().bind(task.progressProperty());
|
bar.progressProperty().bind(task.progressProperty());
|
||||||
@@ -208,9 +219,11 @@ public final class TaskListPane extends StackPane {
|
|||||||
setRight(state);
|
setRight(state);
|
||||||
setBottom(bar);
|
setBottom(bar);
|
||||||
|
|
||||||
bar.minWidthProperty().bind(widthProperty());
|
bar.minWidthProperty().bind(binding);
|
||||||
bar.prefWidthProperty().bind(widthProperty());
|
bar.prefWidthProperty().bind(binding);
|
||||||
bar.maxWidthProperty().bind(widthProperty());
|
bar.maxWidthProperty().bind(binding);
|
||||||
|
|
||||||
|
paddingProperty().bind(progressNodePadding);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void unbind() {
|
public void unbind() {
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import org.jackhuang.hmcl.game.Version;
|
|||||||
import org.jackhuang.hmcl.setting.Profile;
|
import org.jackhuang.hmcl.setting.Profile;
|
||||||
import org.jackhuang.hmcl.task.DownloadException;
|
import org.jackhuang.hmcl.task.DownloadException;
|
||||||
import org.jackhuang.hmcl.task.Task;
|
import org.jackhuang.hmcl.task.Task;
|
||||||
|
import org.jackhuang.hmcl.task.TaskStages;
|
||||||
import org.jackhuang.hmcl.ui.Controllers;
|
import org.jackhuang.hmcl.ui.Controllers;
|
||||||
import org.jackhuang.hmcl.ui.construct.MessageDialogPane.MessageType;
|
import org.jackhuang.hmcl.ui.construct.MessageDialogPane.MessageType;
|
||||||
import org.jackhuang.hmcl.ui.wizard.WizardController;
|
import org.jackhuang.hmcl.ui.wizard.WizardController;
|
||||||
@@ -73,14 +74,35 @@ public final class InstallerWizardProvider implements WizardProvider {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object finish(Map<String, Object> settings) {
|
public Object finish(Map<String, Object> settings) {
|
||||||
|
settings.put("title", i18n("install.installer.install_online"));
|
||||||
settings.put("success_message", i18n("install.success"));
|
settings.put("success_message", i18n("install.success"));
|
||||||
settings.put("failure_callback", (FailureCallback) (settings1, exception, next) -> alertFailureMessage(exception, next));
|
settings.put("failure_callback", (FailureCallback) (settings1, exception, next) -> alertFailureMessage(exception, next));
|
||||||
|
settings.put("stages", new TaskStages() {
|
||||||
|
{
|
||||||
|
if (settings.containsKey("forge")) {
|
||||||
|
RemoteVersion forge = (RemoteVersion) settings.get("forge");
|
||||||
|
addStage("hmcl.install.forge", i18n("install.installer.install", i18n("install.installer.forge") + " " + forge.getSelfVersion()));
|
||||||
|
}
|
||||||
|
if (settings.containsKey("liteloader")) {
|
||||||
|
RemoteVersion liteloader = (RemoteVersion) settings.get("liteloader");
|
||||||
|
addStage("hmcl.install.liteloader", i18n("install.installer.install", i18n("install.installer.liteloader") + " " + liteloader.getSelfVersion()));
|
||||||
|
}
|
||||||
|
if (settings.containsKey("optifine")) {
|
||||||
|
RemoteVersion optifine = (RemoteVersion) settings.get("optifine");
|
||||||
|
addStage("hmcl.install.optifine", i18n("install.installer.install", i18n("install.installer.optifine") + " " + optifine.getSelfVersion()));
|
||||||
|
}
|
||||||
|
if (settings.containsKey("fabric")) {
|
||||||
|
RemoteVersion fabric = (RemoteVersion) settings.get("fabric");
|
||||||
|
addStage("hmcl.install.fabric", i18n("install.installer.install", i18n("install.installer.fabric") + " " + fabric.getSelfVersion()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
Task<Version> ret = Task.supplyAsync(() -> version);
|
Task<Version> ret = Task.supplyAsync(() -> version);
|
||||||
|
|
||||||
for (Object value : settings.values()) {
|
for (Object value : settings.values()) {
|
||||||
if (value instanceof RemoteVersion)
|
if (value instanceof RemoteVersion)
|
||||||
ret = ret.thenComposeAsync(profile.getDependency().installLibraryAsync((RemoteVersion) value));
|
ret = ret.thenComposeAsync(version -> profile.getDependency().installLibraryAsync(version, (RemoteVersion) value));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret.thenComposeAsync(profile.getRepository().refreshVersionsAsync());
|
return ret.thenComposeAsync(profile.getRepository().refreshVersionsAsync());
|
||||||
|
|||||||
@@ -107,6 +107,7 @@ public class ModpackInstallWizardProvider implements WizardProvider {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object finish(Map<String, Object> settings) {
|
public Object finish(Map<String, Object> settings) {
|
||||||
|
settings.put("title", i18n("install.modpack"));
|
||||||
settings.put("success_message", i18n("install.success"));
|
settings.put("success_message", i18n("install.success"));
|
||||||
settings.put("failure_callback", new FailureCallback() {
|
settings.put("failure_callback", new FailureCallback() {
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import org.jackhuang.hmcl.download.DownloadProvider;
|
|||||||
import org.jackhuang.hmcl.download.RemoteVersion;
|
import org.jackhuang.hmcl.download.RemoteVersion;
|
||||||
import org.jackhuang.hmcl.game.Version;
|
import org.jackhuang.hmcl.game.Version;
|
||||||
import org.jackhuang.hmcl.setting.Profile;
|
import org.jackhuang.hmcl.setting.Profile;
|
||||||
|
import org.jackhuang.hmcl.task.TaskStages;
|
||||||
import org.jackhuang.hmcl.ui.Controllers;
|
import org.jackhuang.hmcl.ui.Controllers;
|
||||||
import org.jackhuang.hmcl.ui.wizard.WizardController;
|
import org.jackhuang.hmcl.ui.wizard.WizardController;
|
||||||
import org.jackhuang.hmcl.ui.wizard.WizardProvider;
|
import org.jackhuang.hmcl.ui.wizard.WizardProvider;
|
||||||
@@ -53,8 +54,29 @@ public final class UpdateInstallerWizardProvider implements WizardProvider {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object finish(Map<String, Object> settings) {
|
public Object finish(Map<String, Object> settings) {
|
||||||
|
settings.put("title", i18n("install.change_version"));
|
||||||
settings.put("success_message", i18n("install.success"));
|
settings.put("success_message", i18n("install.success"));
|
||||||
settings.put("failure_callback", (FailureCallback) (settings1, exception, next) -> alertFailureMessage(exception, next));
|
settings.put("failure_callback", (FailureCallback) (settings1, exception, next) -> alertFailureMessage(exception, next));
|
||||||
|
settings.put("stages", new TaskStages() {
|
||||||
|
{
|
||||||
|
if (settings.containsKey("forge")) {
|
||||||
|
RemoteVersion forge = (RemoteVersion) settings.get("forge");
|
||||||
|
addStage("hmcl.install.forge", i18n("install.installer.install", i18n("install.installer.forge") + " " + forge.getSelfVersion()));
|
||||||
|
}
|
||||||
|
if (settings.containsKey("liteloader")) {
|
||||||
|
RemoteVersion liteloader = (RemoteVersion) settings.get("liteloader");
|
||||||
|
addStage("hmcl.install.liteloader", i18n("install.installer.install", i18n("install.installer.liteloader") + " " + liteloader.getSelfVersion()));
|
||||||
|
}
|
||||||
|
if (settings.containsKey("optifine")) {
|
||||||
|
RemoteVersion optifine = (RemoteVersion) settings.get("optifine");
|
||||||
|
addStage("hmcl.install.optifine", i18n("install.installer.install", i18n("install.installer.optifine") + " " + optifine.getSelfVersion()));
|
||||||
|
}
|
||||||
|
if (settings.containsKey("fabric")) {
|
||||||
|
RemoteVersion fabric = (RemoteVersion) settings.get("fabric");
|
||||||
|
addStage("hmcl.install.fabric", i18n("install.installer.install", i18n("install.installer.fabric") + " " + fabric.getSelfVersion()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// 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.
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import org.jackhuang.hmcl.download.RemoteVersion;
|
|||||||
import org.jackhuang.hmcl.setting.Profile;
|
import org.jackhuang.hmcl.setting.Profile;
|
||||||
import org.jackhuang.hmcl.task.Schedulers;
|
import org.jackhuang.hmcl.task.Schedulers;
|
||||||
import org.jackhuang.hmcl.task.Task;
|
import org.jackhuang.hmcl.task.Task;
|
||||||
|
import org.jackhuang.hmcl.task.TaskStages;
|
||||||
import org.jackhuang.hmcl.ui.wizard.WizardController;
|
import org.jackhuang.hmcl.ui.wizard.WizardController;
|
||||||
import org.jackhuang.hmcl.ui.wizard.WizardProvider;
|
import org.jackhuang.hmcl.ui.wizard.WizardProvider;
|
||||||
|
|
||||||
@@ -60,8 +61,34 @@ public final class VanillaInstallWizardProvider implements WizardProvider {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object finish(Map<String, Object> settings) {
|
public Object finish(Map<String, Object> settings) {
|
||||||
|
settings.put("title", i18n("install.new_game"));
|
||||||
settings.put("success_message", i18n("install.success"));
|
settings.put("success_message", i18n("install.success"));
|
||||||
settings.put("failure_callback", (FailureCallback) (settings1, exception, next) -> InstallerWizardProvider.alertFailureMessage(exception, next));
|
settings.put("failure_callback", (FailureCallback) (settings1, exception, next) -> InstallerWizardProvider.alertFailureMessage(exception, next));
|
||||||
|
settings.put("stages", new TaskStages() {
|
||||||
|
{
|
||||||
|
if (settings.containsKey("game")) {
|
||||||
|
RemoteVersion game = (RemoteVersion) settings.get("game");
|
||||||
|
addStage("hmcl.install.game", i18n("install.installer.install", i18n("install.installer.game") + " " + game.getSelfVersion()));
|
||||||
|
addStage("hmcl.install.assets", i18n("assets.download"));
|
||||||
|
}
|
||||||
|
if (settings.containsKey("forge")) {
|
||||||
|
RemoteVersion forge = (RemoteVersion) settings.get("forge");
|
||||||
|
addStage("hmcl.install.forge", i18n("install.installer.install", i18n("install.installer.forge") + " " + forge.getSelfVersion()));
|
||||||
|
}
|
||||||
|
if (settings.containsKey("liteloader")) {
|
||||||
|
RemoteVersion liteloader = (RemoteVersion) settings.get("liteloader");
|
||||||
|
addStage("hmcl.install.liteloader", i18n("install.installer.install", i18n("install.installer.liteloader") + " " + liteloader.getSelfVersion()));
|
||||||
|
}
|
||||||
|
if (settings.containsKey("optifine")) {
|
||||||
|
RemoteVersion optifine = (RemoteVersion) settings.get("optifine");
|
||||||
|
addStage("hmcl.install.optifine", i18n("install.installer.install", i18n("install.installer.optifine") + " " + optifine.getSelfVersion()));
|
||||||
|
}
|
||||||
|
if (settings.containsKey("fabric")) {
|
||||||
|
RemoteVersion fabric = (RemoteVersion) settings.get("fabric");
|
||||||
|
addStage("hmcl.install.fabric", i18n("install.installer.install", i18n("install.installer.fabric") + " " + fabric.getSelfVersion()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return finishVersionDownloadingAsync(settings);
|
return finishVersionDownloadingAsync(settings);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -196,13 +196,18 @@ public final class ExportWizardProvider implements WizardProvider {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@Override
|
|
||||||
|
@Override
|
||||||
public Node createPage(WizardController controller, int step, Map<String, Object> settings) {
|
public Node createPage(WizardController controller, int step, Map<String, Object> settings) {
|
||||||
switch (step) {
|
switch (step) {
|
||||||
case 0: return new ModpackTypeSelectionPage(controller);
|
case 0:
|
||||||
case 1: return new ModpackInfoPage(controller, version);
|
return new ModpackTypeSelectionPage(controller);
|
||||||
case 2: return new ModpackFileSelectionPage(controller, profile, version, ModAdviser::suggestMod);
|
case 1:
|
||||||
default: throw new IllegalArgumentException("step");
|
return new ModpackInfoPage(controller, version);
|
||||||
|
case 2:
|
||||||
|
return new ModpackFileSelectionPage(controller, profile, version, ModAdviser::suggestMod);
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("step");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import javafx.beans.property.StringProperty;
|
|||||||
import org.jackhuang.hmcl.task.Task;
|
import org.jackhuang.hmcl.task.Task;
|
||||||
import org.jackhuang.hmcl.task.TaskExecutor;
|
import org.jackhuang.hmcl.task.TaskExecutor;
|
||||||
import org.jackhuang.hmcl.task.TaskListener;
|
import org.jackhuang.hmcl.task.TaskListener;
|
||||||
|
import org.jackhuang.hmcl.task.TaskStages;
|
||||||
import org.jackhuang.hmcl.ui.Controllers;
|
import org.jackhuang.hmcl.ui.Controllers;
|
||||||
import org.jackhuang.hmcl.ui.construct.DialogCloseEvent;
|
import org.jackhuang.hmcl.ui.construct.DialogCloseEvent;
|
||||||
import org.jackhuang.hmcl.ui.construct.MessageDialogPane.MessageType;
|
import org.jackhuang.hmcl.ui.construct.MessageDialogPane.MessageType;
|
||||||
@@ -65,7 +66,7 @@ public interface TaskExecutorDialogWizardDisplayer extends AbstractWizardDisplay
|
|||||||
return;
|
return;
|
||||||
String appendix = StringUtils.getStackTrace(executor.getException());
|
String appendix = StringUtils.getStackTrace(executor.getException());
|
||||||
if (settings.get("failure_callback") instanceof WizardProvider.FailureCallback)
|
if (settings.get("failure_callback") instanceof WizardProvider.FailureCallback)
|
||||||
((WizardProvider.FailureCallback)settings.get("failure_callback")).onFail(settings, executor.getException(), () -> onEnd());
|
((WizardProvider.FailureCallback) settings.get("failure_callback")).onFail(settings, executor.getException(), () -> onEnd());
|
||||||
else if (settings.get("failure_message") instanceof String)
|
else if (settings.get("failure_message") instanceof String)
|
||||||
Controllers.dialog(appendix, (String) settings.get("failure_message"), MessageType.ERROR, () -> onEnd());
|
Controllers.dialog(appendix, (String) settings.get("failure_message"), MessageType.ERROR, () -> onEnd());
|
||||||
else if (!settings.containsKey("forbid_failure_message"))
|
else if (!settings.containsKey("forbid_failure_message"))
|
||||||
@@ -75,6 +76,8 @@ public interface TaskExecutorDialogWizardDisplayer extends AbstractWizardDisplay
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
if (settings.containsKey("stages"))
|
||||||
|
executor.setStages((TaskStages) settings.get("stages"));
|
||||||
pane.setExecutor(executor);
|
pane.setExecutor(executor);
|
||||||
Controllers.dialog(pane);
|
Controllers.dialog(pane);
|
||||||
executor.start();
|
executor.start();
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Hello Minecraft! Launcher
|
||||||
|
* Copyright (C) 2020 huangyuhui <huanghongxun2008@126.com> and contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.jackhuang.hmcl.util.i18n;
|
||||||
|
|
||||||
|
import org.jackhuang.hmcl.task.TaskStages;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||||
|
|
||||||
|
public class LocalizedTaskStages extends TaskStages {
|
||||||
|
public LocalizedTaskStages(List<String> stages) {
|
||||||
|
for (String stage : stages) {
|
||||||
|
addStage(stage, i18n(stage));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -142,7 +142,7 @@ install.failed.version_mismatch=The library requires the game version %s, but th
|
|||||||
install.installer.choose=Choose a %s version
|
install.installer.choose=Choose a %s version
|
||||||
install.installer.fabric=Fabric
|
install.installer.fabric=Fabric
|
||||||
install.installer.forge=Forge
|
install.installer.forge=Forge
|
||||||
install.installer.game=Game
|
install.installer.game=Minecraft
|
||||||
install.installer.install=Install %s
|
install.installer.install=Install %s
|
||||||
install.installer.install_offline=Install/Upgrade from file
|
install.installer.install_offline=Install/Upgrade from file
|
||||||
install.installer.install_offline.extension=Forge/OptiFine installer
|
install.installer.install_offline.extension=Forge/OptiFine installer
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ install.failed.version_mismatch=El library requiere versión del juego %s, pero
|
|||||||
install.installer.choose=Escoja una versión de %s
|
install.installer.choose=Escoja una versión de %s
|
||||||
install.installer.fabric=Fabric
|
install.installer.fabric=Fabric
|
||||||
install.installer.forge=Forge
|
install.installer.forge=Forge
|
||||||
install.installer.game=Juego
|
install.installer.game=Minecraft
|
||||||
install.installer.install=Instalar %s
|
install.installer.install=Instalar %s
|
||||||
install.installer.install_offline=Instalar/actualizar con archivo local
|
install.installer.install_offline=Instalar/actualizar con archivo local
|
||||||
install.installer.install_offline.extension=Instalador de Forge/OptiFine
|
install.installer.install_offline.extension=Instalador de Forge/OptiFine
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ install.failed.version_mismatch=Для библиотеки требуется
|
|||||||
install.installer.choose=Выберите %s версию
|
install.installer.choose=Выберите %s версию
|
||||||
install.installer.fabric=Fabric
|
install.installer.fabric=Fabric
|
||||||
install.installer.forge=Forge
|
install.installer.forge=Forge
|
||||||
install.installer.game=Версия
|
install.installer.game=Minecraft
|
||||||
install.installer.install=Установка %s
|
install.installer.install=Установка %s
|
||||||
install.installer.install_offline=Установить/Обновить из файла
|
install.installer.install_offline=Установить/Обновить из файла
|
||||||
install.installer.install_offline.extension=Forge/OptiFine установщик
|
install.installer.install_offline.extension=Forge/OptiFine установщик
|
||||||
|
|||||||
@@ -139,9 +139,10 @@ install.failed.malformed=剛才下載的檔案格式損壞。您可以切換到
|
|||||||
install.failed.optifine_conflict=暫不支援 OptiFine 與 Forge 同時安裝在 Minecraft 1.13 上
|
install.failed.optifine_conflict=暫不支援 OptiFine 與 Forge 同時安裝在 Minecraft 1.13 上
|
||||||
install.failed.version_mismatch=該軟體需要的遊戲版本為 %s,但實際的遊戲版本為 %s。
|
install.failed.version_mismatch=該軟體需要的遊戲版本為 %s,但實際的遊戲版本為 %s。
|
||||||
install.installer.choose=選擇 %s 版本
|
install.installer.choose=選擇 %s 版本
|
||||||
|
install.installer.fabric=Fabric
|
||||||
install.installer.forge=Forge
|
install.installer.forge=Forge
|
||||||
install.installer.game=遊戲
|
install.installer.game=Minecraft
|
||||||
install.installer.install=安裝 %s
|
install.installer.install=安裝%s
|
||||||
install.installer.install_offline=從本機檔案安裝或升級
|
install.installer.install_offline=從本機檔案安裝或升級
|
||||||
install.installer.install_offline.extension=Forge/OptiFine 安裝器
|
install.installer.install_offline.extension=Forge/OptiFine 安裝器
|
||||||
install.installer.install_offline.tooltip=支援匯入已經下載好的 Forge/OptiFine 安裝器
|
install.installer.install_offline.tooltip=支援匯入已經下載好的 Forge/OptiFine 安裝器
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ install.failed.version_mismatch=该软件需要的游戏版本为 %s,但实际
|
|||||||
install.installer.choose=选择 %s 版本
|
install.installer.choose=选择 %s 版本
|
||||||
install.installer.fabric=Fabric
|
install.installer.fabric=Fabric
|
||||||
install.installer.forge=Forge
|
install.installer.forge=Forge
|
||||||
install.installer.game=游戏
|
install.installer.game=Minecraft
|
||||||
install.installer.install=安装 %s
|
install.installer.install=安装 %s
|
||||||
install.installer.install_offline=从本地文件安装/升级
|
install.installer.install_offline=从本地文件安装/升级
|
||||||
install.installer.install_offline.extension=Forge/OptiFine 安装器
|
install.installer.install_offline.extension=Forge/OptiFine 安装器
|
||||||
|
|||||||
@@ -102,7 +102,8 @@ public class DefaultDependencyManager extends AbstractDependencyManager {
|
|||||||
VersionList<?> versionList = getVersionList(libraryId);
|
VersionList<?> versionList = getVersionList(libraryId);
|
||||||
return versionList.loadAsync(gameVersion)
|
return versionList.loadAsync(gameVersion)
|
||||||
.thenComposeAsync(() -> installLibraryAsync(baseVersion, versionList.getVersion(gameVersion, libraryVersion)
|
.thenComposeAsync(() -> installLibraryAsync(baseVersion, versionList.getVersion(gameVersion, libraryVersion)
|
||||||
.orElseThrow(() -> new IOException("Remote library " + libraryId + " has no version " + libraryVersion))));
|
.orElseThrow(() -> new IOException("Remote library " + libraryId + " has no version " + libraryVersion))))
|
||||||
|
.withStage("hmcl.install." + libraryId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -112,11 +113,7 @@ public class DefaultDependencyManager extends AbstractDependencyManager {
|
|||||||
return removeLibraryAsync(baseVersion.resolvePreservingPatches(repository), libraryVersion.getLibraryId())
|
return removeLibraryAsync(baseVersion.resolvePreservingPatches(repository), libraryVersion.getLibraryId())
|
||||||
.thenComposeAsync(version -> libraryVersion.getInstallTask(this, version))
|
.thenComposeAsync(version -> libraryVersion.getInstallTask(this, version))
|
||||||
.thenApplyAsync(baseVersion::addPatch)
|
.thenApplyAsync(baseVersion::addPatch)
|
||||||
.thenComposeAsync(repository::save);
|
.thenComposeAsync(repository::save).withStage("hmcl.install." + libraryVersion.getLibraryId());
|
||||||
}
|
|
||||||
|
|
||||||
public ExceptionalFunction<Version, Task<Version>, ?> installLibraryAsync(RemoteVersion libraryVersion) {
|
|
||||||
return version -> installLibraryAsync(version, libraryVersion);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<Version> installLibraryAsync(Version oldVersion, Path installer) {
|
public Task<Version> installLibraryAsync(Version oldVersion, Path installer) {
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ public class DefaultGameBuilder extends GameBuilder {
|
|||||||
libraryTask = libraryTask.thenComposeAsync(libraryTaskHelper(gameVersion, entry.getKey(), entry.getValue()));
|
libraryTask = libraryTask.thenComposeAsync(libraryTaskHelper(gameVersion, entry.getKey(), entry.getValue()));
|
||||||
|
|
||||||
for (RemoteVersion remoteVersion : remoteVersions)
|
for (RemoteVersion remoteVersion : remoteVersions)
|
||||||
libraryTask = libraryTask.thenComposeAsync(dependencyManager.installLibraryAsync(remoteVersion));
|
libraryTask = libraryTask.thenComposeAsync(version -> dependencyManager.installLibraryAsync(version, remoteVersion));
|
||||||
|
|
||||||
return libraryTask.whenComplete(exception -> {
|
return libraryTask.whenComplete(exception -> {
|
||||||
if (exception != null)
|
if (exception != null)
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ public class GameInstallTask extends Task<Version> {
|
|||||||
.thenComposeAsync(Task.allOf(
|
.thenComposeAsync(Task.allOf(
|
||||||
new GameAssetDownloadTask(dependencyManager, version, GameAssetDownloadTask.DOWNLOAD_INDEX_FORCIBLY),
|
new GameAssetDownloadTask(dependencyManager, version, GameAssetDownloadTask.DOWNLOAD_INDEX_FORCIBLY),
|
||||||
new GameLibrariesTask(dependencyManager, version)
|
new GameLibrariesTask(dependencyManager, version)
|
||||||
).withComposeAsync(gameRepository.save(version))));
|
).withStage("hmcl.install.assets").withComposeAsync(gameRepository.save(version))));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -133,8 +133,8 @@ public final class CurseInstallTask extends Task<Void> {
|
|||||||
File root = repository.getVersionRoot(name);
|
File root = repository.getVersionRoot(name);
|
||||||
FileUtils.writeText(new File(root, "manifest.json"), JsonUtils.GSON.toJson(manifest));
|
FileUtils.writeText(new File(root, "manifest.json"), JsonUtils.GSON.toJson(manifest));
|
||||||
|
|
||||||
dependencies.add(new CurseCompletionTask(dependencyManager, name, manifest));
|
dependencies.add(new CurseCompletionTask(dependencyManager, name, manifest).withStage("hmcl.modpack.download"));
|
||||||
dependencies.add(new MinecraftInstanceTask<>(zipFile, modpack.getEncoding(), manifest.getOverrides(), manifest, MODPACK_TYPE, repository.getModpackConfiguration(name)));
|
dependencies.add(new MinecraftInstanceTask<>(zipFile, modpack.getEncoding(), manifest.getOverrides(), manifest, MODPACK_TYPE, repository.getModpackConfiguration(name)).withStage("hmcl.modpack.unzip"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final String MODPACK_TYPE = "Curse";
|
public static final String MODPACK_TYPE = "Curse";
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ public abstract class TaskExecutor {
|
|||||||
protected final AtomicInteger totTask = new AtomicInteger(0);
|
protected final AtomicInteger totTask = new AtomicInteger(0);
|
||||||
protected final AtomicBoolean cancelled = new AtomicBoolean(false);
|
protected final AtomicBoolean cancelled = new AtomicBoolean(false);
|
||||||
protected Exception exception;
|
protected Exception exception;
|
||||||
|
private TaskStages stages = TaskStages.EMPTY;
|
||||||
|
|
||||||
public TaskExecutor(Task<?> task) {
|
public TaskExecutor(Task<?> task) {
|
||||||
this.firstTask = task;
|
this.firstTask = task;
|
||||||
@@ -64,4 +65,12 @@ public abstract class TaskExecutor {
|
|||||||
public int getRunningTasks() {
|
public int getRunningTasks() {
|
||||||
return totTask.get();
|
return totTask.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TaskStages getStages() {
|
||||||
|
return stages;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStages(TaskStages stages) {
|
||||||
|
this.stages = stages;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Hello Minecraft! Launcher
|
||||||
|
* Copyright (C) 2020 huangyuhui <huanghongxun2008@126.com> and contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.jackhuang.hmcl.task;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class TaskStages {
|
||||||
|
public static final TaskStages EMPTY = new TaskStages();
|
||||||
|
|
||||||
|
private final List<String> stages = new ArrayList<>();
|
||||||
|
private final Map<String, String> localization = new HashMap<>();
|
||||||
|
|
||||||
|
protected void addStage(String stage, String localizedMessage) {
|
||||||
|
stages.add(stage);
|
||||||
|
localization.put(stage, localizedMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getStages() {
|
||||||
|
return stages;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String localize(String stage) {
|
||||||
|
return localization.get(stage);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user