From 494b27cc224d97b74ceade09ab111386eca06acc Mon Sep 17 00:00:00 2001 From: huangyuhui Date: Tue, 27 Feb 2018 23:05:05 +0800 Subject: [PATCH] May fix RemoteVersion not found exception --- .../ui/download/AdditionalInstallersPage.java | 12 +++- .../ui/download/DownloadWizardProvider.java | 9 +-- .../ui/download/InstallerWizardProvider.java | 7 +- .../hmcl/ui/download/InstallersPage.java | 16 +++-- .../hmcl/ui/download/VersionsPage.java | 2 +- .../resources/assets/fxml/version-item.fxml | 2 +- .../download/DefaultDependencyManager.java | 47 ++++++++----- .../hmcl/download/DefaultGameBuilder.java | 4 ++ .../hmcl/download/DependencyManager.java | 10 +++ .../jackhuang/hmcl/download/GameBuilder.java | 10 ++- .../hmcl/download/RemoteVersion.java | 10 +++ .../jackhuang/hmcl/download/VersionList.java | 41 +++++++++-- .../hmcl/download/forge/ForgeInstallTask.java | 22 ++---- .../download/forge/ForgeRemoteVersion.java | 33 +++++++++ .../hmcl/download/forge/ForgeVersionList.java | 54 +++++++------- .../hmcl/download/game/GameVersionList.java | 24 ++++--- .../liteloader/LiteLoaderInstallTask.java | 24 +------ .../liteloader/LiteLoaderRemoteVersion.java | 36 ++++++++++ .../liteloader/LiteLoaderVersionList.java | 30 ++++---- .../optifine/OptiFineBMCLVersionList.java | 2 +- .../optifine/OptiFineInstallTask.java | 27 ++----- .../optifine/OptiFineRemoteVersion.java | 4 +- .../optifine/OptiFineVersionList.java | 70 ++++++++++--------- .../org/jackhuang/hmcl/task/CoupleTask.java | 9 +-- .../java/org/jackhuang/hmcl/task/Task.java | 8 ++- 25 files changed, 317 insertions(+), 196 deletions(-) create mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeRemoteVersion.java create mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/download/liteloader/LiteLoaderRemoteVersion.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 7f73aa0ca..597a9f2a9 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 @@ -24,6 +24,7 @@ import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; import org.jackhuang.hmcl.Main; import org.jackhuang.hmcl.download.DownloadProvider; +import org.jackhuang.hmcl.download.RemoteVersion; import org.jackhuang.hmcl.game.GameRepository; import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.ui.wizard.WizardController; @@ -31,6 +32,7 @@ import org.jackhuang.hmcl.ui.wizard.WizardPage; import org.jackhuang.hmcl.util.Lang; import java.util.Map; +import java.util.Optional; import static org.jackhuang.hmcl.Main.i18n; @@ -101,24 +103,28 @@ class AdditionalInstallersPage extends StackPane implements WizardPage { return Main.i18n("settings.tabs.installers"); } + private String getVersion(String id) { + return Optional.ofNullable(controller.getSettings().get(id)).map(it -> (RemoteVersion) it).map(RemoteVersion::getSelfVersion).orElse(null); + } + @Override public void onNavigate(Map settings) { lblGameVersion.setText(Main.i18n("install.new_game.current_game_version") + ": " + provider.getGameVersion()); btnForge.setDisable(provider.getForge() != null); if (provider.getForge() != null || controller.getSettings().containsKey("forge")) - lblForge.setText(Main.i18n("install.installer.version", Main.i18n("install.installer.forge")) + ": " + Lang.nonNull(provider.getForge(), controller.getSettings().get("forge"))); + lblForge.setText(Main.i18n("install.installer.version", Main.i18n("install.installer.forge")) + ": " + Lang.nonNull(provider.getForge(), getVersion("forge"))); else lblForge.setText(Main.i18n("install.installer.not_installed", Main.i18n("install.installer.forge"))); btnLiteLoader.setDisable(provider.getLiteLoader() != null); if (provider.getLiteLoader() != null || controller.getSettings().containsKey("liteloader")) - lblLiteLoader.setText(Main.i18n("install.installer.version", Main.i18n("install.installer.liteloader")) + ": " + Lang.nonNull(provider.getLiteLoader(), controller.getSettings().get("liteloader"))); + lblLiteLoader.setText(Main.i18n("install.installer.version", Main.i18n("install.installer.liteloader")) + ": " + Lang.nonNull(provider.getLiteLoader(), getVersion("liteloader"))); else lblLiteLoader.setText(Main.i18n("install.installer.not_installed", Main.i18n("install.installer.liteloader"))); btnOptiFine.setDisable(provider.getOptiFine() != null); if (provider.getOptiFine() != null || controller.getSettings().containsKey("optifine")) - lblOptiFine.setText(Main.i18n("install.installer.version", Main.i18n("install.installer.optifine")) + ": " + Lang.nonNull(provider.getOptiFine(), controller.getSettings().get("optifine"))); + lblOptiFine.setText(Main.i18n("install.installer.version", Main.i18n("install.installer.optifine")) + ": " + Lang.nonNull(provider.getOptiFine(), getVersion("optifine"))); else lblOptiFine.setText(Main.i18n("install.installer.not_installed", Main.i18n("install.installer.optifine"))); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/DownloadWizardProvider.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/DownloadWizardProvider.java index 585b401b8..2c3787c8d 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/DownloadWizardProvider.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/DownloadWizardProvider.java @@ -21,6 +21,7 @@ import javafx.scene.Node; import org.jackhuang.hmcl.Main; import org.jackhuang.hmcl.download.DownloadProvider; import org.jackhuang.hmcl.download.GameBuilder; +import org.jackhuang.hmcl.download.RemoteVersion; import org.jackhuang.hmcl.game.ModpackHelper; import org.jackhuang.hmcl.mod.Modpack; import org.jackhuang.hmcl.setting.Profile; @@ -48,16 +49,16 @@ public final class DownloadWizardProvider implements WizardProvider { GameBuilder builder = profile.getDependency().gameBuilder(); builder.name((String) settings.get("name")); - builder.gameVersion((String) settings.get("game")); + builder.gameVersion(((RemoteVersion) settings.get("game")).getGameVersion()); if (settings.containsKey("forge")) - builder.version("forge", (String) settings.get("forge")); + builder.version((RemoteVersion) settings.get("forge")); if (settings.containsKey("liteloader")) - builder.version("liteloader", (String) settings.get("liteloader")); + builder.version((RemoteVersion) settings.get("liteloader")); if (settings.containsKey("optifine")) - builder.version("optifine", (String) settings.get("optifine")); + builder.version((RemoteVersion) settings.get("optifine")); return builder.buildAsync().finalized((a, b) -> profile.getRepository().refreshVersions()); } 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 index e18b39cb0..9272dc7e3 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallerWizardProvider.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallerWizardProvider.java @@ -20,6 +20,7 @@ package org.jackhuang.hmcl.ui.download; import javafx.scene.Node; import org.jackhuang.hmcl.Main; import org.jackhuang.hmcl.download.BMCLAPIDownloadProvider; +import org.jackhuang.hmcl.download.RemoteVersion; import org.jackhuang.hmcl.game.Version; import org.jackhuang.hmcl.setting.Profile; import org.jackhuang.hmcl.task.Task; @@ -85,13 +86,13 @@ public final class InstallerWizardProvider implements WizardProvider { Task ret = Task.empty(); if (settings.containsKey("forge")) - ret = ret.then(profile.getDependency().installLibraryAsync(gameVersion, version, "forge", (String) settings.get("forge"))); + ret = ret.then(profile.getDependency().installLibraryAsync(version, (RemoteVersion) settings.get("forge"))); if (settings.containsKey("liteloader")) - ret = ret.then(profile.getDependency().installLibraryAsync(gameVersion, version, "liteloader", (String) settings.get("liteloader"))); + ret = ret.then(profile.getDependency().installLibraryAsync(version, (RemoteVersion) settings.get("liteloader"))); if (settings.containsKey("optifine")) - ret = ret.then(profile.getDependency().installLibraryAsync(gameVersion, version, "optifine", (String) settings.get("optifine"))); + ret = ret.then(profile.getDependency().installLibraryAsync(version, (RemoteVersion) settings.get("optifine"))); return ret.then(profile.getRepository().refreshVersionsAsync()); } 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 d64c21be0..6f81fc2bb 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 @@ -25,6 +25,7 @@ import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; import org.jackhuang.hmcl.Main; import org.jackhuang.hmcl.download.DownloadProvider; +import org.jackhuang.hmcl.download.RemoteVersion; import org.jackhuang.hmcl.game.GameRepository; import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.ui.construct.Validator; @@ -33,6 +34,7 @@ import org.jackhuang.hmcl.ui.wizard.WizardPage; import org.jackhuang.hmcl.util.StringUtils; import java.util.Map; +import java.util.Optional; public class InstallersPage extends StackPane implements WizardPage { private final WizardController controller; @@ -76,7 +78,7 @@ public class InstallersPage extends StackPane implements WizardPage { FXUtils.loadFXML(this, "/assets/fxml/download/installers.fxml"); - String gameVersion = (String) controller.getSettings().get("game"); + String gameVersion = ((RemoteVersion) controller.getSettings().get("game")).getGameVersion(); Validator hasVersion = new Validator(s -> !repository.hasVersion(s) && StringUtils.isNotBlank(s)); hasVersion.setMessage(Main.i18n("install.new_game.already_exists")); txtName.getValidators().add(hasVersion); @@ -104,21 +106,25 @@ public class InstallersPage extends StackPane implements WizardPage { return Main.i18n("install.new_game"); } + private String getVersion(String id) { + return ((RemoteVersion) controller.getSettings().get(id)).getSelfVersion(); + } + @Override public void onNavigate(Map settings) { - lblGameVersion.setText(Main.i18n("install.new_game.current_game_version") + ": " + controller.getSettings().get("game")); + lblGameVersion.setText(Main.i18n("install.new_game.current_game_version") + ": " + getVersion("game")); if (controller.getSettings().containsKey("forge")) - lblForge.setText(Main.i18n("install.installer.version", Main.i18n("install.installer.forge")) + ": " + controller.getSettings().get("forge")); + lblForge.setText(Main.i18n("install.installer.version", Main.i18n("install.installer.forge")) + ": " + getVersion("forge")); else lblForge.setText(Main.i18n("install.installer.not_installed", Main.i18n("install.installer.forge"))); if (controller.getSettings().containsKey("liteloader")) - lblLiteLoader.setText(Main.i18n("install.installer.version", Main.i18n("install.installer.liteloader")) + ": " + controller.getSettings().get("liteloader")); + lblLiteLoader.setText(Main.i18n("install.installer.version", Main.i18n("install.installer.liteloader")) + ": " + getVersion("liteloader")); else lblLiteLoader.setText(Main.i18n("install.installer.not_installed", Main.i18n("install.installer.liteloader"))); if (controller.getSettings().containsKey("optifine")) - lblOptiFine.setText(Main.i18n("install.installer.version", Main.i18n("install.installer.optifine")) + ": " + controller.getSettings().get("optifine")); + lblOptiFine.setText(Main.i18n("install.installer.version", Main.i18n("install.installer.optifine")) + ": " + getVersion("optifine")); else lblOptiFine.setText(Main.i18n("install.installer.not_installed", Main.i18n("install.installer.optifine"))); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java index c47b2637b..bf02c6990 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java @@ -96,7 +96,7 @@ public final class VersionsPage extends StackPane implements WizardPage, Refresh list.getSelectionModel().selectedItemProperty().addListener((a, b, newValue) -> { if (newValue == null) return; - controller.getSettings().put(libraryId, newValue.getRemoteVersion().getSelfVersion()); + controller.getSettings().put(libraryId, newValue.getRemoteVersion()); callback.run(); }); refresh(); diff --git a/HMCL/src/main/resources/assets/fxml/version-item.fxml b/HMCL/src/main/resources/assets/fxml/version-item.fxml index 9d0b86063..55c2766ba 100644 --- a/HMCL/src/main/resources/assets/fxml/version-item.fxml +++ b/HMCL/src/main/resources/assets/fxml/version-item.fxml @@ -15,7 +15,7 @@ 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 e3442bbb1..f86b080e1 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java @@ -18,9 +18,12 @@ package org.jackhuang.hmcl.download; import org.jackhuang.hmcl.download.forge.ForgeInstallTask; +import org.jackhuang.hmcl.download.forge.ForgeRemoteVersion; import org.jackhuang.hmcl.download.game.*; import org.jackhuang.hmcl.download.liteloader.LiteLoaderInstallTask; +import org.jackhuang.hmcl.download.liteloader.LiteLoaderRemoteVersion; import org.jackhuang.hmcl.download.optifine.OptiFineInstallTask; +import org.jackhuang.hmcl.download.optifine.OptiFineRemoteVersion; import org.jackhuang.hmcl.game.DefaultGameRepository; import org.jackhuang.hmcl.game.Version; import org.jackhuang.hmcl.task.ParallelTask; @@ -80,25 +83,31 @@ public class DefaultDependencyManager extends AbstractDependencyManager { @Override public Task installLibraryAsync(String gameVersion, Version version, String libraryId, String libraryVersion) { - switch (libraryId) { - case "forge": - return new ForgeInstallTask(this, gameVersion, version, libraryVersion) - .then(variables -> new LibrariesUniqueTask(variables.get("version"))) - .then(variables -> new MaintainTask(variables.get("version"))) - .then(variables -> new VersionJsonSaveTask(repository, variables.get("version"))); - case "liteloader": - return new LiteLoaderInstallTask(this, gameVersion, version, libraryVersion) - .then(variables -> new LibrariesUniqueTask(variables.get("version"))) - .then(variables -> new MaintainTask(variables.get("version"))) - .then(variables -> new VersionJsonSaveTask(repository, variables.get("version"))); - case "optifine": - return new OptiFineInstallTask(this, gameVersion, version, libraryVersion) - .then(variables -> new LibrariesUniqueTask(variables.get("version"))) - .then(variables -> new MaintainTask(variables.get("version"))) - .then(variables -> new VersionJsonSaveTask(repository, variables.get("version"))); - default: - throw new IllegalArgumentException("Library id " + libraryId + " is unrecognized."); - } + VersionList versionList = getVersionList(libraryId); + return versionList.loadAsync(getDownloadProvider()) + .then(variables -> installLibraryAsync(version, versionList.getVersion(gameVersion, libraryVersion) + .orElseThrow(() -> new IllegalStateException("Remote library " + libraryId + " has no version " + libraryVersion)))); + } + + @Override + public Task installLibraryAsync(Version version, RemoteVersion libraryVersion) { + if (libraryVersion instanceof ForgeRemoteVersion) + return new ForgeInstallTask(this, version, (ForgeRemoteVersion) libraryVersion) + .then(variables -> new LibrariesUniqueTask(variables.get("version"))) + .then(variables -> new MaintainTask(variables.get("version"))) + .then(variables -> new VersionJsonSaveTask(repository, variables.get("version"))); + else if (libraryVersion instanceof LiteLoaderRemoteVersion) + return new LiteLoaderInstallTask(this, version, (LiteLoaderRemoteVersion) libraryVersion) + .then(variables -> new LibrariesUniqueTask(variables.get("version"))) + .then(variables -> new MaintainTask(variables.get("version"))) + .then(variables -> new VersionJsonSaveTask(repository, variables.get("version"))); + else if (libraryVersion instanceof OptiFineRemoteVersion) + return new OptiFineInstallTask(this, version, (OptiFineRemoteVersion) libraryVersion) + .then(variables -> new LibrariesUniqueTask(variables.get("version"))) + .then(variables -> new MaintainTask(variables.get("version"))) + .then(variables -> new VersionJsonSaveTask(repository, variables.get("version"))); + else + throw new IllegalArgumentException("Remote library " + libraryVersion + " is unrecognized."); } } 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 78128fa9e..811fc972f 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultGameBuilder.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultGameBuilder.java @@ -67,6 +67,10 @@ public class DefaultGameBuilder extends GameBuilder { result = result.then(libraryTaskHelper(gameVersion, "liteloader")); if (toolVersions.containsKey("optifine")) result = result.then(libraryTaskHelper(gameVersion, "optifine")); + + for (RemoteVersion remoteVersion : remoteVersions) + result = result.then(var -> dependencyManager.installLibraryAsync(var.get("version"), remoteVersion)); + return result; }).finalized((variables, isDependentsSucceeded) -> { if (!isDependentsSucceeded) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DependencyManager.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DependencyManager.java index c7b442e6a..830b90314 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DependencyManager.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DependencyManager.java @@ -66,6 +66,16 @@ public interface DependencyManager { */ Task installLibraryAsync(String gameVersion, Version version, String libraryId, String libraryVersion); + /** + * Install a library to a version. + * **Note**: Installing a library may change the version.json. + * + * @param version the version.json.\ + * @param libraryVersion the remote version of being installed library. + * @return the task to install the specific library. + */ + Task installLibraryAsync(Version version, RemoteVersion libraryVersion); + /** * Get registered version list. * diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/GameBuilder.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/GameBuilder.java index d7910806d..cf7319408 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/GameBuilder.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/GameBuilder.java @@ -19,9 +19,7 @@ package org.jackhuang.hmcl.download; import org.jackhuang.hmcl.task.Task; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; +import java.util.*; /** * The builder which provide a task to build Minecraft environment. @@ -33,6 +31,7 @@ public abstract class GameBuilder { protected String name = ""; protected String gameVersion = ""; protected final Map toolVersions = new HashMap<>(); + protected final Set> remoteVersions = new HashSet<>(); public String getName() { return name; @@ -65,6 +64,11 @@ public abstract class GameBuilder { return this; } + public GameBuilder version(RemoteVersion remoteVersion) { + remoteVersions.add(remoteVersion); + return this; + } + /** * @return the task that can build thw whole Minecraft environment */ diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/RemoteVersion.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/RemoteVersion.java index d4a3ead98..de189fe40 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/RemoteVersion.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/RemoteVersion.java @@ -17,6 +17,7 @@ */ package org.jackhuang.hmcl.download; +import org.jackhuang.hmcl.util.ToStringBuilder; import org.jackhuang.hmcl.util.VersionNumber; import java.util.Objects; @@ -74,6 +75,15 @@ public class RemoteVersion implements Comparable> { return selfVersion.hashCode(); } + @Override + public String toString() { + return new ToStringBuilder(this) + .append("selfVersion", selfVersion) + .append("gameVersion", gameVersion) + .append("tag", tag) + .toString(); + } + @Override public int compareTo(RemoteVersion o) { // newer versions are smaller than older versions diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/VersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/VersionList.java index aaf7295f8..374bef77b 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/VersionList.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/VersionList.java @@ -21,6 +21,7 @@ import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.util.SimpleMultimap; import java.util.*; +import java.util.concurrent.locks.ReentrantReadWriteLock; /** * The remote version list. @@ -45,15 +46,36 @@ public abstract class VersionList { return !versions.isEmpty(); } + protected final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); + /** * @param downloadProvider DownloadProvider * @return the task to reload the remote version list. */ public abstract Task refreshAsync(DownloadProvider downloadProvider); + public Task loadAsync(DownloadProvider downloadProvider) { + return Task.ofThen(variables -> { + lock.readLock().lock(); + boolean loaded; + + try { + loaded = isLoaded(); + } finally { + lock.readLock().unlock(); + } + return loaded ? null : refreshAsync(downloadProvider); + }); + } + private Collection> getVersionsImpl(String gameVersion) { - Collection> ans = versions.get(gameVersion); - return ans.isEmpty() ? versions.values() : ans; + lock.readLock().lock(); + try { + Collection> ans = versions.get(gameVersion); + return ans.isEmpty() ? versions.values() : ans; + } finally { + lock.readLock().unlock(); + } } /** @@ -74,10 +96,15 @@ public abstract class VersionList { * @return the specific remote version, null if it is not found. */ public final Optional> getVersion(String gameVersion, String remoteVersion) { - RemoteVersion result = null; - for (RemoteVersion it : versions.get(gameVersion)) - if (remoteVersion.equals(it.getSelfVersion())) - result = it; - return Optional.ofNullable(result); + lock.readLock().lock(); + try { + RemoteVersion result = null; + for (RemoteVersion it : versions.get(gameVersion)) + if (remoteVersion.equals(it.getSelfVersion())) + result = it; + return Optional.ofNullable(result); + } finally { + lock.readLock().unlock(); + } } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeInstallTask.java index 10df8748d..489ef4009 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeInstallTask.java @@ -18,8 +18,6 @@ package org.jackhuang.hmcl.download.forge; import org.jackhuang.hmcl.download.DefaultDependencyManager; -import org.jackhuang.hmcl.download.RemoteVersion; -import org.jackhuang.hmcl.download.VersionList; import org.jackhuang.hmcl.download.game.GameLibrariesTask; import org.jackhuang.hmcl.game.Library; import org.jackhuang.hmcl.game.SimpleVersionProvider; @@ -47,34 +45,22 @@ import java.util.zip.ZipFile; public final class ForgeInstallTask extends TaskResult { private final DefaultDependencyManager dependencyManager; - private final String gameVersion; private final Version version; - private final String remoteVersion; - private final VersionList forgeVersionList; private final File installer = new File("forge-installer.jar").getAbsoluteFile(); - private RemoteVersion remote; + private ForgeRemoteVersion remote; private final List dependents = new LinkedList<>(); private final List dependencies = new LinkedList<>(); private Task downloadFileTask() { - remote = forgeVersionList.getVersion(gameVersion, remoteVersion) - .orElseThrow(() -> new IllegalArgumentException("Remote forge version " + gameVersion + ", " + remoteVersion + " not found")); return new FileDownloadTask(NetworkUtils.toURL(remote.getUrl()), installer); } - public ForgeInstallTask(DefaultDependencyManager dependencyManager, String gameVersion, Version version, String remoteVersion) { + public ForgeInstallTask(DefaultDependencyManager dependencyManager, Version version, ForgeRemoteVersion remoteVersion) { this.dependencyManager = dependencyManager; - this.gameVersion = gameVersion; this.version = version; - this.remoteVersion = remoteVersion; + this.remote = remoteVersion; - forgeVersionList = dependencyManager.getVersionList("forge"); - - if (!forgeVersionList.isLoaded()) - dependents.add(forgeVersionList.refreshAsync(dependencyManager.getDownloadProvider()) - .then(s -> downloadFileTask())); - else - dependents.add(downloadFileTask()); + dependents.add(downloadFileTask()); } @Override diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeRemoteVersion.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeRemoteVersion.java new file mode 100644 index 000000000..53299e69b --- /dev/null +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeRemoteVersion.java @@ -0,0 +1,33 @@ +/* + * 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.download.forge; + +import org.jackhuang.hmcl.download.RemoteVersion; + +public class ForgeRemoteVersion extends RemoteVersion { + /** + * Constructor. + * + * @param gameVersion the Minecraft version that this remote version suits. + * @param selfVersion the version string of the remote version. + * @param url the installer or universal jar URL. + */ + public ForgeRemoteVersion(String gameVersion, String selfVersion, String url) { + super(gameVersion, selfVersion, url, null); + } +} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeVersionList.java index 555fbcd1c..c87a57a0a 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeVersionList.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeVersionList.java @@ -53,34 +53,40 @@ public final class ForgeVersionList extends VersionList { @Override public void execute() { - ForgeVersionRoot root = Constants.GSON.fromJson(task.getResult(), ForgeVersionRoot.class); - if (root == null) - return; - versions.clear(); + lock.writeLock().lock(); - for (Map.Entry entry : root.getGameVersions().entrySet()) { - Optional gameVersion = VersionNumber.parseVersion(entry.getKey()); - if (!gameVersion.isPresent()) - continue; - for (int v : entry.getValue()) { - ForgeVersion version = root.getNumber().get(v); - if (version == null) - continue; - String jar = null; - for (String[] file : version.getFiles()) - if (file.length > 1 && "installer".equals(file[1])) { - String classifier = version.getGameVersion() + "-" + version.getVersion() - + (StringUtils.isNotBlank(version.getBranch()) ? "-" + version.getBranch() : ""); - String fileName = root.getArtifact() + "-" + classifier + "-" + file[1] + "." + file[0]; - jar = downloadProvider.injectURL(root.getWebPath() + classifier + "/" + fileName); - } + try { + ForgeVersionRoot root = Constants.GSON.fromJson(task.getResult(), ForgeVersionRoot.class); + if (root == null) + return; + versions.clear(); - if (jar == null) + for (Map.Entry entry : root.getGameVersions().entrySet()) { + Optional gameVersion = VersionNumber.parseVersion(entry.getKey()); + if (!gameVersion.isPresent()) continue; - versions.put(gameVersion.get(), new RemoteVersion<>( - version.getGameVersion(), version.getVersion(), jar, null - )); + for (int v : entry.getValue()) { + ForgeVersion version = root.getNumber().get(v); + if (version == null) + continue; + String jar = null; + for (String[] file : version.getFiles()) + if (file.length > 1 && "installer".equals(file[1])) { + String classifier = version.getGameVersion() + "-" + version.getVersion() + + (StringUtils.isNotBlank(version.getBranch()) ? "-" + version.getBranch() : ""); + String fileName = root.getArtifact() + "-" + classifier + "-" + file[1] + "." + file[0]; + jar = downloadProvider.injectURL(root.getWebPath() + classifier + "/" + fileName); + } + + if (jar == null) + continue; + versions.put(gameVersion.get(), new ForgeRemoteVersion( + version.getGameVersion(), version.getVersion(), jar + )); + } } + } finally { + lock.writeLock().unlock(); } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameVersionList.java index da9135ee6..7aa1b01cd 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameVersionList.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameVersionList.java @@ -50,16 +50,22 @@ public final class GameVersionList extends VersionList { @Override public void execute() { - versions.clear(); + lock.writeLock().lock(); - GameRemoteVersions root = Constants.GSON.fromJson(task.getResult(), GameRemoteVersions.class); - for (GameRemoteVersion remoteVersion : root.getVersions()) { - versions.put(remoteVersion.getGameVersion(), new RemoteVersionGame( - remoteVersion.getGameVersion(), - remoteVersion.getGameVersion(), - remoteVersion.getUrl(), - new GameRemoteVersionTag(remoteVersion.getType(), remoteVersion.getReleaseTime())) - ); + try { + versions.clear(); + + GameRemoteVersions root = Constants.GSON.fromJson(task.getResult(), GameRemoteVersions.class); + for (GameRemoteVersion remoteVersion : root.getVersions()) { + versions.put(remoteVersion.getGameVersion(), new RemoteVersionGame( + remoteVersion.getGameVersion(), + remoteVersion.getGameVersion(), + remoteVersion.getUrl(), + new GameRemoteVersionTag(remoteVersion.getType(), remoteVersion.getReleaseTime())) + ); + } + } finally { + lock.writeLock().unlock(); } } }; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/liteloader/LiteLoaderInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/liteloader/LiteLoaderInstallTask.java index 81e26dc1b..50479681b 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/liteloader/LiteLoaderInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/liteloader/LiteLoaderInstallTask.java @@ -18,7 +18,6 @@ package org.jackhuang.hmcl.download.liteloader; import org.jackhuang.hmcl.download.DefaultDependencyManager; -import org.jackhuang.hmcl.download.RemoteVersion; import org.jackhuang.hmcl.download.game.GameLibrariesTask; import org.jackhuang.hmcl.game.LibrariesDownloadInfo; import org.jackhuang.hmcl.game.Library; @@ -41,32 +40,15 @@ import java.util.List; public final class LiteLoaderInstallTask extends TaskResult { private final DefaultDependencyManager dependencyManager; - private final String gameVersion; private final Version version; - private final String remoteVersion; - private final LiteLoaderVersionList liteLoaderVersionList; - private RemoteVersion remote; + private LiteLoaderRemoteVersion remote; private final List dependents = new LinkedList<>(); private final List dependencies = new LinkedList<>(); - private void doRemote() { - remote = liteLoaderVersionList.getVersion(gameVersion, remoteVersion) - .orElseThrow(() -> new IllegalArgumentException("Remote LiteLoader version " + gameVersion + ", " + remoteVersion + " not found")); - } - - public LiteLoaderInstallTask(DefaultDependencyManager dependencyManager, String gameVersion, Version version, String remoteVersion) { + public LiteLoaderInstallTask(DefaultDependencyManager dependencyManager, Version version, LiteLoaderRemoteVersion remoteVersion) { this.dependencyManager = dependencyManager; - this.gameVersion = gameVersion; this.version = version; - this.remoteVersion = remoteVersion; - - liteLoaderVersionList = (LiteLoaderVersionList) dependencyManager.getVersionList("liteloader"); - - if (!liteLoaderVersionList.isLoaded()) - dependents.add(liteLoaderVersionList.refreshAsync(dependencyManager.getDownloadProvider()) - .then(Task.of(this::doRemote))); - else - doRemote(); + this.remote = remoteVersion; } @Override diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/liteloader/LiteLoaderRemoteVersion.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/liteloader/LiteLoaderRemoteVersion.java new file mode 100644 index 000000000..2e0d2692d --- /dev/null +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/liteloader/LiteLoaderRemoteVersion.java @@ -0,0 +1,36 @@ +/* + * 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.download.liteloader; + +import org.jackhuang.hmcl.download.RemoteVersion; +import org.jackhuang.hmcl.game.Library; + +import java.util.Collection; + +public class LiteLoaderRemoteVersion extends RemoteVersion { + /** + * Constructor. + * + * @param gameVersion the Minecraft version that this remote version suits. + * @param selfVersion the version string of the remote version. + * @param url the installer or universal jar URL. + */ + LiteLoaderRemoteVersion(String gameVersion, String selfVersion, String url, String tweakClass, Collection libraries) { + super(gameVersion, selfVersion, url, new LiteLoaderRemoteVersionTag(tweakClass, libraries)); + } +} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/liteloader/LiteLoaderVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/liteloader/LiteLoaderVersionList.java index 2f8596b15..4e48e1be4 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/liteloader/LiteLoaderVersionList.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/liteloader/LiteLoaderVersionList.java @@ -58,17 +58,23 @@ public final class LiteLoaderVersionList extends VersionList entry : root.getVersions().entrySet()) { - String gameVersion = entry.getKey(); - LiteLoaderGameVersions liteLoader = entry.getValue(); - Optional gg = VersionNumber.parseVersion(gameVersion); - if (!gg.isPresent()) - continue; - doBranch(gg.get(), gameVersion, liteLoader.getRepoitory(), liteLoader.getArtifacts(), false); - doBranch(gg.get(), gameVersion, liteLoader.getRepoitory(), liteLoader.getSnapshots(), true); + try { + LiteLoaderVersionsRoot root = Constants.GSON.fromJson(task.getResult(), LiteLoaderVersionsRoot.class); + versions.clear(); + + for (Map.Entry entry : root.getVersions().entrySet()) { + String gameVersion = entry.getKey(); + LiteLoaderGameVersions liteLoader = entry.getValue(); + Optional gg = VersionNumber.parseVersion(gameVersion); + if (!gg.isPresent()) + continue; + doBranch(gg.get(), gameVersion, liteLoader.getRepoitory(), liteLoader.getArtifacts(), false); + doBranch(gg.get(), gameVersion, liteLoader.getRepoitory(), liteLoader.getSnapshots(), true); + } + } finally { + lock.writeLock().unlock(); } } @@ -92,9 +98,9 @@ public final class LiteLoaderVersionList extends VersionList(gameVersion, + versions.put(key, new LiteLoaderRemoteVersion(gameVersion, version, downloadProvider.injectURL(url), - new LiteLoaderRemoteVersionTag(v.getTweakClass(), v.getLibraries()) + v.getTweakClass(), v.getLibraries() )); } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/optifine/OptiFineBMCLVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/optifine/OptiFineBMCLVersionList.java index b3be207f1..55d03006b 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/optifine/OptiFineBMCLVersionList.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/optifine/OptiFineBMCLVersionList.java @@ -67,7 +67,7 @@ public final class OptiFineBMCLVersionList extends VersionList { if (StringUtils.isBlank(element.getGameVersion())) continue; VersionNumber.parseVersion(element.getGameVersion()) - .ifPresent(gameVersion -> versions.put(gameVersion, new RemoteVersion<>(gameVersion, version, mirror, null))); + .ifPresent(gameVersion -> versions.put(gameVersion, new OptiFineRemoteVersion(gameVersion, version, () -> mirror))); } } }; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/optifine/OptiFineInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/optifine/OptiFineInstallTask.java index 872192437..29617a14c 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/optifine/OptiFineInstallTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/optifine/OptiFineInstallTask.java @@ -18,8 +18,6 @@ package org.jackhuang.hmcl.download.optifine; import org.jackhuang.hmcl.download.DefaultDependencyManager; -import org.jackhuang.hmcl.download.RemoteVersion; -import org.jackhuang.hmcl.download.VersionList; import org.jackhuang.hmcl.download.game.GameLibrariesTask; import org.jackhuang.hmcl.game.*; import org.jackhuang.hmcl.task.Task; @@ -39,32 +37,15 @@ import java.util.List; public final class OptiFineInstallTask extends TaskResult { private final DefaultDependencyManager dependencyManager; - private final String gameVersion; private final Version version; - private final String remoteVersion; - private final VersionList optiFineVersionList; - private RemoteVersion remote; + private OptiFineRemoteVersion remote; private final List dependents = new LinkedList<>(); private final List dependencies = new LinkedList<>(); - private void doRemote() { - remote = optiFineVersionList.getVersion(gameVersion, remoteVersion) - .orElseThrow(() -> new IllegalArgumentException("Remote OptiFine version " + gameVersion + ", " + remoteVersion + " not found")); - } - - public OptiFineInstallTask(DefaultDependencyManager dependencyManager, String gameVersion, Version version, String remoteVersion) { + public OptiFineInstallTask(DefaultDependencyManager dependencyManager, Version version, OptiFineRemoteVersion remoteVersion) { this.dependencyManager = dependencyManager; - this.gameVersion = gameVersion; this.version = version; - this.remoteVersion = remoteVersion; - - optiFineVersionList = dependencyManager.getVersionList("optifine"); - - if (!optiFineVersionList.isLoaded()) - dependents.add(optiFineVersionList.refreshAsync(dependencyManager.getDownloadProvider()) - .then(Task.of(this::doRemote))); - else - doRemote(); + this.remote = remoteVersion; } @Override @@ -89,6 +70,8 @@ public final class OptiFineInstallTask extends TaskResult { @Override public void execute() { + String remoteVersion = remote.getSelfVersion(); + Library library = new Library( "net.optifine", "optifine", remoteVersion, null, null, new LibrariesDownloadInfo(new LibraryDownloadInfo( diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/optifine/OptiFineRemoteVersion.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/optifine/OptiFineRemoteVersion.java index 421e12a2c..c197c147c 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/optifine/OptiFineRemoteVersion.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/optifine/OptiFineRemoteVersion.java @@ -24,8 +24,8 @@ import java.util.function.Supplier; public class OptiFineRemoteVersion extends RemoteVersion { private final Supplier url; - public OptiFineRemoteVersion(String gameVersion, String selfVersion, Supplier url, Void tag) { - super(gameVersion, selfVersion, "", tag); + public OptiFineRemoteVersion(String gameVersion, String selfVersion, Supplier url) { + super(gameVersion, selfVersion, "", null); this.url = url; } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/optifine/OptiFineVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/optifine/OptiFineVersionList.java index cfc3212a5..fc3f829a0 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/optifine/OptiFineVersionList.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/optifine/OptiFineVersionList.java @@ -61,48 +61,54 @@ public final class OptiFineVersionList extends VersionList { @Override public void execute() throws Exception { - versions.clear(); + lock.writeLock().lock(); - String html = task.getResult().replace(" ", " ").replace(">", ">").replace("<", "<").replace("
", "
"); + try { + versions.clear(); - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - DocumentBuilder db = factory.newDocumentBuilder(); - Document doc = db.parse(new ByteArrayInputStream(html.getBytes("UTF-8"))); - Element r = doc.getDocumentElement(); - NodeList tables = r.getElementsByTagName("table"); - for (int i = 0; i < tables.getLength(); i++) { - Element e = (Element) tables.item(i); - if ("downloadTable".equals(e.getAttribute("class"))) { - NodeList tr = e.getElementsByTagName("tr"); - for (int k = 0; k < tr.getLength(); k++) { - NodeList downloadLine = ((Element) tr.item(k)).getElementsByTagName("td"); - String url = null, version = null, gameVersion = null; - for (int j = 0; j < downloadLine.getLength(); j++) { - Element td = (Element) downloadLine.item(j); - if (td.getAttribute("class") != null && td.getAttribute("class").startsWith("downloadLineMirror")) - url = ((Element) td.getElementsByTagName("a").item(0)).getAttribute("href"); - if (td.getAttribute("class") != null && td.getAttribute("class").startsWith("downloadLineFile")) - version = td.getTextContent(); + String html = task.getResult().replace(" ", " ").replace(">", ">").replace("<", "<").replace("
", "
"); + + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder db = factory.newDocumentBuilder(); + Document doc = db.parse(new ByteArrayInputStream(html.getBytes("UTF-8"))); + Element r = doc.getDocumentElement(); + NodeList tables = r.getElementsByTagName("table"); + for (int i = 0; i < tables.getLength(); i++) { + Element e = (Element) tables.item(i); + if ("downloadTable".equals(e.getAttribute("class"))) { + NodeList tr = e.getElementsByTagName("tr"); + for (int k = 0; k < tr.getLength(); k++) { + NodeList downloadLine = ((Element) tr.item(k)).getElementsByTagName("td"); + String url = null, version = null, gameVersion = null; + for (int j = 0; j < downloadLine.getLength(); j++) { + Element td = (Element) downloadLine.item(j); + if (td.getAttribute("class") != null && td.getAttribute("class").startsWith("downloadLineMirror")) + url = ((Element) td.getElementsByTagName("a").item(0)).getAttribute("href"); + if (td.getAttribute("class") != null && td.getAttribute("class").startsWith("downloadLineFile")) + version = td.getTextContent(); + } + if (version == null || url == null) + continue; + + Matcher matcher = PATTERN.matcher(version); + while (matcher.find()) + gameVersion = matcher.group(1); + if (gameVersion == null) + continue; + + String finalURL = url; + versions.put(gameVersion, new OptiFineRemoteVersion(gameVersion, version, Lang.hideException(() -> getLink(finalURL)))); } - if (version == null || url == null) - continue; - - Matcher matcher = PATTERN.matcher(version); - while (matcher.find()) - gameVersion = matcher.group(1); - if (gameVersion == null) - continue; - - String finalURL = url; - versions.put(gameVersion, new OptiFineRemoteVersion(gameVersion, version, Lang.hideException(() -> getLink(finalURL)), null)); } } + } finally { + lock.writeLock().unlock(); } } }; } - public static String getLink(String url) throws IOException { + private static String getLink(String url) throws IOException { String result = null; String content = NetworkUtils.doGet(NetworkUtils.toURL(url)); Matcher m = LINK_PATTERN.matcher(content); 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 3c4fd92bc..7b1dec3b9 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/CoupleTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/CoupleTask.java @@ -33,7 +33,6 @@ import java.util.List; final class CoupleTask

extends Task { private final boolean relyingOnDependents; - private final boolean failIfDependentsFail; private final Collection dependents; private final List dependencies = new LinkedList<>(); private final ExceptionalFunction, Task, ?> succ; @@ -45,11 +44,10 @@ 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, ExceptionalFunction, Task, ?> succ, boolean relyingOnDependents, boolean failIfDependentsFail) { - this.dependents = Collections.singleton(pred); + public CoupleTask(P pred, ExceptionalFunction, Task, ?> succ, boolean relyingOnDependents) { + this.dependents = pred == null ? Collections.emptySet() : Collections.singleton(pred); this.succ = succ; this.relyingOnDependents = relyingOnDependents; - this.failIfDependentsFail = failIfDependentsFail; setSignificance(TaskSignificance.MODERATE); setName(succ.toString()); @@ -61,9 +59,6 @@ final class CoupleTask

extends Task { Task task = succ.apply(getVariables()); if (task != null) dependencies.add(task); - - if (failIfDependentsFail && !isDependentsSucceeded()) - throw new SilentException(); } @Override 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 f19a17629..1f614007b 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java @@ -244,7 +244,7 @@ public abstract class Task { } public final Task then(ExceptionalFunction, Task, ?> b) { - return new CoupleTask<>(this, b, true, false); + return new CoupleTask<>(this, b, true); } public final Task with(Task b) { @@ -252,7 +252,7 @@ public abstract class Task { } public final Task with(ExceptionalFunction, Task, E> b) { - return new CoupleTask<>(this, b, false, false); + return new CoupleTask<>(this, b, false); } public final Task finalized(FinalizedCallback b) { @@ -312,6 +312,10 @@ public abstract class Task { return of(ReflectionHelper.getCaller().toString(), scheduler, closure); } + public static Task ofThen(ExceptionalFunction, Task, ?> b) { + return new CoupleTask<>(null, b, true); + } + public static TaskResult ofResult(String id, Callable callable) { return new TaskCallable<>(id, callable); }