Schema good

This commit is contained in:
Daniel Mills 2020-09-12 17:44:52 -04:00
parent 5d35fc80d5
commit 42907b5a5d
15 changed files with 1122 additions and 30 deletions

View File

@ -34,7 +34,6 @@ import com.volmit.iris.gen.provisions.ProvisionBukkit;
import com.volmit.iris.gen.scaffold.IrisGenConfiguration; import com.volmit.iris.gen.scaffold.IrisGenConfiguration;
import com.volmit.iris.gen.scaffold.TerrainTarget; import com.volmit.iris.gen.scaffold.TerrainTarget;
import com.volmit.iris.object.DecorationPart; import com.volmit.iris.object.DecorationPart;
import com.volmit.iris.object.Envelope;
import com.volmit.iris.object.InterpolationMethod; import com.volmit.iris.object.InterpolationMethod;
import com.volmit.iris.object.IrisBiome; import com.volmit.iris.object.IrisBiome;
import com.volmit.iris.object.IrisBiomeGeneratorLink; import com.volmit.iris.object.IrisBiomeGeneratorLink;
@ -71,6 +70,7 @@ import com.volmit.iris.util.MaxNumber;
import com.volmit.iris.util.MinNumber; import com.volmit.iris.util.MinNumber;
import com.volmit.iris.util.MortarSender; import com.volmit.iris.util.MortarSender;
import com.volmit.iris.util.O; import com.volmit.iris.util.O;
import com.volmit.iris.util.PrecisionStopwatch;
import com.volmit.iris.util.RegistryListBiome; import com.volmit.iris.util.RegistryListBiome;
import com.volmit.iris.util.RegistryListBlockType; import com.volmit.iris.util.RegistryListBlockType;
import com.volmit.iris.util.RegistryListDimension; import com.volmit.iris.util.RegistryListDimension;
@ -950,11 +950,13 @@ public class ProjectManager
{ {
try try
{ {
PrecisionStopwatch p = PrecisionStopwatch.start();
Iris.info("Updating Workspace: " + ws.getPath()); Iris.info("Updating Workspace: " + ws.getPath());
J.attemptAsync(() -> writeDocs(ws.getParentFile())); J.attemptAsync(() -> writeDocs(ws.getParentFile()));
JSONObject j = newWorkspaceConfig(ws.getParentFile()); JSONObject j = newWorkspaceConfig(ws.getParentFile());
IO.writeAll(ws, j.toString(4)); IO.writeAll(ws, j.toString(4));
Iris.info("Updated Workspace: " + ws.getPath()); p.end();
Iris.info("Updated Workspace: " + ws.getPath() + " in " + Form.duration(p.getMilliseconds(), 2));
} }
catch(Throwable e) catch(Throwable e)
@ -1003,6 +1005,8 @@ public class ProjectManager
private JSONArray buildSchemas(IrisDataManager dat, File pack) private JSONArray buildSchemas(IrisDataManager dat, File pack)
{ {
String gg = dat.getBiomeLoader().getPreferredFolder();
dat.preferFolder(pack.getName());
JSONArray schemas = new JSONArray(); JSONArray schemas = new JSONArray();
TaskGroup g = tx.startWork(); TaskGroup g = tx.startWork();
g.queue(() -> ex(schemas, IrisDimension.class, dat, "/dimensions/*.json", pack)); g.queue(() -> ex(schemas, IrisDimension.class, dat, "/dimensions/*.json", pack));
@ -1013,6 +1017,7 @@ public class ProjectManager
g.queue(() -> ex(schemas, IrisStructure.class, dat, "/structures/*.json", pack)); g.queue(() -> ex(schemas, IrisStructure.class, dat, "/structures/*.json", pack));
g.queue(() -> ex(schemas, IrisLootTable.class, dat, "/loot/*.json", pack)); g.queue(() -> ex(schemas, IrisLootTable.class, dat, "/loot/*.json", pack));
g.execute(); g.execute();
dat.preferFolder(gg);
return schemas; return schemas;
} }
@ -1022,7 +1027,7 @@ public class ProjectManager
Iris.verbose("Processing Folder " + i.getSimpleName() + " " + fileMatch[0]); Iris.verbose("Processing Folder " + i.getSimpleName() + " " + fileMatch[0]);
JSONObject o = new JSONObject(); JSONObject o = new JSONObject();
o.put("fileMatch", new JSONArray(fileMatch)); o.put("fileMatch", new JSONArray(fileMatch));
o.put("schema", getSchemaFor(i, dat)); o.put("schema", new SchemaBuilder(i, dat).compute());
return o; return o;
} }
@ -1568,6 +1573,12 @@ public class ProjectManager
deff.put("description", tx + "\n\n" + t.type().getDeclaredAnnotation(Desc.class).value()); deff.put("description", tx + "\n\n" + t.type().getDeclaredAnnotation(Desc.class).value());
deff.put("additionalProperties", false); deff.put("additionalProperties", false);
deff.put("properties", scv.getJSONObject("properties")); deff.put("properties", scv.getJSONObject("properties"));
if(deff.getJSONObject("properties").length() == 0)
{
Iris.warn("Schema Def for " + name + " has " + deff.getJSONObject("properties").length() + " Entries" + " (Step " + step + ")");
}
if(scv.has("required")) if(scv.has("required"))
{ {
deff.put("required", scv.getJSONArray("required")); deff.put("required", scv.getJSONArray("required"));
@ -1932,14 +1943,6 @@ public class ProjectManager
IO.writeAll(new File(of, "decoration-part.txt"), m.toString("\n")); IO.writeAll(new File(of, "decoration-part.txt"), m.toString("\n"));
m = new KList<>(); m = new KList<>();
for(Envelope i : Envelope.values())
{
m.add(i.name());
}
IO.writeAll(new File(of, "envelope.txt"), m.toString("\n"));
m = new KList<>();
for(Environment i : Environment.values()) for(Environment i : Environment.values())
{ {
m.add(i.name()); m.add(i.name());

View File

@ -0,0 +1,919 @@
package com.volmit.iris.manager;
import java.awt.GraphicsEnvironment;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.potion.PotionEffectType;
import com.volmit.iris.Iris;
import com.volmit.iris.util.ArrayType;
import com.volmit.iris.util.B;
import com.volmit.iris.util.Desc;
import com.volmit.iris.util.JSONArray;
import com.volmit.iris.util.JSONObject;
import com.volmit.iris.util.KList;
import com.volmit.iris.util.KMap;
import com.volmit.iris.util.MaxNumber;
import com.volmit.iris.util.MinNumber;
import com.volmit.iris.util.RegistryListBiome;
import com.volmit.iris.util.RegistryListBlockType;
import com.volmit.iris.util.RegistryListDimension;
import com.volmit.iris.util.RegistryListEntity;
import com.volmit.iris.util.RegistryListFont;
import com.volmit.iris.util.RegistryListGenerator;
import com.volmit.iris.util.RegistryListItemType;
import com.volmit.iris.util.RegistryListLoot;
import com.volmit.iris.util.RegistryListObject;
import com.volmit.iris.util.RegistryListRegion;
import com.volmit.iris.util.RegistryListStructure;
import com.volmit.iris.util.Required;
public class SchemaBuilder
{
private static final String SYMBOL_LIMIT__N = "*";
private static final String SYMBOL_TYPE__N = "";
private static final JSONArray POTION_TYPES = getPotionTypes();
private static final JSONArray ENCHANT_TYPES = getEnchantmentTypes();
private static final JSONArray BLOCK_TYPES = new JSONArray(B.getBlockTypes());
private static final JSONArray ITEM_TYPES = new JSONArray(B.getItemTypes());
private static final JSONArray FONT_TYPES = new JSONArray(GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames());
private final KMap<String, JSONObject> definitions;
private final Class<?> root;
private final KList<String> warnings;
private final IrisDataManager data;
public SchemaBuilder(Class<?> root, IrisDataManager data)
{
this.data = data;
warnings = new KList<>();
this.definitions = new KMap<String, JSONObject>();
this.root = root;
}
public JSONObject compute()
{
JSONObject schema = new JSONObject();
schema.put("$schema", "http://json-schema.org/draft-07/schema#");
schema.put("$id", "http://volmit.com/iris-schema/" + root.getSimpleName().toLowerCase() + ".json");
JSONObject props = buildProperties(root);
for(String i : props.keySet())
{
if(!schema.has(i))
{
schema.put(i, props.get(i));
}
}
JSONObject defs = new JSONObject();
for(String i : definitions.keySet())
{
defs.put(i, definitions.get(i));
}
schema.put("definitions", defs);
for(String i : warnings)
{
Iris.warn(root.getSimpleName() + ": " + i);
}
return schema;
}
private JSONObject buildProperties(Class<?> c)
{
JSONObject o = new JSONObject();
JSONObject properties = new JSONObject();
o.put("description", getDescription(c));
JSONArray required = new JSONArray();
for(Field k : c.getDeclaredFields())
{
k.setAccessible(true);
if(Modifier.isStatic(k.getModifiers()) || Modifier.isFinal(k.getModifiers()) || Modifier.isTransient(k.getModifiers()))
{
continue;
}
JSONObject property = buildProperty(k, c);
if(property.getBoolean("!required"))
{
required.put(k.getName());
}
property.remove("!required");
properties.put(k.getName(), property);
}
if(required.length() > 0)
{
o.put("required", required);
}
o.put("properties", properties);
return o;
}
private JSONObject buildProperty(Field k, Class<?> cl)
{
JSONObject prop = new JSONObject();
String type = getType(k.getType());
KList<String> description = new KList<String>();
prop.put("!required", k.isAnnotationPresent(Required.class));
prop.put("type", type);
String fancyType = "Unknown Type";
if(type.equals("boolean"))
{
fancyType = "Boolean";
}
else if(type.equals("integer"))
{
fancyType = "Integer";
if(k.isAnnotationPresent(MinNumber.class))
{
int min = (int) k.getDeclaredAnnotation(MinNumber.class).value();
prop.put("minimum", min);
description.add(SYMBOL_LIMIT__N + " Minimum allowed is " + min);
}
if(k.isAnnotationPresent(MaxNumber.class))
{
int max = (int) k.getDeclaredAnnotation(MaxNumber.class).value();
prop.put("maximum", max);
description.add(SYMBOL_LIMIT__N + " Maximum allowed is " + max);
}
}
else if(type.equals("number"))
{
fancyType = "Number";
if(k.isAnnotationPresent(MinNumber.class))
{
double min = k.getDeclaredAnnotation(MinNumber.class).value();
prop.put("minimum", min);
description.add(SYMBOL_LIMIT__N + " Minimum allowed is " + min);
}
if(k.isAnnotationPresent(MaxNumber.class))
{
double max = k.getDeclaredAnnotation(MaxNumber.class).value();
prop.put("maximum", max);
description.add(SYMBOL_LIMIT__N + " Maximum allowed is " + max);
}
}
else if(type.equals("string"))
{
fancyType = "Text";
if(k.isAnnotationPresent(MinNumber.class))
{
int min = (int) k.getDeclaredAnnotation(MinNumber.class).value();
prop.put("minLength", min);
description.add(SYMBOL_LIMIT__N + " Minimum Length allowed is " + min);
}
if(k.isAnnotationPresent(MaxNumber.class))
{
int max = (int) k.getDeclaredAnnotation(MaxNumber.class).value();
prop.put("maxLength", max);
description.add(SYMBOL_LIMIT__N + " Maximum Length allowed is " + max);
}
if(k.isAnnotationPresent(RegistryListBiome.class))
{
String key = "enum-reg-biome";
if(!definitions.containsKey(key))
{
JSONObject j = new JSONObject();
j.put("enum", new JSONArray(data.getBiomeLoader().getPreferredKeys()));
definitions.put(key, j);
}
fancyType = "Iris Biome";
prop.put("$ref", "#/definitions/" + key);
description.add(SYMBOL_TYPE__N + " Must be a valid Biome (use ctrl+space for auto complete!)");
}
else if(k.isAnnotationPresent(RegistryListBlockType.class))
{
String key = "enum-block-type";
if(!definitions.containsKey(key))
{
JSONObject j = new JSONObject();
j.put("enum", BLOCK_TYPES);
definitions.put(key, j);
}
fancyType = "Block Type";
prop.put("$ref", "#/definitions/" + key);
description.add(SYMBOL_TYPE__N + " Must be a valid Block Type (use ctrl+space for auto complete!)");
}
else if(k.isAnnotationPresent(RegistryListItemType.class))
{
String key = "enum-item-type";
if(!definitions.containsKey(key))
{
JSONObject j = new JSONObject();
j.put("enum", ITEM_TYPES);
definitions.put(key, j);
}
fancyType = "Item Type";
prop.put("$ref", "#/definitions/" + key);
description.add(SYMBOL_TYPE__N + " Must be a valid Item Type (use ctrl+space for auto complete!)");
}
else if(k.isAnnotationPresent(RegistryListEntity.class))
{
String key = "enum-reg-entity";
if(!definitions.containsKey(key))
{
JSONObject j = new JSONObject();
j.put("enum", new JSONArray(data.getEntityLoader().getPreferredKeys()));
definitions.put(key, j);
}
fancyType = "Iris Entity";
prop.put("$ref", "#/definitions/" + key);
description.add(SYMBOL_TYPE__N + " Must be a valid Iris Entity (use ctrl+space for auto complete!)");
}
else if(k.isAnnotationPresent(RegistryListFont.class))
{
String key = "enum-font";
if(!definitions.containsKey(key))
{
JSONObject j = new JSONObject();
j.put("enum", FONT_TYPES);
definitions.put(key, j);
}
fancyType = "Font Family";
prop.put("$ref", "#/definitions/" + key);
description.add(SYMBOL_TYPE__N + " Must be a valid Font Family (use ctrl+space for auto complete!)");
}
else if(k.isAnnotationPresent(RegistryListLoot.class))
{
String key = "enum-reg-loot-table";
if(!definitions.containsKey(key))
{
JSONObject j = new JSONObject();
j.put("enum", new JSONArray(data.getLootLoader().getPreferredKeys()));
definitions.put(key, j);
}
fancyType = "Iris Loot Table";
prop.put("$ref", "#/definitions/" + key);
description.add(SYMBOL_TYPE__N + " Must be a valid Loot Table (use ctrl+space for auto complete!)");
}
else if(k.isAnnotationPresent(RegistryListDimension.class))
{
String key = "enum-reg-dimension";
if(!definitions.containsKey(key))
{
JSONObject j = new JSONObject();
j.put("enum", new JSONArray(data.getDimensionLoader().getPreferredKeys()));
definitions.put(key, j);
}
fancyType = "Iris Dimension";
prop.put("$ref", "#/definitions/" + key);
description.add(SYMBOL_TYPE__N + " Must be a valid Dimension (use ctrl+space for auto complete!)");
}
else if(k.isAnnotationPresent(RegistryListGenerator.class))
{
String key = "enum-reg-generator";
if(!definitions.containsKey(key))
{
JSONObject j = new JSONObject();
j.put("enum", new JSONArray(data.getGeneratorLoader().getPreferredKeys()));
definitions.put(key, j);
}
fancyType = "Iris Generator";
prop.put("$ref", "#/definitions/" + key);
description.add(SYMBOL_TYPE__N + " Must be a valid Generator (use ctrl+space for auto complete!)");
}
else if(k.isAnnotationPresent(RegistryListObject.class))
{
String key = "enum-reg-object";
if(!definitions.containsKey(key))
{
JSONObject j = new JSONObject();
j.put("enum", new JSONArray(data.getObjectLoader().getPreferredKeys()));
definitions.put(key, j);
}
fancyType = "Iris Object";
prop.put("$ref", "#/definitions/" + key);
description.add(SYMBOL_TYPE__N + " Must be a valid Object (use ctrl+space for auto complete!)");
}
else if(k.isAnnotationPresent(RegistryListRegion.class))
{
String key = "enum-reg-region";
if(!definitions.containsKey(key))
{
JSONObject j = new JSONObject();
j.put("enum", new JSONArray(data.getRegionLoader().getPreferredKeys()));
definitions.put(key, j);
}
fancyType = "Iris Region";
prop.put("$ref", "#/definitions/" + key);
description.add(SYMBOL_TYPE__N + " Must be a valid Region (use ctrl+space for auto complete!)");
}
else if(k.isAnnotationPresent(RegistryListStructure.class))
{
String key = "enum-reg-structure-tileset";
if(!definitions.containsKey(key))
{
JSONObject j = new JSONObject();
j.put("enum", new JSONArray(data.getStructureLoader().getPreferredKeys()));
definitions.put(key, j);
}
fancyType = "Iris Structure Tileset";
prop.put("$ref", "#/definitions/" + key);
description.add(SYMBOL_TYPE__N + " Must be a valid Structure Tileset (use ctrl+space for auto complete!)");
}
else if(k.getType().equals(Enchantment.class))
{
String key = "enum-enchantment";
if(!definitions.containsKey(key))
{
JSONObject j = new JSONObject();
j.put("enum", ENCHANT_TYPES);
definitions.put(key, j);
}
fancyType = "Enchantment Type";
prop.put("$ref", "#/definitions/" + key);
description.add(SYMBOL_TYPE__N + " Must be a valid Enchantment Type (use ctrl+space for auto complete!)");
}
else if(k.getType().equals(PotionEffectType.class))
{
String key = "enum-potion-effect-type";
if(!definitions.containsKey(key))
{
JSONObject j = new JSONObject();
j.put("enum", POTION_TYPES);
definitions.put(key, j);
}
fancyType = "Potion Effect Type";
prop.put("$ref", "#/definitions/" + key);
description.add(SYMBOL_TYPE__N + " Must be a valid Potion Effect Type (use ctrl+space for auto complete!)");
}
else if(k.getType().isEnum())
{
fancyType = k.getType().getSimpleName().replaceAll("\\QIris\\E", "");
JSONArray a = new JSONArray();
boolean advanced = k.getType().isAnnotationPresent(Desc.class);
for(Object gg : k.getType().getEnumConstants())
{
if(advanced)
{
try
{
JSONObject j = new JSONObject();
String name = ((Enum<?>) gg).name();
j.put("const", name);
Desc dd = k.getType().getField(name).getAnnotation(Desc.class);
j.put("description", dd == null ? ("No Description for " + name) : dd.value());
a.put(j);
}
catch(Throwable e)
{
e.printStackTrace();
}
}
else
{
a.put(((Enum<?>) gg).name());
}
}
String key = (advanced ? "oneof-" : "") + "enum-" + k.getType().getCanonicalName().replaceAll("\\Q.\\E", "-").toLowerCase();
if(!definitions.containsKey(key))
{
JSONObject j = new JSONObject();
j.put(advanced ? "oneOf" : "enum", a);
definitions.put(key, j);
}
prop.put("$ref", "#/definitions/" + key);
description.add(SYMBOL_TYPE__N + " Must be a valid " + k.getType().getSimpleName().replaceAll("\\QIris\\E", "") + " (use ctrl+space for auto complete!)");
}
}
else if(type.equals("object"))
{
fancyType = k.getType().getSimpleName().replaceAll("\\QIris\\E", "") + " (Object)";
String key = "obj-" + k.getType().getCanonicalName().replaceAll("\\Q.\\E", "-").toLowerCase();
if(!definitions.containsKey(key))
{
definitions.put(key, new JSONObject());
definitions.put(key, buildProperties(k.getType()));
}
prop.put("$ref", "#/definitions/" + key);
}
else if(type.equals("array"))
{
fancyType = "List of Something...?";
ArrayType t = k.getDeclaredAnnotation(ArrayType.class);
if(t != null)
{
if(t.min() > 0)
{
prop.put("minItems", t.min());
if(t.min() == 1)
{
description.add(SYMBOL_LIMIT__N + " At least one entry must be defined, or just remove this list.");
}
else
{
description.add(SYMBOL_LIMIT__N + " Requires at least " + t.min() + " entries.");
}
}
String arrayType = getType(t.type());
if(arrayType.equals("integer"))
{
fancyType = "List of Integers";
}
else if(arrayType.equals("number"))
{
fancyType = "List of Numbers";
}
else if(arrayType.equals("object"))
{
fancyType = "List of " + t.type().getSimpleName().replaceAll("\\QIris\\E", "") + "s (Objects)";
String key = "obj-" + t.type().getCanonicalName().replaceAll("\\Q.\\E", "-").toLowerCase();
if(!definitions.containsKey(key))
{
definitions.put(key, new JSONObject());
definitions.put(key, buildProperties(t.type()));
}
JSONObject items = new JSONObject();
items.put("$ref", "#/definitions/" + key);
prop.put("items", items);
}
else if(arrayType.equals("string"))
{
fancyType = "List of Text";
if(k.isAnnotationPresent(RegistryListBiome.class))
{
fancyType = "List of Iris Biomes";
String key = "enum-reg-biome";
if(!definitions.containsKey(key))
{
JSONObject j = new JSONObject();
j.put("enum", new JSONArray(data.getBiomeLoader().getPreferredKeys()));
definitions.put(key, j);
}
JSONObject items = new JSONObject();
items.put("$ref", "#/definitions/" + key);
prop.put("items", items);
description.add(SYMBOL_TYPE__N + " Must be a valid Biome (use ctrl+space for auto complete!)");
}
else if(k.isAnnotationPresent(RegistryListBlockType.class))
{
fancyType = "List of Block Types";
String key = "enum-block-type";
if(!definitions.containsKey(key))
{
JSONObject j = new JSONObject();
j.put("enum", BLOCK_TYPES);
definitions.put(key, j);
}
JSONObject items = new JSONObject();
items.put("$ref", "#/definitions/" + key);
prop.put("items", items);
description.add(SYMBOL_TYPE__N + " Must be a valid Block Type (use ctrl+space for auto complete!)");
}
else if(k.isAnnotationPresent(RegistryListItemType.class))
{
fancyType = "List of Item Types";
String key = "enum-item-type";
if(!definitions.containsKey(key))
{
JSONObject j = new JSONObject();
j.put("enum", ITEM_TYPES);
definitions.put(key, j);
}
JSONObject items = new JSONObject();
items.put("$ref", "#/definitions/" + key);
prop.put("items", items);
description.add(SYMBOL_TYPE__N + " Must be a valid Item Type (use ctrl+space for auto complete!)");
}
else if(k.isAnnotationPresent(RegistryListEntity.class))
{
fancyType = "List of Iris Entities";
String key = "enum-reg-entity";
if(!definitions.containsKey(key))
{
JSONObject j = new JSONObject();
j.put("enum", new JSONArray(data.getEntityLoader().getPreferredKeys()));
definitions.put(key, j);
}
JSONObject items = new JSONObject();
items.put("$ref", "#/definitions/" + key);
prop.put("items", items);
description.add(SYMBOL_TYPE__N + " Must be a valid Iris Entity (use ctrl+space for auto complete!)");
}
else if(k.isAnnotationPresent(RegistryListFont.class))
{
String key = "enum-font";
fancyType = "List of Font Families";
if(!definitions.containsKey(key))
{
JSONObject j = new JSONObject();
j.put("enum", FONT_TYPES);
definitions.put(key, j);
}
JSONObject items = new JSONObject();
items.put("$ref", "#/definitions/" + key);
prop.put("items", items);
description.add(SYMBOL_TYPE__N + " Must be a valid Font Family (use ctrl+space for auto complete!)");
}
else if(k.isAnnotationPresent(RegistryListLoot.class))
{
fancyType = "List of Iris Loot Tables";
String key = "enum-reg-loot-table";
if(!definitions.containsKey(key))
{
JSONObject j = new JSONObject();
j.put("enum", new JSONArray(data.getLootLoader().getPreferredKeys()));
definitions.put(key, j);
}
JSONObject items = new JSONObject();
items.put("$ref", "#/definitions/" + key);
prop.put("items", items);
description.add(SYMBOL_TYPE__N + " Must be a valid Loot Table (use ctrl+space for auto complete!)");
}
else if(k.isAnnotationPresent(RegistryListDimension.class))
{
fancyType = "List of Iris Dimensions";
String key = "enum-reg-dimension";
if(!definitions.containsKey(key))
{
JSONObject j = new JSONObject();
j.put("enum", new JSONArray(data.getDimensionLoader().getPreferredKeys()));
definitions.put(key, j);
}
JSONObject items = new JSONObject();
items.put("$ref", "#/definitions/" + key);
prop.put("items", items);
description.add(SYMBOL_TYPE__N + " Must be a valid Dimension (use ctrl+space for auto complete!)");
}
else if(k.isAnnotationPresent(RegistryListGenerator.class))
{
fancyType = "List of Iris Generators";
String key = "enum-reg-generator";
if(!definitions.containsKey(key))
{
JSONObject j = new JSONObject();
j.put("enum", new JSONArray(data.getGeneratorLoader().getPreferredKeys()));
definitions.put(key, j);
}
JSONObject items = new JSONObject();
items.put("$ref", "#/definitions/" + key);
prop.put("items", items);
description.add(SYMBOL_TYPE__N + " Must be a valid Generator (use ctrl+space for auto complete!)");
}
else if(k.isAnnotationPresent(RegistryListObject.class))
{
fancyType = "List of Iris Objects";
String key = "enum-reg-object";
if(!definitions.containsKey(key))
{
JSONObject j = new JSONObject();
j.put("enum", new JSONArray(data.getObjectLoader().getPreferredKeys()));
definitions.put(key, j);
}
JSONObject items = new JSONObject();
items.put("$ref", "#/definitions/" + key);
prop.put("items", items);
description.add(SYMBOL_TYPE__N + " Must be a valid Object (use ctrl+space for auto complete!)");
}
else if(k.isAnnotationPresent(RegistryListRegion.class))
{
fancyType = "List of Iris Regions";
String key = "enum-reg-region";
if(!definitions.containsKey(key))
{
JSONObject j = new JSONObject();
j.put("enum", new JSONArray(data.getRegionLoader().getPreferredKeys()));
definitions.put(key, j);
}
JSONObject items = new JSONObject();
items.put("$ref", "#/definitions/" + key);
prop.put("items", items);
description.add(SYMBOL_TYPE__N + " Must be a valid Region (use ctrl+space for auto complete!)");
}
else if(k.isAnnotationPresent(RegistryListStructure.class))
{
fancyType = "List of Iris Structure Tilesets";
String key = "enum-reg-structure-tileset";
if(!definitions.containsKey(key))
{
JSONObject j = new JSONObject();
j.put("enum", new JSONArray(data.getStructureLoader().getPreferredKeys()));
definitions.put(key, j);
}
JSONObject items = new JSONObject();
items.put("$ref", "#/definitions/" + key);
prop.put("items", items);
description.add(SYMBOL_TYPE__N + " Must be a valid Structure Tileset (use ctrl+space for auto complete!)");
}
else if(t.type().equals(Enchantment.class))
{
fancyType = "List of Enchantment Types";
String key = "enum-enchantment";
if(!definitions.containsKey(key))
{
JSONObject j = new JSONObject();
j.put("enum", ENCHANT_TYPES);
definitions.put(key, j);
}
JSONObject items = new JSONObject();
items.put("$ref", "#/definitions/" + key);
prop.put("items", items);
description.add(SYMBOL_TYPE__N + " Must be a valid Enchantment Type (use ctrl+space for auto complete!)");
}
else if(t.type().equals(PotionEffectType.class))
{
fancyType = "List of Potion Effect Types";
String key = "enum-potion-effect-type";
if(!definitions.containsKey(key))
{
JSONObject j = new JSONObject();
j.put("enum", POTION_TYPES);
definitions.put(key, j);
}
JSONObject items = new JSONObject();
items.put("$ref", "#/definitions/" + key);
prop.put("items", items);
description.add(SYMBOL_TYPE__N + " Must be a valid Potion Effect Type (use ctrl+space for auto complete!)");
}
else if(t.type().isEnum())
{
fancyType = "List of " + t.type().getSimpleName().replaceAll("\\QIris\\E", "") + "s";
JSONArray a = new JSONArray();
boolean advanced = t.type().isAnnotationPresent(Desc.class);
for(Object gg : t.type().getEnumConstants())
{
if(advanced)
{
try
{
JSONObject j = new JSONObject();
String name = ((Enum<?>) gg).name();
j.put("const", name);
Desc dd = t.type().getField(name).getAnnotation(Desc.class);
j.put("description", dd == null ? ("No Description for " + name) : dd.value());
a.put(j);
}
catch(Throwable e)
{
e.printStackTrace();
}
}
else
{
a.put(((Enum<?>) gg).name());
}
}
String key = (advanced ? "oneof-" : "") + "enum-" + t.type().getCanonicalName().replaceAll("\\Q.\\E", "-").toLowerCase();
if(!definitions.containsKey(key))
{
JSONObject j = new JSONObject();
j.put(advanced ? "oneOf" : "enum", a);
definitions.put(key, j);
}
JSONObject items = new JSONObject();
items.put("$ref", "#/definitions/" + key);
prop.put("items", items);
description.add(SYMBOL_TYPE__N + " Must be a valid " + t.type().getSimpleName().replaceAll("\\QIris\\E", "") + " (use ctrl+space for auto complete!)");
}
}
}
else
{
warnings.add("Undefined array type for field " + k.getName() + " (" + k.getType().getSimpleName() + ") in class " + cl.getSimpleName());
}
}
else
{
warnings.add("Unexpected Schema Type: " + type + " for field " + k.getName() + " (" + k.getType().getSimpleName() + ") in class " + cl.getSimpleName());
}
KList<String> d = new KList<>();
d.add(k.getName());
d.add(getFieldDescription(k));
d.add(" ");
d.add(fancyType);
d.add(getDescription(k.getType()));
description.forEach((g) -> d.add(g.trim()));
prop.put("type", type);
prop.put("description", d.toString("\n"));
return prop;
}
private String getType(Class<?> c)
{
if(c.equals(int.class) || c.equals(Integer.class) || c.equals(long.class))
{
return "integer";
}
if(c.equals(float.class) || c.equals(double.class))
{
return "number";
}
if(c.equals(boolean.class))
{
return "boolean";
}
if(c.equals(String.class) || c.isEnum() || c.equals(Enchantment.class) || c.equals(PotionEffectType.class))
{
return "string";
}
if(c.equals(KList.class))
{
return "array";
}
if(c.equals(KMap.class))
{
return "object";
}
if(!c.isAnnotationPresent(Desc.class))
{
warnings.addIfMissing("Unsupported Type: " + c.getCanonicalName() + " Did you forget @Desc?");
}
return "object";
}
private String getFieldDescription(Field r)
{
if(r.isAnnotationPresent(Desc.class))
{
return r.getDeclaredAnnotation(Desc.class).value();
}
warnings.addIfMissing("Missing @Desc on field " + r.getName() + " (" + r.getType() + ")");
return "No Field Description";
}
private String getDescription(Class<?> r)
{
if(r.isAnnotationPresent(Desc.class))
{
return r.getDeclaredAnnotation(Desc.class).value();
}
if(!r.isPrimitive() && !r.equals(KList.class) && !r.equals(KMap.class) && r.getCanonicalName().startsWith("com.volmit."))
{
warnings.addIfMissing("Missing @Desc on " + r.getSimpleName());
}
return "";
}
private static JSONArray getEnchantmentTypes()
{
JSONArray a = new JSONArray();
for(Field gg : Enchantment.class.getDeclaredFields())
{
a.put(gg.getName());
}
return a;
}
private static JSONArray getPotionTypes()
{
JSONArray a = new JSONArray();
for(PotionEffectType gg : PotionEffectType.values())
{
a.put(gg.getName().toUpperCase().replaceAll("\\Q \\E", "_"));
}
return a;
}
}

View File

@ -1,15 +1,20 @@
package com.volmit.iris.object; package com.volmit.iris.object;
import com.volmit.iris.util.Desc;
import com.volmit.iris.util.DontObfuscate; import com.volmit.iris.util.DontObfuscate;
@Desc("Defines if an object is allowed to place in carvings, surfaces or both.")
public enum CarvingMode public enum CarvingMode
{ {
@Desc("Only place this object on surfaces (NOT under carvings)")
@DontObfuscate @DontObfuscate
SURFACE_ONLY, SURFACE_ONLY,
@Desc("Only place this object under carvings (NOT on the surface)")
@DontObfuscate @DontObfuscate
CARVING_ONLY, CARVING_ONLY,
@Desc("This object can place anywhere")
@DontObfuscate @DontObfuscate
ANYWHERE; ANYWHERE;

View File

@ -1,15 +1,20 @@
package com.volmit.iris.object; package com.volmit.iris.object;
import com.volmit.iris.util.Desc;
import com.volmit.iris.util.DontObfuscate; import com.volmit.iris.util.DontObfuscate;
@Desc("Represents a location where decorations should go")
public enum DecorationPart public enum DecorationPart
{ {
@Desc("The default, decorate anywhere")
@DontObfuscate @DontObfuscate
NONE, NONE,
@Desc("Targets shore lines (typically for sugar cane)")
@DontObfuscate @DontObfuscate
SHORE_LINE, SHORE_LINE,
@Desc("Target sea surfaces (typically for lilypads)")
@DontObfuscate @DontObfuscate
SEA_SURFACE SEA_SURFACE
} }

View File

@ -1,15 +0,0 @@
package com.volmit.iris.object;
import com.volmit.iris.util.DontObfuscate;
public enum Envelope
{
@DontObfuscate
EVERYWHERE,
@DontObfuscate
CELLS,
@DontObfuscate
VEINS,
}

View File

@ -1,15 +1,20 @@
package com.volmit.iris.object; package com.volmit.iris.object;
import com.volmit.iris.util.Desc;
import com.volmit.iris.util.DontObfuscate; import com.volmit.iris.util.DontObfuscate;
@Desc("Represents a basic font style to apply to a font family")
public enum FontStyle public enum FontStyle
{ {
@Desc("Plain old text")
@DontObfuscate @DontObfuscate
PLAIN, PLAIN,
@Desc("Italicized Text")
@DontObfuscate @DontObfuscate
ITALIC, ITALIC,
@Desc("Bold Text")
@DontObfuscate @DontObfuscate
BOLD, BOLD,
} }

View File

@ -1,27 +1,36 @@
package com.volmit.iris.object; package com.volmit.iris.object;
import com.volmit.iris.util.Desc;
import com.volmit.iris.util.DontObfuscate; import com.volmit.iris.util.DontObfuscate;
@Desc("Represents a biome type")
public enum InferredType public enum InferredType
{ {
@Desc("Represents any shore biome type")
@DontObfuscate @DontObfuscate
SHORE, SHORE,
@Desc("Represents any land biome type")
@DontObfuscate @DontObfuscate
LAND, LAND,
@Desc("Represents any sea biome type")
@DontObfuscate @DontObfuscate
SEA, SEA,
@Desc("Represents any cave biome type")
@DontObfuscate @DontObfuscate
CAVE, CAVE,
@Desc("Represents any river biome type")
@DontObfuscate @DontObfuscate
RIVER, RIVER,
@Desc("Represents any lake biome type")
@DontObfuscate @DontObfuscate
LAKE, LAKE,
@Desc("Defers the type to whatever another biome type that already exists is.")
@DontObfuscate @DontObfuscate
DEFER; DEFER;
} }

View File

@ -1,87 +1,116 @@
package com.volmit.iris.object; package com.volmit.iris.object;
import com.volmit.iris.util.Desc;
import com.volmit.iris.util.DontObfuscate; import com.volmit.iris.util.DontObfuscate;
@Desc("An interpolation method (or function) is simply a method of smoothing a position based on surrounding points on a grid. Bicubic for example is smoother, but has 4 times the checks than Bilinear for example. Try using BILINEAR_STARCAST_9 for beautiful results.")
public enum InterpolationMethod public enum InterpolationMethod
{ {
@Desc("No interpolation. Nearest Neighbor (bad for terrain, great for performance).")
@DontObfuscate @DontObfuscate
NONE, NONE,
@Desc("Uses 4 nearby points in a square to calculate a 2d slope. Very fast but creates square artifacts. See: https://en.wikipedia.org/wiki/Bilinear_interpolation")
@DontObfuscate @DontObfuscate
BILINEAR, BILINEAR,
@Desc("Starcast is Iris's own creation. It uses raytrace checks to find a horizontal boundary nearby. 3 Checks in a circle. Typically starcast is used with another interpolation method. See BILINEAR_STARCAST_9 For example. Starcast is meant to 'break up' large, abrupt cliffs to make cheap interpolation smoother.")
@DontObfuscate @DontObfuscate
STARCAST_3, STARCAST_3,
@Desc("Starcast is Iris's own creation. It uses raytrace checks to find a horizontal boundary nearby. 6 Checks in a circle. Typically starcast is used with another interpolation method. See BILINEAR_STARCAST_9 For example. Starcast is meant to 'break up' large, abrupt cliffs to make cheap interpolation smoother.")
@DontObfuscate @DontObfuscate
STARCAST_6, STARCAST_6,
@Desc("Starcast is Iris's own creation. It uses raytrace checks to find a horizontal boundary nearby. 9 Checks in a circle. Typically starcast is used with another interpolation method. See BILINEAR_STARCAST_9 For example. Starcast is meant to 'break up' large, abrupt cliffs to make cheap interpolation smoother.")
@DontObfuscate @DontObfuscate
STARCAST_9, STARCAST_9,
@Desc("Starcast is Iris's own creation. It uses raytrace checks to find a horizontal boundary nearby. 12 Checks in a circle. Typically starcast is used with another interpolation method. See BILINEAR_STARCAST_9 For example. Starcast is meant to 'break up' large, abrupt cliffs to make cheap interpolation smoother.")
@DontObfuscate @DontObfuscate
STARCAST_12, STARCAST_12,
@Desc("Uses starcast to break up the abrupt sharp cliffs, then smooths the rest out with bilinear.")
@DontObfuscate @DontObfuscate
BILINEAR_STARCAST_3, BILINEAR_STARCAST_3,
@Desc("Uses starcast to break up the abrupt sharp cliffs, then smooths the rest out with bilinear.")
@DontObfuscate @DontObfuscate
BILINEAR_STARCAST_6, BILINEAR_STARCAST_6,
@Desc("Uses starcast to break up the abrupt sharp cliffs, then smooths the rest out with bilinear.")
@DontObfuscate @DontObfuscate
BILINEAR_STARCAST_9, BILINEAR_STARCAST_9,
@Desc("Uses starcast to break up the abrupt sharp cliffs, then smooths the rest out with bilinear.")
@DontObfuscate @DontObfuscate
BILINEAR_STARCAST_12, BILINEAR_STARCAST_12,
@Desc("Uses starcast to break up the abrupt sharp cliffs, then smooths the rest out with hermite.")
@DontObfuscate @DontObfuscate
HERMITE_STARCAST_3, HERMITE_STARCAST_3,
@Desc("Uses starcast to break up the abrupt sharp cliffs, then smooths the rest out with hermite.")
@DontObfuscate @DontObfuscate
HERMITE_STARCAST_6, HERMITE_STARCAST_6,
@Desc("Uses starcast to break up the abrupt sharp cliffs, then smooths the rest out with hermite.")
@DontObfuscate @DontObfuscate
HERMITE_STARCAST_9, HERMITE_STARCAST_9,
@Desc("Uses starcast to break up the abrupt sharp cliffs, then smooths the rest out with hermite.")
@DontObfuscate @DontObfuscate
HERMITE_STARCAST_12, HERMITE_STARCAST_12,
@Desc("Uses bilinear but on a bezier curve. See: https://en.wikipedia.org/wiki/Bezier_curve")
@DontObfuscate @DontObfuscate
BILINEAR_BEZIER, BILINEAR_BEZIER,
@Desc("Uses Bilinear but with parametric curves alpha 2.")
@DontObfuscate @DontObfuscate
BILINEAR_PARAMETRIC_2, BILINEAR_PARAMETRIC_2,
@Desc("Uses Bilinear but with parametric curves alpha 4.")
@DontObfuscate @DontObfuscate
BILINEAR_PARAMETRIC_4, BILINEAR_PARAMETRIC_4,
@Desc("Uses Bilinear but with parametric curves alpha 1.5.")
@DontObfuscate @DontObfuscate
BILINEAR_PARAMETRIC_1_5, BILINEAR_PARAMETRIC_1_5,
@Desc("Bicubic noise creates 4, 4-point splines for a total of 16 checks. Bcubic can go higher than expected and lower than expected right before a large change in slope.")
@DontObfuscate @DontObfuscate
BICUBIC, BICUBIC,
@Desc("Hermite is similar to bicubic, but faster and it can be tuned a little bit")
@DontObfuscate @DontObfuscate
HERMITE, HERMITE,
@Desc("Essentially bicubic with zero tension")
@DontObfuscate @DontObfuscate
CATMULL_ROM_SPLINE, CATMULL_ROM_SPLINE,
@Desc("Essentially bicubic with max tension")
@DontObfuscate @DontObfuscate
HERMITE_TENSE, HERMITE_TENSE,
@Desc("Hermite is similar to bicubic, this variant reduces the dimple artifacts of bicubic")
@DontObfuscate @DontObfuscate
HERMITE_LOOSE, HERMITE_LOOSE,
@Desc("Hermite is similar to bicubic, this variant reduces the dimple artifacts of bicubic")
@DontObfuscate @DontObfuscate
HERMITE_LOOSE_HALF_POSITIVE_BIAS, HERMITE_LOOSE_HALF_POSITIVE_BIAS,
@Desc("Hermite is similar to bicubic, this variant reduces the dimple artifacts of bicubic")
@DontObfuscate @DontObfuscate
HERMITE_LOOSE_HALF_NEGATIVE_BIAS, HERMITE_LOOSE_HALF_NEGATIVE_BIAS,
@Desc("Hermite is similar to bicubic, this variant reduces the dimple artifacts of bicubic")
@DontObfuscate @DontObfuscate
HERMITE_LOOSE_FULL_POSITIVE_BIAS, HERMITE_LOOSE_FULL_POSITIVE_BIAS,
@Desc("Hermite is similar to bicubic, this variant reduces the dimple artifacts of bicubic")
@DontObfuscate @DontObfuscate
HERMITE_LOOSE_FULL_NEGATIVE_BIAS, HERMITE_LOOSE_FULL_NEGATIVE_BIAS,

View File

@ -1,21 +1,28 @@
package com.volmit.iris.object; package com.volmit.iris.object;
import com.volmit.iris.util.Desc;
import com.volmit.iris.util.DontObfuscate; import com.volmit.iris.util.DontObfuscate;
@Desc("An inventory slot type is used to represent a type of slot for items to fit into in any given inventory.")
public enum InventorySlotType public enum InventorySlotType
{ {
@Desc("Typically the one you want to go with. Storage represnents most slots in inventories.")
@DontObfuscate @DontObfuscate
STORAGE, STORAGE,
@Desc("Used for the fuel slot in Furnaces, Blast furnaces, smokers etc.")
@DontObfuscate @DontObfuscate
FUEL, FUEL,
@Desc("Used for the cook slot in furnaces")
@DontObfuscate @DontObfuscate
FURNACE, FURNACE,
@Desc("Used for the cook slot in blast furnaces")
@DontObfuscate @DontObfuscate
BLAST_FURNACE, BLAST_FURNACE,
@Desc("Used for the cook slot in smokers")
@DontObfuscate @DontObfuscate
SMOKER, SMOKER,
} }

View File

@ -23,7 +23,6 @@ import lombok.experimental.Accessors;
@Data @Data
public class IrisCarveLayer public class IrisCarveLayer
{ {
@Required @Required
@DontObfuscate @DontObfuscate
@Desc("The 4d slope this carve layer follows") @Desc("The 4d slope this carve layer follows")

View File

@ -1,15 +1,20 @@
package com.volmit.iris.object; package com.volmit.iris.object;
import com.volmit.iris.util.Desc;
import com.volmit.iris.util.DontObfuscate; import com.volmit.iris.util.DontObfuscate;
@Desc("A loot mode is used to descrive what to do with the existing loot layers before adding this loot. Using ADD will simply add this table to the building list of tables (i.e. add dimension tables, region tables then biome tables). By using clear or replace, you remove the parent tables before and add just your tables.")
public enum LootMode public enum LootMode
{ {
@Desc("Add to the existing parent loot tables")
@DontObfuscate @DontObfuscate
ADD, ADD,
@Desc("Clear all loot tables then add this table")
@DontObfuscate @DontObfuscate
CLEAR, CLEAR,
@Desc("Replace all loot tables with this table (same as clear)")
@DontObfuscate @DontObfuscate
REPLACE; REPLACE;
} }

View File

@ -1,30 +1,40 @@
package com.volmit.iris.object; package com.volmit.iris.object;
import com.volmit.iris.util.Desc;
import com.volmit.iris.util.DontObfuscate; import com.volmit.iris.util.DontObfuscate;
@Desc("Object Place modes are useful for positioning objects just right. The default value is CENTER_HEIGHT.")
public enum ObjectPlaceMode public enum ObjectPlaceMode
{ {
@Desc("The default place mode. This mode picks a center point (where the center of the object will be) and takes the height. That height is used for the whole object.")
@DontObfuscate @DontObfuscate
CENTER_HEIGHT, CENTER_HEIGHT,
@Desc("Samples a lot of points where the object will cover (horizontally) and picks the highest height, that height is then used to place the object. This mode is useful for preventing any part of your object from being buried though it will float off of cliffs.")
@DontObfuscate @DontObfuscate
MAX_HEIGHT, MAX_HEIGHT,
@Desc("Samples only 4 points where the object will cover (horizontally) and picks the highest height, that height is then used to place the object. This mode is useful for preventing any part of your object from being buried though it will float off of cliffs.\"")
@DontObfuscate @DontObfuscate
FAST_MAX_HEIGHT, FAST_MAX_HEIGHT,
@Desc("Samples a lot of points where the object will cover (horizontally) and picks the lowest height, that height is then used to place the object. This mode is useful for preventing any part of your object from overhanging a cliff though it gets buried a lot")
@DontObfuscate @DontObfuscate
MIN_HEIGHT, MIN_HEIGHT,
@Desc("Samples only 4 points where the object will cover (horizontally) and picks the lowest height, that height is then used to place the object. This mode is useful for preventing any part of your object from overhanging a cliff though it gets buried a lot")
@DontObfuscate @DontObfuscate
FAST_MIN_HEIGHT, FAST_MIN_HEIGHT,
@Desc("Stilting is MAX_HEIGHT but it repeats the bottom most block of your object until it hits the surface. This is expensive because it has to first sample every height value for each x,z position of your object. Avoid using this unless its structures for performance reasons.")
@DontObfuscate @DontObfuscate
STILT, STILT,
@Desc("Just like stilting but very inaccurate. Useful for stilting a lot of objects without too much care on accuracy (you can use the over-stilt value to force stilts under ground further)")
@DontObfuscate @DontObfuscate
FAST_STILT, FAST_STILT,
@Desc("Samples the height of the terrain at every x,z position of your object and pushes it down to the surface. It's pretty much like a melt function over the terrain.")
@DontObfuscate @DontObfuscate
PAINT; PAINT;
} }

View File

@ -1,15 +1,20 @@
package com.volmit.iris.object; package com.volmit.iris.object;
import com.volmit.iris.util.Desc;
import com.volmit.iris.util.DontObfuscate; import com.volmit.iris.util.DontObfuscate;
@Desc("A structure tile condition is for a specific wall if a tile is allowed to place if a wall exists.")
public enum StructureTileCondition public enum StructureTileCondition
{ {
@Desc("This face REQUIRES a wall for this tile to place here")
@DontObfuscate @DontObfuscate
REQUIRED, REQUIRED,
@Desc("This face DOESNT CARE if a wall is here for this tile to place here")
@DontObfuscate @DontObfuscate
AGNOSTIC, AGNOSTIC,
@Desc("This face CANNOT HAVE a wall for this tile to place here")
@DontObfuscate @DontObfuscate
NEVER; NEVER;

View File

@ -99,6 +99,64 @@ public class ObjectResourceLoader extends ResourceLoader<IrisObject>
} }
} }
public String[] getPreferredKeys()
{
if(preferredFolder == null || preferredFolder.isEmpty())
{
return getPossibleKeys();
}
if(possibleKeys != null)
{
return possibleKeys;
}
Iris.info("Building " + resourceTypeName + " Preference Lists");
KSet<String> m = new KSet<>();
for(File i : getFolders())
{
for(File j : i.listFiles())
{
if(!j.getPath().contains(preferredFolder))
{
continue;
}
if(j.isFile() && j.getName().endsWith(".iob"))
{
m.add(j.getName().replaceAll("\\Q.iob\\E", ""));
}
else if(j.isDirectory())
{
for(File k : j.listFiles())
{
if(k.isFile() && k.getName().endsWith(".iob"))
{
m.add(j.getName() + "/" + k.getName().replaceAll("\\Q.iob\\E", ""));
}
else if(k.isDirectory())
{
for(File l : k.listFiles())
{
if(l.isFile() && l.getName().endsWith(".iob"))
{
m.add(j.getName() + "/" + k.getName() + "/" + l.getName().replaceAll("\\Q.iob\\E", ""));
}
}
}
}
}
}
}
KList<String> v = new KList<>(m);
possibleKeys = v.toArray(new String[v.size()]);
return possibleKeys;
}
public String[] getPossibleKeys() public String[] getPossibleKeys()
{ {
if(possibleKeys != null) if(possibleKeys != null)
@ -115,7 +173,7 @@ public class ObjectResourceLoader extends ResourceLoader<IrisObject>
{ {
if(j.isFile() && j.getName().endsWith(".iob")) if(j.isFile() && j.getName().endsWith(".iob"))
{ {
m.add(j.getName().replaceAll("\\Q.json\\E", "")); m.add(j.getName().replaceAll("\\Q.iob\\E", ""));
} }
else if(j.isDirectory()) else if(j.isDirectory())

View File

@ -22,6 +22,7 @@ public class ResourceLoader<T extends IrisRegistrant>
protected IrisLock lock; protected IrisLock lock;
protected String preferredFolder = null; protected String preferredFolder = null;
protected String[] possibleKeys = null; protected String[] possibleKeys = null;
protected String[] preferredKeys = null;
public ResourceLoader(File root, String folderName, String resourceTypeName, Class<? extends T> objectClass) public ResourceLoader(File root, String folderName, String resourceTypeName, Class<? extends T> objectClass)
{ {
@ -35,6 +36,53 @@ public class ResourceLoader<T extends IrisRegistrant>
loadCache = new KMap<>(); loadCache = new KMap<>();
} }
public String[] getPreferredKeys()
{
if(preferredFolder == null || preferredFolder.isEmpty())
{
return getPossibleKeys();
}
if(preferredKeys != null)
{
return preferredKeys;
}
Iris.info("Building " + resourceTypeName + " Preference Lists");
KSet<String> m = new KSet<>();
for(File i : getFolders())
{
for(File j : i.listFiles())
{
if(!j.getPath().contains(preferredFolder))
{
continue;
}
if(j.isFile() && j.getName().endsWith(".json"))
{
m.add(j.getName().replaceAll("\\Q.json\\E", ""));
}
else if(j.isDirectory())
{
for(File k : j.listFiles())
{
if(k.isFile() && k.getName().endsWith(".json"))
{
m.add(j.getName() + "/" + k.getName().replaceAll("\\Q.json\\E", ""));
}
}
}
}
}
KList<String> v = new KList<>(m);
preferredKeys = v.toArray(new String[v.size()]);
return preferredKeys;
}
public String[] getPossibleKeys() public String[] getPossibleKeys()
{ {
if(possibleKeys != null) if(possibleKeys != null)