4
0
Fork 0
mirror of https://github.com/Anvilcraft/modpacktools synced 2024-11-17 23:41:55 +01:00

The Big improvement

completely changed command loading system
This commit is contained in:
LordMZTE 2020-06-18 14:37:38 +02:00
parent 53db66abde
commit b78a95fa8e
11 changed files with 352 additions and 333 deletions

View file

@ -22,6 +22,7 @@ dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
compile 'org.slf4j:slf4j-simple:2.0.0-alpha1'
compile 'com.j2html:j2html:1.4.0'
compile 'org.reflections:reflections:0.9.12'
}
sourceSets {

View file

@ -1,49 +1,33 @@
package ley.anvil.modpacktools;
import ley.anvil.modpacktools.commands.Commands;
import ley.anvil.modpacktools.command.CommandLoader;
import ley.anvil.modpacktools.command.CommandReturn;
import ley.anvil.modpacktools.util.Config;
import java.util.NoSuchElementException;
public class Main {
public static final Config CONFIG = new Config();
public static final Config CONFIG = new Config();
public static final CommandLoader LOADER = new CommandLoader("ley.anvil.modpacktools.commands");
public static void main(String[] args) {
if(args.length == 0) {
Commands.help();
return;
}
switch(args[0].toLowerCase() /* ignores case of commands */) {
case "help":
default:
Commands.help();
break;
case "init":
Commands.init();
break;
case "addmod":
Commands.addMod(args);
break;
case "buildtwitch":
Commands.buildTwitch();
break;
case "buildmodpackjson":
Commands.buildModpackJSON();
break;
case "buildraw":
Commands.buildRaw();
break;
case "buildserver":
Commands.buildServer(args);
break;
case "downloadmods":
Commands.downloadMods(args);
break;
case "createmodlist":
Commands.createModlist(args);
break;
case "makeserver":
Commands.makeServer(args);
break;
}
}
public static void main(String[] args) {
if(args.length <= 0) {
printHelp();
return;
}
try {
CommandReturn ret = LOADER.runCommand(args[0], args);
if(!ret.hadSuccess())
System.out.println(ret.getRet());
}catch(NoSuchElementException e) {
System.out.println(e.getMessage());
printHelp();
}
}
private static void printHelp() {
System.out.println("Commands:");
LOADER.getCommands().forEach((k, v) -> System.out.println(k));
}
}

View file

@ -0,0 +1,42 @@
package ley.anvil.modpacktools.command;
import org.reflections.Reflections;
import org.reflections.scanners.SubTypesScanner;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.NoSuchElementException;
public class CommandLoader {
private final String commandsPkg;
private final Map<String, ICommand> commands = new HashMap<>();
public CommandLoader(String commandsPkg) {
this.commandsPkg = commandsPkg;
loadCommands();
}
private void loadCommands() {
Reflections reflections = new Reflections(commandsPkg, new SubTypesScanner(false));
reflections.getSubTypesOf(ICommand.class).stream()
.filter(t -> t.isAnnotationPresent(LoadCommand.class))
.forEach(t -> {
try {
commands.put(t.getAnnotation(LoadCommand.class).value(), t.newInstance());
}catch(InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
});
}
public CommandReturn runCommand(String name, String[] args) throws NoSuchElementException {
return commands.computeIfAbsent(name.toLowerCase(), x -> {
throw new NoSuchElementException("Command " + x + " Not Found");
}).execute(args);
}
public Map<String, ICommand> getCommands() {
return Collections.unmodifiableMap(commands);
}
}

View file

@ -0,0 +1,31 @@
package ley.anvil.modpacktools.command;
public class CommandReturn {
private final String ret;
private final boolean success;
private CommandReturn(String ret, boolean success) {
this.ret = ret;
this.success = success;
}
public static CommandReturn fail(String ret) {
return new CommandReturn(ret, false);
}
public static CommandReturn success() {
return success("");
}
public static CommandReturn success(String ret) {
return new CommandReturn(ret, true);
}
public boolean hadSuccess() {
return success;
}
public String getRet() {
return ret;
}
}

View file

@ -0,0 +1,15 @@
package ley.anvil.modpacktools.command;
public interface ICommand {
/**
* Executes this Command
* @param args Arguments for the Command
* @return If the Command was executed successful
*/
CommandReturn execute(String[] args);
default String getName() {
return this.getClass().getAnnotation(LoadCommand.class).value();
}
}

View file

@ -0,0 +1,18 @@
package ley.anvil.modpacktools.command;
import java.lang.annotation.*;
/**
* Tells The {@code CommandLoader} to load this command
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface LoadCommand {
/**
* the name of this command, must be lower case
*
* @return the name of this command
*/
String value();
}

View file

@ -1,4 +1,4 @@
package ley.anvil.modpacktools.commands;
package ley.anvil.modpacktools.commandhelper;
import com.google.gson.Gson;
import com.google.gson.JsonArray;

View file

@ -0,0 +1,114 @@
package ley.anvil.modpacktools.commands;
import com.therandomlabs.curseapi.CurseAPI;
import com.therandomlabs.curseapi.CurseException;
import com.therandomlabs.curseapi.project.CurseProject;
import ley.anvil.addonscript.curse.CurseTools;
import ley.anvil.addonscript.v1.AddonscriptJSON;
import ley.anvil.modpacktools.Main;
import ley.anvil.modpacktools.command.CommandReturn;
import ley.anvil.modpacktools.command.ICommand;
import ley.anvil.modpacktools.command.LoadCommand;
import okhttp3.HttpUrl;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@LoadCommand("addmod")
public class AddMod implements ICommand {
@Override
public CommandReturn execute(String[] args) {
//Check if the command has the correct number of args
if(args.length >= 2) {
//TODO Theres no way this command will work in this state of course
AddonscriptJSON json = null;
AddonscriptJSON.Version version = null;
if (json != null && json.versions != null) {
if (json.versions.size() == 1) {
version = json.versions.get(0);
} else {
for (AddonscriptJSON.Version v : json.versions) {
if (v.versionid == -1) {
version = v;
break;
}
}
}
}
if (version == null) {
throw new RuntimeException("Error: The modpack.json does not include a version with id -1");
}
//The url must match this
String regex = "(?m)^(http)(s)?://(www\\.)?(curseforge.com/minecraft/mc-mods/)[0-z,\\-]+/(files)/[0-9]+$";
String endPartRegex = "(/files/)[0-9]+$";
if(args[1].matches(regex)) {
CurseTools.addCurseRepo(json);
try {
//remove fileID
System.out.println("Getting ID");
CurseProject project = CurseAPI.project(HttpUrl.get(args[1].replaceAll(endPartRegex, ""))).get();
int projectID = project.id();
//extract fileID
Pattern pattern = Pattern.compile("[0-9]+$");
Matcher matcher = pattern.matcher(args[1]);
int fileID = 0;
if(matcher.find()) {
fileID = Integer.parseInt(matcher.group(0));
}
File manifestFile = new File(Main.CONFIG.JAR_LOCATION, Main.CONFIG.CONFIG
.getTable("Locations")
.getString("manifestFile"));
System.out.println("Reading Addonscript");
//Get Mods in manifest file
//Check if Mod already exsits
for(AddonscriptJSON.Relation file : version.relations) {
if (file.file != null) {
String[] parts = file.file.split(":");
if (parts.length == 3 && parts[0].equals("curse")) { //TODO check, if it is a Curse repo, waiting for Addonscript to update this
int projID = Integer.parseInt(parts[1]);
if (projID == projectID) {
return CommandReturn.fail("The Mod Is already Installed");
}
}
}
}
System.out.println("Adding Mod " + project.name());
//Construct Mod
AddonscriptJSON.Relation rel = new AddonscriptJSON.Relation();
rel.file = CurseTools.toArtifact(projectID, fileID);
rel.type = "included";
rel.installer = "internal.dir";
//Add Mod to array
if (version.relations == null) {
version.relations = new ArrayList<>();
}
version.relations.add(rel);
//Overwrite Old Manifest File
FileWriter manifestWriter = new FileWriter(manifestFile, false);
System.out.println("Printing Manifest");
json.write(manifestWriter);
manifestWriter.close();
} catch(CurseException | IOException e) {
e.printStackTrace();
}
} else {
AddonscriptJSON.Relation rel = new AddonscriptJSON.Relation();
rel.file = args[1];
rel.type = "included";
rel.installer = "internal.dir";
if (version.relations == null) {
version.relations = new ArrayList<>();
}
version.relations.add(rel);
}
} else {
return CommandReturn.fail("Syntax: addmod <curseforge url>");
}
return CommandReturn.success();
}
}

View file

@ -1,279 +0,0 @@
package ley.anvil.modpacktools.commands;
import com.therandomlabs.curseapi.CurseAPI;
import com.therandomlabs.curseapi.CurseException;
import com.therandomlabs.curseapi.project.CurseProject;
import j2html.TagCreator;
import j2html.tags.ContainerTag;
import ley.anvil.addonscript.curse.CurseTools;
import ley.anvil.addonscript.v1.AddonscriptJSON;
import ley.anvil.modpacktools.Main;
import okhttp3.HttpUrl;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVPrinter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static j2html.TagCreator.*;
public class Commands {
/**
* Prints out all available commands
*/
public static void help() {
System.out.println("Help Goes here!");
}
/**
* Creates a modpack dev environment in the current folder
*/
public static void init() {
}
//Commands for modpack devs (only available in a modpack dev environment)
/**
* Adds a mod to the modpack
* @param modlink Can be a link to a curseforge file or to a file download
*/
//TODO Renaming?
public static void addMod(String[] modlink) {
//Check if the command has the correct number of args
if(modlink.length >= 2) {
AddonscriptJSON json = getJSON();
AddonscriptJSON.Version version = null;
if (json != null && json.versions != null) {
if (json.versions.size() == 1) {
version = json.versions.get(0);
} else {
for (AddonscriptJSON.Version v : json.versions) {
if (v.versionid == -1) {
version = v;
break;
}
}
}
}
if (version == null) {
throw new RuntimeException("Error: The modpack.json does not include a version with id -1");
}
//The url must match this
String regex = "(?m)^(http)(s)?://(www\\.)?(curseforge.com/minecraft/mc-mods/)[0-z,\\-]+/(files)/[0-9]+$";
String endPartRegex = "(/files/)[0-9]+$";
if(modlink[1].matches(regex)) {
CurseTools.addCurseRepo(json);
try {
//remove fileID
System.out.println("Getting ID");
CurseProject project = CurseAPI.project(HttpUrl.get(modlink[1].replaceAll(endPartRegex, ""))).get();
int projectID = project.id();
//extract fileID
Pattern pattern = Pattern.compile("[0-9]+$");
Matcher matcher = pattern.matcher(modlink[1]);
int fileID = 0;
if(matcher.find()) {
fileID = Integer.parseInt(matcher.group(0));
}
File manifestFile = new File(Main.CONFIG.JAR_LOCATION, Main.CONFIG.CONFIG
.getTable("Locations")
.getString("manifestFile"));
System.out.println("Reading Addonscript");
//Get Mods in manifest file
//Check if Mod already exsits
for(AddonscriptJSON.Relation file : version.relations) {
if (file.file != null) {
String[] parts = file.file.split(":");
if (parts.length == 3 && parts[0].equals("curse")) { //TODO check, if it is a Curse repo, waiting for Addonscript to update this
int projID = Integer.parseInt(parts[1]);
if (projID == projectID) {
System.out.println("The mod is already installed!");
return;
}
}
}
}
System.out.println("Adding Mod " + project.name());
//Construct Mod
AddonscriptJSON.Relation rel = new AddonscriptJSON.Relation();
rel.file = CurseTools.toArtifact(projectID, fileID);
rel.type = "included";
rel.installer = "internal.dir";
//Add Mod to array
if (version.relations == null) {
version.relations = new ArrayList<>();
}
version.relations.add(rel);
//Overwrite Old Manifest File
FileWriter manifestWriter = new FileWriter(manifestFile, false);
System.out.println("Printing Manifest");
json.write(manifestWriter);
manifestWriter.close();
} catch(CurseException | IOException e) {
e.printStackTrace();
}
} else {
AddonscriptJSON.Relation rel = new AddonscriptJSON.Relation();
rel.file = modlink[1];
rel.type = "included";
rel.installer = "internal.dir";
if (version.relations == null) {
version.relations = new ArrayList<>();
}
version.relations.add(rel);
}
} else {
System.out.println("Syntax: addmod <curseforge url>");
}
}
/**
* Builds the modpack as a Twitch modpack zip
*/
public static void buildTwitch() {
}
/**
* Builds the modpack as a modpack.json
*/
public static void buildModpackJSON() {
}
/**
* Builds the modpack as a raw zip file (for example for the Technic Launcher)
*/
public static void buildRaw() {
}
/**
* Builds the modpack as a server
* @param dir The directory where to create the server
*/
public static void buildServer(String[] dir) {
}
/**
* Downloads all mods in this pack
* @param dir The mods directory
*/
public static void downloadMods(String[] dir) {
}
/**
* Creates a modlist of this pack
* @param format 1 Can be html or csv, 2 can be any valid file to write to
*/
public static void createModlist(String[] format) {
if(format.length >= 3) {
if(format[1].equalsIgnoreCase("csv")) {
File csvFile = new File(format[2]);
if(csvFile.exists()) {
System.out.println("Delete " + csvFile);
return;
}
System.out.println("Printing CSV into " + csvFile);
try(CSVPrinter printer = new CSVPrinter(new FileWriter(csvFile), CSVFormat.EXCEL.withDelimiter(';'))) {
printer.printRecord("Name", "Authors", "Link", "Downloads", "ID");
printer.println();
ArrayList<ModInfo> modlist = ModInfo.getModInfo();
Collections.sort(modlist, Comparator.comparing(a -> a.getName().toLowerCase()));
for(ModInfo mod : modlist) {
String name = mod.getName();
String[] authorArr = mod.getAuthors();
String link = mod.getLink();
int downloads = mod.getDownloads();
int id = mod.getId();
StringBuilder sb = new StringBuilder();
for(String author : authorArr) {
sb.append(author);
sb.append(", ");
}
String authors = sb.toString();
authors = authors.substring(0, authors.length() - 2);
printer.printRecord(name, authors, link, downloads, id);
}
} catch(IOException e) {
e.printStackTrace();
}
} else if(format[1].equalsIgnoreCase("html")) {
File htmlFile = new File(format[2]);
if(htmlFile.exists()) {
System.out.println("Delete " + htmlFile);
return;
}
ArrayList<ModInfo> mods = ModInfo.getModInfo();
Collections.sort(mods, Comparator.comparing(a -> a.getName().toLowerCase()));
ContainerTag table = body(
TagCreator.table(TagCreator.attrs("#mods"), TagCreator.tbody(
tr(td(b("Name")),
td(b("Authors")),
td(b("ID")),
td(b("Downloads"))
),
TagCreator.each(mods, i -> {
StringBuilder sb = new StringBuilder();
for(String author : i.getAuthors()) {
sb.append(author);
sb.append(", ");
}
String authors = sb.toString();
authors = authors.substring(0, authors.length() - 2);
return tr(td(a(i.getName())
.withHref(i.getLink())
.withRel("noopener noreferrer")
.withTarget("_blank")),
td(authors),
td(String.valueOf(i.getId())),
td(String.valueOf(i.getDownloads())));
})
))
);
try {
System.out.println("Writing HTML");
FileWriter htmlWrite = new FileWriter(htmlFile);
htmlWrite.write(table.render());
htmlWrite.close();
} catch(IOException e) {
e.printStackTrace();
}
} else {
System.out.println("Expected Either HTML or CSV as format");
}
} else {
System.out.println("Syntax: createmodlist <csv/html> <file>");
}
}
//Commands for users (available outside a modpack dev environment)
/**
* Creates a server from a modpack zip file
* @param args The path to the zip file, The directory where to create the server
*/
public static void makeServer(String[] args) {
}
public static AddonscriptJSON getJSON() {
//TODO Return the current AddonscriptJSON/ModpackJSON
return null;
}
}

View file

@ -0,0 +1,105 @@
package ley.anvil.modpacktools.commands;
import j2html.TagCreator;
import j2html.tags.ContainerTag;
import ley.anvil.modpacktools.command.CommandReturn;
import ley.anvil.modpacktools.command.ICommand;
import ley.anvil.modpacktools.command.LoadCommand;
import ley.anvil.modpacktools.commandhelper.ModInfo;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVPrinter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import static j2html.TagCreator.*;
@LoadCommand("createmodlist")
public class CreateModList implements ICommand {
@Override
public CommandReturn execute(String[] args) {
if(args.length >= 3) {
if(args[1].equalsIgnoreCase("csv")) {
File csvFile = new File(args[2]);
if(csvFile.exists()) {
return CommandReturn.fail("Delete " + csvFile);
}
System.out.println("Printing CSV into " + csvFile);
try(CSVPrinter printer = new CSVPrinter(new FileWriter(csvFile), CSVFormat.EXCEL.withDelimiter(';'))) {
printer.printRecord("Name", "Authors", "Link", "Downloads", "ID");
printer.println();
ArrayList<ModInfo> modlist = ModInfo.getModInfo();
Collections.sort(modlist, Comparator.comparing(a -> a.getName().toLowerCase()));
for(ModInfo mod : modlist) {
String name = mod.getName();
String[] authorArr = mod.getAuthors();
String link = mod.getLink();
int downloads = mod.getDownloads();
int id = mod.getId();
StringBuilder sb = new StringBuilder();
for(String author : authorArr) {
sb.append(author);
sb.append(", ");
}
String authors = sb.toString();
authors = authors.substring(0, authors.length() - 2);
printer.printRecord(name, authors, link, downloads, id);
}
}catch(IOException e) {
e.printStackTrace();
}
}else if(args[1].equalsIgnoreCase("html")) {
File htmlFile = new File(args[2]);
if(htmlFile.exists()) {
return CommandReturn.fail("Delete " + htmlFile);
}
ArrayList<ModInfo> mods = ModInfo.getModInfo();
Collections.sort(mods, Comparator.comparing(a -> a.getName().toLowerCase()));
ContainerTag table = body(
TagCreator.table(TagCreator.attrs("#mods"), TagCreator.tbody(
tr(td(b("Name")),
td(b("Authors")),
td(b("ID")),
td(b("Downloads"))
),
TagCreator.each(mods, i -> {
StringBuilder sb = new StringBuilder();
for(String author : i.getAuthors()) {
sb.append(author);
sb.append(", ");
}
String authors = sb.toString();
authors = authors.substring(0, authors.length() - 2);
return tr(td(a(i.getName())
.withHref(i.getLink())
.withRel("noopener noreferrer")
.withTarget("_blank")),
td(authors),
td(String.valueOf(i.getId())),
td(String.valueOf(i.getDownloads())));
})
))
);
try {
System.out.println("Writing HTML");
FileWriter htmlWrite = new FileWriter(htmlFile);
htmlWrite.write(table.render());
htmlWrite.close();
}catch(IOException e) {
e.printStackTrace();
}
}else {
return CommandReturn.fail("Expected Either HTML or CSV as format");
}
}else {
return CommandReturn.fail("Syntax: createmodlist <csv/html> <file>");
}
return CommandReturn.success();
}
}

View file

@ -1,12 +0,0 @@
package ley.anvil.modpacktools.commands;
public interface ICommand {
/**
* Executes this Command
* @param args Arguments for the Command
* @return If the Command was executed successful
*/
boolean execure(String[] args);
}