From d68e591dd3db486d1465338110f5b48013c3a167 Mon Sep 17 00:00:00 2001 From: Timo Ley Date: Fri, 24 Jul 2020 00:02:45 +0200 Subject: [PATCH] Big AddonscriptJSON overhaul and many chaos --- .../curse/CurseforgeRepository.java | 3 +- .../anvil/addonscript/curse/ManifestJSON.java | 2 +- .../installer/InternalDirInstaller.java | 2 - .../addonscript/maven/MavenRepository.java | 2 +- .../ley/anvil/addonscript/util/ASBase.java | 2 + .../ley/anvil/addonscript/util/Indexes.java | 23 ++ .../java/ley/anvil/addonscript/util/JSON.java | 2 +- .../ley/anvil/addonscript/util/Utils.java | 20 ++ .../anvil/addonscript/v1/AddonscriptJSON.java | 281 ++++++++++++------ 9 files changed, 247 insertions(+), 90 deletions(-) create mode 100644 src/main/java/ley/anvil/addonscript/util/Indexes.java create mode 100644 src/main/java/ley/anvil/addonscript/util/Utils.java diff --git a/src/main/java/ley/anvil/addonscript/curse/CurseforgeRepository.java b/src/main/java/ley/anvil/addonscript/curse/CurseforgeRepository.java index e05648e..2383c5f 100644 --- a/src/main/java/ley/anvil/addonscript/curse/CurseforgeRepository.java +++ b/src/main/java/ley/anvil/addonscript/curse/CurseforgeRepository.java @@ -24,9 +24,10 @@ public class CurseforgeRepository implements IRepository { @Override public AddonscriptJSON.Meta getMeta(String artifact) { - AddonscriptJSON.Meta meta = new AddonscriptJSON.Meta(); + AddonscriptJSON.Meta meta = null; CurseFile file = getFile(artifact); if (file != null) { + meta = new AddonscriptJSON.Meta(); try { CurseProject project = file.project(); meta.name = project.name(); diff --git a/src/main/java/ley/anvil/addonscript/curse/ManifestJSON.java b/src/main/java/ley/anvil/addonscript/curse/ManifestJSON.java index ee4639c..09f6202 100644 --- a/src/main/java/ley/anvil/addonscript/curse/ManifestJSON.java +++ b/src/main/java/ley/anvil/addonscript/curse/ManifestJSON.java @@ -87,7 +87,7 @@ public class ManifestJSON extends JSON { AddonscriptJSON.File overrides = new AddonscriptJSON.File(); overrides.id = "overrides"; overrides.installer = "internal.override"; - overrides.path = this.overrides; + overrides.link = "file://" + this.overrides; version.files.add(overrides); for (File f : files) { diff --git a/src/main/java/ley/anvil/addonscript/installer/InternalDirInstaller.java b/src/main/java/ley/anvil/addonscript/installer/InternalDirInstaller.java index e8a17c7..6f34df1 100644 --- a/src/main/java/ley/anvil/addonscript/installer/InternalDirInstaller.java +++ b/src/main/java/ley/anvil/addonscript/installer/InternalDirInstaller.java @@ -9,8 +9,6 @@ import java.nio.file.StandardCopyOption; public class InternalDirInstaller implements IInstaller { - public static String ID = "internal.dir"; - @Override public void install(String[] params, File input) { if (params.length >= 1) { diff --git a/src/main/java/ley/anvil/addonscript/maven/MavenRepository.java b/src/main/java/ley/anvil/addonscript/maven/MavenRepository.java index 59f5ace..6072dfb 100644 --- a/src/main/java/ley/anvil/addonscript/maven/MavenRepository.java +++ b/src/main/java/ley/anvil/addonscript/maven/MavenRepository.java @@ -19,6 +19,6 @@ public class MavenRepository implements IRepository { @Override public AddonscriptJSON.Meta getMeta(String artifact) { - return new AddonscriptJSON.Meta(); + return null; } } diff --git a/src/main/java/ley/anvil/addonscript/util/ASBase.java b/src/main/java/ley/anvil/addonscript/util/ASBase.java index 03edcea..15a65e8 100644 --- a/src/main/java/ley/anvil/addonscript/util/ASBase.java +++ b/src/main/java/ley/anvil/addonscript/util/ASBase.java @@ -1,5 +1,6 @@ package ley.anvil.addonscript.util; +import com.google.gson.annotations.Expose; import ley.anvil.addonscript.v1.AddonscriptJSON; import java.io.Reader; @@ -14,6 +15,7 @@ public abstract class ASBase extends JSON { /** * The version of the AddonScript file */ + @Expose public int asversion; public Class getImpl() { diff --git a/src/main/java/ley/anvil/addonscript/util/Indexes.java b/src/main/java/ley/anvil/addonscript/util/Indexes.java new file mode 100644 index 0000000..a467fa8 --- /dev/null +++ b/src/main/java/ley/anvil/addonscript/util/Indexes.java @@ -0,0 +1,23 @@ +package ley.anvil.addonscript.util; + +import ley.anvil.addonscript.installer.IInstaller; +import ley.anvil.addonscript.v1.AddonscriptJSON; + +import java.util.HashMap; +import java.util.Map; + +public class Indexes { + + public Indexes() { + INSTALLERS = new HashMap<>(); + REPOSITORIES = new HashMap<>(); + ADDONS = new HashMap<>(); + VERSIONS = new HashMap<>(); + } + + public Map INSTALLERS; + public Map REPOSITORIES; + public Map ADDONS; + public Map VERSIONS; + +} diff --git a/src/main/java/ley/anvil/addonscript/util/JSON.java b/src/main/java/ley/anvil/addonscript/util/JSON.java index dec6257..9676f02 100644 --- a/src/main/java/ley/anvil/addonscript/util/JSON.java +++ b/src/main/java/ley/anvil/addonscript/util/JSON.java @@ -8,7 +8,7 @@ import java.io.Writer; public abstract class JSON { - public static Gson gson = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create(); + public static Gson gson = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().excludeFieldsWithoutExposeAnnotation().create(); public String toJSON() { return gson.toJson(this); diff --git a/src/main/java/ley/anvil/addonscript/util/Utils.java b/src/main/java/ley/anvil/addonscript/util/Utils.java new file mode 100644 index 0000000..fdcc10f --- /dev/null +++ b/src/main/java/ley/anvil/addonscript/util/Utils.java @@ -0,0 +1,20 @@ +package ley.anvil.addonscript.util; + +import ley.anvil.addonscript.v1.AddonscriptJSON; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; + +public class Utils { + + public static AddonscriptJSON getFromURL(String link) { + try { + return AddonscriptJSON.read(new InputStreamReader(new URL(link).openStream())); + } catch (IOException e) { + e.printStackTrace(); + return new AddonscriptJSON(); + } + } + +} diff --git a/src/main/java/ley/anvil/addonscript/v1/AddonscriptJSON.java b/src/main/java/ley/anvil/addonscript/v1/AddonscriptJSON.java index 4c1a8fb..d937faa 100644 --- a/src/main/java/ley/anvil/addonscript/v1/AddonscriptJSON.java +++ b/src/main/java/ley/anvil/addonscript/v1/AddonscriptJSON.java @@ -1,26 +1,30 @@ package ley.anvil.addonscript.v1; +import com.google.gson.annotations.Expose; +import javafx.util.Pair; import ley.anvil.addonscript.curse.CurseforgeRepository; +import ley.anvil.addonscript.maven.MavenRepository; import ley.anvil.addonscript.python.PythonInstaller; import ley.anvil.addonscript.util.ASBase; import ley.anvil.addonscript.installer.IInstaller; import ley.anvil.addonscript.util.IRepository; import ley.anvil.addonscript.installer.InternalDirInstaller; +import ley.anvil.addonscript.util.Indexes; +import ley.anvil.addonscript.util.Utils; +import org.python.jline.internal.Nullable; import java.io.Reader; -import java.util.HashMap; +import java.util.ArrayList; import java.util.List; -import java.util.Map; public class AddonscriptJSON extends ASBase { - public Map INSTALLERS; - public Map REPOSITORIES; + public Indexes indexes; + public boolean loaded; public static AddonscriptJSON fromJSON(String json) { return fromJSON(json, AddonscriptJSON.class); } - public static AddonscriptJSON read(Reader reader) { return read(reader, AddonscriptJSON.class); } @@ -32,51 +36,78 @@ public class AddonscriptJSON extends ASBase { } public AddonscriptJSON() { - INSTALLERS = new HashMap<>(); - REPOSITORIES = new HashMap<>(); + indexes = new Indexes(); + loaded = false; } - public void setup() { - INSTALLERS.put("internal.dir", new InternalDirInstaller()); - for (Installer i : installers) { - INSTALLERS.put(i.id, i.getInstaller()); - } + public void load() { + indexes.INSTALLERS.put("internal.dir", new InternalDirInstaller()); for (Repository r : repositories) { - REPOSITORIES.put(r.id, r.getRepository()); + indexes.REPOSITORIES.put(r.id, r.getRepository()); } + for (IndexEntry e : index) { + if (e.type != null && e.type.equals("addon")) + indexes.ADDONS.put(e.id, Utils.getFromURL(e.link)); + else if (e.type != null && e.type.equals("version")) + indexes.VERSIONS.put(e.versionid, Utils.getFromURL(e.link).getDefaultVersion()); + } + for (Version v : versions) { + if (!indexes.VERSIONS.containsKey(v.versionid)) + indexes.VERSIONS.put(v.versionid, v); + } + loaded = true; } - + + public Version getDefaultVersion() { + for (Version v : versions) { + if (v.versionid == -1) + return v; + } + if (versions.size() > 0) + return versions.get(0); + return new Version(); + } + + public Version getVersion(int versionid) { + if (indexes.VERSIONS.containsKey(versionid)) + return indexes.VERSIONS.get(versionid); + return null; + } + + public Version getVersion(String versionCondition) { + return null; //TODO Interpret version range + } + + + + //JSON Parts + /** * The ID of the addon */ + @Expose public String id; /** * The type of the addon * For example mod or modpack */ + @Expose public String type; - /** - * Optional - * External Addonscript files for this Addon, specific versions of specific editions - */ - public List external; - - /** - * Optional - * Links to external Addonscript files, that should be applied/merged to this - */ - public List apply; + @Expose + public List index; /** * A list of versions of this addon */ + @Expose public List versions; /** * A list of repositories this file uses */ + @Expose public List repositories; /** @@ -88,35 +119,53 @@ public class AddonscriptJSON extends ASBase { * Optional * Meta information for this addon */ + @Expose public Meta meta; public static class Version implements Comparable { + + public List getRelations(String side, boolean optionals, @Nullable String edition) { + List list = new ArrayList<>(); + for (Relation r : relations) { + if (r.hasOption(side) && (r.hasOption("required") || (optionals && r.hasOption("optional")) || r.hasOption("edition:" + edition))) + list.add(r); + } + return list; + } + /** * The name of this version * (for example: 1.0, 1.1, 2.0) */ - public String versionname; + @Expose + public String version; /** * The numeric ID of this version * Used to identify, which version is higher/lower than another * Can be -1 if this file uses only one version */ + @Expose public int versionid; /** * The Minecraft versions, which are compatile with this version */ + @Expose public List mcversion; /** + * Optional * Meta Information about this version */ + @Expose public VersionMeta meta; /** * A list of files of this version */ + @Expose public List files; /** * A lis of addons, that are related to this addon */ + @Expose public List relations; @Override @@ -129,11 +178,13 @@ public class AddonscriptJSON extends ASBase { /** * The name of the contributor */ + @Expose public String name; /** * The roles of the contributor * (for example: author, developer, owner ...) */ + @Expose public List roles; } @@ -141,43 +192,45 @@ public class AddonscriptJSON extends ASBase { /** * The name of the addon */ + @Expose public String name; /** * A link to the icon of this addon */ + @Expose public String icon; /** * A list of the contributors of this addon */ + @Expose public List contributors; /** * The website of the addon */ + @Expose public String website; /** * The description of the addon */ + @Expose public List description; - /** - * A link to an external description - */ - public String extdescr; - } public static class VersionMeta { /** * The changelog of this version */ + @Expose public List changelog; /** * The UNIX Timestamp when this version was released */ + @Expose public int timestamp; } @@ -186,20 +239,24 @@ public class AddonscriptJSON extends ASBase { * The ID of this repository * Must be unique to this file */ + @Expose public String id; /** * The type of this repository * Currently supported: curseforge, forge */ + @Expose public String type; /** * The base url of this repository */ + @Expose public String url; public IRepository getRepository() { switch (type) { case "curseforge": return new CurseforgeRepository(); + case "maven": return new MavenRepository(url); default: return null; } } @@ -222,9 +279,6 @@ public class AddonscriptJSON extends ASBase { } } - /** - * - */ public static class File { /** * The ID of this file. @@ -233,28 +287,26 @@ public class AddonscriptJSON extends ASBase { * Addonscript will then try to install the first of them * and only if this fails, it will try the next. */ + @Expose public String id; /** * The installer for this file * Format: <installerid>:<param 1>:<param 2>... * Installer ID can be internal.<some internal installer> */ + @Expose public String installer = "internal.dir:mods"; /** - * Optional: Use this, path or artifact - * A link to this file. + * Optional: Use this or artifact + * A link to this file. Can also point to a relative file or directory by using file://<relative path>. */ + @Expose public String link; /** - * Optional: Use this, link or artifact - * A relative path to this file. - * It can also be a path to a directory, if the installer supports directories - */ - public String path; - /** - * Optional: Use this, link or path + * Optional: Use this or link * An artifact from a repository, which is this file */ + @Expose public String artifact; /** * Optional: Defaults if empty @@ -266,46 +318,116 @@ public class AddonscriptJSON extends ASBase { * "client" - This file works on the client side * "server" - This file works on the server side */ + @Expose public List options; - public boolean server() { - return options != null && options.contains("server"); + public boolean hasOption(String option) { + if (options != null) + return option.contains(option); + else { + switch (option) { + case "client": + case "server": + case "required": return true; + default: return false; + } + } } - public boolean client() { - return options != null && options.contains("client"); + public String getLink(Indexes indexes) { + if (link != null && !link.equals("")) { + return link; + } + else if (artifact != null && !artifact.equals("")) { + for (IRepository repo : indexes.REPOSITORIES.values()) { + String url = repo.getFileURL(artifact); + if (!url.equals("")) + return url; + } + } + return ""; + } + + public Meta getMeta(Indexes indexes) { + if (artifact != null && !artifact.equals("")) { + for (IRepository repo : indexes.REPOSITORIES.values()) { + Meta meta = repo.getMeta(artifact); + if (meta != null) { + return meta; + } + } + } + return null; } } public static class Relation { - /** - * Optional: Use either this or file - * An external Addonscript for this relation - */ - public Script script; + + public Meta getMeta(Indexes indexes) { + if(indexes.ADDONS.values().contains(id)) + return indexes.ADDONS.get(id).meta; + else if(meta != null) + return meta; + else + return file.getMeta(indexes); + } + + public List> getLinks(Indexes indexes, String side, boolean optionals, @Nullable String installer, @Nullable String edition) { + List> list = new ArrayList<>(); + + if (indexes.ADDONS.containsKey(id)) { + AddonscriptJSON addon = indexes.ADDONS.get(id); + if (!addon.loaded) + addon.load(); + Version version = addon.getVersion(versions); + if (version != null) { + for (File f : version.files) { + if (f != null && f.hasOption(side) && (installer == null || installer.equals(f.installer)) && ((f.hasOption("optional") && optionals) || f.hasOption("edition:" + edition) || f.hasOption("required"))) + list.add(new Pair<>(f.getLink(indexes), f.installer)); + } + } + } + + if (file != null && file.hasOption(side) && (installer == null || installer.equals(file.installer)) && ((file.hasOption("optional") && optionals) || file.hasOption("edition:" + edition) || file.hasOption("required"))) + list.add(new Pair<>(file.getLink(indexes), file.installer)); + + return list; + } + + /** * The ID of the relation * This should be unique in this Addonscript file */ + @Expose public String id; + /** + * Optional: Wildcard if empty + * A version range string, which specifies, which versions of the addon can be used + */ + @Expose + public String versions; /** * Optional: Use either this or script * The file of this relation * Can be a direct link or an artifact from a repository */ + @Expose public File file; /** * The addon type of this relation * For example: mod, modloader, config, script... */ + @Expose public String type; /** * Optional * Meta information for this relation - * This is not always useful, because some repositories, like curseforge, are + * This is not always useful, because some repositories, like curseforge or external Addonscripts are * already exposing this information */ + @Expose public Meta meta; /** * Optional: Defaults if empty @@ -320,45 +442,36 @@ public class AddonscriptJSON extends ASBase { * "recommended" - This relation is recomended but not required for this addon * "incompatible" - This relation is incompatible with this addon */ + @Expose public List options; - public boolean server() { - return options != null && options.contains("server"); + public boolean hasOption(String option) { + if (options != null) + return option.contains(option); + else { + switch (option) { + case "client": + case "server": + case "required": return true; + default: return false; + } + } } - public boolean client() { - return options != null && options.contains("client"); - } } - public static class External { - /** - * Optional: Wildcard if empty - * The versionid of the version, for which this external script should be used - */ + public static class IndexEntry { + @Expose + public String type; + @Expose + public String link; + @Expose public int versionid; - /** - * Optional: Wildcard if empty - * The edition id of the edition, for which this external script should be used - */ + @Expose public String edition; - /** - * The link to the external script - */ - public String link; - } - - public static class Script { - /** - * The link to the script - */ - public String link; - /** - * Optional: Wildcard if empty - * A version range string, which specifies, which versions of the addon can be used - */ - public String version; + @Expose + public String id; } public static class Edition { @@ -370,7 +483,7 @@ public class AddonscriptJSON extends ASBase { * Optional: Wildcard if empty * A version range string, which specifies, which versions have this edition */ - public String version; + public String versions; /** * Optional * Meta information about this edition