diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskListPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskListPane.java index 23abe5b1c..413f16a64 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskListPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskListPane.java @@ -26,11 +26,14 @@ import javafx.scene.layout.BorderPane; import javafx.scene.layout.StackPane; import org.jackhuang.hmcl.download.forge.ForgeInstallTask; import org.jackhuang.hmcl.download.game.GameAssetDownloadTask; +import org.jackhuang.hmcl.download.game.GameInstallTask; 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.*; +import org.jackhuang.hmcl.mod.MinecraftInstanceTask; +import org.jackhuang.hmcl.mod.ModpackInstallTask; +import org.jackhuang.hmcl.mod.ModpackUpdateTask; import org.jackhuang.hmcl.mod.curse.CurseCompletionTask; import org.jackhuang.hmcl.mod.curse.CurseInstallTask; import org.jackhuang.hmcl.mod.multimc.MultiMCModpackInstallTask; @@ -86,6 +89,8 @@ public final class TaskListPane extends StackPane { if (task instanceof GameAssetDownloadTask) { task.setName(i18n("assets.download_all")); + } else if (task instanceof GameInstallTask) { + task.setName(i18n("install.installer.install", i18n("install.installer.game"))); } else if (task instanceof ForgeInstallTask) { task.setName(i18n("install.installer.install", i18n("install.installer.forge"))); } else if (task instanceof LiteLoaderInstallTask) { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameItem.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameItem.java index 559eba474..68cd799b1 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameItem.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameItem.java @@ -34,6 +34,7 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import static org.jackhuang.hmcl.download.LibraryAnalyzer.LibraryType.MINECRAFT; import static org.jackhuang.hmcl.util.Lang.handleUncaught; import static org.jackhuang.hmcl.util.Lang.threadPool; import static org.jackhuang.hmcl.util.StringUtils.removePrefix; @@ -60,6 +61,7 @@ public class GameItem extends Control { StringBuilder libraries = new StringBuilder(game); LibraryAnalyzer analyzer = LibraryAnalyzer.analyze(profile.getRepository().getResolvedPreservingPatchesVersion(id)); analyzer.forEachLibrary((libraryId, libraryVersion) -> { + if (libraryId.equals(MINECRAFT.getPatchId())) return; if (I18n.hasKey("install.installer." + libraryId)) { libraries.append(", ").append(i18n("install.installer." + libraryId)); if (libraryVersion != null) 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 aed1b4117..b22a0ab7c 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 @@ -88,13 +88,14 @@ public class InstallerListPage extends ListPageBase { itemsProperty().clear(); analyzer.forEachLibrary((libraryId, libraryVersion) -> { String title = I18n.hasKey("install.installer." + libraryId) ? i18n("install.installer." + libraryId) : libraryId; - if (Lang.test(() -> profile.getDependency().getVersionList(libraryId))) + Consumer action = "game".equals(libraryId) ? null : removeAction.apply(libraryId); + if (libraryVersion != null && Lang.test(() -> profile.getDependency().getVersionList(libraryId))) itemsProperty().add( - new InstallerItem(title, libraryVersion, () -> { - Controllers.getDecorator().startWizard(new UpdateInstallerWizardProvider(profile, gameVersion, version, libraryId, libraryVersion)); - }, removeAction.apply(libraryId))); + new InstallerItem(title, libraryVersion, () -> { + Controllers.getDecorator().startWizard(new UpdateInstallerWizardProvider(profile, gameVersion, version, libraryId, libraryVersion)); + }, action)); else - itemsProperty().add(new InstallerItem(title, libraryVersion, null, removeAction.apply(libraryId))); + itemsProperty().add(new InstallerItem(title, libraryVersion, null, action)); }); }).start(); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/Versions.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/Versions.java index dc4e28715..853e77869 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/Versions.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/Versions.java @@ -21,7 +21,6 @@ import javafx.stage.FileChooser; import org.jackhuang.hmcl.download.game.GameAssetDownloadTask; import org.jackhuang.hmcl.game.GameRepository; import org.jackhuang.hmcl.game.LauncherHelper; -import org.jackhuang.hmcl.game.Version; import org.jackhuang.hmcl.setting.Accounts; import org.jackhuang.hmcl.setting.EnumGameDirectory; import org.jackhuang.hmcl.setting.Profile; @@ -77,8 +76,7 @@ public class Versions { } public static void updateGameAssets(Profile profile, String version) { - Version resolvedVersion = profile.getRepository().getResolvedVersion(version); - TaskExecutor executor = new GameAssetDownloadTask(profile.getDependency(), resolvedVersion, GameAssetDownloadTask.DOWNLOAD_INDEX_FORCIBLY) + TaskExecutor executor = new GameAssetDownloadTask(profile.getDependency(), profile.getRepository().getVersion(version), GameAssetDownloadTask.DOWNLOAD_INDEX_FORCIBLY) .executor(); Controllers.taskDialog(executor, i18n("version.manage.redownload_assets_index")); executor.start(); 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 c249fd83e..35b71fb33 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java @@ -68,7 +68,8 @@ public class DefaultDependencyManager extends AbstractDependencyManager { } @Override - public Task checkGameCompletionAsync(Version version) { + public Task checkGameCompletionAsync(Version original) { + Version version = original.resolve(repository); return Task.allOf( Task.composeAsync(() -> { if (!repository.getVersionJar(version).exists()) 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 f9ff5bd5d..823188ab7 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultGameBuilder.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultGameBuilder.java @@ -17,14 +17,9 @@ */ package org.jackhuang.hmcl.download; -import org.jackhuang.hmcl.download.game.GameAssetDownloadTask; -import org.jackhuang.hmcl.download.game.GameDownloadTask; -import org.jackhuang.hmcl.download.game.GameLibrariesTask; -import org.jackhuang.hmcl.download.game.VersionJsonDownloadTask; import org.jackhuang.hmcl.game.Version; import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.util.function.ExceptionalFunction; -import org.jackhuang.hmcl.util.gson.JsonUtils; import java.util.Map; @@ -52,24 +47,16 @@ public class DefaultGameBuilder extends GameBuilder { @Override public Task buildAsync() { - return new VersionJsonDownloadTask(gameVersion, dependencyManager).thenComposeAsync(rawJson -> { - Version original = JsonUtils.GSON.fromJson(rawJson, Version.class); - Version version = original.setId(name).setJar(null); - Task vanillaTask = downloadGameAsync(gameVersion, version).thenComposeAsync(Task.allOf( - new GameAssetDownloadTask(dependencyManager, version, GameAssetDownloadTask.DOWNLOAD_INDEX_FORCIBLY), - new GameLibrariesTask(dependencyManager, version) // Game libraries will be downloaded for multiple times partly, this time is for vanilla libraries. - ).withComposeAsync(dependencyManager.getGameRepository().save(version))); // using [with] because download failure here are tolerant. + Task libraryTask = Task.supplyAsync(() -> new Version(name)); + libraryTask = libraryTask.thenComposeAsync(libraryTaskHelper(gameVersion, "game", gameVersion)); - Task libraryTask = vanillaTask.thenSupplyAsync(() -> version); + for (Map.Entry entry : toolVersions.entrySet()) + libraryTask = libraryTask.thenComposeAsync(libraryTaskHelper(gameVersion, entry.getKey(), entry.getValue())); - for (Map.Entry entry : toolVersions.entrySet()) - libraryTask = libraryTask.thenComposeAsync(libraryTaskHelper(gameVersion, entry.getKey(), entry.getValue())); + for (RemoteVersion remoteVersion : remoteVersions) + libraryTask = libraryTask.thenComposeAsync(dependencyManager.installLibraryAsync(remoteVersion)); - for (RemoteVersion remoteVersion : remoteVersions) - libraryTask = libraryTask.thenComposeAsync(dependencyManager.installLibraryAsync(remoteVersion)); - - return libraryTask; - }).whenComplete(exception -> { + return libraryTask.whenComplete(exception -> { if (exception != null) dependencyManager.getGameRepository().removeVersionFromDisk(name); }); @@ -78,9 +65,4 @@ public class DefaultGameBuilder extends GameBuilder { private ExceptionalFunction, ?> libraryTaskHelper(String gameVersion, String libraryId, String libraryVersion) { return version -> dependencyManager.installLibraryAsync(gameVersion, version, libraryId, libraryVersion); } - - protected Task downloadGameAsync(String gameVersion, Version version) { - return new GameDownloadTask(dependencyManager, gameVersion, version); - } - } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/MaintainTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/MaintainTask.java index d751670ea..1feb9abcf 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/MaintainTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/MaintainTask.java @@ -56,7 +56,9 @@ public class MaintainTask extends Task { if (version.getInheritsFrom() != null) throw new IllegalArgumentException("MaintainTask requires independent game version"); - if (version.resolve(null).getMainClass().contains("launchwrapper")) { + String mainClass = version.resolve(null).getMainClass(); + + if (mainClass != null && mainClass.contains("launchwrapper")) { return maintainOptiFineLibrary(repository, maintainGameWithLaunchWrapper(unique(version))); } else { // Vanilla Minecraft does not need maintain diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameAssetDownloadTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameAssetDownloadTask.java index 378141f0b..130162f14 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameAssetDownloadTask.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameAssetDownloadTask.java @@ -51,16 +51,16 @@ public final class GameAssetDownloadTask extends Task { * Constructor. * * @param dependencyManager the dependency manager that can provides {@link org.jackhuang.hmcl.game.GameRepository} - * @param version the resolved version + * @param version the game version */ public GameAssetDownloadTask(AbstractDependencyManager dependencyManager, Version version, boolean forceDownloadingIndex) { this.dependencyManager = dependencyManager; - this.version = version; - this.assetIndexInfo = version.getAssetIndex(); + this.version = version.resolve(dependencyManager.getGameRepository()); + this.assetIndexInfo = this.version.getAssetIndex(); this.assetIndexFile = dependencyManager.getGameRepository().getIndexFile(version.getId(), assetIndexInfo.getId()); if (!assetIndexFile.exists() || forceDownloadingIndex) - dependents.add(new GameAssetIndexDownloadTask(dependencyManager, version)); + dependents.add(new GameAssetIndexDownloadTask(dependencyManager, this.version)); } @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 47d77fe44..a405dc619 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 @@ -43,7 +43,7 @@ public final class GameDownloadTask extends Task { public GameDownloadTask(DefaultDependencyManager dependencyManager, String gameVersion, Version version) { this.dependencyManager = dependencyManager; this.gameVersion = gameVersion; - this.version = version; + this.version = version.resolve(dependencyManager.getGameRepository()); setSignificance(TaskSignificance.MODERATE); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameInstallTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameInstallTask.java new file mode 100644 index 000000000..826d0a65a --- /dev/null +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameInstallTask.java @@ -0,0 +1,79 @@ +/* + * Hello Minecraft! Launcher + * Copyright (C) 2019 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.download.game; + +import org.jackhuang.hmcl.download.DefaultDependencyManager; +import org.jackhuang.hmcl.game.DefaultGameRepository; +import org.jackhuang.hmcl.game.Version; +import org.jackhuang.hmcl.task.Task; +import org.jackhuang.hmcl.util.gson.JsonUtils; + +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +import static org.jackhuang.hmcl.download.LibraryAnalyzer.LibraryType.MINECRAFT; + +public class GameInstallTask extends Task { + + private final DefaultGameRepository gameRepository; + private final DefaultDependencyManager dependencyManager; + private final Version version; + private final GameRemoteVersion remote; + private final VersionJsonDownloadTask downloadTask; + private final List> dependencies = new LinkedList<>(); + + public GameInstallTask(DefaultDependencyManager dependencyManager, Version version, GameRemoteVersion remoteVersion) { + this.dependencyManager = dependencyManager; + this.gameRepository = dependencyManager.getGameRepository(); + this.version = version; + this.remote = remoteVersion; + this.downloadTask = new VersionJsonDownloadTask(remoteVersion.getGameVersion(), dependencyManager); + } + + @Override + public Collection> getDependents() { + return Collections.singleton(downloadTask); + } + + @Override + public Collection> getDependencies() { + return dependencies; + } + + @Override + public boolean isRelyingOnDependencies() { + return false; + } + + @Override + public void execute() throws Exception { + Version patch = JsonUtils.GSON.fromJson(downloadTask.getResult(), Version.class) + .setId(MINECRAFT.getPatchId()).setVersion(remote.getGameVersion()).setJar(null).setPriority(0); + setResult(patch); + + Version version = new Version(this.version.getId()).addPatch(patch); + dependencies.add(new GameDownloadTask(dependencyManager, remote.getGameVersion(), version) + .thenComposeAsync(Task.allOf( + new GameAssetDownloadTask(dependencyManager, version, GameAssetDownloadTask.DOWNLOAD_INDEX_FORCIBLY), + new GameLibrariesTask(dependencyManager, version) + ).withComposeAsync(gameRepository.save(version)))); + } + +} 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 49ca6e09f..8bbc316fc 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 @@ -43,17 +43,17 @@ public final class GameLibrariesTask extends Task { * Constructor. * * @param dependencyManager the dependency manager that can provides {@link org.jackhuang.hmcl.game.GameRepository} - * @param version the resolved version + * @param version the game version */ public GameLibrariesTask(AbstractDependencyManager dependencyManager, Version version) { - this(dependencyManager, version, version.getLibraries()); + this(dependencyManager, version, version.resolve(dependencyManager.getGameRepository()).getLibraries()); } /** * Constructor. * * @param dependencyManager the dependency manager that can provides {@link org.jackhuang.hmcl.game.GameRepository} - * @param version the resolved version + * @param version the game version */ public GameLibrariesTask(AbstractDependencyManager dependencyManager, Version version, List libraries) { this.dependencyManager = dependencyManager; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameRemoteVersion.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameRemoteVersion.java index 1a5eb712d..50f36569c 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameRemoteVersion.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/game/GameRemoteVersion.java @@ -17,8 +17,11 @@ */ package org.jackhuang.hmcl.download.game; +import org.jackhuang.hmcl.download.DefaultDependencyManager; import org.jackhuang.hmcl.download.RemoteVersion; import org.jackhuang.hmcl.game.ReleaseType; +import org.jackhuang.hmcl.game.Version; +import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.util.Immutable; import java.util.Date; @@ -47,6 +50,11 @@ public final class GameRemoteVersion extends RemoteVersion { return type; } + @Override + public Task getInstallTask(DefaultDependencyManager dependencyManager, Version baseVersion) { + return new GameInstallTask(dependencyManager, baseVersion, this); + } + @Override public int compareTo(RemoteVersion o) { if (!(o instanceof GameRemoteVersion)) 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 d246baa62..eff68e362 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 @@ -21,7 +21,6 @@ import org.jackhuang.hmcl.download.DownloadProvider; import org.jackhuang.hmcl.download.VersionList; import org.jackhuang.hmcl.task.GetTask; import org.jackhuang.hmcl.task.Task; -import org.jackhuang.hmcl.util.StringUtils; import org.jackhuang.hmcl.util.gson.JsonUtils; import org.jackhuang.hmcl.util.io.NetworkUtils; @@ -48,7 +47,7 @@ public final class GameVersionList extends VersionList { protected Collection getVersionsImpl(String gameVersion) { lock.readLock().lock(); try { - return StringUtils.isBlank(gameVersion) ? versions.values() : versions.get(gameVersion); + return versions.values(); } finally { lock.readLock().unlock(); } 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 30024cd98..d165f96d5 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 @@ -62,7 +62,7 @@ public final class VersionJsonDownloadTask extends Task { @Override public void execute() { - RemoteVersion remoteVersion = gameVersionList.getVersions(gameVersion).stream().findFirst() + RemoteVersion remoteVersion = gameVersionList.getVersion(gameVersion, gameVersion) .orElseThrow(() -> new IllegalStateException("Cannot find specific version " + gameVersion + " in remote repository")); String jsonURL = dependencyManager.getDownloadProvider().injectURL(remoteVersion.getUrl()); dependencies.add(new GetTask(NetworkUtils.toURL(jsonURL)).storeTo(this::setResult)); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/DefaultGameRepository.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/DefaultGameRepository.java index b6165fb68..0901aab12 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/DefaultGameRepository.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/DefaultGameRepository.java @@ -160,7 +160,7 @@ public class DefaultGameRepository implements GameRepository { } if (fromVersion.getId().equals(fromVersion.getJar())) - fromVersion = fromVersion.setJar(to); + fromVersion = fromVersion.setJar(null); FileUtils.writeText(toJson, JsonUtils.GSON.toJson(fromVersion.setId(to))); return true; } catch (IOException | JsonParseException | VersionNotFoundException e) {