From ee8be3166fb352c43dda56998e5c957fe9c49dd7 Mon Sep 17 00:00:00 2001 From: huanghongxun Date: Wed, 11 Mar 2020 00:27:29 +0800 Subject: [PATCH] fix: changing game version without alerting incompatibility --- .../ui/download/AdditionalInstallersPage.java | 49 ++++-- .../ui/download/InstallerWizardProvider.java | 156 ------------------ .../hmcl/ui/download/InstallersPage.java | 4 +- .../ModpackInstallWizardProvider.java | 2 +- .../UpdateInstallerWizardProvider.java | 84 +++++++++- .../VanillaInstallWizardProvider.java | 5 +- .../hmcl/ui/versions/InstallerListPage.java | 12 +- .../resources/assets/lang/I18N.properties | 1 + .../resources/assets/lang/I18N_zh.properties | 1 + .../assets/lang/I18N_zh_CN.properties | 1 + .../download/DefaultDependencyManager.java | 2 +- .../hmcl/download/DefaultGameBuilder.java | 2 +- 12 files changed, 127 insertions(+), 192 deletions(-) delete mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallerWizardProvider.java diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/AdditionalInstallersPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/AdditionalInstallersPage.java index 351f8cf0f..ab2d74e9c 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/AdditionalInstallersPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/AdditionalInstallersPage.java @@ -17,18 +17,16 @@ */ package org.jackhuang.hmcl.ui.download; -import com.jfoenix.controls.JFXButton; -import javafx.fxml.FXML; +import javafx.beans.binding.Bindings; +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.SimpleBooleanProperty; import javafx.scene.control.Label; -import javafx.scene.layout.StackPane; -import javafx.scene.layout.VBox; import org.jackhuang.hmcl.download.DownloadProvider; import org.jackhuang.hmcl.download.LibraryAnalyzer; import org.jackhuang.hmcl.download.RemoteVersion; import org.jackhuang.hmcl.game.GameRepository; -import org.jackhuang.hmcl.ui.FXUtils; +import org.jackhuang.hmcl.game.Version; import org.jackhuang.hmcl.ui.wizard.WizardController; -import org.jackhuang.hmcl.ui.wizard.WizardPage; import org.jackhuang.hmcl.util.Lang; import java.util.Map; @@ -38,15 +36,24 @@ import static org.jackhuang.hmcl.download.LibraryAnalyzer.LibraryType.*; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; class AdditionalInstallersPage extends InstallersPage { - protected final InstallerWizardProvider provider; + protected final BooleanProperty compatible = new SimpleBooleanProperty(); + protected final GameRepository repository; + protected final String gameVersion; + protected final Version version; - public AdditionalInstallersPage(InstallerWizardProvider provider, WizardController controller, GameRepository repository, DownloadProvider downloadProvider) { - super(controller, repository, provider.getGameVersion(), downloadProvider); - this.provider = provider; + public AdditionalInstallersPage(String gameVersion, Version version, WizardController controller, GameRepository repository, DownloadProvider downloadProvider) { + super(controller, repository, gameVersion, downloadProvider); + this.gameVersion = gameVersion; + this.version = version; + this.repository = repository; txtName.getValidators().clear(); - txtName.setText(provider.getVersion().getId()); + txtName.setText(version.getId()); txtName.setEditable(false); + + btnInstall.disableProperty().bind(Bindings.createBooleanBinding( + () -> !compatible.get() || !txtName.validate(), + txtName.textProperty(), compatible)); } @Override @@ -65,7 +72,7 @@ class AdditionalInstallersPage extends InstallersPage { @Override public void onNavigate(Map settings) { - LibraryAnalyzer analyzer = LibraryAnalyzer.analyze(provider.getVersion().resolvePreservingPatches(provider.getProfile().getRepository())); + LibraryAnalyzer analyzer = LibraryAnalyzer.analyze(version.resolvePreservingPatches(repository)); String game = analyzer.getVersion(MINECRAFT).orElse(null); String fabric = analyzer.getVersion(FABRIC).orElse(null); String forge = analyzer.getVersion(FORGE).orElse(null); @@ -76,13 +83,25 @@ class AdditionalInstallersPage extends InstallersPage { String[] libraryIds = new String[]{"game", "fabric", "forge", "liteloader", "optifine"}; String[] versions = new String[]{game, fabric, forge, liteLoader, optiFine}; + String currentGameVersion = Lang.nonNull(getVersion("game"), game); + + boolean compatible = true; for (int i = 0; i < libraryIds.length; ++i) { String libraryId = libraryIds[i]; - if (versions[i] != null || controller.getSettings().containsKey(libraryId)) - labels[i].setText(i18n("install.installer.version", i18n("install.installer." + libraryId)) + ": " + Lang.nonNull(getVersion(libraryId), versions[i])); - else + String libraryVersion = Lang.nonNull(getVersion(libraryId), versions[i]); + boolean alreadyInstalled = versions[i] != null; + if (!"game".equals(libraryId) && currentGameVersion != null && !currentGameVersion.equals(game) && getVersion(libraryId) == null && alreadyInstalled) { + // For third-party libraries, if game version is being changed, and the library is not being reinstalled, + // warns the user that we should update the library. + labels[i].setText(i18n("install.installer.change_version", i18n("install.installer." + libraryId), libraryVersion)); + compatible = false; + } else if (alreadyInstalled || controller.getSettings().containsKey(libraryId)) { + labels[i].setText(i18n("install.installer.version", i18n("install.installer." + libraryId)) + ": " + libraryVersion); + } else { labels[i].setText(i18n("install.installer.not_installed", i18n("install.installer." + libraryId))); + } } + this.compatible.set(compatible); } @Override diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallerWizardProvider.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallerWizardProvider.java deleted file mode 100644 index 17b164c80..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallerWizardProvider.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Hello Minecraft! Launcher - * Copyright (C) 2020 huangyuhui 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 . - */ -package org.jackhuang.hmcl.ui.download; - -import javafx.scene.Node; -import org.jackhuang.hmcl.download.ArtifactMalformedException; -import org.jackhuang.hmcl.download.DefaultDependencyManager; -import org.jackhuang.hmcl.download.DownloadProvider; -import org.jackhuang.hmcl.download.RemoteVersion; -import org.jackhuang.hmcl.download.VersionMismatchException; -import org.jackhuang.hmcl.download.fabric.FabricInstallTask; -import org.jackhuang.hmcl.download.game.GameAssetIndexDownloadTask; -import org.jackhuang.hmcl.download.game.LibraryDownloadException; -import org.jackhuang.hmcl.download.optifine.OptiFineInstallTask; -import org.jackhuang.hmcl.game.Version; -import org.jackhuang.hmcl.setting.Profile; -import org.jackhuang.hmcl.task.DownloadException; -import org.jackhuang.hmcl.task.Task; -import org.jackhuang.hmcl.ui.Controllers; -import org.jackhuang.hmcl.ui.construct.MessageDialogPane.MessageType; -import org.jackhuang.hmcl.ui.wizard.WizardController; -import org.jackhuang.hmcl.ui.wizard.WizardProvider; -import org.jackhuang.hmcl.util.StringUtils; -import org.jackhuang.hmcl.util.i18n.I18n; -import org.jackhuang.hmcl.util.io.ResponseCodeException; - -import java.net.SocketTimeoutException; -import java.net.URL; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import static org.jackhuang.hmcl.util.i18n.I18n.i18n; - -public final class InstallerWizardProvider implements WizardProvider { - private final Profile profile; - private final String gameVersion; - private final Version version; - - public InstallerWizardProvider(Profile profile, String gameVersion, Version version) { - this.profile = profile; - this.gameVersion = gameVersion; - this.version = version; - } - - public Profile getProfile() { - return profile; - } - - public String getGameVersion() { - return gameVersion; - } - - public Version getVersion() { - return version; - } - - @Override - public void start(Map settings) { - } - - @Override - public Object finish(Map settings) { - settings.put("title", i18n("install.installer.install_online")); - settings.put("success_message", i18n("install.success")); - settings.put("failure_callback", (FailureCallback) (settings1, exception, next) -> alertFailureMessage(exception, next)); - - Task ret = Task.supplyAsync(() -> version); - List stages = new ArrayList<>(); - for (Object value : settings.values()) { - if (value instanceof RemoteVersion) { - RemoteVersion remoteVersion = (RemoteVersion) value; - ret = ret.thenComposeAsync(version -> profile.getDependency().installLibraryAsync(version, remoteVersion)); - stages.add(String.format("hmcl.install.%s:%s", remoteVersion.getLibraryId(), remoteVersion.getSelfVersion())); - } - } - - return ret.thenComposeAsync(profile.getRepository().refreshVersionsAsync()).withStagesHint(stages); - } - - @Override - public Node createPage(WizardController controller, int step, Map settings) { - DownloadProvider provider = profile.getDependency().getPrimaryDownloadProvider(); - switch (step) { - case 0: - return new AdditionalInstallersPage(this, controller, profile.getRepository(), provider); - default: - throw new IllegalStateException(); - } - } - - @Override - public boolean cancel() { - return true; - } - - public static void alertFailureMessage(Exception exception, Runnable next) { - if (exception instanceof LibraryDownloadException) { - String message = i18n("launch.failed.download_library", ((LibraryDownloadException) exception).getLibrary().getName()) + "\n"; - if (exception.getCause() instanceof ResponseCodeException) { - ResponseCodeException rce = (ResponseCodeException) exception.getCause(); - int responseCode = rce.getResponseCode(); - URL url = rce.getUrl(); - if (responseCode == 404) - message += i18n("download.code.404", url); - else - message += i18n("download.failed", url, responseCode); - } else { - message += StringUtils.getStackTrace(exception.getCause()); - } - Controllers.dialog(message, i18n("install.failed.downloading"), MessageType.ERROR, next); - } else if (exception instanceof DownloadException) { - if (exception.getCause() instanceof SocketTimeoutException) { - Controllers.dialog(i18n("install.failed.downloading.timeout", ((DownloadException) exception).getUrl()), i18n("install.failed.downloading"), MessageType.ERROR, next); - } else if (exception.getCause() instanceof ResponseCodeException) { - ResponseCodeException responseCodeException = (ResponseCodeException) exception.getCause(); - if (I18n.hasKey("download.code." + responseCodeException.getResponseCode())) { - Controllers.dialog(i18n("download.code." + responseCodeException.getResponseCode(), ((DownloadException) exception).getUrl()), i18n("install.failed.downloading"), MessageType.ERROR, next); - } else { - Controllers.dialog(i18n("install.failed.downloading.detail", ((DownloadException) exception).getUrl()) + "\n" + StringUtils.getStackTrace(exception.getCause()), i18n("install.failed.downloading"), MessageType.ERROR, next); - } - } else { - Controllers.dialog(i18n("install.failed.downloading.detail", ((DownloadException) exception).getUrl()) + "\n" + StringUtils.getStackTrace(exception.getCause()), i18n("install.failed.downloading"), MessageType.ERROR, next); - } - } else if (exception instanceof OptiFineInstallTask.UnsupportedOptiFineInstallationException || - exception instanceof FabricInstallTask.UnsupportedFabricInstallationException) { - Controllers.dialog(i18n("install.failed.optifine_conflict"), i18n("install.failed"), MessageType.ERROR, next); - } else if (exception instanceof DefaultDependencyManager.UnsupportedLibraryInstallerException) { - Controllers.dialog(i18n("install.failed.install_online"), i18n("install.failed"), MessageType.ERROR, next); - } else if (exception instanceof ArtifactMalformedException) { - Controllers.dialog(i18n("install.failed.malformed"), i18n("install.failed"), MessageType.ERROR, next); - } else if (exception instanceof GameAssetIndexDownloadTask.GameAssetIndexMalformedException) { - Controllers.dialog(i18n("assets.index.malformed"), i18n("install.failed"), MessageType.ERROR, next); - } else if (exception instanceof VersionMismatchException) { - VersionMismatchException e = ((VersionMismatchException) exception); - Controllers.dialog(i18n("install.failed.version_mismatch", e.getExpect(), e.getActual()), i18n("install.failed"), MessageType.ERROR, next); - } else { - Controllers.dialog(StringUtils.getStackTrace(exception), i18n("install.failed"), MessageType.ERROR, next); - } - } -} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallersPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallersPage.java index eec131442..f3f490486 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallersPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallersPage.java @@ -20,6 +20,7 @@ package org.jackhuang.hmcl.ui.download; import com.jfoenix.controls.JFXButton; import com.jfoenix.controls.JFXTextField; import com.jfoenix.effects.JFXDepthManager; +import javafx.beans.binding.Bindings; import javafx.fxml.FXML; import javafx.scene.Node; import javafx.scene.control.Label; @@ -91,7 +92,8 @@ public class InstallersPage extends StackPane implements WizardPage { Validator nameValidator = new Validator(OperatingSystem::isNameValid); nameValidator.setMessage(i18n("install.new_game.malformed")); txtName.getValidators().addAll(hasVersion, nameValidator); - txtName.textProperty().addListener(e -> btnInstall.setDisable(!txtName.validate())); + btnInstall.disableProperty().bind(Bindings.createBooleanBinding(() -> !txtName.validate(), + txtName.textProperty())); txtName.setText(gameVersion); Node[] buttons = new Node[]{btnGame, btnFabric, btnForge, btnLiteLoader, btnOptiFine}; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/ModpackInstallWizardProvider.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/ModpackInstallWizardProvider.java index 83ca3c325..fdee06d60 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/ModpackInstallWizardProvider.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/ModpackInstallWizardProvider.java @@ -119,7 +119,7 @@ public class ModpackInstallWizardProvider implements WizardProvider { Controllers.dialog(i18n("install.success"), i18n("install.success"), MessageType.INFORMATION, next); } } else { - InstallerWizardProvider.alertFailureMessage(exception, next); + UpdateInstallerWizardProvider.alertFailureMessage(exception, next); } } }); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/UpdateInstallerWizardProvider.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/UpdateInstallerWizardProvider.java index 88755d8ea..e901da89a 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/UpdateInstallerWizardProvider.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/UpdateInstallerWizardProvider.java @@ -18,23 +18,36 @@ package org.jackhuang.hmcl.ui.download; import javafx.scene.Node; -import org.jackhuang.hmcl.download.DownloadProvider; -import org.jackhuang.hmcl.download.RemoteVersion; +import org.jackhuang.hmcl.download.*; +import org.jackhuang.hmcl.download.fabric.FabricInstallTask; +import org.jackhuang.hmcl.download.game.GameAssetIndexDownloadTask; +import org.jackhuang.hmcl.download.game.LibraryDownloadException; +import org.jackhuang.hmcl.download.optifine.OptiFineInstallTask; import org.jackhuang.hmcl.game.Version; import org.jackhuang.hmcl.setting.Profile; +import org.jackhuang.hmcl.task.DownloadException; +import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.ui.Controllers; +import org.jackhuang.hmcl.ui.construct.MessageDialogPane; import org.jackhuang.hmcl.ui.wizard.WizardController; import org.jackhuang.hmcl.ui.wizard.WizardProvider; +import org.jackhuang.hmcl.util.StringUtils; +import org.jackhuang.hmcl.util.i18n.I18n; +import org.jackhuang.hmcl.util.io.ResponseCodeException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.net.SocketTimeoutException; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; import java.util.Map; -import static org.jackhuang.hmcl.ui.download.InstallerWizardProvider.alertFailureMessage; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; public final class UpdateInstallerWizardProvider implements WizardProvider { private final Profile profile; + private final DefaultDependencyManager dependencyManager; private final String gameVersion; private final Version version; private final String libraryId; @@ -42,6 +55,7 @@ public final class UpdateInstallerWizardProvider implements WizardProvider { public UpdateInstallerWizardProvider(@NotNull Profile profile, @NotNull String gameVersion, @NotNull Version version, @NotNull String libraryId, @Nullable String oldLibraryVersion) { this.profile = profile; + this.dependencyManager = profile.getDependency(); this.gameVersion = gameVersion; this.version = version; this.libraryId = libraryId; @@ -60,8 +74,20 @@ public final class UpdateInstallerWizardProvider implements WizardProvider { // We remove library but not save it, // so if installation failed will not break down current version. - return profile.getDependency().installLibraryAsync(version, (RemoteVersion) settings.get(libraryId)) - .thenComposeAsync(profile.getRepository().refreshVersionsAsync()); + Task ret = Task.supplyAsync(() -> version); + List stages = new ArrayList<>(); + for (Object value : settings.values()) { + if (value instanceof RemoteVersion) { + RemoteVersion remoteVersion = (RemoteVersion) value; + ret = ret.thenComposeAsync(version -> dependencyManager.installLibraryAsync(version, remoteVersion)); + stages.add(String.format("hmcl.install.%s:%s", remoteVersion.getLibraryId(), remoteVersion.getSelfVersion())); + if ("game".equals(remoteVersion.getLibraryId())) { + stages.add("hmcl.install.assets"); + } + } + } + + return ret.thenComposeAsync(profile.getRepository()::save).thenComposeAsync(profile.getRepository().refreshVersionsAsync()).withStagesHint(stages); } @Override @@ -72,6 +98,9 @@ public final class UpdateInstallerWizardProvider implements WizardProvider { return new VersionsPage(controller, i18n("install.installer.choose", i18n("install.installer." + libraryId)), gameVersion, provider, libraryId, () -> { if (oldLibraryVersion == null) { controller.onFinish(); + } else if ("game".equals(libraryId)) { + String newGameVersion = ((RemoteVersion) settings.get(libraryId)).getSelfVersion(); + controller.onNext(new AdditionalInstallersPage(newGameVersion, version, controller, profile.getRepository(), provider)); } else { Controllers.confirmDialog(i18n("install.change_version.confirm", i18n("install.installer." + libraryId), oldLibraryVersion, ((RemoteVersion) settings.get(libraryId)).getSelfVersion()), i18n("install.change_version"), controller::onFinish, controller::onCancel); @@ -93,4 +122,49 @@ public final class UpdateInstallerWizardProvider implements WizardProvider { // So we cancel this wizard when VersionPage calls the method. return true; } + + public static void alertFailureMessage(Exception exception, Runnable next) { + if (exception instanceof LibraryDownloadException) { + String message = i18n("launch.failed.download_library", ((LibraryDownloadException) exception).getLibrary().getName()) + "\n"; + if (exception.getCause() instanceof ResponseCodeException) { + ResponseCodeException rce = (ResponseCodeException) exception.getCause(); + int responseCode = rce.getResponseCode(); + URL url = rce.getUrl(); + if (responseCode == 404) + message += i18n("download.code.404", url); + else + message += i18n("download.failed", url, responseCode); + } else { + message += StringUtils.getStackTrace(exception.getCause()); + } + Controllers.dialog(message, i18n("install.failed.downloading"), MessageDialogPane.MessageType.ERROR, next); + } else if (exception instanceof DownloadException) { + if (exception.getCause() instanceof SocketTimeoutException) { + Controllers.dialog(i18n("install.failed.downloading.timeout", ((DownloadException) exception).getUrl()), i18n("install.failed.downloading"), MessageDialogPane.MessageType.ERROR, next); + } else if (exception.getCause() instanceof ResponseCodeException) { + ResponseCodeException responseCodeException = (ResponseCodeException) exception.getCause(); + if (I18n.hasKey("download.code." + responseCodeException.getResponseCode())) { + Controllers.dialog(i18n("download.code." + responseCodeException.getResponseCode(), ((DownloadException) exception).getUrl()), i18n("install.failed.downloading"), MessageDialogPane.MessageType.ERROR, next); + } else { + Controllers.dialog(i18n("install.failed.downloading.detail", ((DownloadException) exception).getUrl()) + "\n" + StringUtils.getStackTrace(exception.getCause()), i18n("install.failed.downloading"), MessageDialogPane.MessageType.ERROR, next); + } + } else { + Controllers.dialog(i18n("install.failed.downloading.detail", ((DownloadException) exception).getUrl()) + "\n" + StringUtils.getStackTrace(exception.getCause()), i18n("install.failed.downloading"), MessageDialogPane.MessageType.ERROR, next); + } + } else if (exception instanceof OptiFineInstallTask.UnsupportedOptiFineInstallationException || + exception instanceof FabricInstallTask.UnsupportedFabricInstallationException) { + Controllers.dialog(i18n("install.failed.optifine_conflict"), i18n("install.failed"), MessageDialogPane.MessageType.ERROR, next); + } else if (exception instanceof DefaultDependencyManager.UnsupportedLibraryInstallerException) { + Controllers.dialog(i18n("install.failed.install_online"), i18n("install.failed"), MessageDialogPane.MessageType.ERROR, next); + } else if (exception instanceof ArtifactMalformedException) { + Controllers.dialog(i18n("install.failed.malformed"), i18n("install.failed"), MessageDialogPane.MessageType.ERROR, next); + } else if (exception instanceof GameAssetIndexDownloadTask.GameAssetIndexMalformedException) { + Controllers.dialog(i18n("assets.index.malformed"), i18n("install.failed"), MessageDialogPane.MessageType.ERROR, next); + } else if (exception instanceof VersionMismatchException) { + VersionMismatchException e = ((VersionMismatchException) exception); + Controllers.dialog(i18n("install.failed.version_mismatch", e.getExpect(), e.getActual()), i18n("install.failed"), MessageDialogPane.MessageType.ERROR, next); + } else { + Controllers.dialog(StringUtils.getStackTrace(exception), i18n("install.failed"), MessageDialogPane.MessageType.ERROR, next); + } + } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VanillaInstallWizardProvider.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VanillaInstallWizardProvider.java index a4eb7202c..19ba95755 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VanillaInstallWizardProvider.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VanillaInstallWizardProvider.java @@ -62,7 +62,7 @@ public final class VanillaInstallWizardProvider implements WizardProvider { public Object finish(Map settings) { settings.put("title", i18n("install.new_game")); 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) -> UpdateInstallerWizardProvider.alertFailureMessage(exception, next)); return finishVersionDownloadingAsync(settings); } @@ -72,7 +72,8 @@ public final class VanillaInstallWizardProvider implements WizardProvider { DownloadProvider provider = profile.getDependency().getPrimaryDownloadProvider(); switch (step) { case 0: - return new VersionsPage(controller, i18n("install.installer.choose", i18n("install.installer.game")), "", provider, "game", () -> controller.onNext(new InstallersPage(controller, profile.getRepository(), ((RemoteVersion) controller.getSettings().get("game")).getGameVersion(), provider))); + return new VersionsPage(controller, i18n("install.installer.choose", i18n("install.installer.game")), "", provider, "game", + () -> controller.onNext(new InstallersPage(controller, profile.getRepository(), ((RemoteVersion) controller.getSettings().get("game")).getGameVersion(), provider))); default: throw new IllegalStateException("error step " + step + ", settings: " + settings + ", pages: " + controller.getPages()); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/InstallerListPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/InstallerListPage.java index f8049305b..7e157becb 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/InstallerListPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/InstallerListPage.java @@ -30,7 +30,6 @@ import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.task.TaskExecutor; import org.jackhuang.hmcl.task.TaskListener; import org.jackhuang.hmcl.ui.*; -import org.jackhuang.hmcl.ui.download.InstallerWizardProvider; import org.jackhuang.hmcl.ui.download.UpdateInstallerWizardProvider; import org.jackhuang.hmcl.util.Lang; import org.jackhuang.hmcl.util.io.FileUtils; @@ -88,7 +87,7 @@ public class InstallerListPage extends ListPageBase { for (LibraryAnalyzer.LibraryType type : LibraryAnalyzer.LibraryType.values()) { String libraryId = type.getPatchId(); String libraryVersion = analyzer.getVersion(type).orElse(null); - Consumer action = libraryVersion == null ? null : removeAction.apply(libraryId); + Consumer action = "game".equals(libraryId) || libraryVersion == null ? null : removeAction.apply(libraryId); itemsProperty().add(new InstallerItem(libraryId, libraryVersion, () -> { Controllers.getDecorator().startWizard(new UpdateInstallerWizardProvider(profile, gameVersion, version, libraryId, libraryVersion)); }, action)); @@ -114,13 +113,6 @@ public class InstallerListPage extends ListPageBase { }, Platform::runLater); } - public void installOnline() { - if (gameVersion == null) - Controllers.dialog(i18n("version.cannot_read")); - else - Controllers.getDecorator().startWizard(new InstallerWizardProvider(profile, gameVersion, version)); - } - public void installOffline() { FileChooser chooser = new FileChooser(); chooser.getExtensionFilters().add(new FileChooser.ExtensionFilter(i18n("install.installer.install_offline.extension"), "*.jar", "*.exe")); @@ -142,7 +134,7 @@ public class InstallerListPage extends ListPageBase { } else { if (executor.getException() == null) return; - InstallerWizardProvider.alertFailureMessage(executor.getException(), null); + UpdateInstallerWizardProvider.alertFailureMessage(executor.getException(), null); } }); } diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index ad185ed34..5c023a79c 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -139,6 +139,7 @@ install.failed.install_online=Unable to recognize the provided installer file install.failed.malformed=The files just downloaded a moment ago is malformed. You may switch to other download provider to resolve this problem. install.failed.optifine_conflict=Fabric, OptiFine and Forge are installed simultaneously on Minecraft 1.13 install.failed.version_mismatch=The library requires the game version %s, but the actual version is %s. +install.installer.change_version=%s version: %s, this version is not compatible with current game version. Click here to choose another one. install.installer.choose=Choose a %s version install.installer.fabric=Fabric install.installer.forge=Forge diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index 4008d1d7e..f20f02c17 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -138,6 +138,7 @@ install.failed.install_online=無法識別要安裝的軟體 install.failed.malformed=剛才下載的檔案格式損壞。您可以切換到其他下載來源以解決此問題。 install.failed.optifine_conflict=暫不支援 OptiFine 與 Forge 同時安裝在 Minecraft 1.13 上 install.failed.version_mismatch=該軟體需要的遊戲版本為 %s,但實際的遊戲版本為 %s。 +install.installer.change_version=%s 版本: %s,該版本與當前遊戲不相容,您需要點擊此處更換版本或刪除 install.installer.choose=選擇 %s 版本 install.installer.fabric=Fabric install.installer.forge=Forge 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 7c0957cca..d44c91a18 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -138,6 +138,7 @@ install.failed.install_online=无法识别要安装的软件 install.failed.malformed=刚才下载的文件格式损坏。您可以切换到其他下载源来解决此问题。 install.failed.optifine_conflict=暂不支持 OptiFine, Fabric 与 Forge 同时安装在 Minecraft 1.13 及以上版本 install.failed.version_mismatch=该软件需要的游戏版本为 %s,但实际的游戏版本为 %s。 +install.installer.change_version=%s 版本: %s,该版本与当前游戏不兼容,您需要点击此处更换版本或删除 install.installer.choose=选择 %s 版本 install.installer.fabric=Fabric install.installer.forge=Forge diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java index 30b04b38d..de3fc72a3 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java @@ -112,7 +112,7 @@ public class DefaultDependencyManager extends AbstractDependencyManager { return removeLibraryAsync(baseVersion.resolvePreservingPatches(repository), libraryVersion.getLibraryId()) .thenComposeAsync(version -> libraryVersion.getInstallTask(this, version)) .thenApplyAsync(baseVersion::addPatch) - .thenComposeAsync(repository::save).withStage(String.format("hmcl.install.%s:%s", libraryVersion.getLibraryId(), libraryVersion.getSelfVersion())); + .withStage(String.format("hmcl.install.%s:%s", libraryVersion.getLibraryId(), libraryVersion.getSelfVersion())); } public Task installLibraryAsync(Version oldVersion, Path installer) { 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 94e8c08d1..32240ed6e 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultGameBuilder.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultGameBuilder.java @@ -66,7 +66,7 @@ public class DefaultGameBuilder extends GameBuilder { stages.add(String.format("hmcl.install.%s:%s", remoteVersion.getLibraryId(), remoteVersion.getSelfVersion())); } - return libraryTask.whenComplete(exception -> { + return libraryTask.thenComposeAsync(dependencyManager.getGameRepository()::save).whenComplete(exception -> { if (exception != null) dependencyManager.getGameRepository().removeVersionFromDisk(name); }).withStagesHint(stages);