From 056c0901f264f805ded35d43f04de7a950ae6e05 Mon Sep 17 00:00:00 2001 From: huangyuhui Date: Wed, 24 Jan 2018 19:42:04 +0800 Subject: [PATCH] make launch script --- .../jackhuang/hmcl/game/LauncherHelper.java | 63 ++++++-- .../hmcl/setting/VersionSetting.java | 132 ++++++++-------- .../jackhuang/hmcl/ui/AdvancedListBox.java | 23 +++ .../org/jackhuang/hmcl/ui/Controllers.java | 8 + .../java/org/jackhuang/hmcl/ui/MainPage.java | 13 +- .../main/java/org/jackhuang/hmcl/ui/SVG.java | 4 + .../org/jackhuang/hmcl/ui/VersionItem.java | 22 ++- .../org/jackhuang/hmcl/ui/VersionPage.java | 12 +- .../hmcl/ui/construct/InputDialogPane.java | 55 +++++++ .../ui/{ => construct}/MessageDialogPane.java | 3 +- .../hmcl/ui/construct/TaskListPane.java | 146 ++++++++++++++++++ .../ui/wizard/AbstractWizardDisplayer.java | 43 +----- .../hmcl/ui/wizard/WizardController.java | 2 +- .../resources/assets/fxml/input-dialog.fxml | 23 +++ .../resources/assets/fxml/version-item.fxml | 21 ++- .../assets/fxml/version/version.fxml | 14 +- .../main/resources/assets/fxml/wizard.fxml | 1 + .../resources/assets/lang/I18N.properties | 64 ++++---- .../assets/lang/I18N_zh_CN.properties | 60 +++---- .../src/main/resources/assets/svg/script.fxml | 3 + .../hmcl/download/DefaultGameBuilder.java | 3 +- .../game/GameAssetIndexDownloadTask.java | 1 + .../hmcl/download/game/GameDownloadTask.java | 2 + .../hmcl/download/game/GameLibrariesTask.java | 1 + .../game/GameLoggingDownloadTask.java | 1 + .../game/VersionJsonDownloadTask.java | 2 + .../download/game/VersionJsonSaveTask.java | 2 + .../org/jackhuang/hmcl/task/CoupleTask.java | 14 +- .../jackhuang/hmcl/task/FileDownloadTask.java | 6 + .../java/org/jackhuang/hmcl/task/GetTask.java | 2 + .../org/jackhuang/hmcl/task/ParallelTask.java | 6 +- .../java/org/jackhuang/hmcl/task/Task.java | 39 +++-- .../org/jackhuang/hmcl/task/TaskExecutor.java | 72 ++++----- .../org/jackhuang/hmcl/task/TaskListener.java | 5 + 34 files changed, 610 insertions(+), 258 deletions(-) create mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/InputDialogPane.java rename HMCL/src/main/java/org/jackhuang/hmcl/ui/{ => construct}/MessageDialogPane.java (94%) create mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskListPane.java create mode 100644 HMCL/src/main/resources/assets/fxml/input-dialog.fxml create mode 100644 HMCL/src/main/resources/assets/svg/script.fxml 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 623ffbb0a..0791332c2 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java @@ -39,11 +39,11 @@ import org.jackhuang.hmcl.ui.Controllers; import org.jackhuang.hmcl.ui.DialogController; import org.jackhuang.hmcl.ui.LaunchingStepsPane; import org.jackhuang.hmcl.ui.LogWindow; -import org.jackhuang.hmcl.util.Lang; -import org.jackhuang.hmcl.util.Log4jLevel; -import org.jackhuang.hmcl.util.ManagedProcess; -import org.jackhuang.hmcl.util.Pair; +import org.jackhuang.hmcl.ui.construct.MessageBox; +import org.jackhuang.hmcl.util.*; +import java.io.*; +import java.nio.Buffer; import java.util.*; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.atomic.AtomicInteger; @@ -55,7 +55,7 @@ public final class LauncherHelper { private final LaunchingStepsPane launchingStepsPane = new LaunchingStepsPane(); public static final Queue PROCESSES = new ConcurrentLinkedQueue<>(); - public void launch(String selectedVersion) { + public void launch(String selectedVersion, String launcherName) { Profile profile = Settings.INSTANCE.getSelectedProfile(); GameRepository repository = profile.getRepository(); DefaultDependencyManager dependencyManager = profile.getDependency(); @@ -86,16 +86,26 @@ public final class LauncherHelper { repository, selectedVersion, variables.get("account"), setting.toLaunchOptions(profile.getGameDir()), new HMCLProcessListener(variables.get("account"), setting) )); })) - .then(variables -> variables.get("launcher").launchAsync()) + .then(variables -> { + if (launcherName == null) { + return variables.get("launcher").launchAsync(); + } else { + variables.set("script", variables.get("launcher").makeLaunchScript(launcherName)); + return null; + } + }) .then(Task.of(variables -> { - PROCESSES.add(variables.get(DefaultLauncher.LAUNCH_ASYNC_ID)); - if (setting.getLauncherVisibility() == LauncherVisibility.CLOSE) - Main.stopApplication(); + if (launcherName == null) { + PROCESSES.add(variables.get(DefaultLauncher.LAUNCH_ASYNC_ID)); + if (setting.getLauncherVisibility() == LauncherVisibility.CLOSE) + Main.stopApplication(); + } })) .executor(); - executor.setTaskListener(new TaskListener() { + executor.addTaskListener(new TaskListener() { AtomicInteger finished = new AtomicInteger(0); + @Override public void onFinished(Task task) { finished.incrementAndGet(); @@ -105,14 +115,43 @@ public final class LauncherHelper { } @Override - public void onTerminate() { - Platform.runLater(Controllers::closeDialog); + public void onTerminate(AutoTypingMap variables) { + Platform.runLater(() -> { + Controllers.closeDialog(); + + if (variables.containsKey("script")) { + Controllers.dialog(Main.i18n("version.launch_script.success", variables.get("script").getAbsolutePath())); + } + }); } }); executor.start(); } + private void checkGameState(VersionSetting setting) throws InterruptedException { + JavaVersion java = setting.getJavaVersion(); + if (java == null) { + // TODO + return; + } + + if (java.getParsedVersion() < JavaVersion.JAVA_8) { + MessageBox.show(Main.i18n("launch.advice.newer_java")); + } + if (java.getPlatform() == org.jackhuang.hmcl.util.Platform.BIT_32 && + org.jackhuang.hmcl.util.Platform.IS_64_BIT) { + MessageBox.show(Main.i18n("launch.advice.different_platform")); + } + if (java.getPlatform() == org.jackhuang.hmcl.util.Platform.BIT_32 && + setting.getMaxMemory() > 1.5 * 1024) { + MessageBox.show(Main.i18n("launch.advice.too_large_memory_for_32bit")); + } + if (OperatingSystem.TOTAL_MEMORY > 0 && OperatingSystem.TOTAL_MEMORY < setting.getMaxMemory()) { + MessageBox.show(Main.i18n("launch.advice.not_enough_space")); + } + } + public static void stopManagedProcesses() { synchronized (PROCESSES) { while (!PROCESSES.isEmpty()) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionSetting.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionSetting.java index a0fb74e28..3f4dc9a95 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionSetting.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionSetting.java @@ -46,6 +46,12 @@ public final class VersionSetting { this.global = global; } + private final ImmediateBooleanProperty usesGlobalProperty = new ImmediateBooleanProperty(this, "usesGlobal", false); + + public ImmediateBooleanProperty usesGlobalProperty() { + return usesGlobalProperty; + } + /** * HMCL Version Settings have been divided into 2 parts. * 1. Global settings. @@ -54,12 +60,6 @@ public final class VersionSetting { * * Defaults false because if one version uses global first, custom version file will not be generated. */ - private final ImmediateBooleanProperty usesGlobalProperty = new ImmediateBooleanProperty(this, "usesGlobal", false); - - public ImmediateBooleanProperty usesGlobalProperty() { - return usesGlobalProperty; - } - public boolean isUsesGlobal() { return usesGlobalProperty.get(); } @@ -70,15 +70,15 @@ public final class VersionSetting { // java - /** - * Java version or null if user customizes java directory. - */ private final ImmediateStringProperty javaProperty = new ImmediateStringProperty(this, "java", ""); public ImmediateStringProperty javaProperty() { return javaProperty; } + /** + * Java version or null if user customizes java directory. + */ public String getJava() { return javaProperty.get(); } @@ -87,15 +87,15 @@ public final class VersionSetting { javaProperty.set(java); } - /** - * User customized java directory or null if user uses system Java. - */ private final ImmediateStringProperty javaDirProperty = new ImmediateStringProperty(this, "javaDir", ""); public ImmediateStringProperty javaDirProperty() { return javaDirProperty; } + /** + * User customized java directory or null if user uses system Java. + */ public String getJavaDir() { return javaDirProperty.get(); } @@ -104,15 +104,15 @@ public final class VersionSetting { javaDirProperty.set(javaDir); } - /** - * The command to launch java, i.e. optirun. - */ private final ImmediateStringProperty wrapperProperty = new ImmediateStringProperty(this, "wrapper", ""); public ImmediateStringProperty wrapperProperty() { return wrapperProperty; } + /** + * The command to launch java, i.e. optirun. + */ public String getWrapper() { return wrapperProperty.get(); } @@ -121,15 +121,15 @@ public final class VersionSetting { wrapperProperty.set(wrapper); } - /** - * The permanent generation size of JVM garbage collection. - */ private final ImmediateStringProperty permSizeProperty = new ImmediateStringProperty(this, "permSize", ""); public ImmediateStringProperty permSizeProperty() { return permSizeProperty; } + /** + * The permanent generation size of JVM garbage collection. + */ public String getPermSize() { return permSizeProperty.get(); } @@ -138,15 +138,15 @@ public final class VersionSetting { permSizeProperty.set(permSize); } - /** - * The maximum memory that JVM can allocate for heap. - */ private final ImmediateIntegerProperty maxMemoryProperty = new ImmediateIntegerProperty(this, "maxMemory", (int) OperatingSystem.SUGGESTED_MEMORY); public ImmediateIntegerProperty maxMemoryProperty() { return maxMemoryProperty; } + /** + * The maximum memory/MB that JVM can allocate for heap. + */ public int getMaxMemory() { return maxMemoryProperty.get(); } @@ -172,16 +172,16 @@ public final class VersionSetting { minMemoryProperty.set(minMemory); } - /** - * The command that will be executed before launching the Minecraft. - * Operating system relevant. - */ private final ImmediateStringProperty preLaunchCommandProperty = new ImmediateStringProperty(this, "precalledCommand", ""); public ImmediateStringProperty preLaunchCommandProperty() { return preLaunchCommandProperty; } + /** + * The command that will be executed before launching the Minecraft. + * Operating system relevant. + */ public String getPreLaunchCommand() { return preLaunchCommandProperty.get(); } @@ -192,15 +192,15 @@ public final class VersionSetting { // options - /** - * The user customized arguments passed to JVM. - */ private final ImmediateStringProperty javaArgsProperty = new ImmediateStringProperty(this, "javaArgs", ""); public ImmediateStringProperty javaArgsProperty() { return javaArgsProperty; } + /** + * The user customized arguments passed to JVM. + */ public String getJavaArgs() { return javaArgsProperty.get(); } @@ -209,16 +209,15 @@ public final class VersionSetting { javaArgsProperty.set(javaArgs); } - - /** - * The user customized arguments passed to Minecraft. - */ private final ImmediateStringProperty minecraftArgsProperty = new ImmediateStringProperty(this, "minecraftArgs", ""); public ImmediateStringProperty minecraftArgsProperty() { return minecraftArgsProperty; } + /** + * The user customized arguments passed to Minecraft. + */ public String getMinecraftArgs() { return minecraftArgsProperty.get(); } @@ -227,15 +226,15 @@ public final class VersionSetting { minecraftArgsProperty.set(minecraftArgs); } - /** - * True if disallow HMCL use default JVM arguments. - */ private final ImmediateBooleanProperty noJVMArgsProperty = new ImmediateBooleanProperty(this, "noJVMArgs", false); public ImmediateBooleanProperty noJVMArgsProperty() { return noJVMArgsProperty; } + /** + * True if disallow HMCL use default JVM arguments. + */ public boolean isNoJVMArgs() { return noJVMArgsProperty.get(); } @@ -244,15 +243,15 @@ public final class VersionSetting { noJVMArgsProperty.set(noJVMArgs); } - /** - * True if HMCL does not check game's completeness. - */ private final ImmediateBooleanProperty notCheckGameProperty = new ImmediateBooleanProperty(this, "notCheckGame", false); public ImmediateBooleanProperty notCheckGameProperty() { return notCheckGameProperty; } + /** + * True if HMCL does not check game's completeness. + */ public boolean isNotCheckGame() { return notCheckGameProperty.get(); } @@ -261,16 +260,15 @@ public final class VersionSetting { notCheckGameProperty.set(notCheckGame); } - - /** - * True if HMCL does not find/download libraries in/to common path. - */ private final ImmediateBooleanProperty noCommonProperty = new ImmediateBooleanProperty(this, "noCommon", false); public ImmediateBooleanProperty noCommonProperty() { return noCommonProperty; } + /** + * True if HMCL does not find/download libraries in/to common path. + */ public boolean isNoCommon() { return noCommonProperty.get(); } @@ -279,15 +277,15 @@ public final class VersionSetting { noCommonProperty.set(noCommon); } - /** - * True if show the logs after game launched. - */ private final ImmediateBooleanProperty showLogsProperty = new ImmediateBooleanProperty(this, "showLogs", false); public ImmediateBooleanProperty showLogsProperty() { return showLogsProperty; } + /** + * True if show the logs after game launched. + */ public boolean isShowLogs() { return showLogsProperty.get(); } @@ -298,17 +296,17 @@ public final class VersionSetting { // Minecraft settings. - /** - * The server ip that will be entered after Minecraft successfully loaded immediately. - * - * Format: ip:port or without port. - */ private final ImmediateStringProperty serverIpProperty = new ImmediateStringProperty(this, "serverIp", ""); public ImmediateStringProperty serverIpProperty() { return serverIpProperty; } + /** + * The server ip that will be entered after Minecraft successfully loaded immediately. + * + * Format: ip:port or without port. + */ public String getServerIp() { return serverIpProperty.get(); } @@ -318,15 +316,15 @@ public final class VersionSetting { } - /** - * True if Minecraft started in fullscreen mode. - */ private final ImmediateBooleanProperty fullscreenProperty = new ImmediateBooleanProperty(this, "fullscreen", false); public ImmediateBooleanProperty fullscreenProperty() { return fullscreenProperty; } + /** + * True if Minecraft started in fullscreen mode. + */ public boolean isFullscreen() { return fullscreenProperty.get(); } @@ -335,19 +333,19 @@ public final class VersionSetting { fullscreenProperty.set(fullscreen); } - /** - * The width of Minecraft window, defaults 800. - * - * The field saves int value. - * String type prevents unexpected value from causing JsonSyntaxException. - * We can only reset this field instead of recreating the whole setting file. - */ private final ImmediateIntegerProperty widthProperty = new ImmediateIntegerProperty(this, "width", 854); public ImmediateIntegerProperty widthProperty() { return widthProperty; } + /** + * The width of Minecraft window, defaults 800. + * + * The field saves int value. + * String type prevents unexpected value from JsonParseException. + * We can only reset this field instead of recreating the whole setting file. + */ public int getWidth() { return widthProperty.get(); } @@ -357,19 +355,19 @@ public final class VersionSetting { } - /** - * The height of Minecraft window, defaults 480. - * - * The field saves int value. - * String type prevents unexpected value from causing JsonSyntaxException. - * We can only reset this field instead of recreating the whole setting file. - */ private final ImmediateIntegerProperty heightProperty = new ImmediateIntegerProperty(this, "height", 480); public ImmediateIntegerProperty heightProperty() { return heightProperty; } + /** + * The height of Minecraft window, defaults 480. + * + * The field saves int value. + * String type prevents unexpected value from JsonParseException. + * We can only reset this field instead of recreating the whole setting file. + */ public int getHeight() { return heightProperty.get(); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/AdvancedListBox.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/AdvancedListBox.java index 6a5d36c99..2becb9568 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/AdvancedListBox.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/AdvancedListBox.java @@ -17,6 +17,7 @@ */ package org.jackhuang.hmcl.ui; +import javafx.collections.ObservableList; import javafx.scene.Node; import javafx.scene.control.ScrollPane; import javafx.scene.layout.Pane; @@ -51,7 +52,29 @@ public class AdvancedListBox extends ScrollPane { return this; } + public AdvancedListBox remove(Node child) { + if (child instanceof Pane) + container.getChildren().remove(child); + else { + StackPane pane = null; + for (Node node : container.getChildren()) + if (node instanceof StackPane) { + ObservableList list = ((StackPane) node).getChildren(); + if (list.size() == 1 && list.get(0) == child) + pane = (StackPane) node; + } + if (pane == null) + throw new Error(); + container.getChildren().remove(pane); + } + return this; + } + public AdvancedListBox startCategory(String category) { return add(new ClassTitle(category)); } + + public void setSpacing(double spacing) { + container.setSpacing(spacing); + } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java index 18461ea4a..75ec72525 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java @@ -26,8 +26,12 @@ import javafx.stage.Stage; import org.jackhuang.hmcl.Main; import org.jackhuang.hmcl.setting.Settings; import org.jackhuang.hmcl.task.Task; +import org.jackhuang.hmcl.ui.construct.InputDialogPane; +import org.jackhuang.hmcl.ui.construct.MessageDialogPane; import org.jackhuang.hmcl.util.JavaVersion; +import java.util.function.Consumer; + public final class Controllers { private static Scene scene; @@ -103,6 +107,10 @@ public final class Controllers { dialog(new MessageDialogPane(text, decorator.getDialog())); } + public static void inputDialog(String text, Consumer onResult) { + dialog(new InputDialogPane(text, decorator.getDialog(), onResult)); + } + public static void closeDialog() { decorator.getDialog().close(); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/MainPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/MainPage.java index ed38274c8..aaaafaef4 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/MainPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/MainPage.java @@ -76,11 +76,16 @@ public final class MainPage extends StackPane implements DecoratorPage { if (Settings.INSTANCE.getSelectedAccount() == null) Controllers.dialog(Main.i18n("login.no_Player007")); else - LauncherHelper.INSTANCE.launch(version); + LauncherHelper.INSTANCE.launch(version, null); }); - item.setOnDeleteButtonClicked(e -> { - profile.getRepository().removeVersionFromDisk(version); - Platform.runLater(this::loadVersions); + item.setOnScriptButtonClicked(e -> { + if (Settings.INSTANCE.getSelectedAccount() == null) + Controllers.dialog(Main.i18n("login.no_Player007")); + else { + Controllers.inputDialog(Main.i18n("mainwindow.enter_script_name"), file -> { + LauncherHelper.INSTANCE.launch(version, file); + }); + } }); item.setOnSettingsButtonClicked(e -> { Controllers.getDecorator().showPage(Controllers.getVersionPage()); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/SVG.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/SVG.java index 22e5a7d7b..20465e770 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/SVG.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/SVG.java @@ -81,6 +81,10 @@ public final class SVG { return createSVGPath("M1008 6.286q18.857 13.714 15.429 36.571l-146.286 877.714q-2.857 16.571-18.286 25.714-8 4.571-17.714 4.571-6.286 0-13.714-2.857l-258.857-105.714-138.286 168.571q-10.286 13.143-28 13.143-7.429 0-12.571-2.286-10.857-4-17.429-13.429t-6.571-20.857v-199.429l493.714-605.143-610.857 528.571-225.714-92.571q-21.143-8-22.857-31.429-1.143-22.857 18.286-33.714l950.857-548.571q8.571-5.143 18.286-5.14311.429 0 20.571 6.286z", fill, width, height); } + public static Node script(String fill, double width, double height) { + return createSVGPath("M14,20A2,2 0 0,0 16,18V5H9A1,1 0 0,0 8,6V16H5V5A3,3 0 0,1 8,2H19A3,3 0 0,1 22,5V6H18V18L18,19A3,3 0 0,1 15,22H5A3,3 0 0,1 2,19V18H12A2,2 0 0,0 14,20Z", fill, width, height); + } + public static Node pencil(String fill, double width, double height) { return createSVGPath("M20.71,4.04C21.1,3.65 21.1,3 20.71,2.63L18.37,0.29C18,-0.1 17.35,-0.1 16.96,0.29L15,2.25L18.75,6M17.75,7L14,3.25L4,13.25V17H7.75L17.75,7Z", fill, width, height); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/VersionItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/VersionItem.java index ca1a2df6b..254c0ab24 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/VersionItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/VersionItem.java @@ -26,12 +26,15 @@ import javafx.scene.effect.BlurType; import javafx.scene.effect.DropShadow; import javafx.scene.image.Image; import javafx.scene.image.ImageView; +import javafx.scene.input.MouseButton; import javafx.scene.input.MouseEvent; import javafx.scene.layout.Pane; import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; import javafx.scene.paint.Color; +import java.util.Optional; + public final class VersionItem extends StackPane { @FXML private Pane icon; @@ -42,29 +45,37 @@ public final class VersionItem extends StackPane { @FXML private StackPane body; @FXML - private JFXButton btnDelete; - @FXML private JFXButton btnSettings; @FXML private JFXButton btnLaunch; @FXML + private JFXButton btnScript; + @FXML private Label lblVersionName; @FXML private Label lblGameVersion; @FXML private ImageView iconView; + private EventHandler launchClickedHandler = null; + public VersionItem() { FXUtils.loadFXML(this, "/assets/fxml/version-item.fxml"); FXUtils.limitWidth(this, 160); FXUtils.limitHeight(this, 156); setEffect(new DropShadow(BlurType.GAUSSIAN, Color.rgb(0, 0, 0, 0.26), 5.0, 0.12, -1.0, 1.0)); btnSettings.setGraphic(SVG.gear("black", 15, 15)); - btnDelete.setGraphic(SVG.delete("black", 15, 15)); btnLaunch.setGraphic(SVG.launch("black", 15, 15)); + btnScript.setGraphic(SVG.script("black", 15, 15)); icon.translateYProperty().bind(Bindings.createDoubleBinding(() -> header.getBoundsInParent().getHeight() - icon.getHeight() / 2 - 16, header.boundsInParentProperty(), icon.heightProperty())); FXUtils.limitSize(iconView, 32, 32); + + setOnMouseClicked(e -> { + if (e.getButton() == MouseButton.PRIMARY) + if (e.getClickCount() == 2) + Optional.ofNullable(launchClickedHandler).ifPresent(h -> h.handle(e)); + }); } public void setVersionName(String versionName) { @@ -83,11 +94,12 @@ public final class VersionItem extends StackPane { btnSettings.setOnMouseClicked(handler); } - public void setOnDeleteButtonClicked(EventHandler handler) { - btnDelete.setOnMouseClicked(handler); + public void setOnScriptButtonClicked(EventHandler handler) { + btnScript.setOnMouseClicked(handler); } public void setOnLaunchButtonClicked(EventHandler handler) { + launchClickedHandler = handler; btnLaunch.setOnMouseClicked(handler); } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/VersionPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/VersionPage.java index af29b4d67..9c5ced658 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/VersionPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/VersionPage.java @@ -82,7 +82,7 @@ public final class VersionPage extends StackPane implements DecoratorPage { FXUtils.installTooltip(btnBrowseMenu, 0, 5000, 0, new Tooltip(Main.i18n("game_settings.exploration"))); FXUtils.installTooltip(btnManagementMenu, 0, 5000, 0, new Tooltip(Main.i18n("game_settings.management"))); - FXUtils.installTooltip(btnExport, 0, 5000, 0, new Tooltip(Main.i18n("modpack.task.save"))); + FXUtils.installTooltip(btnExport, 0, 5000, 0, new Tooltip(Main.i18n("modpack.export"))); } public void load(String id, Profile profile) { @@ -108,6 +108,12 @@ public final class VersionPage extends StackPane implements DecoratorPage { managementPopup.show(btnManagementMenu, JFXPopup.PopupVPosition.TOP, JFXPopup.PopupHPosition.RIGHT, -12, 15); } + public void onDelete() { + profile.getRepository().removeVersionFromDisk(version); + profile.getRepository().refreshVersions(); + Controllers.navigate(null); + } + public void onExport() { Controllers.getDecorator().startWizard(new ExportWizardProvider(profile, version), Main.i18n("modpack.wizard")); } @@ -145,7 +151,7 @@ public final class VersionPage extends StackPane implements DecoratorPage { public void onManagement() { switch (managementList.getSelectionModel().getSelectedIndex()) { case 0: // rename a version - Optional res = FXUtils.inputDialog("Input", Main.i18n("versions.manage.rename.message"), null, version); + Optional res = FXUtils.inputDialog("Input", Main.i18n("version.manage.rename.message"), null, version); if (res.isPresent()) { if (profile.getRepository().renameVersion(version, res.get())) { profile.getRepository().refreshVersions(); @@ -154,7 +160,7 @@ public final class VersionPage extends StackPane implements DecoratorPage { } break; case 1: // remove a version - if (FXUtils.alert(Alert.AlertType.CONFIRMATION, "Confirm", Main.i18n("versions.manage.remove.confirm") + version)) { + if (FXUtils.alert(Alert.AlertType.CONFIRMATION, "Confirm", Main.i18n("version.manage.remove.confirm") + version)) { if (profile.getRepository().removeVersionFromDisk(version)) { profile.getRepository().refreshVersions(); Controllers.navigate(null); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/InputDialogPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/InputDialogPane.java new file mode 100644 index 000000000..7fc59d97b --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/InputDialogPane.java @@ -0,0 +1,55 @@ +/* + * Hello Minecraft! Launcher. + * Copyright (C) 2017 huangyuhui + * + * 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 {http://www.gnu.org/licenses/}. + */ +package org.jackhuang.hmcl.ui.construct; + +import com.jfoenix.controls.JFXButton; +import com.jfoenix.controls.JFXDialog; +import com.jfoenix.controls.JFXTextField; +import javafx.fxml.FXML; +import javafx.scene.control.Label; +import javafx.scene.layout.StackPane; +import org.jackhuang.hmcl.ui.FXUtils; + +import java.util.function.Consumer; + +public class InputDialogPane extends StackPane { + private final String text; + private final JFXDialog dialog; + + @FXML + private JFXButton acceptButton; + @FXML + private JFXButton cancelButton; + @FXML + private JFXTextField textField; + @FXML + private Label content; + + public InputDialogPane(String text, JFXDialog dialog, Consumer onResult) { + this.text = text; + this.dialog = dialog; + + FXUtils.loadFXML(this, "/assets/fxml/input-dialog.fxml"); + content.setText(text); + cancelButton.setOnMouseClicked(e -> dialog.close()); + acceptButton.setOnMouseClicked(e -> { + onResult.accept(textField.getText()); + dialog.close(); + }); + } +} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/MessageDialogPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MessageDialogPane.java similarity index 94% rename from HMCL/src/main/java/org/jackhuang/hmcl/ui/MessageDialogPane.java rename to HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MessageDialogPane.java index 45ddfdb2d..ba9322a72 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/MessageDialogPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MessageDialogPane.java @@ -15,13 +15,14 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see {http://www.gnu.org/licenses/}. */ -package org.jackhuang.hmcl.ui; +package org.jackhuang.hmcl.ui.construct; import com.jfoenix.controls.JFXButton; import com.jfoenix.controls.JFXDialog; import javafx.fxml.FXML; import javafx.scene.control.Label; import javafx.scene.layout.StackPane; +import org.jackhuang.hmcl.ui.FXUtils; public final class MessageDialogPane extends StackPane { private final String text; 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 new file mode 100644 index 000000000..7e3157279 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskListPane.java @@ -0,0 +1,146 @@ +/* + * Hello Minecraft! Launcher. + * Copyright (C) 2017 huangyuhui + * + * 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 {http://www.gnu.org/licenses/}. + */ +package org.jackhuang.hmcl.ui.construct; + +import com.jfoenix.controls.JFXProgressBar; +import javafx.application.Platform; +import javafx.scene.control.Label; +import javafx.scene.layout.BorderPane; +import javafx.scene.layout.Region; +import javafx.scene.layout.StackPane; +import org.jackhuang.hmcl.Main; +import org.jackhuang.hmcl.download.forge.ForgeInstallTask; +import org.jackhuang.hmcl.download.game.GameAssetDownloadTask; +import org.jackhuang.hmcl.download.game.GameAssetRefreshTask; +import org.jackhuang.hmcl.download.liteloader.LiteLoaderInstallTask; +import org.jackhuang.hmcl.download.optifine.OptiFineInstallTask; +import org.jackhuang.hmcl.game.HMCLModpackExportTask; +import org.jackhuang.hmcl.game.HMCLModpackInstallTask; +import org.jackhuang.hmcl.mod.CurseCompletionTask; +import org.jackhuang.hmcl.mod.CurseInstallTask; +import org.jackhuang.hmcl.mod.MultiMCModpackInstallTask; +import org.jackhuang.hmcl.task.FileDownloadTask; +import org.jackhuang.hmcl.task.Task; +import org.jackhuang.hmcl.task.TaskExecutor; +import org.jackhuang.hmcl.task.TaskListener; +import org.jackhuang.hmcl.ui.AdvancedListBox; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +public final class TaskListPane extends StackPane { + private final TaskExecutor executor; + private final AdvancedListBox listBox = new AdvancedListBox(); + private final Map nodes = new HashMap<>(); + + public TaskListPane(TaskExecutor executor, Runnable onTerminate) { + this.executor = executor; + listBox.setSpacing(0); + + executor.addTaskListener(new TaskListener() { + @Override + public void onReady(Task task) { + if (!task.getSignificance().shouldShow()) + return; + ProgressListNode node = new ProgressListNode(task); + nodes.put(task, node); + Platform.runLater(() -> listBox.add(node)); + + if (task instanceof GameAssetRefreshTask) { + task.setName(Main.i18n("assets.download")); + } else if (task instanceof GameAssetDownloadTask) { + task.setName(Main.i18n("assets.download_all")); + } else if (task instanceof ForgeInstallTask) { + task.setName(Main.i18n("install.installer.install", Main.i18n("install.installer.forge"))); + } else if (task instanceof LiteLoaderInstallTask) { + task.setName(Main.i18n("install.installer.install", Main.i18n("install.installer.liteloader"))); + } else if (task instanceof OptiFineInstallTask) { + task.setName(Main.i18n("install.installer.install", Main.i18n("install.installer.optifine"))); + } else if (task instanceof CurseCompletionTask) { + task.setName(Main.i18n("modpack.type.curse.completion")); + } else if (task instanceof CurseInstallTask) { + task.setName(Main.i18n("modpack.install", Main.i18n("modpack.type.curse"))); + } else if (task instanceof MultiMCModpackInstallTask) { + task.setName(Main.i18n("modpack.install", Main.i18n("modpack.type.curse"))); + } else if (task instanceof HMCLModpackInstallTask) { + task.setName(Main.i18n("modpack.install", Main.i18n("modpack.type.curse"))); + } else if (task instanceof HMCLModpackExportTask) { + task.setName(Main.i18n("modpack.export")); + } + } + + @Override + public void onFinished(Task task) { + ProgressListNode node = nodes.remove(task); + if (node == null) + return; + node.unbind(); + Platform.runLater(() -> listBox.remove(node)); + } + + @Override + public void onFailed(Task task, Throwable throwable) { + ProgressListNode node = nodes.remove(task); + if (node == null) + return; + Platform.runLater(() -> node.setThrowable(throwable)); + } + + @Override + public void onTerminate() { + Optional.ofNullable(onTerminate).ifPresent(Runnable::run); + } + }); + + getChildren().setAll(listBox); + } + + private static class ProgressListNode extends StackPane { + private final JFXProgressBar bar = new JFXProgressBar(); + private final Label title = new Label(); + private final Label state = new Label(); + + public ProgressListNode(Task task) { + bar.progressProperty().bind(task.progressProperty()); + title.setText(task.getName()); + state.textProperty().bind(task.messageProperty()); + + BorderPane borderPane = new BorderPane(); + borderPane.setLeft(title); + borderPane.setRight(state); + getChildren().addAll(bar, borderPane); + + bar.setMinHeight(20); + bar.minWidthProperty().bind(widthProperty()); + bar.prefWidthProperty().bind(widthProperty()); + bar.maxWidthProperty().bind(widthProperty()); + } + + public void unbind() { + bar.progressProperty().unbind(); + state.textProperty().unbind(); + } + + public void setThrowable(Throwable throwable) { + unbind(); + state.setText(throwable.getLocalizedMessage()); + bar.setProgress(0); + } + } +} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/AbstractWizardDisplayer.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/AbstractWizardDisplayer.java index acafdba6f..33c207433 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/AbstractWizardDisplayer.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/AbstractWizardDisplayer.java @@ -26,6 +26,7 @@ import org.jackhuang.hmcl.task.Schedulers; import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.task.TaskExecutor; import org.jackhuang.hmcl.task.TaskListener; +import org.jackhuang.hmcl.ui.construct.TaskListPane; import org.jackhuang.hmcl.util.Lang; import java.util.Map; @@ -91,45 +92,9 @@ public interface AbstractWizardDisplayer extends WizardDisplayer { @Override default void handleTask(Map settings, Task task) { - VBox vbox = new VBox(); - JFXProgressBar progressBar = new JFXProgressBar(); - Label label = new Label(); - progressBar.setMaxHeight(10); - vbox.getChildren().addAll(progressBar, label); - - StackPane root = new StackPane(); - root.getChildren().add(vbox); - navigateTo(root, Navigation.NavigationDirection.FINISH); - - AtomicInteger finishedTasks = new AtomicInteger(0); - - TaskExecutor executor = task.with(Task.of(Schedulers.javafx(), this::navigateToSuccess)).executor(e -> new TaskListener() { - @Override - public void onReady(Task task) { - Platform.runLater(() -> progressBar.setProgress(finishedTasks.get() * 1.0 / e.getRunningTasks())); - } - - @Override - public void onFinished(Task task) { - Platform.runLater(() -> { - label.setText(task.getName()); - progressBar.setProgress(finishedTasks.incrementAndGet() * 1.0 / e.getRunningTasks()); - }); - } - - @Override - public void onFailed(Task task, Throwable throwable) { - Platform.runLater(() -> { - label.setText(task.getName()); - progressBar.setProgress(finishedTasks.incrementAndGet() * 1.0 / e.getRunningTasks()); - }); - } - - @Override - public void onTerminate() { - Platform.runLater(AbstractWizardDisplayer.this::navigateToSuccess); - } - }); + TaskExecutor executor = task.with(Task.of(Schedulers.javafx(), this::navigateToSuccess)).executor(); + TaskListPane pane = new TaskListPane(executor, () -> Platform.runLater(AbstractWizardDisplayer.this::navigateToSuccess)); + navigateTo(pane, Navigation.NavigationDirection.FINISH); getCancelQueue().add(executor); executor.start(); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/WizardController.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/WizardController.java index 0e8b8bde3..34a728c4a 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/WizardController.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/wizard/WizardController.java @@ -103,7 +103,7 @@ public class WizardController implements Navigation { if (result instanceof DeferredWizardResult) displayer.handleDeferredWizardResult(settings, ((DeferredWizardResult) result)); else if (result instanceof Summary) displayer.navigateTo(((Summary) result).getComponent(), NavigationDirection.NEXT); else if (result instanceof Task) displayer.handleTask(settings, ((Task) result)); - else throw new IllegalStateException("Unrecognized wizard result: " + result); + else if (result != null) throw new IllegalStateException("Unrecognized wizard result: " + result); } @Override diff --git a/HMCL/src/main/resources/assets/fxml/input-dialog.fxml b/HMCL/src/main/resources/assets/fxml/input-dialog.fxml new file mode 100644 index 000000000..cfbd81048 --- /dev/null +++ b/HMCL/src/main/resources/assets/fxml/input-dialog.fxml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/HMCL/src/main/resources/assets/fxml/version-item.fxml b/HMCL/src/main/resources/assets/fxml/version-item.fxml index cc2afa521..d536c14b6 100644 --- a/HMCL/src/main/resources/assets/fxml/version-item.fxml +++ b/HMCL/src/main/resources/assets/fxml/version-item.fxml @@ -6,6 +6,7 @@ + @@ -28,12 +29,26 @@ - - + + + + + - + + + + + + + + + + + + diff --git a/HMCL/src/main/resources/assets/fxml/version/version.fxml b/HMCL/src/main/resources/assets/fxml/version/version.fxml index ca97f8682..dcdeef0ab 100644 --- a/HMCL/src/main/resources/assets/fxml/version/version.fxml +++ b/HMCL/src/main/resources/assets/fxml/version/version.fxml @@ -23,6 +23,12 @@ + + + + + @@ -57,9 +63,9 @@ - diff --git a/HMCL/src/main/resources/assets/fxml/wizard.fxml b/HMCL/src/main/resources/assets/fxml/wizard.fxml index b86285a28..24994f178 100644 --- a/HMCL/src/main/resources/assets/fxml/wizard.fxml +++ b/HMCL/src/main/resources/assets/fxml/wizard.fxml @@ -7,6 +7,7 @@ diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 5ade51da1..007b9fcdc 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -17,17 +17,17 @@ #author: huangyuhui, dxNeil launch.failed=Failed to launch. launch.failed_creating_process=Failed to create process, maybe your java path is wrong, please modify your java path. -launch.failed_sh_permission=Failed to add permission to the launch script. -launch.failed_packing_jar=Failed to pack the jar. +launch.failed.sh_permission=Failed to add permission to the launch script. +launch.failed.packing_jar=Failed to pack the jar. launch.unsupported_launcher_version=Sorry, the launcher cannot launch minecraft, but will retry launching it. -launch.too_big_memory_alloc_64bit=You have allocated too much memory, because of your 32-Bit Java Runtime Environment, your game probably crash. The maximum memory is 1024MB. The launcher will try to launch it. -launch.too_big_memory_alloc_free_space_too_low=You have allocated too much memory, because the physical memory size is %dMB, your game probably crash. The launcher will try to launch it. -launch.cannot_create_jvm=We find that it cannot create java virutal machine. The Java argements may have problems. You can enable the no args mode in the settings. +launch.advice.too_large_memory_for_32bit=You have allocated too much memory, because of your 32-Bit Java Runtime Environment, your game probably crash. The maximum memory is 1024MB. The launcher will try to launch it. +launch.advice.not_enough_space=You have allocated too much memory, because the physical memory size is %dMB, your game probably crash. The launcher will try to launch it. +launch.failed.cannot_create_jvm=We find that it cannot create java virutal machine. The Java argements may have problems. You can enable the no args mode in the settings. launch.circular_dependency_versions=Found circular dependency versions, please check if your client has been modified. -launch.not_finished_downloading_libraries=Did not finish downloading libraries, continue launching game? -launch.not_finished_decompressing_natives=Did not finish decompressing native libraries, continue launching game? +launch.failed.downloading_libraries=Did not finish downloading libraries, continue launching game? +launch.failed.decompressing_natives=Did not finish decompressing native libraries, continue launching game? launch.wrong_javadir=Incorrect Java directory, will reset to default Java directory. -launch.exited_abnormally=Game exited abnormally, please visit the log, or ask someone for help. +launch.failed.exited_abnormally=Game exited abnormally, please visit the log, or ask someone for help. launch.state.logging_in=Logging In launch.state.generating_launching_codes=Generating Launching Codes @@ -111,9 +111,9 @@ ui.label.newProfileWindow.copy_from=Copy From: ui.newProfileWindow.title=New Config ui.button.ok=OK -ui.button.refresh=Refresh -ui.button.run=Play -ui.button.settings=Settings +ui.button.refresh=Refresh +version.launch=Play +version.manage.settings=Settings ui.button.about=About ui.button.others=Others ui.button.logout=Log Out @@ -208,8 +208,8 @@ modpack.export_finished=Exporting the modpack finished. See modpack.included_launcher=The modpack is included the launcher, you can publish it directly. modpack.not_included_launcher=You can use the modpack by clicking the "Import Modpack" button. modpack.enter_name=Enter your desired name for this game. - -modpack.task.save=Export Modpack +modpack.author=Author +modpack.export=Export Modpack modpack.task.install=Import Modpack modpack.task.install.error=Failed to install the modpack. Maybe the files is incorrect, or a management issue occurred. modpack.task.install.will=Install the modpack: @@ -274,10 +274,10 @@ advancedsettings.server_ip=Server Host advancedsettings.dont_check_game_completeness=Don't check game completeness mainwindow.show_log=Show Logs -mainwindow.make_launch_script=Make Launching Script. -mainwindow.make_launch_script_failed=Failed to make script. +version.launch_script=Make Launching Script. +version.launch_script.failed=Failed to make script. mainwindow.enter_script_name=Enter the script name. -mainwindow.make_launch_succeed=Finished script creation. +version.launch_script.success=Finished script creation, %s. mainwindow.no_version=No version found. Switch to Game Downloads Tab? launcher.about=About Author\nMinecraft Forum ID: klkl6523\nCopyright (c) 2013 huangyuhui\nOpened source under GPL v3 license:http://github.com/huanghongxun/HMCL/\nThis software used project Gson which is under Apache License 2.0, thanks contributors. @@ -308,21 +308,21 @@ game_settings=Games main_page=Home launcher_settings=Launcher -versions.release=Release -versions.snapshot=Snapshot -versions.old_beta=Beta -versions.old_alpha=Old Alpha +version.game.release=Release +version.game.snapshot=Snapshot +version.game.old_beta=Beta +version.game.old_alpha=Old Alpha -versions.manage.rename=Rename this version -versions.manage.rename.message=Please enter the new name -versions.manage.remove=Delete this version -versions.manage.remove.confirm=Sure to remove the version -versions.manage.redownload_json=Redownload Minecraft Configuration(minecraft.json) -versions.manage.redownload_assets_index=Redownload Assets Index -versions.manage.remove_libraries=Delete library files +version.manage.rename=Rename this version +version.manage.rename.message=Please enter the new name +version.manage.remove=Delete this version +version.manage.remove.confirm=Sure to remove the version +version.manage.redownload_json=Redownload Minecraft Configuration(minecraft.json) +version.manage.redownload_assets_index=Redownload Assets Index +version.manage.remove_libraries=Delete library files -advice.os64butjdk32=Your OS is 64-Bit but your Java is 32-Bit. The 64-Bit Java is recommended. -advice.java8=Java 8 is suggested, which can make game run more fluently. And many mods and Minecraft 1.12 and newer versions requires Java 8. +launch.advice.different_platform=Your OS is 64-Bit but your Java is 32-Bit. The 64-Bit Java is recommended. +launch.advice.newer_java=Java 8 is suggested, which can make game run more fluently. And many mods and Minecraft 1.12 and newer versions requires Java 8. assets.download_all=Download Assets Files assets.failed=Failed to get the list, try again. @@ -407,3 +407,9 @@ install.select=Select an operation install=Install New Game settings.icon=Game Icon launcher=Launcher +install.installer.install= +modpack.install=Install %s modpack +modpack.type.curse=Curse +modpack.type.multimc=MultiMC +modpack.type.hmcl=HMCL +modpack.type.curse.completion=Install relative files to Curse modpack diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties index 761b2b269..964246487 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -17,17 +17,17 @@ #author: huangyuhui launch.failed=启动失败 launch.failed_creating_process=启动失败,在创建新进程时发生错误,可能是Java路径错误。 -launch.failed_sh_permission=为启动文件添加权限时发生错误 -launch.failed_packing_jar=在打包jar时发生错误 +launch.failed.sh_permission=为启动文件添加权限时发生错误 +launch.failed.packing_jar=在打包jar时发生错误 launch.unsupported_launcher_version=对不起,本启动器现在可能不能启动这个版本的Minecraft,但启动器还是会尝试启动,请尽快将此问题报告给作者。 -launch.too_big_memory_alloc_64bit=您设置的内存大小过大,由于可能超过了32位Java的内存分配限制,所以可能无法启动游戏,请将内存调至1024MB或更小,启动器仍会尝试启动。 -launch.too_big_memory_alloc_free_space_too_low=您设置的内存大小过大,由于超过了系统内存大小%dMB,所以可能影响游戏体验或无法启动游戏,启动器仍会尝试启动。 -launch.cannot_create_jvm=截获到无法创建Java虚拟机,可能是Java参数有问题,可以在设置中开启无参数模式启动 +launch.advice.too_large_memory_for_32bit=您设置的内存大小过大,由于可能超过了32位Java的内存分配限制,所以可能无法启动游戏,请将内存调至1024MB或更小,启动器仍会尝试启动。 +launch.advice.not_enough_space=您设置的内存大小过大,由于超过了系统内存大小%dMB,所以可能影响游戏体验或无法启动游戏,启动器仍会尝试启动。 +launch.failed.cannot_create_jvm=截获到无法创建Java虚拟机,可能是Java参数有问题,可以在设置中开启无参数模式启动 launch.circular_dependency_versions=发现游戏版本循环引用,请确认您的客户端未被修改或修改导致出现此问题。 -launch.not_finished_downloading_libraries=未完成游戏依赖库的下载,还要继续启动游戏吗? -launch.not_finished_decompressing_natives=未能解压游戏本地库,还要继续启动游戏吗? +launch.failed.downloading_libraries=未完成游戏依赖库的下载,还要继续启动游戏吗? +launch.failed.decompressing_natives=未能解压游戏本地库,还要继续启动游戏吗? launch.wrong_javadir=错误的Java路径,将自动重置为默认Java路径。 -launch.exited_abnormally=游戏非正常退出,请查看日志文件,或联系他人寻求帮助。 +launch.failed.exited_abnormally=游戏非正常退出,请查看日志文件,或联系他人寻求帮助。 launch.state.logging_in=登录中 launch.state.generating_launching_codes=正在生成启动代码 @@ -112,8 +112,8 @@ ui.newProfileWindow.title=新建配置 ui.button.ok=确认 ui.button.refresh=刷新 -ui.button.run=启动Minecraft -ui.button.settings= +version.launch=启动游戏 +version.manage.settings=游戏设置 ui.button.about=关于 ui.button.others=其他 ui.button.logout=登出 @@ -209,7 +209,7 @@ modpack.not_included_launcher=整合包未包含启动器,可使用本软件 modpack.enter_name=给游戏起个你喜欢的名字 modpack.author=作者 -modpack.task.save=导出整合包 +modpack.export=导出整合包 modpack.task.install=导入整合包 modpack.task.install.error=安装失败,可能是整合包格式不正确或操作文件失败 modpack.task.install.will=将会安装整合包: @@ -274,10 +274,10 @@ advancedsettings.server_ip=直入服务器ip地址(不必填写,启动游戏 advancedsettings.dont_check_game_completeness=不检查游戏完整性 mainwindow.show_log=查看日志 -mainwindow.make_launch_script=生成启动脚本 -mainwindow.make_launch_script_failed=生成启动脚本失败 +version.launch_script=生成启动脚本 +version.launch_script.failed=生成启动脚本失败 mainwindow.enter_script_name=输入要生成脚本的文件名 -mainwindow.make_launch_succeed=启动脚本已生成完毕: +version.launch_script.success=启动脚本已生成完毕: %s. mainwindow.no_version=未找到任何版本,是否进入游戏下载? launcher.about=默认背景图感谢gamerteam提供。\n关于作者:\n百度ID:huanghongxun20\nmcbbs:huanghongxun\nMinecraft Forum ID: klkl6523\n欢迎提交Bug哦\nCopyright (c) 2013-2017 huangyuhui.\n免责声明:Minecraft软件版权归Mojang AB所有,使用本软件产生的版权问题本软件制作方概不负责。\n本启动器在GPLv3协议下开源:https://github.com/huanghongxun/HMCL/ ,感谢issues和pull requests贡献者\n本软件使用了基于Apache License 2.0的Gson项目,感谢贡献者。 @@ -308,21 +308,21 @@ game_settings=游戏设置 main_page=主页 launcher_settings=启动器设置 -versions.release=稳定版 -versions.snapshot=快照版 -versions.old_beta=测试版 -versions.old_alpha=远古版 +version.game.release=稳定版 +version.game.snapshot=快照版 +version.game.old_beta=测试版 +version.game.old_alpha=远古版 -versions.manage.rename=重命名该版本 -versions.manage.rename.message=请输入要改成的名字 -versions.manage.remove=删除该版本 -versions.manage.remove.confirm=真的要删除版本 -versions.manage.redownload_json=重新下载版本配置(minecraft.json) -versions.manage.redownload_assets_index=重新下载资源配置(assets_index.json) -versions.manage.remove_libraries=删除所有库文件 +version.manage.rename=重命名该版本 +version.manage.rename.message=请输入要改成的名字 +version.manage.remove=删除该版本 +version.manage.remove.confirm=真的要删除版本 +version.manage.redownload_json=重新下载版本配置(minecraft.json) +version.manage.redownload_assets_index=重新下载资源配置(assets_index.json) +version.manage.remove_libraries=删除所有库文件 -advice.os64butjdk32=您的系统是64位的但是Java是32位的,推荐您安装64位Java. -advice.java8=检测到您未使用Java 8及更新版本,Java 8能使游戏更流畅而且Minecraft 1.12及更新版本和很多Mod强制需要需要Java 8。 +launch.advice.different_platform=您的系统是64位的但是Java是32位的,推荐您安装64位Java. +launch.advice.newer_java=检测到您未使用Java 8及更新版本,Java 8能使游戏更流畅而且Minecraft 1.12及更新版本和很多Mod强制需要需要Java 8。 assets.download_all=下载资源文件 assets.failed=获取列表失败,请刷新重试。 @@ -407,3 +407,9 @@ install.select=请选择安装方式 install=添加游戏 settings.icon=游戏图标 launcher=启动器 +install.installer.install=安装%s +modpack.install=安装%s整合包 +modpack.type.curse=Curse +modpack.type.multimc=MultiMC +modpack.type.hmcl=HMCL +modpack.type.curse.completion=下载Curse整合包相关文件 diff --git a/HMCL/src/main/resources/assets/svg/script.fxml b/HMCL/src/main/resources/assets/svg/script.fxml new file mode 100644 index 000000000..f71133022 --- /dev/null +++ b/HMCL/src/main/resources/assets/svg/script.fxml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultGameBuilder.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultGameBuilder.java index 322eafbe4..4b9dc67d6 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultGameBuilder.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultGameBuilder.java @@ -23,6 +23,7 @@ import org.jackhuang.hmcl.task.ParallelTask; import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.util.AutoTypingMap; import org.jackhuang.hmcl.util.Constants; +import org.jackhuang.hmcl.util.ExceptionalFunction; import java.util.function.Function; @@ -63,7 +64,7 @@ public class DefaultGameBuilder extends GameBuilder { }); } - private Function, Task> libraryTaskHelper(String gameVersion, String libraryId) { + private ExceptionalFunction, Task, ?> libraryTaskHelper(String gameVersion, String libraryId) { return variables -> dependencyManager.installLibraryAsync(gameVersion, variables.get("version"), libraryId, toolVersions.get(libraryId)); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameAssetIndexDownloadTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameAssetIndexDownloadTask.java index ab6a10ffc..00aa82d70 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameAssetIndexDownloadTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameAssetIndexDownloadTask.java @@ -50,6 +50,7 @@ public final class GameAssetIndexDownloadTask extends Task { public GameAssetIndexDownloadTask(AbstractDependencyManager dependencyManager, Version version) { this.dependencyManager = dependencyManager; this.version = version; + setSignificance(TaskSignificance.MODERATE); } @Override diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameDownloadTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameDownloadTask.java index 0b50ed692..b6effe99c 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameDownloadTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameDownloadTask.java @@ -39,6 +39,8 @@ public final class GameDownloadTask extends Task { public GameDownloadTask(DefaultDependencyManager dependencyManager, Version version) { this.dependencyManager = dependencyManager; this.version = version; + + setSignificance(TaskSignificance.MODERATE); } @Override diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameLibrariesTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameLibrariesTask.java index 1535b7034..3c6686f04 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameLibrariesTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameLibrariesTask.java @@ -49,6 +49,7 @@ public final class GameLibrariesTask extends Task { public GameLibrariesTask(AbstractDependencyManager dependencyManager, Version version) { this.dependencyManager = dependencyManager; this.version = version; + setSignificance(TaskSignificance.MODERATE); } @Override diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameLoggingDownloadTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameLoggingDownloadTask.java index 4e9deedd1..ef4e14c76 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameLoggingDownloadTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameLoggingDownloadTask.java @@ -50,6 +50,7 @@ public final class GameLoggingDownloadTask extends Task { public GameLoggingDownloadTask(DependencyManager dependencyManager, Version version) { this.dependencyManager = dependencyManager; this.version = version; + setSignificance(TaskSignificance.MODERATE); } @Override diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/VersionJsonDownloadTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/VersionJsonDownloadTask.java index de0228502..12c414a07 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/VersionJsonDownloadTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/VersionJsonDownloadTask.java @@ -47,6 +47,8 @@ public final class VersionJsonDownloadTask extends Task { if (!gameVersionList.isLoaded()) dependents.add(gameVersionList.refreshAsync(dependencyManager.getDownloadProvider())); + + setSignificance(TaskSignificance.MODERATE); } @Override diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/VersionJsonSaveTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/VersionJsonSaveTask.java index 5fdeb1f01..9c12645b6 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/VersionJsonSaveTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/VersionJsonSaveTask.java @@ -45,6 +45,8 @@ public final class VersionJsonSaveTask extends Task { public VersionJsonSaveTask(DefaultGameRepository repository, Version version) { this.repository = repository; this.version = version; + + setSignificance(TaskSignificance.MODERATE); } @Override diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/CoupleTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/CoupleTask.java index 074a25296..06afe0f00 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/CoupleTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/CoupleTask.java @@ -18,6 +18,7 @@ package org.jackhuang.hmcl.task; import org.jackhuang.hmcl.util.AutoTypingMap; +import org.jackhuang.hmcl.util.ExceptionalFunction; import java.util.Collection; import java.util.Collections; @@ -35,7 +36,7 @@ final class CoupleTask

extends Task { private final boolean relyingOnDependents; private final Collection dependents; private final List dependencies = new LinkedList<>(); - private final Function, Task> succ; + private final ExceptionalFunction, Task, ?> succ; /** * A task that combines two tasks and make sure pred runs before succ. @@ -44,24 +45,21 @@ final class CoupleTask

extends Task { * @param succ a callback that returns the task runs after pred, succ will be executed asynchronously. You can do something that relies on the result of pred. * @param relyingOnDependents true if this task chain will be broken when task pred fails. */ - public CoupleTask(P pred, Function, Task> succ, boolean relyingOnDependents) { + public CoupleTask(P pred, ExceptionalFunction, Task, ?> succ, boolean relyingOnDependents) { this.dependents = Collections.singleton(pred); this.succ = succ; this.relyingOnDependents = relyingOnDependents; + + setSignificance(TaskSignificance.MODERATE); } @Override - public void execute() { + public void execute() throws Exception { Task task = succ.apply(getVariables()); if (task != null) dependencies.add(task); } - @Override - public boolean isHidden() { - return true; - } - @Override public Collection getDependents() { return dependents; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FileDownloadTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FileDownloadTask.java index c1defe1dd..aba4e5902 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FileDownloadTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FileDownloadTask.java @@ -88,6 +88,8 @@ public class FileDownloadTask extends Task { this.hash = hash; this.retry = retry; this.proxy = proxy; + + setName(file.getName()); } private void closeFiles() { @@ -101,6 +103,10 @@ public class FileDownloadTask extends Task { return onFailed; } + public URL getUrl() { + return url; + } + @Override public void execute() throws Exception { URL currentURL = url; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/GetTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/GetTask.java index e6f0d8d47..9cd1d0a2e 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/GetTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/GetTask.java @@ -65,6 +65,8 @@ public final class GetTask extends TaskResult { this.retry = retry; this.proxy = proxy; this.id = id; + + setName(url.toString()); } @Override diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/ParallelTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/ParallelTask.java index 565cdb16c..52ad66f13 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/ParallelTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/ParallelTask.java @@ -37,17 +37,13 @@ public final class ParallelTask extends Task { */ public ParallelTask(Task... tasks) { this.tasks = tasks; + setSignificance(TaskSignificance.MINOR); } @Override public void execute() { } - @Override - public boolean isHidden() { - return true; - } - @Override public Collection getDependents() { return Arrays.asList(tasks); 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 e916662db..0e5b5c104 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java @@ -22,10 +22,7 @@ import javafx.beans.property.ReadOnlyDoubleWrapper; import javafx.beans.property.ReadOnlyStringProperty; import javafx.beans.property.ReadOnlyStringWrapper; import org.jackhuang.hmcl.event.EventManager; -import org.jackhuang.hmcl.util.AutoTypingMap; -import org.jackhuang.hmcl.util.ExceptionalConsumer; -import org.jackhuang.hmcl.util.ExceptionalRunnable; -import org.jackhuang.hmcl.util.Properties; +import org.jackhuang.hmcl.util.*; import java.util.Collection; import java.util.Collections; @@ -42,11 +39,17 @@ public abstract class Task { private final EventManager onDone = new EventManager<>(); + private TaskSignificance significance = TaskSignificance.MAJOR; + /** * True if not logging when executing this task. */ - public boolean isHidden() { - return false; + public final TaskSignificance getSignificance() { + return significance; + } + + public void setSignificance(TaskSignificance significance) { + this.significance = significance; } /** @@ -139,10 +142,10 @@ public abstract class Task { } protected void updateProgress(double progress) { - if (progress > 1.0) + if (progress < 0 || progress > 1.0) throw new IllegalArgumentException("Progress is must between 0 and 1."); long now = System.currentTimeMillis(); - if (now - lastTime >= getProgressInterval()) { + if (lastTime == Long.MIN_VALUE || now - lastTime >= getProgressInterval()) { updateProgressImmediately(progress); lastTime = now; } @@ -186,7 +189,7 @@ public abstract class Task { public final TaskExecutor executor(Function taskListener) { TaskExecutor executor = new TaskExecutor(this); - executor.setTaskListener(taskListener.apply(executor)); + executor.addTaskListener(taskListener.apply(executor)); return executor; } @@ -224,7 +227,7 @@ public abstract class Task { return then(s -> b); } - public final Task then(Function, Task> b) { + public final Task then(ExceptionalFunction, Task, ?> b) { return new CoupleTask<>(this, b, true); } @@ -232,7 +235,7 @@ public abstract class Task { return with(s -> b); } - public final Task with(Function, Task> b) { + public final Task with(ExceptionalFunction, Task, ?> b) { return new CoupleTask<>(this, b, false); } @@ -264,4 +267,18 @@ public abstract class Task { public static TaskResult ofResult(String id, Function, V> closure) { return new TaskCallable2<>(id, closure); } + + public enum TaskSignificance { + MAJOR, + MODERATE, + MINOR; + + public boolean shouldLog() { + return this != MINOR; + } + + public boolean shouldShow() { + return this == MAJOR; + } + } } 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 5b0d7c37e..1e17e85da 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskExecutor.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskExecutor.java @@ -22,13 +22,11 @@ import org.jackhuang.hmcl.util.ExceptionalRunnable; import org.jackhuang.hmcl.util.Lang; import org.jackhuang.hmcl.util.Logging; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Objects; +import java.util.*; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Future; +import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.Level; @@ -40,7 +38,7 @@ import java.util.logging.Level; public final class TaskExecutor { private final Task firstTask; - private TaskListener taskListener = TaskListener.DefaultTaskListener.INSTANCE; + private List taskListeners = new LinkedList<>(); private boolean canceled = false; private Exception lastException; private final AtomicInteger totTask = new AtomicInteger(0); @@ -52,15 +50,8 @@ public final class TaskExecutor { this.firstTask = task; } - public TaskListener getTaskListener() { - return taskListener; - } - - public void setTaskListener(TaskListener taskListener) { - if (taskListener == null) - this.taskListener = TaskListener.DefaultTaskListener.INSTANCE; - else - this.taskListener = taskListener; + public void addTaskListener(TaskListener taskListener) { + taskListeners.add(taskListener); } public boolean isCanceled() { @@ -78,7 +69,10 @@ public final class TaskExecutor { public void start() { workerQueue.add(scheduler.schedule(() -> { if (!executeTasks(Collections.singleton(firstTask))) - taskListener.onTerminate(); + taskListeners.forEach(it -> { + it.onTerminate(); + it.onTerminate(variables); + }); })); } @@ -86,7 +80,10 @@ public final class TaskExecutor { AtomicBoolean flag = new AtomicBoolean(true); Future future = scheduler.schedule(() -> { if (!executeTasks(Collections.singleton(firstTask))) { - taskListener.onTerminate(); + taskListeners.forEach(it -> { + it.onTerminate(); + it.onTerminate(variables); + }); flag.set(false); } }); @@ -108,7 +105,7 @@ public final class TaskExecutor { } } - private boolean executeTasks(Collection tasks) { + private boolean executeTasks(Collection tasks) throws InterruptedException { if (tasks.isEmpty()) return true; @@ -119,38 +116,35 @@ public final class TaskExecutor { if (canceled) return false; Invoker invoker = new Invoker(task, latch, success); - Future future = task.getScheduler().schedule(invoker); - if (future != null) - workerQueue.add(future); + try { + Future future = task.getScheduler().schedule(invoker); + if (future != null) + workerQueue.add(future); + } catch (RejectedExecutionException e) { + throw new InterruptedException(); + } } if (canceled) return false; - try { - latch.await(); - return success.get() && !canceled; - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - // Once interrupted, we are aborting the subscription. - // and operations fail. - return false; - } + latch.await(); + return success.get() && !canceled; } private boolean executeTask(Task task) { if (canceled) return false; - if (!task.isHidden()) + if (task.getSignificance().shouldLog()) Logging.LOG.log(Level.FINE, "Executing task: {0}", task.getName()); - taskListener.onReady(task); + taskListeners.forEach(it -> it.onReady(task)); - boolean doDependentsSucceeded = executeTasks(task.getDependents()); boolean flag = false; try { + boolean doDependentsSucceeded = executeTasks(task.getDependents()); if (!doDependentsSucceeded && task.isRelyingOnDependents() || canceled) throw new SilentException(); @@ -166,27 +160,29 @@ public final class TaskExecutor { throw new IllegalStateException("Subtasks failed for " + task.getName()); flag = true; - if (!task.isHidden()) { + if (task.getSignificance().shouldLog()) { Logging.LOG.log(Level.FINER, "Task finished: {0}", task.getName()); task.onDone().fireEvent(new TaskEvent(this, task, false)); - taskListener.onFinished(task); + taskListeners.forEach(it -> it.onFinished(task)); } } catch (InterruptedException e) { - if (!task.isHidden()) { + if (task.getSignificance().shouldLog()) { lastException = e; Logging.LOG.log(Level.FINE, "Task aborted: " + task.getName(), e); task.onDone().fireEvent(new TaskEvent(this, task, true)); - taskListener.onFailed(task, e); + taskListeners.forEach(it -> it.onFailed(task, e)); } } catch (SilentException e) { // do nothing + } catch (RejectedExecutionException e) { + return false; } catch (Exception e) { - if (!task.isHidden()) { + if (task.getSignificance().shouldLog()) { lastException = e; Logging.LOG.log(Level.FINE, "Task failed: " + task.getName(), e); task.onDone().fireEvent(new TaskEvent(this, task, true)); - taskListener.onFailed(task, e); + taskListeners.forEach(it -> it.onFailed(task, e)); } } finally { task.setVariables(null); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskListener.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskListener.java index ecceaebca..f811218b3 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskListener.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskListener.java @@ -17,6 +17,8 @@ */ package org.jackhuang.hmcl.task; +import org.jackhuang.hmcl.util.AutoTypingMap; + import java.util.EventListener; /** @@ -37,6 +39,9 @@ public abstract class TaskListener implements EventListener { public void onTerminate() { } + public void onTerminate(AutoTypingMap variables) { + } + public static class DefaultTaskListener extends TaskListener { public static final DefaultTaskListener INSTANCE = new DefaultTaskListener();