mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2025-07-21 19:55:00 +00:00
974 lines
26 KiB
Java
974 lines
26 KiB
Java
package com.volmit.iris.manager;
|
|
|
|
import java.awt.GraphicsEnvironment;
|
|
import java.lang.reflect.Field;
|
|
import java.lang.reflect.Modifier;
|
|
import java.util.List;
|
|
|
|
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 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));
|
|
o.put("type", getType(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();
|
|
JSONArray ja = new JSONArray();
|
|
|
|
for(String i : data.getBlockLoader().getPreferredKeys())
|
|
{
|
|
ja.put(i);
|
|
}
|
|
|
|
for(String i : B.getBlockTypes())
|
|
{
|
|
ja.put(i);
|
|
}
|
|
|
|
j.put("enum", ja);
|
|
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();
|
|
JSONArray ja = new JSONArray();
|
|
|
|
for(String i : data.getBlockLoader().getPreferredKeys())
|
|
{
|
|
ja.put(i);
|
|
}
|
|
|
|
for(String i : B.getBlockTypes())
|
|
{
|
|
ja.put(i);
|
|
}
|
|
|
|
j.put("enum", ja);
|
|
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()));
|
|
|
|
try
|
|
{
|
|
k.setAccessible(true);
|
|
Object value = k.get(cl.newInstance());
|
|
|
|
if(value != null)
|
|
{
|
|
if(value instanceof List)
|
|
{
|
|
d.add("* Default Value is an empty list");
|
|
}
|
|
|
|
else if(!cl.isPrimitive() && !(value instanceof Number) && !(value instanceof String) && !(cl.isEnum()))
|
|
{
|
|
d.add("* Default Value is a default object (create this object to see default properties)");
|
|
}
|
|
|
|
else
|
|
{
|
|
d.add("* Default Value is " + value.toString());
|
|
}
|
|
}
|
|
}
|
|
|
|
catch(Throwable e)
|
|
{
|
|
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|