147 lines
5.1 KiB
Java
147 lines
5.1 KiB
Java
package io.gitlab.jfronny.inceptum.launcher.system.source;
|
|
|
|
import io.gitlab.jfronny.commons.HashUtils;
|
|
import io.gitlab.jfronny.commons.StringFormatter;
|
|
import io.gitlab.jfronny.commons.cache.MemoryOperationResultCache;
|
|
import io.gitlab.jfronny.commons.tuple.Triple;
|
|
import io.gitlab.jfronny.commons.tuple.Tuple;
|
|
import io.gitlab.jfronny.inceptum.common.Net;
|
|
import io.gitlab.jfronny.inceptum.common.Utils;
|
|
import io.gitlab.jfronny.inceptum.launcher.api.CurseforgeApi;
|
|
import io.gitlab.jfronny.inceptum.launcher.model.curseforge.*;
|
|
|
|
import java.io.IOException;
|
|
import java.net.URISyntaxException;
|
|
import java.nio.file.Files;
|
|
import java.nio.file.Path;
|
|
import java.util.*;
|
|
|
|
public final class CurseforgeModSource implements ModSource {
|
|
private static final MemoryOperationResultCache<Triple<Integer, Integer, String>, Optional<ModSource>> UPDATE_CACHE = new MemoryOperationResultCache<>(Utils.CACHE_SIZE);
|
|
private static final MemoryOperationResultCache<Tuple<Integer, Integer>, Set<ModSource>> DEPENDENCIES_CACHE = new MemoryOperationResultCache<>(Utils.CACHE_SIZE);
|
|
|
|
private final int projectId;
|
|
private final int fileId;
|
|
private final CurseforgeFile current;
|
|
private final CurseforgeMod mod;
|
|
|
|
public CurseforgeModSource(int projectId, int fileId) throws IOException {
|
|
this.projectId = projectId;
|
|
this.fileId = fileId;
|
|
this.current = CurseforgeApi.getFile(projectId, fileId);
|
|
this.mod = CurseforgeApi.getMod(projectId);
|
|
}
|
|
|
|
public CurseforgeModSource(String projectSlug, int fileId) throws IOException {
|
|
this.mod = CurseforgeApi.getMod(projectSlug);
|
|
this.projectId = mod.id();
|
|
this.fileId = fileId;
|
|
this.current = CurseforgeApi.getFile(projectId, fileId);
|
|
}
|
|
|
|
@Override
|
|
public ModDownload download() throws IOException {
|
|
Path path = getJarPath();
|
|
try {
|
|
Net.downloadFile(current.downloadUrl(), path);
|
|
} catch (URISyntaxException e) {
|
|
throw new IOException("Could not download file", e);
|
|
}
|
|
byte[] data = Files.readAllBytes(path);
|
|
return new ModDownload(HashUtils.sha1(data), HashUtils.murmur2(data), path);
|
|
}
|
|
|
|
@Override
|
|
public Set<ModSource> getDependencies(String gameVersion) throws IOException {
|
|
return DEPENDENCIES_CACHE.get(Tuple.of(projectId, fileId), () -> {
|
|
Set<ModSource> deps = new HashSet<>();
|
|
for (CurseforgeFile.Dependency dependency : current.dependencies()) {
|
|
if (dependency.relationType() == 3) { //TODO support other types (IDs are documented on field declaration)
|
|
for (CurseforgeMod.LatestFileIndex index : CurseforgeApi.getMod(dependency.modId()).latestFilesIndexes()) {
|
|
if (index.gameVersion().equals(gameVersion)) {
|
|
deps.add(new CurseforgeModSource(dependency.modId(), index.fileId()));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return deps;
|
|
});
|
|
}
|
|
|
|
@Override
|
|
public Optional<ModSource> getUpdate(String gameVersion) throws IOException {
|
|
return UPDATE_CACHE.get(Tuple.of(projectId, fileId, gameVersion), () -> {
|
|
for (CurseforgeMod.LatestFileIndex file : mod.latestFilesIndexes()) {
|
|
if (file.gameVersion().equals(gameVersion)) {
|
|
return file.fileId() == fileId
|
|
? Optional.empty()
|
|
: Optional.of(new CurseforgeModSource(projectId, file.fileId()));
|
|
}
|
|
}
|
|
return Optional.empty();
|
|
});
|
|
}
|
|
|
|
@Override
|
|
public String getVersion() {
|
|
return current.displayName();
|
|
}
|
|
|
|
@Override
|
|
public String getName() {
|
|
return "curseforge/" + getShortName() + '/' + current.id();
|
|
}
|
|
|
|
@Override
|
|
public String getShortName() {
|
|
return mod.slug() == null ? Integer.toString(mod.id()) : mod.slug();
|
|
}
|
|
|
|
@Override
|
|
public String getFileName() {
|
|
return current.fileName();
|
|
}
|
|
|
|
@Override
|
|
public String getDescription() {
|
|
try {
|
|
return CurseforgeApi.getDescription(mod.id());
|
|
} catch (IOException e) {
|
|
return "Could not get description\n\n" + StringFormatter.toString(e);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public String getSummary() {
|
|
return mod.summary();
|
|
}
|
|
|
|
@Override
|
|
public boolean equals(Object obj) {
|
|
return obj instanceof ModSource ms && equals(ms);
|
|
}
|
|
|
|
@Override
|
|
public boolean equals(ModSource other) {
|
|
return other instanceof CurseforgeModSource cu && cu.projectId == projectId && cu.fileId == fileId;
|
|
}
|
|
|
|
@Override
|
|
public boolean projectMatches(ModSource other) {
|
|
return other instanceof CurseforgeModSource cu && cu.projectId == projectId;
|
|
}
|
|
|
|
public int getFileId() {
|
|
return fileId;
|
|
}
|
|
|
|
public int getProjectId() {
|
|
return projectId;
|
|
}
|
|
|
|
public CurseforgeModpackManifest.File toManifest() {
|
|
return new CurseforgeModpackManifest.File(projectId, fileId, true);
|
|
}
|
|
}
|