254 lines
13 KiB
Java
254 lines
13 KiB
Java
package io.gitlab.jfronny.inceptum.frontend.gui.window;
|
|
|
|
import imgui.ImGui;
|
|
import imgui.flag.ImGuiTableFlags;
|
|
import imgui.type.ImString;
|
|
import io.gitlab.jfronny.inceptum.Inceptum;
|
|
import io.gitlab.jfronny.inceptum.model.curseforge.CurseforgeMod;
|
|
import io.gitlab.jfronny.inceptum.model.inceptum.InstanceMeta;
|
|
import io.gitlab.jfronny.inceptum.model.inceptum.ModDescription;
|
|
import io.gitlab.jfronny.inceptum.model.modrinth.ModrinthProjectType;
|
|
import io.gitlab.jfronny.inceptum.util.PathUtil;
|
|
import io.gitlab.jfronny.inceptum.util.mds.IWModDescription;
|
|
import io.gitlab.jfronny.inceptum.util.mds.ModsDirScanner;
|
|
import io.gitlab.jfronny.inceptum.util.source.CurseforgeModSource;
|
|
import io.gitlab.jfronny.inceptum.util.source.ModDownload;
|
|
import io.gitlab.jfronny.inceptum.util.source.ModSource;
|
|
import io.gitlab.jfronny.inceptum.util.source.ModrinthModSource;
|
|
import io.gitlab.jfronny.inceptum.model.modrinth.ModrinthSearchResult;
|
|
import io.gitlab.jfronny.inceptum.model.modrinth.ModrinthVersion;
|
|
import io.gitlab.jfronny.inceptum.util.Utils;
|
|
import io.gitlab.jfronny.inceptum.util.api.CurseforgeApi;
|
|
import io.gitlab.jfronny.inceptum.util.api.ModrinthApi;
|
|
|
|
import java.io.IOException;
|
|
import java.net.URI;
|
|
import java.net.URISyntaxException;
|
|
import java.nio.file.Path;
|
|
import java.util.List;
|
|
|
|
public class AddModWindow extends Window {
|
|
private final ImString query = new ImString("", GuiUtil.INPUT_FIELD_LENGTH);
|
|
private final Path modsDir;
|
|
private final InstanceMeta instance;
|
|
private final ModsDirScanner mds;
|
|
private int cfPage = 0;
|
|
private int mrPage = 0;
|
|
private ModrinthSearchResult mr = null;
|
|
private List<CurseforgeMod> cf = null;
|
|
|
|
public AddModWindow(Path modsDir, InstanceMeta instance, ModsDirScanner mds) {
|
|
super(modsDir.getParent().getFileName().toString() + " - Add Mods");
|
|
this.modsDir = modsDir;
|
|
this.instance = instance;
|
|
this.mds = mds;
|
|
}
|
|
|
|
private void reSearch() throws IOException {
|
|
String query = this.query.get();
|
|
new Thread(() -> {
|
|
try {
|
|
ModrinthSearchResult ms = ModrinthApi.search(query, mrPage, instance.getMinecraftVersion(), ModrinthProjectType.mod);
|
|
if (!this.query.get().equals(query)) return;
|
|
mr = ms;
|
|
List<CurseforgeMod> cs = CurseforgeApi.search(instance.getMinecraftVersion(), query, cfPage, "Popularity");
|
|
if (!this.query.get().equals(query)) return;
|
|
cf = cs;
|
|
} catch (IOException e) {
|
|
Utils.LOGGER.error("Could not run search", e);
|
|
}
|
|
}, "search" + query).start();
|
|
}
|
|
|
|
@Override
|
|
public void draw() {
|
|
try {
|
|
if (ImGui.inputTextWithHint("Search", "Your search query", query)) {
|
|
reSearch();
|
|
}
|
|
|
|
if (ImGui.beginTabBar("ModsSelect")) {
|
|
if (ImGui.beginTabItem("Modrinth")) {
|
|
if (mr != null) {
|
|
boolean hasNext = (mr.offset + mr.hits.size() < mr.total_hits);
|
|
if (mrPage > 0) {
|
|
if (ImGui.button("Previous Page")) {
|
|
mrPage--;
|
|
reSearch();
|
|
}
|
|
if (hasNext)
|
|
ImGui.sameLine();
|
|
}
|
|
if (hasNext && ImGui.button("Next Page")) {
|
|
mrPage++;
|
|
reSearch();
|
|
}
|
|
}
|
|
if (mr != null && ImGui.beginTable("mods" + modsDir, 3, ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.Borders)) {
|
|
for (ModrinthSearchResult.ModResult mod : mr.hits) {
|
|
String modId = (mod.slug != null ? mod.slug : mod.project_id);
|
|
final String idPrefix = "local-";
|
|
if (mod.project_id.startsWith(idPrefix))
|
|
mod.project_id = mod.project_id.substring(idPrefix.length());
|
|
//TODO detail view
|
|
ImGui.tableNextColumn();
|
|
ImGui.text(mod.title);
|
|
ImGui.tableNextColumn();
|
|
ImGui.text(mod.description);
|
|
ImGui.tableNextColumn();
|
|
boolean alreadyPresent = false;
|
|
for (IWModDescription mdsMod : mds.getMods()) {
|
|
alreadyPresent = mdsMod.mod().isPresent()
|
|
&& mdsMod.mod().get().sources.keySet().stream()
|
|
.anyMatch(s -> s instanceof ModrinthModSource ms
|
|
&& ms.getModId().equals(mod.project_id));
|
|
if (alreadyPresent)
|
|
break;
|
|
}
|
|
if (alreadyPresent) {
|
|
ImGui.text("Installed");
|
|
}
|
|
else {
|
|
if (ImGui.button("Add##" + mod.project_id)) {
|
|
ModrinthVersion stable = null;
|
|
ModrinthVersion beta = null;
|
|
ModrinthVersion latest = null;
|
|
for (ModrinthVersion version : ModrinthApi.getVersions(mod.project_id)) {
|
|
if (version.game_versions.contains(instance.getMinecraftVersion()) && version.loaders.contains("fabric")) {
|
|
latest = version;
|
|
if (version.version_type == ModrinthVersion.VersionType.beta || version.version_type == ModrinthVersion.VersionType.release) {
|
|
beta = version;
|
|
}
|
|
if (version.version_type == ModrinthVersion.VersionType.release) {
|
|
stable = version;
|
|
}
|
|
}
|
|
}
|
|
if (stable != null) beta = stable;
|
|
if (beta != null) latest = beta;
|
|
if (latest == null) {
|
|
Inceptum.showError("No valid version could be identified for this mod", "No version found");
|
|
}
|
|
else {
|
|
ModrinthVersion finalLatest = latest;
|
|
new Thread(() -> {
|
|
try {
|
|
download(new ModrinthModSource(finalLatest.id), modsDir.resolve((mod.slug == null ? mod.project_id : mod.slug) + PathUtil.EXT_IMOD), mds).write();
|
|
} catch (IOException e) {
|
|
Inceptum.showError("Could not download mod", e);
|
|
}
|
|
}).start();
|
|
}
|
|
}
|
|
}
|
|
ImGui.sameLine();
|
|
if (ImGui.button("Web##" + mod.project_id)) {
|
|
Utils.openWebBrowser(new URI("https://modrinth.com/mod/" + modId));
|
|
}
|
|
}
|
|
ImGui.endTable();
|
|
}
|
|
ImGui.endTabItem();
|
|
}
|
|
if (ImGui.beginTabItem("Curseforge")) {
|
|
if (cf != null) {
|
|
boolean hasNext = cf.size() == 20;
|
|
if (cfPage > 0) {
|
|
if (ImGui.button("Previous Page")) {
|
|
cfPage--;
|
|
reSearch();
|
|
}
|
|
if (hasNext)
|
|
ImGui.sameLine();
|
|
}
|
|
if (hasNext && ImGui.button("Next Page")) {
|
|
cfPage++;
|
|
reSearch();
|
|
}
|
|
}
|
|
if (cf != null && ImGui.beginTable("curseforge" + modsDir, 3, ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.Borders)) {
|
|
for (CurseforgeMod mod : cf) {
|
|
//TODO detail view
|
|
ImGui.tableNextColumn();
|
|
ImGui.text(mod.name);
|
|
ImGui.tableNextColumn();
|
|
ImGui.text(mod.summary);
|
|
ImGui.tableNextColumn();
|
|
boolean alreadyPresent = false;
|
|
for (IWModDescription mdsMod : mds.getMods()) {
|
|
alreadyPresent = mdsMod.mod().isPresent()
|
|
&& mdsMod.mod().get().sources.keySet().stream()
|
|
.anyMatch(s -> s instanceof CurseforgeModSource ms
|
|
&& ms.getProjectId() == mod.id);
|
|
if (alreadyPresent)
|
|
break;
|
|
}
|
|
if (alreadyPresent) {
|
|
ImGui.text("Installed");
|
|
}
|
|
else {
|
|
if (ImGui.button("Add##" + mod.id)) {
|
|
CurseforgeMod.LatestFileIndex latest = null;
|
|
for (CurseforgeMod.LatestFileIndex file : mod.latestFilesIndexes) {
|
|
if (file.gameVersion.equals(instance.getMinecraftVersion())) {
|
|
if (latest == null) latest = file;
|
|
}
|
|
}
|
|
if (latest == null) {
|
|
Inceptum.showError("No valid version could be identified for this mod", "No version found");
|
|
}
|
|
else {
|
|
CurseforgeMod.LatestFileIndex finalLatest = latest;
|
|
new Thread(() -> {
|
|
try {
|
|
download(new CurseforgeModSource(mod.id, finalLatest.fileId), modsDir.resolve((mod.slug == null ? mod.id : mod.slug) + PathUtil.EXT_IMOD), mds).write();
|
|
} catch (IOException e) {
|
|
Inceptum.showError("Could not download mod", e);
|
|
}
|
|
}).start();
|
|
}
|
|
}
|
|
}
|
|
ImGui.sameLine();
|
|
if (ImGui.button("Web##" + mod.id)) {
|
|
Utils.openWebBrowser(new URI(mod.links.websiteUrl));
|
|
}
|
|
}
|
|
ImGui.endTable();
|
|
}
|
|
ImGui.endTabItem();
|
|
}
|
|
ImGui.endTabBar();
|
|
}
|
|
} catch (IOException | URISyntaxException e) {
|
|
Utils.LOGGER.error("Something went wrong while rendering an AddModWindow", e);
|
|
}
|
|
}
|
|
|
|
public static DownloadMeta download(ModSource ms, Path metaFile, ModsDirScanner mds) throws IOException {
|
|
for (IWModDescription value : mds.getMods()) {
|
|
if (value.mod().isEmpty()) continue;
|
|
for (ModSource source : value.mod().get().sources.keySet()) {
|
|
if (ms.equals(source)) {
|
|
return new DownloadMeta(new ModDownload(value.mod().get().sha1, value.mod().get().murmur2, value.path()), value.mod().get(), source, metaFile);
|
|
}
|
|
}
|
|
}
|
|
ModDownload md = ms.download();
|
|
ModDescription manifest = ModDescription.of(md.sha1(), md.murmur2(), ms, mds.getGameVersion());
|
|
for (ModSource dependency : ms.getDependencies(mds.getGameVersion())) {
|
|
DownloadMeta depMan = download(dependency, metaFile.getParent().resolve(dependency.getShortName() + PathUtil.EXT_IMOD), mds);
|
|
depMan.description.dependents.add(md.file().getFileName().toString());
|
|
manifest.dependencies.add(depMan.download.file().getFileName().toString());
|
|
depMan.write();
|
|
}
|
|
return new DownloadMeta(md, manifest, ms, metaFile);
|
|
}
|
|
|
|
public record DownloadMeta(ModDownload download, ModDescription description, ModSource source, Path metaFile) {
|
|
public void write() throws IOException {
|
|
Utils.writeObject(metaFile, description);
|
|
}
|
|
}
|
|
}
|