add: redownload corrupt files when game crashed
This commit is contained in:
@@ -28,6 +28,7 @@ import org.jackhuang.hmcl.util.io.FileUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.*;
|
||||
import java.util.logging.Level;
|
||||
|
||||
@@ -221,6 +222,20 @@ public class HMCLGameRepository extends DefaultGameRepository {
|
||||
beingModpackVersions.remove(id);
|
||||
}
|
||||
|
||||
public void markVersionLaunchedAbnormally(String id) {
|
||||
try {
|
||||
Files.createFile(getVersionRoot(id).toPath().resolve(".abnormal"));
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean unmarkVersionLaunchedAbnormally(String id) {
|
||||
File file = new File(getVersionRoot(id), ".abnormal");
|
||||
boolean result = file.isFile();
|
||||
file.delete();
|
||||
return result;
|
||||
}
|
||||
|
||||
private static final Gson GSON = new GsonBuilder()
|
||||
.setPrettyPrinting()
|
||||
.create();
|
||||
|
||||
@@ -135,7 +135,7 @@ public final class LauncherHelper {
|
||||
if (setting.isNotCheckGame())
|
||||
return null;
|
||||
else
|
||||
return dependencyManager.checkGameCompletionAsync(version);
|
||||
return dependencyManager.checkGameCompletionAsync(version, repository.unmarkVersionLaunchedAbnormally(selectedVersion));
|
||||
}), Task.composeAsync(null, () -> {
|
||||
try {
|
||||
ModpackConfiguration<?> configuration = ModpackHelper.readModpackConfiguration(repository.getModpackConfiguration(selectedVersion));
|
||||
@@ -168,7 +168,7 @@ public final class LauncherHelper {
|
||||
setting.toLaunchOptions(profile.getGameDir(), !setting.isNotCheckJVM()),
|
||||
launcherVisibility == LauncherVisibility.CLOSE
|
||||
? null // Unnecessary to start listening to game process output when close launcher immediately after game launched.
|
||||
: new HMCLProcessListener(authInfo, gameVersion.isPresent())
|
||||
: new HMCLProcessListener(repository, selectedVersion, authInfo, gameVersion.isPresent())
|
||||
);
|
||||
}).thenComposeAsync(launcher -> { // launcher is prev task's result
|
||||
if (scriptFile == null) {
|
||||
@@ -209,12 +209,12 @@ public final class LauncherHelper {
|
||||
|
||||
@Override
|
||||
public void onStop(boolean success, TaskExecutor executor) {
|
||||
if (!success && !Controllers.isStopped()) {
|
||||
Platform.runLater(() -> {
|
||||
// Check if the application has stopped
|
||||
// because onStop will be invoked if tasks fail when the executor service shut down.
|
||||
if (!Controllers.isStopped()) {
|
||||
launchingStepsPane.fireEvent(new DialogCloseEvent());
|
||||
if (!success) {
|
||||
Exception ex = executor.getException();
|
||||
if (ex != null) {
|
||||
String message;
|
||||
@@ -264,9 +264,9 @@ public final class LauncherHelper {
|
||||
MessageType.ERROR);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
launchingStepsPane.setExecutor(null);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -444,6 +444,8 @@ public final class LauncherHelper {
|
||||
*/
|
||||
class HMCLProcessListener implements ProcessListener {
|
||||
|
||||
private final HMCLGameRepository repository;
|
||||
private final String version;
|
||||
private final Map<String, String> forbiddenTokens;
|
||||
private ManagedProcess process;
|
||||
private boolean lwjgl;
|
||||
@@ -452,7 +454,9 @@ public final class LauncherHelper {
|
||||
private final LinkedList<Pair<String, Log4jLevel>> logs;
|
||||
private final CountDownLatch latch = new CountDownLatch(1);
|
||||
|
||||
public HMCLProcessListener(AuthInfo authInfo, boolean detectWindow) {
|
||||
public HMCLProcessListener(HMCLGameRepository repository, String version, AuthInfo authInfo, boolean detectWindow) {
|
||||
this.repository = repository;
|
||||
this.version = version;
|
||||
this.detectWindow = detectWindow;
|
||||
|
||||
if (authInfo == null)
|
||||
@@ -559,6 +563,12 @@ public final class LauncherHelper {
|
||||
// Game crashed before opening the game window.
|
||||
if (!lwjgl) finishLaunch();
|
||||
|
||||
launchingLatch.countDown();
|
||||
|
||||
if (exitType != ExitType.NORMAL) {
|
||||
repository.markVersionLaunchedAbnormally(version);
|
||||
}
|
||||
|
||||
if (exitType != ExitType.NORMAL && logWindow == null)
|
||||
Platform.runLater(() -> {
|
||||
logWindow = new LogWindow();
|
||||
|
||||
@@ -132,9 +132,9 @@ public final class TaskListPane extends StackPane {
|
||||
task.setName(i18n("modpack.scan"));
|
||||
}
|
||||
|
||||
Platform.runLater(() -> {
|
||||
ProgressListNode node = new ProgressListNode(task);
|
||||
nodes.put(task, node);
|
||||
Platform.runLater(() -> {
|
||||
StageNode stageNode = stageNodes.stream().filter(x -> x.stage.equals(task.getStage())).findAny().orElse(null);
|
||||
listBox.add(listBox.indexOf(stageNode) + 1, node);
|
||||
});
|
||||
@@ -148,11 +148,11 @@ public final class TaskListPane extends StackPane {
|
||||
});
|
||||
}
|
||||
|
||||
Platform.runLater(() -> {
|
||||
ProgressListNode node = nodes.remove(task);
|
||||
if (node == null)
|
||||
return;
|
||||
node.unbind();
|
||||
Platform.runLater(() -> {
|
||||
listBox.remove(node);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ public class Versions {
|
||||
}
|
||||
|
||||
public static void updateGameAssets(Profile profile, String version) {
|
||||
TaskExecutor executor = new GameAssetDownloadTask(profile.getDependency(), profile.getRepository().getVersion(version), GameAssetDownloadTask.DOWNLOAD_INDEX_FORCIBLY)
|
||||
TaskExecutor executor = new GameAssetDownloadTask(profile.getDependency(), profile.getRepository().getVersion(version), GameAssetDownloadTask.DOWNLOAD_INDEX_FORCIBLY, true)
|
||||
.executor();
|
||||
Controllers.taskDialog(executor, i18n("version.manage.redownload_assets_index"));
|
||||
executor.start();
|
||||
|
||||
@@ -25,7 +25,6 @@ import org.jackhuang.hmcl.download.optifine.OptiFineInstallTask;
|
||||
import org.jackhuang.hmcl.game.DefaultGameRepository;
|
||||
import org.jackhuang.hmcl.game.Version;
|
||||
import org.jackhuang.hmcl.task.Task;
|
||||
import org.jackhuang.hmcl.util.function.ExceptionalFunction;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
@@ -76,7 +75,7 @@ public class DefaultDependencyManager extends AbstractDependencyManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Task<?> checkGameCompletionAsync(Version original) {
|
||||
public Task<?> checkGameCompletionAsync(Version original, boolean integrityCheck) {
|
||||
Version version = original.resolve(repository);
|
||||
return Task.allOf(
|
||||
Task.composeAsync(() -> {
|
||||
@@ -85,14 +84,14 @@ public class DefaultDependencyManager extends AbstractDependencyManager {
|
||||
else
|
||||
return null;
|
||||
}),
|
||||
new GameAssetDownloadTask(this, version, GameAssetDownloadTask.DOWNLOAD_INDEX_IF_NECESSARY),
|
||||
new GameLibrariesTask(this, version)
|
||||
new GameAssetDownloadTask(this, version, GameAssetDownloadTask.DOWNLOAD_INDEX_IF_NECESSARY, integrityCheck),
|
||||
new GameLibrariesTask(this, version, integrityCheck)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Task<?> checkLibraryCompletionAsync(Version version) {
|
||||
return new GameLibrariesTask(this, version, version.getLibraries());
|
||||
public Task<?> checkLibraryCompletionAsync(Version version, boolean integrityCheck) {
|
||||
return new GameLibrariesTask(this, version, integrityCheck, version.getLibraries());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -46,7 +46,7 @@ public interface DependencyManager {
|
||||
*
|
||||
* @return the task to check game completion.
|
||||
*/
|
||||
Task<?> checkGameCompletionAsync(Version version);
|
||||
Task<?> checkGameCompletionAsync(Version version, boolean integrityCheck);
|
||||
|
||||
/**
|
||||
* Check if the game is complete.
|
||||
@@ -54,7 +54,7 @@ public interface DependencyManager {
|
||||
*
|
||||
* @return the task to check game completion.
|
||||
*/
|
||||
Task<?> checkLibraryCompletionAsync(Version version);
|
||||
Task<?> checkLibraryCompletionAsync(Version version, boolean integrityCheck);
|
||||
|
||||
/**
|
||||
* The builder to build a brand new game then libraries such as Forge, LiteLoader and OptiFine.
|
||||
|
||||
@@ -84,7 +84,7 @@ public final class FabricInstallTask extends Task<Version> {
|
||||
public void execute() {
|
||||
setResult(getPatch(JsonUtils.GSON.fromJson(launchMetaTask.getResult(), FabricInfo.class), remote.getGameVersion(), remote.getSelfVersion()));
|
||||
|
||||
dependencies.add(dependencyManager.checkLibraryCompletionAsync(getResult()));
|
||||
dependencies.add(dependencyManager.checkLibraryCompletionAsync(getResult(), true));
|
||||
}
|
||||
|
||||
private static String getLaunchMetaUrl(String gameVersion, String loaderVersion) {
|
||||
|
||||
@@ -45,14 +45,7 @@ import java.nio.file.FileSystem;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.*;
|
||||
import java.util.jar.Attributes;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.zip.ZipException;
|
||||
@@ -133,7 +126,7 @@ public class ForgeNewInstallTask extends Task<Version> {
|
||||
}
|
||||
}
|
||||
|
||||
dependents.add(new GameLibrariesTask(dependencyManager, version, profile.getLibraries()));
|
||||
dependents.add(new GameLibrariesTask(dependencyManager, version, true, profile.getLibraries()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -273,7 +266,7 @@ public class ForgeNewInstallTask extends Task<Version> {
|
||||
.setPriority(30000)
|
||||
.setId(LibraryAnalyzer.LibraryType.FORGE.getPatchId())
|
||||
.setVersion(selfVersion));
|
||||
dependencies.add(dependencyManager.checkLibraryCompletionAsync(forgeVersion));
|
||||
dependencies.add(dependencyManager.checkLibraryCompletionAsync(forgeVersion, true));
|
||||
|
||||
FileUtils.deleteDirectory(temp.toFile());
|
||||
}
|
||||
|
||||
@@ -27,11 +27,7 @@ import org.jackhuang.hmcl.util.gson.JsonUtils;
|
||||
import org.jackhuang.hmcl.util.io.FileUtils;
|
||||
import org.jackhuang.hmcl.util.io.IOUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.*;
|
||||
import java.nio.file.Path;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@@ -90,7 +86,7 @@ public class ForgeOldInstallTask extends Task<Version> {
|
||||
.setPriority(30000)
|
||||
.setId(LibraryAnalyzer.LibraryType.FORGE.getPatchId())
|
||||
.setVersion(selfVersion));
|
||||
dependencies.add(dependencyManager.checkLibraryCompletionAsync(installProfile.getVersionInfo()));
|
||||
dependencies.add(dependencyManager.checkLibraryCompletionAsync(installProfile.getVersionInfo(), true));
|
||||
} catch (ZipException ex) {
|
||||
throw new ArtifactMalformedException("Malformed forge installer file", ex);
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import org.jackhuang.hmcl.game.Version;
|
||||
import org.jackhuang.hmcl.task.FileDownloadTask;
|
||||
import org.jackhuang.hmcl.task.Task;
|
||||
import org.jackhuang.hmcl.util.CacheRepository;
|
||||
import org.jackhuang.hmcl.util.Logging;
|
||||
import org.jackhuang.hmcl.util.gson.JsonUtils;
|
||||
import org.jackhuang.hmcl.util.io.FileUtils;
|
||||
import org.jackhuang.hmcl.util.io.NetworkUtils;
|
||||
@@ -37,6 +38,7 @@ import java.net.URL;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@@ -49,6 +51,7 @@ public final class GameAssetDownloadTask extends Task<Void> {
|
||||
private final Version version;
|
||||
private final AssetIndexInfo assetIndexInfo;
|
||||
private final File assetIndexFile;
|
||||
private final boolean integrityCheck;
|
||||
private final List<Task<?>> dependents = new LinkedList<>();
|
||||
private final List<Task<?>> dependencies = new LinkedList<>();
|
||||
|
||||
@@ -58,11 +61,12 @@ public final class GameAssetDownloadTask extends Task<Void> {
|
||||
* @param dependencyManager the dependency manager that can provides {@link org.jackhuang.hmcl.game.GameRepository}
|
||||
* @param version the game version
|
||||
*/
|
||||
public GameAssetDownloadTask(AbstractDependencyManager dependencyManager, Version version, boolean forceDownloadingIndex) {
|
||||
public GameAssetDownloadTask(AbstractDependencyManager dependencyManager, Version version, boolean forceDownloadingIndex, boolean integrityCheck) {
|
||||
this.dependencyManager = dependencyManager;
|
||||
this.version = version.resolve(dependencyManager.getGameRepository());
|
||||
this.assetIndexInfo = this.version.getAssetIndex();
|
||||
this.assetIndexFile = dependencyManager.getGameRepository().getIndexFile(version.getId(), assetIndexInfo.getId());
|
||||
this.integrityCheck = integrityCheck;
|
||||
|
||||
if (!assetIndexFile.exists() || forceDownloadingIndex) {
|
||||
dependents.add(new GameAssetIndexDownloadTask(dependencyManager, this.version));
|
||||
@@ -101,9 +105,14 @@ public final class GameAssetDownloadTask extends Task<Void> {
|
||||
throw new InterruptedException();
|
||||
|
||||
File file = dependencyManager.getGameRepository().getAssetObject(version.getId(), assetIndexInfo.getId(), assetObject);
|
||||
if (file.isFile())
|
||||
dependencyManager.getCacheRepository().tryCacheFile(file.toPath(), CacheRepository.SHA1, assetObject.getHash());
|
||||
else {
|
||||
boolean download = !file.isFile();
|
||||
try {
|
||||
if (!download && integrityCheck && !assetObject.validateChecksum(file.toPath(), true))
|
||||
download = true;
|
||||
} catch (IOException e) {
|
||||
Logging.LOG.log(Level.WARNING, "Unable to calc hash value of file " + file.toPath(), e);
|
||||
}
|
||||
if (download) {
|
||||
List<URL> urls = dependencyManager.getPreferredDownloadProviders().stream()
|
||||
.map(downloadProvider -> downloadProvider.getAssetBaseURL() + assetObject.getLocation())
|
||||
.map(NetworkUtils::toURL)
|
||||
@@ -116,6 +125,8 @@ public final class GameAssetDownloadTask extends Task<Void> {
|
||||
.setCaching(true)
|
||||
.setCandidate(dependencyManager.getCacheRepository().getCommonDirectory()
|
||||
.resolve("assets").resolve("objects").resolve(assetObject.getLocation())));
|
||||
} else {
|
||||
dependencyManager.getCacheRepository().tryCacheFile(file.toPath(), CacheRepository.SHA1, assetObject.getHash());
|
||||
}
|
||||
|
||||
updateProgress(++progress, index.getObjects().size());
|
||||
|
||||
@@ -71,8 +71,8 @@ public class GameInstallTask extends Task<Version> {
|
||||
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)
|
||||
new GameAssetDownloadTask(dependencyManager, version, GameAssetDownloadTask.DOWNLOAD_INDEX_FORCIBLY, true),
|
||||
new GameLibrariesTask(dependencyManager, version, true)
|
||||
).withStage("hmcl.install.assets").withComposeAsync(gameRepository.save(version))));
|
||||
}
|
||||
|
||||
|
||||
@@ -21,10 +21,14 @@ import org.jackhuang.hmcl.download.AbstractDependencyManager;
|
||||
import org.jackhuang.hmcl.game.Library;
|
||||
import org.jackhuang.hmcl.game.Version;
|
||||
import org.jackhuang.hmcl.task.Task;
|
||||
import org.jackhuang.hmcl.util.Logging;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
|
||||
/**
|
||||
* This task is to download game libraries.
|
||||
@@ -36,6 +40,7 @@ public final class GameLibrariesTask extends Task<Void> {
|
||||
|
||||
private final AbstractDependencyManager dependencyManager;
|
||||
private final Version version;
|
||||
private final boolean integrityCheck;
|
||||
private final List<Library> libraries;
|
||||
private final List<Task<?>> dependencies = new LinkedList<>();
|
||||
|
||||
@@ -45,8 +50,8 @@ public final class GameLibrariesTask extends Task<Void> {
|
||||
* @param dependencyManager the dependency manager that can provides {@link org.jackhuang.hmcl.game.GameRepository}
|
||||
* @param version the game version
|
||||
*/
|
||||
public GameLibrariesTask(AbstractDependencyManager dependencyManager, Version version) {
|
||||
this(dependencyManager, version, version.resolve(dependencyManager.getGameRepository()).getLibraries());
|
||||
public GameLibrariesTask(AbstractDependencyManager dependencyManager, Version version, boolean integrityCheck) {
|
||||
this(dependencyManager, version, integrityCheck, version.resolve(dependencyManager.getGameRepository()).getLibraries());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,9 +60,10 @@ public final class GameLibrariesTask extends Task<Void> {
|
||||
* @param dependencyManager the dependency manager that can provides {@link org.jackhuang.hmcl.game.GameRepository}
|
||||
* @param version the game version
|
||||
*/
|
||||
public GameLibrariesTask(AbstractDependencyManager dependencyManager, Version version, List<Library> libraries) {
|
||||
public GameLibrariesTask(AbstractDependencyManager dependencyManager, Version version, boolean integrityCheck, List<Library> libraries) {
|
||||
this.dependencyManager = dependencyManager;
|
||||
this.version = version;
|
||||
this.integrityCheck = integrityCheck;
|
||||
this.libraries = libraries;
|
||||
|
||||
setSignificance(TaskSignificance.MODERATE);
|
||||
@@ -72,10 +78,22 @@ public final class GameLibrariesTask extends Task<Void> {
|
||||
public void execute() {
|
||||
libraries.stream().filter(Library::appliesToCurrentEnvironment).forEach(library -> {
|
||||
File file = dependencyManager.getGameRepository().getLibraryFile(version, library);
|
||||
if (!file.exists())
|
||||
Path jar = file.toPath();
|
||||
boolean download = !file.isFile();
|
||||
try {
|
||||
if (!download && integrityCheck && !library.getDownload().validateChecksum(jar, true)) download = true;
|
||||
if (!download && integrityCheck &&
|
||||
library.getChecksums() != null && !library.getChecksums().isEmpty() &&
|
||||
!LibraryDownloadTask.checksumValid(jar.toFile(), library.getChecksums())) download = true;
|
||||
} catch (IOException e) {
|
||||
Logging.LOG.log(Level.WARNING, "Unable to calc hash value of file " + jar, e);
|
||||
}
|
||||
|
||||
if (download) {
|
||||
dependencies.add(new LibraryDownloadTask(dependencyManager, file, library));
|
||||
else
|
||||
} else {
|
||||
dependencyManager.getCacheRepository().tryCacheLibrary(library, file.toPath());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -19,12 +19,7 @@ package org.jackhuang.hmcl.download.liteloader;
|
||||
|
||||
import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
||||
import org.jackhuang.hmcl.download.LibraryAnalyzer;
|
||||
import org.jackhuang.hmcl.game.Arguments;
|
||||
import org.jackhuang.hmcl.game.Artifact;
|
||||
import org.jackhuang.hmcl.game.LibrariesDownloadInfo;
|
||||
import org.jackhuang.hmcl.game.Library;
|
||||
import org.jackhuang.hmcl.game.LibraryDownloadInfo;
|
||||
import org.jackhuang.hmcl.game.Version;
|
||||
import org.jackhuang.hmcl.game.*;
|
||||
import org.jackhuang.hmcl.task.Task;
|
||||
import org.jackhuang.hmcl.util.Lang;
|
||||
|
||||
@@ -79,7 +74,7 @@ public final class LiteLoaderInstallTask extends Task<Version> {
|
||||
.setLogging(Collections.emptyMap()) // Mods may log in malformed format, causing XML parser to crash. So we suppress using official log4j configuration
|
||||
);
|
||||
|
||||
dependencies.add(dependencyManager.checkLibraryCompletionAsync(getResult()));
|
||||
dependencies.add(dependencyManager.checkLibraryCompletionAsync(getResult(), true));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,14 +20,7 @@ package org.jackhuang.hmcl.download.optifine;
|
||||
import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
||||
import org.jackhuang.hmcl.download.LibraryAnalyzer;
|
||||
import org.jackhuang.hmcl.download.VersionMismatchException;
|
||||
import org.jackhuang.hmcl.game.Arguments;
|
||||
import org.jackhuang.hmcl.game.Artifact;
|
||||
import org.jackhuang.hmcl.game.DefaultGameRepository;
|
||||
import org.jackhuang.hmcl.game.GameVersion;
|
||||
import org.jackhuang.hmcl.game.LibrariesDownloadInfo;
|
||||
import org.jackhuang.hmcl.game.Library;
|
||||
import org.jackhuang.hmcl.game.LibraryDownloadInfo;
|
||||
import org.jackhuang.hmcl.game.Version;
|
||||
import org.jackhuang.hmcl.game.*;
|
||||
import org.jackhuang.hmcl.task.FileDownloadTask;
|
||||
import org.jackhuang.hmcl.task.Task;
|
||||
import org.jackhuang.hmcl.util.io.CompressingUtils;
|
||||
@@ -184,7 +177,7 @@ public final class OptiFineInstallTask extends Task<Version> {
|
||||
libraries
|
||||
));
|
||||
|
||||
dependencies.add(dependencyManager.checkLibraryCompletionAsync(getResult()));
|
||||
dependencies.add(dependencyManager.checkLibraryCompletionAsync(getResult(), true));
|
||||
}
|
||||
|
||||
public static class UnsupportedOptiFineInstallationException extends Exception {
|
||||
|
||||
@@ -18,9 +18,14 @@
|
||||
package org.jackhuang.hmcl.game;
|
||||
|
||||
import com.google.gson.JsonParseException;
|
||||
import org.jackhuang.hmcl.util.DigestUtils;
|
||||
import org.jackhuang.hmcl.util.Hex;
|
||||
import org.jackhuang.hmcl.util.StringUtils;
|
||||
import org.jackhuang.hmcl.util.gson.Validation;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author huangyuhui
|
||||
@@ -56,4 +61,9 @@ public final class AssetObject implements Validation {
|
||||
if (StringUtils.isBlank(hash) || hash.length() < 2)
|
||||
throw new JsonParseException("AssetObject hash cannot be blank.");
|
||||
}
|
||||
|
||||
public boolean validateChecksum(Path file, boolean defaultValue) throws IOException {
|
||||
if (hash == null) return defaultValue;
|
||||
return Hex.encodeHex(DigestUtils.digest("SHA-1", file)).equalsIgnoreCase(hash);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,12 +19,13 @@ package org.jackhuang.hmcl.game;
|
||||
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import org.jackhuang.hmcl.util.Immutable;
|
||||
import org.jackhuang.hmcl.util.StringUtils;
|
||||
import org.jackhuang.hmcl.util.ToStringBuilder;
|
||||
import org.jackhuang.hmcl.util.*;
|
||||
import org.jackhuang.hmcl.util.gson.TolerableValidationException;
|
||||
import org.jackhuang.hmcl.util.gson.Validation;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author huangyuhui
|
||||
@@ -79,4 +80,9 @@ public class DownloadInfo implements Validation {
|
||||
if (StringUtils.isBlank(url))
|
||||
throw new TolerableValidationException();
|
||||
}
|
||||
|
||||
public boolean validateChecksum(Path file, boolean defaultValue) throws IOException {
|
||||
if (getSha1() == null) return defaultValue;
|
||||
return Hex.encodeHex(DigestUtils.digest("SHA-1", file)).equalsIgnoreCase(getSha1());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user