190 lines
8.5 KiB
Java
190 lines
8.5 KiB
Java
package io.gitlab.jfronny.inceptum.cli.commands;
|
|
|
|
import io.gitlab.jfronny.commons.io.JFiles;
|
|
import io.gitlab.jfronny.commons.throwable.ThrowingBiFunction;
|
|
import io.gitlab.jfronny.inceptum.cli.*;
|
|
import io.gitlab.jfronny.inceptum.common.Utils;
|
|
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.ModsDirScanner;
|
|
import io.gitlab.jfronny.inceptum.launcher.util.Unchecked;
|
|
|
|
import java.io.FileNotFoundException;
|
|
import java.io.IOException;
|
|
import java.nio.file.Files;
|
|
import java.nio.file.Path;
|
|
import java.util.*;
|
|
|
|
public class ModCommand extends Command {
|
|
//TODO ModAddCommand (search and install)
|
|
public ModCommand() {
|
|
super("Allows managing mods in instances", "", List.of("mod"), List.of(
|
|
new ModListCommand(),
|
|
new ModUpdateCommand(),
|
|
new ModRemoveCommand()
|
|
));
|
|
}
|
|
|
|
@Override
|
|
protected void invoke(CommandArgs args) {
|
|
Utils.LOGGER.error("No known mod command was specified");
|
|
}
|
|
|
|
public static class ModListCommand extends BaseInstanceCommand {
|
|
private final boolean filterUpdatable;
|
|
|
|
public ModListCommand() {
|
|
this("Lists the mods in an instance", List.of("list", "ls"), List.of(
|
|
new ModListCommand("List only updatable mods", List.of("updatable"), List.of(), true)
|
|
), false);
|
|
}
|
|
|
|
private ModListCommand(String help, List<String> aliases, List<Command> subCommands, boolean filterUpdatable) {
|
|
super(help, "", aliases, subCommands);
|
|
this.filterUpdatable = filterUpdatable;
|
|
}
|
|
|
|
@Override
|
|
protected void invoke(CommandArgs args, Instance instance) throws IOException {
|
|
if (!instance.isFabric()) {
|
|
System.err.println("This is not a fabric instance");
|
|
return;
|
|
}
|
|
System.out.println("Scanning installed mods, this might take a while");
|
|
instance.mds().runOnce((path, mod) -> {
|
|
boolean hasSources = !mod.getMetadata().sources().isEmpty();
|
|
boolean updatable = hasSources && mod.getMetadata().sources().values().stream().anyMatch(Optional::isPresent);
|
|
if (filterUpdatable && !updatable) return;
|
|
System.out.println("- " + path.getFileName().toString());
|
|
System.out.println(" " + mod.getName());
|
|
for (String s : mod.getDescription()) {
|
|
System.out.println(" " + s);
|
|
}
|
|
if (hasSources) {
|
|
System.out.println(" Sources:");
|
|
for (var entry : mod.getMetadata().sources().entrySet()) {
|
|
System.out.println(" - " + entry.getKey().getName() + " (" + entry.getKey().getVersion() + ")");
|
|
System.out.println(" Local: " + entry.getKey().getJarPath().toString());
|
|
if (entry.getValue().isPresent()) System.out.println(" Updatable to: " + entry.getValue().get().getVersion());
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
public static class ModRemoveCommand extends BaseInstanceCommand {
|
|
private final boolean ignoreDependencies;
|
|
|
|
public ModRemoveCommand() {
|
|
this("Removes mods from an instance", List.of("remove", "delete", "rm", "del"), List.of(
|
|
new ModRemoveCommand("Skip dependency checks", List.of("ignore-dependencies"), List.of(), true)
|
|
), false);
|
|
}
|
|
|
|
private ModRemoveCommand(String help, List<String> aliases, List<Command> subCommands, boolean ignoreDependencies) {
|
|
super(help, "<mod file>...", aliases, subCommands);
|
|
this.ignoreDependencies = ignoreDependencies;
|
|
}
|
|
|
|
@Override
|
|
protected void invoke(CommandArgs args, Instance instance) throws IOException {
|
|
if (!instance.isFabric()) {
|
|
Utils.LOGGER.error("This is not a fabric instance");
|
|
return;
|
|
}
|
|
if (args.length == 0) {
|
|
Utils.LOGGER.error("You must specify mods to remove");
|
|
return;
|
|
}
|
|
Set<Path> mods = new HashSet<>();
|
|
for (String arg : args) {
|
|
Path p = instance.getModsDir().resolve(arg);
|
|
if (!Files.exists(p)) p = instance.getModsDir().resolve(arg + ".imod");
|
|
if (!Files.exists(p)) {
|
|
Utils.LOGGER.error("Nonexistant mod file: " + instance.getModsDir().resolve(arg));
|
|
return;
|
|
}
|
|
mods.add(p);
|
|
}
|
|
ModsDirScanner mds = instance.mds();
|
|
if (!ignoreDependencies && !mds.isComplete()) {
|
|
Utils.LOGGER.error("Scanning mods dir to search for dependencies. This might take a while");
|
|
mds.runOnce((path, mod) -> System.out.println("Scanned " + path));
|
|
}
|
|
for (Path mod : mods) {
|
|
try {
|
|
mds.get(mod).delete();
|
|
} catch (IOException e) {
|
|
Utils.LOGGER.error("Could not delete " + mod, e);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public static class ModUpdateCommand extends BaseInstanceCommand {
|
|
private final ThrowingBiFunction<CommandArgs, Path, Set<Path>, IOException> pathSupplier;
|
|
|
|
public ModUpdateCommand() {
|
|
this("Update mods in an instance", "<mod file>...", List.of("update", "upgrade", "up"), List.of(
|
|
new ModUpdateCommand("Update all mods in an instance", "", List.of("all"), List.of(), (args, instancePath) -> Set.copyOf(JFiles.list(instancePath)))
|
|
), (args, instancePath) -> {
|
|
Set<Path> mods = new HashSet<>();
|
|
for (String arg : args) {
|
|
Path p = instancePath.resolve("mods").resolve(arg);
|
|
if (!Files.exists(p)) p = instancePath.resolve("mods").resolve(arg + ".imod");
|
|
if (!Files.exists(p)) {
|
|
throw new FileNotFoundException("Nonexistant mod file: " + instancePath.resolve("mods").resolve(arg));
|
|
}
|
|
mods.add(p);
|
|
}
|
|
return mods;
|
|
});
|
|
}
|
|
|
|
private ModUpdateCommand(String help, String usage, List<String> aliases, List<Command> subCommands, ThrowingBiFunction<CommandArgs, Path, Set<Path>, IOException> pathSupplier) {
|
|
super(help, usage, aliases, subCommands);
|
|
this.pathSupplier = pathSupplier;
|
|
}
|
|
|
|
@Override
|
|
protected void invoke(CommandArgs args, Instance instance) throws IOException {
|
|
if (!instance.isFabric()) {
|
|
throw new IOException("This is not a fabric instance");
|
|
}
|
|
if (args.length == 0) {
|
|
throw new IllegalArgumentException("You must specify mods to remove");
|
|
}
|
|
Set<Path> mods = pathSupplier.apply(args, instance.path());
|
|
ModsDirScanner mds = instance.mds();
|
|
if (!mds.isComplete()) {
|
|
Utils.LOGGER.error("Scanning mods dir to search for dependencies. This might take a while");
|
|
mds.runOnce((path, mod) -> System.out.println("Scanned " + path));
|
|
}
|
|
for (Path mod : mods) {
|
|
try {
|
|
Mod md = mds.get(mod);
|
|
md.delete();
|
|
md.getMetadata().sources().values().stream()
|
|
.filter(Optional::isPresent)
|
|
.map(Optional::get)
|
|
.findFirst()
|
|
.ifPresentOrElse(update -> {
|
|
try {
|
|
Utils.LOGGER.info("Updating " + mod + " to " + update.getVersion());
|
|
md.update(update);
|
|
Utils.LOGGER.info("Update completed");
|
|
} catch (IOException e) {
|
|
throw new Unchecked(e);
|
|
}
|
|
}, () -> Utils.LOGGER.error("Could not find any update for " + mod));
|
|
} catch (IOException e) {
|
|
throw new IOException("Could not delete " + mod, e);
|
|
} catch (Unchecked e) {
|
|
throw new IOException("Could not delete " + mod, e.exception);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|