2022-09-04 21:21:24 +02:00
|
|
|
package io.gitlab.jfronny.inceptum.launcher.system.source;
|
2021-11-02 19:52:35 +01:00
|
|
|
|
2022-04-28 23:13:37 +02:00
|
|
|
import io.gitlab.jfronny.commons.HashUtils;
|
2023-07-24 14:29:06 +02:00
|
|
|
import io.gitlab.jfronny.commons.StringFormatter;
|
2022-09-04 21:21:24 +02:00
|
|
|
import io.gitlab.jfronny.commons.cache.MemoryOperationResultCache;
|
2022-04-28 21:07:03 +02:00
|
|
|
import io.gitlab.jfronny.commons.tuple.Triple;
|
|
|
|
import io.gitlab.jfronny.commons.tuple.Tuple;
|
2022-09-04 21:21:24 +02:00
|
|
|
import io.gitlab.jfronny.inceptum.common.Net;
|
|
|
|
import io.gitlab.jfronny.inceptum.common.Utils;
|
|
|
|
import io.gitlab.jfronny.inceptum.launcher.api.CurseforgeApi;
|
2022-11-04 17:02:24 +01:00
|
|
|
import io.gitlab.jfronny.inceptum.launcher.model.curseforge.*;
|
2021-11-02 19:52:35 +01:00
|
|
|
|
|
|
|
import java.io.IOException;
|
2022-01-18 18:43:39 +01:00
|
|
|
import java.net.URISyntaxException;
|
2021-11-02 19:52:35 +01:00
|
|
|
import java.nio.file.Files;
|
|
|
|
import java.nio.file.Path;
|
2022-09-04 21:21:24 +02:00
|
|
|
import java.util.*;
|
2021-11-02 19:52:35 +01:00
|
|
|
|
|
|
|
public final class CurseforgeModSource implements ModSource {
|
2022-09-04 21:21:24 +02:00
|
|
|
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);
|
2022-01-24 19:21:23 +01:00
|
|
|
|
2021-11-02 19:52:35 +01:00
|
|
|
private final int projectId;
|
|
|
|
private final int fileId;
|
|
|
|
private final CurseforgeFile current;
|
2021-11-04 14:07:34 +01:00
|
|
|
private final CurseforgeMod mod;
|
2021-11-02 19:52:35 +01:00
|
|
|
|
|
|
|
public CurseforgeModSource(int projectId, int fileId) throws IOException {
|
|
|
|
this.projectId = projectId;
|
|
|
|
this.fileId = fileId;
|
2021-11-04 14:07:34 +01:00
|
|
|
this.current = CurseforgeApi.getFile(projectId, fileId);
|
|
|
|
this.mod = CurseforgeApi.getMod(projectId);
|
2021-11-02 19:52:35 +01:00
|
|
|
}
|
|
|
|
|
2022-06-05 16:45:22 +02:00
|
|
|
public CurseforgeModSource(String projectSlug, int fileId) throws IOException {
|
|
|
|
this.mod = CurseforgeApi.getMod(projectSlug);
|
2023-05-05 18:49:56 +02:00
|
|
|
this.projectId = mod.id();
|
2022-06-05 16:45:22 +02:00
|
|
|
this.fileId = fileId;
|
|
|
|
this.current = CurseforgeApi.getFile(projectId, fileId);
|
|
|
|
}
|
|
|
|
|
2021-11-02 19:52:35 +01:00
|
|
|
@Override
|
2021-12-25 22:09:51 +01:00
|
|
|
public ModDownload download() throws IOException {
|
|
|
|
Path path = getJarPath();
|
2022-01-18 18:43:39 +01:00
|
|
|
try {
|
2023-05-05 18:49:56 +02:00
|
|
|
Net.downloadFile(current.downloadUrl(), path);
|
2022-01-18 18:43:39 +01:00
|
|
|
} catch (URISyntaxException e) {
|
|
|
|
throw new IOException("Could not download file", e);
|
|
|
|
}
|
2021-11-02 19:52:35 +01:00
|
|
|
byte[] data = Files.readAllBytes(path);
|
|
|
|
return new ModDownload(HashUtils.sha1(data), HashUtils.murmur2(data), path);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2022-06-05 16:45:22 +02:00
|
|
|
public Set<ModSource> getDependencies(String gameVersion) throws IOException {
|
2022-01-24 19:21:23 +01:00
|
|
|
return DEPENDENCIES_CACHE.get(Tuple.of(projectId, fileId), () -> {
|
|
|
|
Set<ModSource> deps = new HashSet<>();
|
2023-05-05 18:49:56 +02:00
|
|
|
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()));
|
2022-06-05 16:45:22 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-01-24 19:21:23 +01:00
|
|
|
}
|
|
|
|
return deps;
|
|
|
|
});
|
2021-11-02 19:52:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public Optional<ModSource> getUpdate(String gameVersion) throws IOException {
|
2022-01-24 19:21:23 +01:00
|
|
|
return UPDATE_CACHE.get(Tuple.of(projectId, fileId, gameVersion), () -> {
|
2023-05-05 18:49:56 +02:00
|
|
|
for (CurseforgeMod.LatestFileIndex file : mod.latestFilesIndexes()) {
|
|
|
|
if (file.gameVersion().equals(gameVersion)) {
|
|
|
|
return file.fileId() == fileId
|
2022-01-24 19:21:23 +01:00
|
|
|
? Optional.empty()
|
2023-05-05 18:49:56 +02:00
|
|
|
: Optional.of(new CurseforgeModSource(projectId, file.fileId()));
|
2022-01-24 19:21:23 +01:00
|
|
|
}
|
2021-11-02 19:52:35 +01:00
|
|
|
}
|
2022-01-24 19:21:23 +01:00
|
|
|
return Optional.empty();
|
|
|
|
});
|
2021-11-02 19:52:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public String getVersion() {
|
2023-05-05 18:49:56 +02:00
|
|
|
return current.displayName();
|
2021-11-02 19:52:35 +01:00
|
|
|
}
|
|
|
|
|
2021-11-04 14:07:34 +01:00
|
|
|
@Override
|
|
|
|
public String getName() {
|
2023-05-05 18:49:56 +02:00
|
|
|
return "curseforge/" + getShortName() + '/' + current.id();
|
2021-12-28 13:13:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public String getShortName() {
|
2023-05-05 18:49:56 +02:00
|
|
|
return mod.slug() == null ? Integer.toString(mod.id()) : mod.slug();
|
2021-12-25 22:09:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public String getFileName() {
|
2023-05-05 18:49:56 +02:00
|
|
|
return current.fileName();
|
2021-11-04 14:07:34 +01:00
|
|
|
}
|
|
|
|
|
2023-07-24 14:29:06 +02:00
|
|
|
@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);
|
|
|
|
}
|
|
|
|
|
2021-11-02 19:52:35 +01:00
|
|
|
@Override
|
|
|
|
public boolean equals(ModSource other) {
|
|
|
|
return other instanceof CurseforgeModSource cu && cu.projectId == projectId && cu.fileId == fileId;
|
|
|
|
}
|
|
|
|
|
2023-07-24 14:29:06 +02:00
|
|
|
@Override
|
|
|
|
public boolean projectMatches(ModSource other) {
|
|
|
|
return other instanceof CurseforgeModSource cu && cu.projectId == projectId;
|
|
|
|
}
|
|
|
|
|
2021-11-02 19:52:35 +01:00
|
|
|
public int getFileId() {
|
|
|
|
return fileId;
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getProjectId() {
|
|
|
|
return projectId;
|
|
|
|
}
|
2022-09-18 15:15:30 +02:00
|
|
|
|
|
|
|
public CurseforgeModpackManifest.File toManifest() {
|
2022-11-18 21:58:40 +01:00
|
|
|
return new CurseforgeModpackManifest.File(projectId, fileId, true);
|
2022-09-18 15:15:30 +02:00
|
|
|
}
|
2021-11-02 19:52:35 +01:00
|
|
|
}
|