Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -498,7 +498,15 @@ public RemoteAddon.Version toVersion() {
null,
fileDate(),
versionType,
new RemoteAddon.File(Collections.emptyMap(), downloadUrl(), fileName()),
new RemoteAddon.File(hashes == null ? Collections.emptyMap() : hashes.stream().collect(Collectors.toMap(
hash -> switch (hash.algo()) {
case 1 -> "sha1";
case 2 -> "md5";
default -> "algo" + hash.algo();
},
LatestFileHash::value,
(a, b) -> a
)), downloadUrl(), fileName()),
dependencies.stream().map(dependency -> {
if (!RELATION_TYPE.containsKey(dependency.relationType())) {
throw new IllegalStateException("Broken datas.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,16 +121,33 @@ public void execute() throws Exception {
manifest.files().parallelStream()
.map(file -> {
updateProgress(finished.incrementAndGet(), manifest.files().size());
if (StringUtils.isBlank(file.fileName()) || file.url() == null) {
try {
RemoteAddon.File remoteFile = CurseForgeRemoteAddonRepository.MODS.getAddonFile(Integer.toString(file.projectID()), Integer.toString(file.fileID()));
return file.withFileName(remoteFile.filename()).withURL(remoteFile.url());
} catch (FileNotFoundException fof) {
LOG.warning("Could not query api.curseforge.com for deleted mods: " + file.projectID() + ", " + file.fileID(), fof);
notFound.set(true);
return file;
} catch (IOException | JsonParseException e) {
LOG.warning("Unable to fetch the file name projectID=" + file.projectID() + ", fileID=" + file.fileID(), e);
if (StringUtils.isBlank(file.fileName()) || file.url() == null || file.hashes() == null || file.hashes().isEmpty()) {
RemoteAddon.File remoteFile = null;
Exception lastException = null;
for (int attempt = 0; attempt < 3; attempt++) {
try {
remoteFile = CurseForgeRemoteAddonRepository.MODS.getAddonFile(Integer.toString(file.projectID()), Integer.toString(file.fileID()));
break;
} catch (FileNotFoundException fof) {
LOG.warning("Could not query api.curseforge.com for deleted mods: " + file.projectID() + ", " + file.fileID(), fof);
notFound.set(true);
return file;
} catch (IOException | JsonParseException e) {
lastException = e;
if (attempt < 2) {
try {
Thread.sleep(500L * (attempt + 1));
} catch (InterruptedException ignored) {
Thread.currentThread().interrupt();
break;
}
}
}
}
if (remoteFile != null) {
return file.withFileName(remoteFile.filename()).withURL(remoteFile.url()).withHashes(remoteFile.hashes());
} else {
LOG.warning("Unable to fetch the file name projectID=" + file.projectID() + ", fileID=" + file.fileID(), lastException);
allNameKnown.set(false);
return file;
}
Expand All @@ -150,12 +167,26 @@ public void execute() throws Exception {
.filter(f -> f.fileName() != null)
.flatMap(f -> {
try {
Path path = guessFilePath(f, dependency.getDownloadProvider(), resourcePacksRoot, shaderPacksRoot);
Path path = null;
for (int attempt = 0; attempt < 3; attempt++) {
try {
path = guessFilePath(f, dependency.getDownloadProvider(), resourcePacksRoot, shaderPacksRoot);
break;
} catch (IOException e) {
if (attempt == 2) throw e;
try {
Thread.sleep(500L * (attempt + 1));
} catch (InterruptedException ignored) {
Thread.currentThread().interrupt();
break;
}
}
}
if (path == null) {
return Stream.empty();
}

var task = new FileDownloadTask(f.url(), path);
var task = new FileDownloadTask(f.url(), path, f.getIntegrityCheck());
task.setCacheRepository(dependency.getCacheRepository());
task.setCaching(true);
return Stream.of(task.withCounter("hmcl.modpack.download"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,12 @@ public record CurseManifestFile(@SerializedName("projectID") int projectID,
@SerializedName("fileID") int fileID,
@SerializedName("fileName") String fileName,
@SerializedName("url") String url,
@SerializedName("required") boolean required) implements Validation {
@SerializedName("required") boolean required,
@SerializedName("hashes") java.util.Map<String, String> hashes) implements Validation {

public CurseManifestFile(int projectID, int fileID, String fileName, String url, boolean required) {
this(projectID, fileID, fileName, url, required, null);
}

@Override
public void validate() throws JsonParseException {
Expand All @@ -51,12 +56,31 @@ public String url() {
}
}

@Nullable
public org.jackhuang.hmcl.task.FileDownloadTask.IntegrityCheck getIntegrityCheck() {
if (hashes == null || hashes.isEmpty()) return null;
if (hashes.containsKey("sha1")) {
return new org.jackhuang.hmcl.task.FileDownloadTask.IntegrityCheck("SHA-1", hashes.get("sha1"));
} else if (hashes.containsKey("md5")) {
return new org.jackhuang.hmcl.task.FileDownloadTask.IntegrityCheck("MD5", hashes.get("md5"));
} else if (hashes.containsKey("sha256")) {
return new org.jackhuang.hmcl.task.FileDownloadTask.IntegrityCheck("SHA-256", hashes.get("sha256"));
} else if (hashes.containsKey("sha512")) {
return new org.jackhuang.hmcl.task.FileDownloadTask.IntegrityCheck("SHA-512", hashes.get("sha512"));
}
return null;
}

public CurseManifestFile withFileName(String fileName) {
return new CurseManifestFile(projectID, fileID, fileName, url, required);
return new CurseManifestFile(projectID, fileID, fileName, url, required, hashes);
}

public CurseManifestFile withURL(String url) {
return new CurseManifestFile(projectID, fileID, fileName, url, required);
return new CurseManifestFile(projectID, fileID, fileName, url, required, hashes);
}

public CurseManifestFile withHashes(java.util.Map<String, String> hashes) {
return new CurseManifestFile(projectID, fileID, fileName, url, required, hashes);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ public void execute() throws Exception {
dependencies.add(builder.buildAsync());
}

Path rootPath = repository.getInstanceRoot(instanceId).toAbsolutePath().normalize();
Path rootPath = repository.getRunDirectory(instanceId).toAbsolutePath().normalize();
Map<String, ModpackConfiguration.FileInformation> files = manifest.getManifest().getFiles().stream()
.collect(Collectors.toMap(ModpackConfiguration.FileInformation::getPath,
Function.identity()));
Expand Down