fix: downloading libraries of optifine

This commit is contained in:
huanghongxun
2020-04-18 18:57:01 +08:00
parent 0639d82914
commit e630c6dff7
5 changed files with 96 additions and 51 deletions

View File

@@ -126,13 +126,15 @@ public final class LauncherHelper {
DefaultDependencyManager dependencyManager = profile.getDependency(); DefaultDependencyManager dependencyManager = profile.getDependency();
Version version = MaintainTask.maintain(repository, repository.getResolvedVersion(selectedVersion)); Version version = MaintainTask.maintain(repository, repository.getResolvedVersion(selectedVersion));
Optional<String> gameVersion = GameVersion.minecraftVersion(repository.getVersionJar(version)); Optional<String> gameVersion = GameVersion.minecraftVersion(repository.getVersionJar(version));
boolean integrityCheck = repository.unmarkVersionLaunchedAbnormally(selectedVersion);
TaskExecutor executor = Task.allOf( TaskExecutor executor = dependencyManager.checkPatchCompletionAsync(repository.getVersion(selectedVersion), integrityCheck)
.thenComposeAsync(Task.allOf(
Task.composeAsync(() -> { Task.composeAsync(() -> {
if (setting.isNotCheckGame()) if (setting.isNotCheckGame())
return null; return null;
else else
return dependencyManager.checkGameCompletionAsync(version, repository.unmarkVersionLaunchedAbnormally(selectedVersion)); return dependencyManager.checkGameCompletionAsync(version, integrityCheck);
}), Task.composeAsync(() -> { }), Task.composeAsync(() -> {
try { try {
ModpackConfiguration<?> configuration = ModpackHelper.readModpackConfiguration(repository.getModpackConfiguration(selectedVersion)); ModpackConfiguration<?> configuration = ModpackHelper.readModpackConfiguration(repository.getModpackConfiguration(selectedVersion));
@@ -145,7 +147,7 @@ public final class LauncherHelper {
} catch (IOException e) { } catch (IOException e) {
return null; return null;
} }
})).withStage("launch.state.dependencies") }))).withStage("launch.state.dependencies")
.thenComposeAsync(Task.supplyAsync(() -> { .thenComposeAsync(Task.supplyAsync(() -> {
try { try {
return account.logIn(); return account.logIn();

View File

@@ -23,11 +23,18 @@ import org.jackhuang.hmcl.download.game.GameDownloadTask;
import org.jackhuang.hmcl.download.game.GameLibrariesTask; import org.jackhuang.hmcl.download.game.GameLibrariesTask;
import org.jackhuang.hmcl.download.optifine.OptiFineInstallTask; import org.jackhuang.hmcl.download.optifine.OptiFineInstallTask;
import org.jackhuang.hmcl.game.DefaultGameRepository; import org.jackhuang.hmcl.game.DefaultGameRepository;
import org.jackhuang.hmcl.game.GameVersion;
import org.jackhuang.hmcl.game.Library;
import org.jackhuang.hmcl.game.Version; import org.jackhuang.hmcl.game.Version;
import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.task.Task;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import static org.jackhuang.hmcl.download.LibraryAnalyzer.LibraryType.OPTIFINE;
/** /**
* Note: This class has no state. * Note: This class has no state.
@@ -86,6 +93,28 @@ public class DefaultDependencyManager extends AbstractDependencyManager {
return new GameLibrariesTask(this, version, integrityCheck, version.getLibraries()); return new GameLibrariesTask(this, version, integrityCheck, version.getLibraries());
} }
@Override
public Task<?> checkPatchCompletionAsync(Version version, boolean integrityCheck) {
return Task.composeAsync(() -> {
List<Task<?>> tasks = new ArrayList<>();
Optional<String> gameVersion = GameVersion.minecraftVersion(repository.getVersionJar(version));
if (!gameVersion.isPresent()) return null;
LibraryAnalyzer analyzer = LibraryAnalyzer.analyze(version.resolvePreservingPatches(getGameRepository()));
version.resolve(getGameRepository()).getLibraries().stream().filter(Library::appliesToCurrentEnvironment).forEach(library -> {
Optional<String> libraryVersion = analyzer.getVersion(OPTIFINE);
if (OPTIFINE.matchLibrary(library) && libraryVersion.isPresent()) {
if (GameLibrariesTask.shouldDownloadLibrary(repository, version, library, integrityCheck)) {
tasks.add(installLibraryAsync(gameVersion.get(), version, OPTIFINE.getPatchId(), libraryVersion.get()));
}
}
});
return Task.allOf(tasks);
});
}
@Override @Override
public Task<Version> installLibraryAsync(String gameVersion, Version baseVersion, String libraryId, String libraryVersion) { public Task<Version> installLibraryAsync(String gameVersion, Version baseVersion, String libraryId, String libraryVersion) {
if (baseVersion.isResolved()) throw new IllegalArgumentException("Version should not be resolved"); if (baseVersion.isResolved()) throw new IllegalArgumentException("Version should not be resolved");

View File

@@ -56,6 +56,16 @@ public interface DependencyManager {
*/ */
Task<?> checkLibraryCompletionAsync(Version version, boolean integrityCheck); Task<?> checkLibraryCompletionAsync(Version version, boolean integrityCheck);
/**
* Check if patches of this version in complete.
* If not, reinstall the patch if possible.
*
* @param version the version to be checked
* @param integrityCheck check if some libraries are corrupt.
* @return the task to check patches completion.
*/
Task<?> checkPatchCompletionAsync(Version version, boolean integrityCheck);
/** /**
* The builder to build a brand new game then libraries such as Forge, LiteLoader and OptiFine. * The builder to build a brand new game then libraries such as Forge, LiteLoader and OptiFine.
*/ */

View File

@@ -91,10 +91,7 @@ public final class LibraryAnalyzer implements Iterable<LibraryAnalyzer.LibraryMa
List<Library> libraries = new ArrayList<>(); List<Library> libraries = new ArrayList<>();
for (Library library : version.getLibraries()) { for (Library library : version.getLibraries()) {
String groupId = library.getGroupId(); if (type.matchLibrary(library)) {
String artifactId = library.getArtifactId();
if (type.group.matcher(groupId).matches() && type.artifact.matcher(artifactId).matches()) {
// skip // skip
} else { } else {
libraries.add(library); libraries.add(library);
@@ -129,11 +126,8 @@ public final class LibraryAnalyzer implements Iterable<LibraryAnalyzer.LibraryMa
Map<String, Pair<Library, String>> libraries = new HashMap<>(); Map<String, Pair<Library, String>> libraries = new HashMap<>();
for (Library library : version.resolve(null).getLibraries()) { for (Library library : version.resolve(null).getLibraries()) {
String groupId = library.getGroupId();
String artifactId = library.getArtifactId();
for (LibraryType type : LibraryType.values()) { for (LibraryType type : LibraryType.values()) {
if (type.group.matcher(groupId).matches() && type.artifact.matcher(artifactId).matches()) { if (type.matchLibrary(library)) {
libraries.put(type.getPatchId(), pair(library, library.getVersion())); libraries.put(type.getPatchId(), pair(library, library.getVersion()));
break; break;
} }
@@ -180,6 +174,10 @@ public final class LibraryAnalyzer implements Iterable<LibraryAnalyzer.LibraryMa
return type; return type;
return null; return null;
} }
public boolean matchLibrary(Library library) {
return group.matcher(library.getGroupId()).matches() && artifact.matcher(library.getArtifactId()).matches();
}
} }
public static class LibraryMark { public static class LibraryMark {

View File

@@ -18,8 +18,10 @@
package org.jackhuang.hmcl.download.game; package org.jackhuang.hmcl.download.game;
import org.jackhuang.hmcl.download.AbstractDependencyManager; import org.jackhuang.hmcl.download.AbstractDependencyManager;
import org.jackhuang.hmcl.game.GameRepository;
import org.jackhuang.hmcl.game.Library; import org.jackhuang.hmcl.game.Library;
import org.jackhuang.hmcl.game.Version; import org.jackhuang.hmcl.game.Version;
import org.jackhuang.hmcl.task.FileDownloadTask;
import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.task.Task;
import org.jackhuang.hmcl.util.Logging; import org.jackhuang.hmcl.util.Logging;
import org.jackhuang.hmcl.util.io.FileUtils; import org.jackhuang.hmcl.util.io.FileUtils;
@@ -29,7 +31,6 @@ import java.io.IOException;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.jar.JarFile;
import java.util.logging.Level; import java.util.logging.Level;
/** /**
@@ -76,25 +77,23 @@ public final class GameLibrariesTask extends Task<Void> {
return dependencies; return dependencies;
} }
@Override public static boolean shouldDownloadLibrary(GameRepository gameRepository, Version version, Library library, boolean integrityCheck) {
public void execute() { File file = gameRepository.getLibraryFile(version, library);
libraries.stream().filter(Library::appliesToCurrentEnvironment).forEach(library -> {
File file = dependencyManager.getGameRepository().getLibraryFile(version, library);
Path jar = file.toPath(); Path jar = file.toPath();
boolean download = !file.isFile(); if (!file.isFile()) return true;
try { try {
if (!download && integrityCheck && !library.getDownload().validateChecksum(jar, true)) download = true; if (integrityCheck && !library.getDownload().validateChecksum(jar, true)) return true;
if (!download && integrityCheck && if (integrityCheck &&
library.getChecksums() != null && !library.getChecksums().isEmpty() && library.getChecksums() != null && !library.getChecksums().isEmpty() &&
!LibraryDownloadTask.checksumValid(file, library.getChecksums())) download = true; !LibraryDownloadTask.checksumValid(file, library.getChecksums())) return true;
if (!download && integrityCheck) { if (integrityCheck) {
String ext = FileUtils.getExtension(file); String ext = FileUtils.getExtension(file);
if (ext.equals("jar")) { if (ext.equals("jar")) {
try (JarFile jarFile = new JarFile(file)) { try {
jarFile.getManifest(); FileDownloadTask.ZIP_INTEGRITY_CHECK_HANDLER.checkIntegrity(jar, jar);
} catch (IOException ignored) { } catch (IOException ignored) {
// the Jar file is malformed, so re-download it. // the Jar file is malformed, so re-download it.
download = true; return true;
} }
} }
} }
@@ -102,7 +101,14 @@ public final class GameLibrariesTask extends Task<Void> {
Logging.LOG.log(Level.WARNING, "Unable to calc hash value of file " + jar, e); Logging.LOG.log(Level.WARNING, "Unable to calc hash value of file " + jar, e);
} }
if (download) { return false;
}
@Override
public void execute() {
libraries.stream().filter(Library::appliesToCurrentEnvironment).forEach(library -> {
File file = dependencyManager.getGameRepository().getLibraryFile(version, library);
if (shouldDownloadLibrary(dependencyManager.getGameRepository(), version, library, integrityCheck)) {
dependencies.add(new LibraryDownloadTask(dependencyManager, file, library)); dependencies.add(new LibraryDownloadTask(dependencyManager, file, library));
} else { } else {
dependencyManager.getCacheRepository().tryCacheLibrary(library, file.toPath()); dependencyManager.getCacheRepository().tryCacheLibrary(library, file.toPath());