From 1392ad413aa8086c72c1e528f1d3989240f1d4d7 Mon Sep 17 00:00:00 2001 From: huangyuhui Date: Thu, 6 Sep 2018 00:13:16 +0800 Subject: [PATCH] Only cache verified files and copy cached files to current directory --- .../hmcl/game/HMCLDependencyManager.java | 16 + .../hmcl/game/HMCLGameDownloadTask.java | 34 +- .../hmcl/game/HMCLGameLibrariesTask.java | 61 ++++ .../hmcl/game/HMCLGameRepository.java | 12 +- .../hmcl/game/HMCLLibraryDownloadTask.java | 79 +++++ .../hmcl/game/HMCLLocalRepository.java | 303 ++++++++++++++++++ .../hmcl/setting/EnumCommonDirectory.java | 4 - .../org/jackhuang/hmcl/setting/Profile.java | 3 +- .../org/jackhuang/hmcl/setting/Settings.java | 9 +- .../org/jackhuang/hmcl/ui/SettingsPage.java | 1 - .../download/DefaultDependencyManager.java | 5 + .../hmcl/download/DependencyManager.java | 10 +- .../hmcl/download/forge/ForgeInstallTask.java | 3 +- .../liteloader/LiteLoaderInstallTask.java | 2 +- .../optifine/OptiFineInstallTask.java | 3 +- 15 files changed, 500 insertions(+), 45 deletions(-) create mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameLibrariesTask.java create mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLLibraryDownloadTask.java create mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLLocalRepository.java diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLDependencyManager.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLDependencyManager.java index 7c81dabd8..815fd51e5 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLDependencyManager.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLDependencyManager.java @@ -20,7 +20,10 @@ package org.jackhuang.hmcl.game; import org.jackhuang.hmcl.download.DefaultDependencyManager; import org.jackhuang.hmcl.download.DownloadProvider; import org.jackhuang.hmcl.download.GameBuilder; +import org.jackhuang.hmcl.download.game.GameAssetDownloadTask; import org.jackhuang.hmcl.setting.Profile; +import org.jackhuang.hmcl.task.ParallelTask; +import org.jackhuang.hmcl.task.Task; /** * @author huangyuhui @@ -38,4 +41,17 @@ public class HMCLDependencyManager extends DefaultDependencyManager { public GameBuilder gameBuilder() { return new HMCLGameBuilder(profile); } + + @Override + public Task checkGameCompletionAsync(Version version) { + return new ParallelTask( + new GameAssetDownloadTask(this, version), + new HMCLGameLibrariesTask(this, version) + ); + } + + @Override + public Task checkLibraryCompletionAsync(Version version) { + return new HMCLGameLibrariesTask(this, version); + } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameDownloadTask.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameDownloadTask.java index 83ad03709..ffd2947c4 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameDownloadTask.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameDownloadTask.java @@ -18,7 +18,6 @@ package org.jackhuang.hmcl.game; import org.jackhuang.hmcl.setting.Profile; -import org.jackhuang.hmcl.setting.Settings; import org.jackhuang.hmcl.task.FileDownloadTask; import org.jackhuang.hmcl.task.FileDownloadTask.IntegrityCheck; import org.jackhuang.hmcl.task.Task; @@ -28,6 +27,9 @@ import org.jackhuang.hmcl.util.NetworkUtils; import java.io.File; import java.io.IOException; +import java.net.URL; +import java.nio.file.Path; +import java.util.Collection; import java.util.LinkedList; import java.util.List; import java.util.Optional; @@ -51,7 +53,7 @@ public class HMCLGameDownloadTask extends Task { } @Override - public List getDependencies() { + public Collection getDependencies() { return dependencies; } @@ -59,24 +61,26 @@ public class HMCLGameDownloadTask extends Task { public void execute() { File jar = profile.getRepository().getVersionJar(version); - // Force using common directory will not affect the behaviour that repository acts - // Since we always copy the downloaded jar to .minecraft/versions// - File cache = new File(Optional.ofNullable(Settings.instance().getCommonDirectory()) - .orElse(Settings.getDefaultCommonDirectory()), - "jars/" + gameVersion + ".jar"); - if (cache.exists()) + Optional path = HMCLLocalRepository.REPOSITORY.getVersion(gameVersion, version); + if (path.isPresent()) { try { - FileUtils.copyFile(cache, jar); + FileUtils.copyFile(path.get().toFile(), jar); return; } catch (IOException e) { - Logging.LOG.log(Level.SEVERE, "Unable to copy cached Minecraft jar from " + cache + " to " + jar, e); + Logging.LOG.log(Level.SEVERE, "Unable to copy cached Minecraft jar from " + path.get() + " to " + jar, e); } + } - dependencies.add(new FileDownloadTask( - NetworkUtils.toURL(profile.getDependency().getDownloadProvider().injectURL(version.getDownloadInfo().getUrl())), - cache, - new IntegrityCheck("SHA-1", version.getDownloadInfo().getSha1()) - ).then(Task.of(v -> FileUtils.copyFile(cache, jar)))); + URL url = NetworkUtils.toURL(profile.getDependency().getDownloadProvider().injectURL(version.getDownloadInfo().getUrl())); + + if (version.getDownloadInfo().getSha1() == null) { + // We do not know jar's hash, then we will not cache it. + dependencies.add(new FileDownloadTask(url, jar)); + } else { + dependencies.add(new FileDownloadTask(url, jar, + new IntegrityCheck("SHA-1", version.getDownloadInfo().getSha1()) + ).then(Task.of(v -> HMCLLocalRepository.REPOSITORY.cacheVersion(version, jar.toPath())))); + } } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameLibrariesTask.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameLibrariesTask.java new file mode 100644 index 000000000..72651d774 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameLibrariesTask.java @@ -0,0 +1,61 @@ +/* + * 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.game; + +import org.jackhuang.hmcl.task.Task; +import org.jackhuang.hmcl.util.Lang; + +import java.io.File; +import java.util.LinkedList; +import java.util.List; + +public class HMCLGameLibrariesTask extends Task { + + private final HMCLDependencyManager dependencyManager; + private final Version version; + private final List dependencies = new LinkedList<>(); + + /** + * Constructor. + * + * @param dependencyManager the dependency manager that can provides {@link org.jackhuang.hmcl.game.GameRepository} + * @param version the resolved version + */ + public HMCLGameLibrariesTask(HMCLDependencyManager dependencyManager, Version version) { + this.dependencyManager = dependencyManager; + this.version = version; + setSignificance(TaskSignificance.MODERATE); + } + + @Override + public List getDependencies() { + return dependencies; + } + + @Override + public void execute() { + version.getLibraries().stream().filter(Library::appliesToCurrentEnvironment).forEach(library -> { + File file = dependencyManager.getGameRepository().getLibraryFile(version, library); + if (!file.exists()) + dependencies.add(new HMCLLibraryDownloadTask(dependencyManager, file, library)); + else + HMCLLocalRepository.REPOSITORY.tryCacheLibrary(library, file.toPath()); + }); + } + +} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java index 4d4ea3f04..187b00ec9 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java @@ -56,7 +56,7 @@ public class HMCLGameRepository extends DefaultGameRepository { @Override public File getAssetDirectory(String version, String assetId) { - if (Settings.instance().isCommonDirectoryDisabled() || useSelf(assetId)) + if (useSelf(assetId)) return super.getAssetDirectory(version, assetId); else return new File(Settings.instance().getCommonDirectory(), "assets"); @@ -77,16 +77,6 @@ public class HMCLGameRepository extends DefaultGameRepository { } } - @Override - public File getLibraryFile(Version version, Library lib) { - File self = super.getLibraryFile(version, lib); - if (Settings.instance().isCommonDirectoryDisabled() || self.exists()) - return self; - else - return new File(Settings.instance().getCommonDirectory(), "libraries/" + lib.getPath()); - } - - @Override protected void refreshVersionsImpl() { versionSettings.clear(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLLibraryDownloadTask.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLLibraryDownloadTask.java new file mode 100644 index 000000000..2cd66ffea --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLLibraryDownloadTask.java @@ -0,0 +1,79 @@ +/* + * 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.game; + +import org.jackhuang.hmcl.download.game.LibraryDownloadException; +import org.jackhuang.hmcl.download.game.LibraryDownloadTask; +import org.jackhuang.hmcl.task.Task; +import org.jackhuang.hmcl.util.FileUtils; +import org.jackhuang.hmcl.util.Logging; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import java.util.Collection; +import java.util.Collections; +import java.util.Optional; +import java.util.logging.Level; + +public final class HMCLLibraryDownloadTask extends LibraryDownloadTask { + + private boolean cached = false; + + public HMCLLibraryDownloadTask(HMCLDependencyManager dependencyManager, File file, Library library) { + super(dependencyManager, file, library); + } + + @Override + public void preExecute() throws Exception { + Optional libPath = HMCLLocalRepository.REPOSITORY.getLibrary(library); + if (libPath.isPresent()) { + try { + FileUtils.copyFile(libPath.get().toFile(), jar); + cached = true; + return; + } catch (IOException e) { + Logging.LOG.log(Level.WARNING, "Failed to copy file from cache", e); + // We cannot copy cached file to current location + // so we try to download a new one. + } + } + + super.preExecute(); + } + + @Override + public Collection getDependents() { + if (cached) return Collections.emptyList(); + else return super.getDependents(); + } + + @Override + public void execute() throws Exception { + if (cached) return; + super.execute(); + } + + @Override + public void postExecute() throws Exception { + super.postExecute(); + + if (!cached) + HMCLLocalRepository.REPOSITORY.cacheLibrary(library, jar.toPath(), xz); + } +} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLLocalRepository.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLLocalRepository.java new file mode 100644 index 000000000..a9b85fa7a --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLLocalRepository.java @@ -0,0 +1,303 @@ +/* + * 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.game; + +import javafx.beans.property.SimpleStringProperty; +import javafx.beans.property.StringProperty; +import org.jackhuang.hmcl.download.game.LibraryDownloadTask; +import org.jackhuang.hmcl.ui.FXUtils; +import org.jackhuang.hmcl.util.*; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.*; +import java.util.function.Supplier; +import java.util.logging.Level; +import java.util.stream.Collectors; + +public class HMCLLocalRepository { + private final StringProperty directory = new SimpleStringProperty(); + + private Path cacheDir; + private Path librariesDir; + private Path jarsDir; + private Path indexFile; + + private Index index = null; + + public HMCLLocalRepository() { + FXUtils.onChange(directory, t -> changeDirectory(Paths.get(t))); + } + + public String getDirectory() { + return directory.get(); + } + + public StringProperty directoryProperty() { + return directory; + } + + public void setDirectory(String directory) { + this.directory.set(directory); + } + + private void changeDirectory(Path commonDir) { + cacheDir = commonDir.resolve("cache"); + librariesDir = commonDir.resolve("libraries"); + jarsDir = commonDir.resolve("jars"); + indexFile = cacheDir.resolve("index.json"); + + try { + index = Constants.GSON.fromJson(FileUtils.readText(indexFile.toFile()), Index.class); + } catch (IOException e) { + Logging.LOG.log(Level.WARNING, "Unable to read index file", e); + index = new Index(); + } + } + + private Path getFile(String algorithm, String hash) { + return cacheDir.resolve(algorithm).resolve(hash.substring(0, 2)).resolve(hash); + } + + private boolean fileExists(String algorithm, String hash) { + if (hash == null) return false; + return Files.exists(getFile(algorithm, hash)); + } + + public void tryCacheLibrary(Library library, Path jar) { + if (index.getLibraries().stream().anyMatch(it -> library.getName().equals(it.getName()))) + return; + + try { + LibraryDownloadInfo info = library.getDownload(); + String hash = info.getSha1(); + if (hash != null) { + String checksum = Hex.encodeHex(DigestUtils.digest("SHA-1", jar)); + if (hash.equalsIgnoreCase(checksum)) + cacheLibrary(library, jar, false); + } else if (library.getChecksums() != null && !library.getChecksums().isEmpty()) { + if (LibraryDownloadTask.checksumValid(jar.toFile(), library.getChecksums())) + cacheLibrary(library, jar, true); + } else { + // or we will not cache the library + } + } catch (IOException e) { + Logging.LOG.log(Level.WARNING, "Unable to calc hash value of file " + jar, e); + } + } + + public synchronized Optional getLibrary(Library library) { + LibraryDownloadInfo info = library.getDownload(); + String hash = info.getSha1(); + + if (fileExists(SHA1, hash)) + return Optional.of(getFile(SHA1, hash)); + + // check if this library is from Forge + List libraries = index.getLibraries().stream() + .filter(it -> it.getName().equals(library.getName())) + .collect(Collectors.toList()); + for (LibraryIndex libIndex : libraries) { + if (fileExists(SHA1, libIndex.getHash())) { + Path file = getFile(SHA1, libIndex.getHash()); + if (libIndex.getType().equalsIgnoreCase(LibraryIndex.TYPE_FORGE)) { + if (LibraryDownloadTask.checksumValid(file.toFile(), library.getChecksums())) + return Optional.of(file); + } + } + } + + // check old common directory + Path jar = librariesDir.resolve(info.getPath()); + if (Files.exists(jar)) { + try { + if (hash != null) { + String checksum = Hex.encodeHex(DigestUtils.digest("SHA-1", jar)); + if (hash.equalsIgnoreCase(checksum)) + return Optional.of(restore(jar, () -> cacheLibrary(library, jar, false))); + } else if (library.getChecksums() != null && !library.getChecksums().isEmpty()) { + if (LibraryDownloadTask.checksumValid(jar.toFile(), library.getChecksums())) + return Optional.of(restore(jar, () -> cacheLibrary(library, jar, true))); + } else { + return Optional.of(jar); + } + } catch (IOException e) { + // we cannot check the hashcode or unable to move file. + } + } + + return Optional.empty(); + } + + public synchronized Path cacheLibrary(Library library, Path path, boolean forge) throws IOException { + String hash = library.getDownload().getSha1(); + if (hash == null) + hash = Hex.encodeHex(DigestUtils.digest(SHA1, path)); + + Path cache = getFile(SHA1, hash); + FileUtils.copyFile(path.toFile(), cache.toFile()); + + LibraryIndex libIndex = new LibraryIndex(library.getName(), hash, forge ? LibraryIndex.TYPE_FORGE : LibraryIndex.TYPE_JAR); + index.getLibraries().add(libIndex); + saveIndex(); + + return cache; + } + + public synchronized Optional getVersion(String gameVersion, Version version) { + DownloadInfo info = version.getDownloadInfo(); + String hash = info.getSha1(); + + if (fileExists(SHA1, hash)) + return Optional.of(getFile(SHA1, hash)); + + // check old common directory, but we will no longer maintain it. + Path jar = jarsDir.resolve(gameVersion + ".jar"); + if (Files.exists(jar)) { + if (hash != null) { + try { + String checksum = Hex.encodeHex(DigestUtils.digest("SHA-1", jar)); + if (!checksum.equalsIgnoreCase(hash)) { + // The file is not the one we want + return Optional.empty(); + } else { + return Optional.of(restore(jar, () -> cacheVersion(version, jar))); + } + } catch (IOException e) { + // we cannot check the hashcode. + return Optional.empty(); + } + } else { + return Optional.of(jar); + } + } + + return Optional.empty(); + } + + public synchronized Path cacheVersion(Version version, Path path) throws IOException { + if (version.getDownloadInfo().getSha1() == null) + throw new IllegalStateException(); + + Path cache = getFile(SHA1, version.getDownloadInfo().getSha1()); + FileUtils.copyFile(path.toFile(), cache.toFile()); + return cache; + } + + private Path restore(Path original, ExceptionalSupplier cacheSupplier) throws IOException { + Path cache = cacheSupplier.get(); + Files.delete(original); + Files.createLink(original, cache); + return cache; + } + + private void saveIndex() { + if (indexFile == null || index == null) return; + try { + FileUtils.writeText(indexFile.toFile(), Constants.GSON.toJson(index)); + } catch (IOException e) { + Logging.LOG.log(Level.SEVERE, "Unable to save index.json", e); + } + } + + private static final String SHA1 = "SHA-1"; + public static final HMCLLocalRepository REPOSITORY = new HMCLLocalRepository(); + + /** + * { + * "libraries": { + * // allow a library has multiple hash code. + * [ + * "name": "net.minecraftforge:forge:1.11.2-13.20.0.2345", + * "hash": "blablabla", + * "type": "forge" + * ] + * }, + * "indexes": [ + * { + * "name": "1.7.10", + * "hash": "..." + * } + * ] + * // we don't cache asset objects in our repository which are already stored in a cache repository. + * } + */ + private class Index { + private final Set libraries; + + public Index() { + this(new HashSet<>()); + } + + public Index(Set libraries) { + this.libraries = libraries; + } + + public Set getLibraries() { + return libraries; + } + } + + private class LibraryIndex { + private final String name; + private final String hash; + private final String type; + + public LibraryIndex() { + this(null, null, null); + } + + public LibraryIndex(String name, String hash, String type) { + this.name = name; + this.hash = hash; + this.type = type; + } + + public String getName() { + return name; + } + + public String getHash() { + return hash; + } + + public String getType() { + return type; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + LibraryIndex that = (LibraryIndex) o; + return Objects.equals(name, that.name) && + Objects.equals(hash, that.hash) && + Objects.equals(type, that.type); + } + + @Override + public int hashCode() { + return Objects.hash(name, hash, type); + } + + public static final String TYPE_FORGE = "forge"; + public static final String TYPE_JAR = "jar"; + } +} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/EnumCommonDirectory.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/EnumCommonDirectory.java index 5ca9fd426..b6cb26556 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/EnumCommonDirectory.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/EnumCommonDirectory.java @@ -18,10 +18,6 @@ package org.jackhuang.hmcl.setting; public enum EnumCommonDirectory { - /** - * same to game directory - */ - DISABLED, /** * %appdata%/.minecraft or ~/.minecraft */ diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Profile.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Profile.java index 8325e50db..af17a2d0c 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Profile.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Profile.java @@ -18,7 +18,6 @@ package org.jackhuang.hmcl.setting; import com.google.gson.*; -import javafx.application.Platform; import javafx.beans.InvalidationListener; import javafx.beans.Observable; import javafx.beans.property.*; @@ -231,7 +230,7 @@ public final class Profile implements Observable { } protected void invalidate() { - Platform.runLater(observableHelper::invalidate); + observableHelper.invalidate(); } public static final class Serializer implements JsonSerializer, JsonDeserializer { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java index 0f1a8e806..2d8686d11 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java @@ -20,6 +20,7 @@ package org.jackhuang.hmcl.setting; import javafx.scene.text.Font; import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.download.DownloadProvider; +import org.jackhuang.hmcl.game.HMCLLocalRepository; import static org.jackhuang.hmcl.setting.ConfigHolder.config; @@ -45,6 +46,8 @@ public class Settings { ProxyManager.init(); Accounts.init(); Profiles.init(); + + HMCLLocalRepository.REPOSITORY.directoryProperty().bind(config().commonDirectoryProperty()); } public Font getFont() { @@ -64,18 +67,12 @@ public class Settings { config().setLogLines(logLines); } - public boolean isCommonDirectoryDisabled() { - return config().getCommonDirType() == EnumCommonDirectory.DISABLED; - } - public static String getDefaultCommonDirectory() { return Launcher.MINECRAFT_DIRECTORY.getAbsolutePath(); } public String getCommonDirectory() { switch (config().getCommonDirType()) { - case DISABLED: - return null; case DEFAULT: return getDefaultCommonDirectory(); case CUSTOM: diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/SettingsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/SettingsPage.java index a660c125e..d60c0ff7c 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/SettingsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/SettingsPage.java @@ -138,7 +138,6 @@ public final class SettingsPage extends SettingsView implements DecoratorPage { // ==== fileCommonLocation.loadChildren(Arrays.asList( - fileCommonLocation.createChildren(i18n("launcher.common_directory.disabled"), EnumCommonDirectory.DISABLED), fileCommonLocation.createChildren(i18n("launcher.common_directory.default"), EnumCommonDirectory.DEFAULT) ), EnumCommonDirectory.CUSTOM); fileCommonLocation.selectedDataProperty().bindBidirectional(config().commonDirTypeProperty()); 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 16150408f..e72ef378a 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultDependencyManager.java @@ -72,6 +72,11 @@ public class DefaultDependencyManager extends AbstractDependencyManager { ); } + @Override + public Task checkLibraryCompletionAsync(Version version) { + return new GameLibrariesTask(this, version); + } + @Override public Task installLibraryAsync(String gameVersion, Version version, String libraryId, String libraryVersion) { VersionList versionList = getVersionList(libraryId); 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 d54e303a5..65add1341 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DependencyManager.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DependencyManager.java @@ -36,12 +36,20 @@ public interface DependencyManager { /** * Check if the game is complete. - * Check libraries, assets, logging files and so on. + * Check libraries, assets files and so on. * * @return the task to check game completion. */ Task checkGameCompletionAsync(Version version); + /** + * Check if the game is complete. + * Check libraries, assets files and so on. + * + * @return the task to check game completion. + */ + Task checkLibraryCompletionAsync(Version version); + /** * The builder to build a brand new game then libraries such as Forge, LiteLoader and OptiFine. */ 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 d82b27713..596d1ced1 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,7 +18,6 @@ package org.jackhuang.hmcl.download.forge; import org.jackhuang.hmcl.download.DefaultDependencyManager; -import org.jackhuang.hmcl.download.game.GameLibrariesTask; import org.jackhuang.hmcl.game.Library; import org.jackhuang.hmcl.game.SimpleVersionProvider; import org.jackhuang.hmcl.game.Version; @@ -114,7 +113,7 @@ public final class ForgeInstallTask extends TaskResult { .resolve(provider).setJar(null) .setId(version.getId()).setLogging(Collections.emptyMap())); - dependencies.add(new GameLibrariesTask(dependencyManager, installProfile.getVersionInfo())); + dependencies.add(dependencyManager.checkLibraryCompletionAsync(installProfile.getVersionInfo())); } if (!installer.delete()) 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 d9fd49da4..440e880b9 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 @@ -82,7 +82,7 @@ public final class LiteLoaderInstallTask extends TaskResult { .setLogging(Collections.emptyMap()) ); - dependencies.add(new GameLibrariesTask(dependencyManager, tempVersion)); + dependencies.add(dependencyManager.checkLibraryCompletionAsync(tempVersion)); } } 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 f2ca3bce4..f59f3124a 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,7 +18,6 @@ package org.jackhuang.hmcl.download.optifine; import org.jackhuang.hmcl.download.DefaultDependencyManager; -import org.jackhuang.hmcl.download.game.GameLibrariesTask; import org.jackhuang.hmcl.game.LibrariesDownloadInfo; import org.jackhuang.hmcl.game.Library; import org.jackhuang.hmcl.game.LibraryDownloadInfo; @@ -92,7 +91,7 @@ public final class OptiFineInstallTask extends TaskResult { .setMainClass("net.minecraft.launchwrapper.Launch") ); - dependencies.add(new GameLibrariesTask(dependencyManager, version.setLibraries(libraries))); + dependencies.add(dependencyManager.checkLibraryCompletionAsync(version.setLibraries(libraries))); } }