100 lines
4.6 KiB
Java
100 lines
4.6 KiB
Java
package io.gitlab.jfronny.inceptum.launcher.system.mds;
|
|
|
|
import io.gitlab.jfronny.commons.io.JFiles;
|
|
import io.gitlab.jfronny.gson.JsonParseException;
|
|
import io.gitlab.jfronny.inceptum.common.Utils;
|
|
import io.gitlab.jfronny.inceptum.launcher.model.fabric.FabricModJson;
|
|
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.ModMeta;
|
|
import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance;
|
|
import io.gitlab.jfronny.inceptum.launcher.system.instance.Mod;
|
|
import io.gitlab.jfronny.inceptum.launcher.system.mds.noop.NoopMod;
|
|
import io.gitlab.jfronny.inceptum.launcher.system.instance.ModPath;
|
|
import io.gitlab.jfronny.inceptum.launcher.system.source.ModSource;
|
|
import org.jetbrains.annotations.Nullable;
|
|
|
|
import java.io.FileNotFoundException;
|
|
import java.io.IOException;
|
|
import java.net.URISyntaxException;
|
|
import java.nio.file.*;
|
|
import java.util.List;
|
|
import java.util.function.*;
|
|
|
|
public record FileScanTask(ProtoInstance instance, Path file, BiConsumer<Path, Mod> discovered, String gameVersion) implements Runnable {
|
|
@Override
|
|
public void run() {
|
|
if (!Files.exists(file)) return;
|
|
if (Files.isDirectory(file)) return; // Directories are not supported
|
|
try {
|
|
if (ModPath.isJar(file)) {
|
|
final MetadataRef imod = new MetadataRef(file.getParent().resolve(file.getFileName() + ModPath.EXT_IMOD), ModMeta::of);
|
|
evaluateSources(file, imod);
|
|
discovered.accept(imod.imodPath, new MdsMod(instance, imod.imodPath, file, false, imod.meta, getFmj(file, imod.meta)));
|
|
} else if (ModPath.isImod(file)) {
|
|
String fn = file.getFileName().toString();
|
|
Path modFile = file.getParent().resolve(fn.substring(0, fn.length() - ModPath.EXT_IMOD.length()));
|
|
final MetadataRef imod = new MetadataRef(file, null);
|
|
evaluateSources(modFile, imod);
|
|
boolean managedJar = !Files.exists(modFile);
|
|
discovered.accept(imod.imodPath, new MdsMod(instance, imod.imodPath, managedJar ? imod.jarPath : modFile, managedJar, imod.meta, getFmj(modFile, imod.meta)));
|
|
} else discovered.accept(file, new NoopMod(file));
|
|
} catch (IOException | URISyntaxException | JsonParseException e) {
|
|
Utils.LOGGER.error("Could not scan file for mod info", e);
|
|
}
|
|
}
|
|
|
|
private <TEx extends Throwable> void evaluateSources(Path modFile, MetadataRef ref) throws IOException, TEx {
|
|
boolean modified = false;
|
|
if (ref.meta.initialize(gameVersion)) {
|
|
JFiles.writeObject(ref.imodPath, ref.meta);
|
|
modified = true;
|
|
}
|
|
ModSource selectedSource = null;
|
|
for (ModSource source : ref.meta.sources.keySet()) {
|
|
source.getUpdate(gameVersion);
|
|
if (!Files.exists(source.getJarPath())) source.download();
|
|
selectedSource = source;
|
|
}
|
|
if (selectedSource != null) {
|
|
if (Files.exists(modFile)) {
|
|
Files.delete(modFile);
|
|
Path newImod = ref.imodPath.getParent().resolve(selectedSource.getShortName() + ModPath.EXT_IMOD);
|
|
Files.move(ref.imodPath, newImod);
|
|
ref.imodPath = newImod;
|
|
modified = true;
|
|
}
|
|
ref.jarPath = selectedSource.getJarPath();
|
|
}
|
|
if (modified) ref.update();
|
|
}
|
|
|
|
private @Nullable FabricModJson getFmj(Path modJarDefault, ModMeta md) throws IOException, URISyntaxException {
|
|
if (!Files.exists(modJarDefault)) {
|
|
if (md.sources.isEmpty()) {
|
|
throw new FileNotFoundException("Mod " + modJarDefault.getFileName().toString() + " doesn't specify a source and has no file");
|
|
}
|
|
modJarDefault = List.copyOf(md.sources.keySet()).get(0).getJarPath();
|
|
}
|
|
try (FileSystem fs = Utils.openZipFile(modJarDefault, false)) {
|
|
Path fmjPath = fs.getPath("fabric.mod.json");
|
|
if (!Files.exists(fmjPath)) return null;
|
|
return JFiles.readObject(fmjPath, FabricModJson.class);
|
|
}
|
|
}
|
|
|
|
private static class MetadataRef {
|
|
public MetadataRef(Path imodPath, @Nullable Function<Path, ModMeta> defaultMeta) throws IOException {
|
|
this.imodPath = imodPath;
|
|
if (!Files.exists(imodPath) && defaultMeta != null) JFiles.writeObject(imodPath, defaultMeta.apply(imodPath));
|
|
if (Files.exists(imodPath)) update();
|
|
}
|
|
|
|
public Path imodPath;
|
|
public Path jarPath; // filled in from evaluateSources
|
|
public ModMeta meta;
|
|
|
|
public void update() throws IOException {
|
|
this.meta = JFiles.readObject(imodPath, ModMeta.class);
|
|
}
|
|
}
|
|
}
|