mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2025-07-03 00:17:15 +00:00
Schemas
This commit is contained in:
parent
efe800c606
commit
6d8c92b512
@ -140,6 +140,13 @@ public class IrisBukkit extends JavaPlugin implements IrisPlatform {
|
||||
return f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getStudioFolder() {
|
||||
File f = new File(getDataFolder(), "packs/");
|
||||
f.mkdirs();
|
||||
return f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChunkGenerator getDefaultWorldGenerator(String worldName, String id) {
|
||||
return new IrisBukkitChunkGenerator(this, EngineConfiguration.builder()
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.volmit.iris.engine;
|
||||
|
||||
import art.arcane.chrono.PrecisionStopwatch;
|
||||
import com.volmit.iris.engine.dimension.IrisBiome;
|
||||
import com.volmit.iris.engine.feature.features.FeatureTerrain;
|
||||
import com.volmit.iris.engine.pipeline.EnginePipeline;
|
||||
import com.volmit.iris.engine.pipeline.EnginePlumbing;
|
||||
@ -11,6 +12,7 @@ import com.volmit.iris.platform.PlatformBlock;
|
||||
import com.volmit.iris.platform.PlatformNamespaceKey;
|
||||
import com.volmit.iris.platform.PlatformRegistry;
|
||||
import com.volmit.iris.platform.PlatformWorld;
|
||||
import com.volmit.iris.util.NSK;
|
||||
import lombok.Data;
|
||||
import manifold.util.concurrent.ConcurrentWeakHashMap;
|
||||
|
||||
@ -57,8 +59,8 @@ public class Engine implements Closeable {
|
||||
.build())
|
||||
.build();
|
||||
data.loadData(getConfiguration().isMutable()
|
||||
? getPlatform().getStudioFolder(getConfiguration().getDimension())
|
||||
: getWorld().getIrisDataFolder());
|
||||
? getPlatform().getStudioFolder()
|
||||
: getWorld().getIrisDataFolder(), getConfiguration().getDimension());
|
||||
}
|
||||
|
||||
public PlatformBlock block(String block)
|
||||
|
@ -1,6 +1,8 @@
|
||||
package com.volmit.iris.engine;
|
||||
|
||||
import com.volmit.iris.platform.PlatformNamespaceKey;
|
||||
import com.volmit.iris.platform.PlatformWorld;
|
||||
import com.volmit.iris.util.NSK;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
@ -24,5 +26,5 @@ public class EngineConfiguration {
|
||||
private int threadPriority = 3;
|
||||
|
||||
@Builder.Default
|
||||
private String dimension = "overworld";
|
||||
private PlatformNamespaceKey dimension = new NSK("overworld", "main");
|
||||
}
|
||||
|
@ -6,21 +6,26 @@ import art.arcane.amulet.io.JarLoader;
|
||||
import art.arcane.cram.PakFile;
|
||||
import art.arcane.cram.PakKey;
|
||||
import art.arcane.cram.PakResource;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.TypeAdapterFactory;
|
||||
import com.google.gson.*;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import com.google.gson.stream.JsonToken;
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
import com.volmit.iris.engine.dimension.IrisDimension;
|
||||
import com.volmit.iris.engine.dimension.IrisGenerator;
|
||||
import com.volmit.iris.engine.dimension.IrisRange;
|
||||
import com.volmit.iris.engine.resolver.*;
|
||||
import com.volmit.iris.platform.PlatformNamespaceKey;
|
||||
import com.volmit.iris.util.NSK;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.*;
|
||||
|
||||
@Data
|
||||
public class EngineData {
|
||||
public class EngineData implements TypeAdapterFactory {
|
||||
private final Engine engine;
|
||||
private final Gson gson;
|
||||
private List<Resolvable> resolvableTypes;
|
||||
@ -35,12 +40,31 @@ public class EngineData {
|
||||
.filter(i -> i.isAssignableFrom(Resolvable.class) || Resolvable.class.isAssignableFrom(i))
|
||||
.filter(i -> !i.equals(EngineResolvable.class))
|
||||
.map(i -> J.attempt(() -> (Resolvable) i.getDeclaredConstructor().newInstance(), null)).toList(), List.of());
|
||||
GsonBuilder gsonBuilder = new GsonBuilder();
|
||||
GsonBuilder gsonBuilder = new GsonBuilder().registerTypeAdapterFactory(this);
|
||||
resolvableTypes.forEach(i -> i.apply(gsonBuilder));
|
||||
this.gson = gsonBuilder.setPrettyPrinting().create();
|
||||
i("Registered " + resolvableTypes.size() + " Mutators with " + resolvableTypes.stream().filter(i -> i instanceof TypeAdapterFactory).count() + " Type Adapter Factories");
|
||||
}
|
||||
|
||||
public void generateSchemas(File folder) throws IOException {
|
||||
folder.mkdirs();
|
||||
|
||||
for(Resolvable i : resolvableTypes) {
|
||||
IO.writeAll(new File(folder, i.entity().getId() + ".json"), i.generateSchema(this).toString());
|
||||
}
|
||||
}
|
||||
|
||||
public <T extends Resolvable> T resolve(Class<T> clazz, PlatformNamespaceKey key)
|
||||
{
|
||||
Resolver<?> r = resolvers.get(clazz);
|
||||
|
||||
if(r == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (T) r.resolve(key);
|
||||
}
|
||||
|
||||
public void registerResolver(Class<?> type, Resolver<?> resolver, String namespace)
|
||||
{
|
||||
if(resolvers.containsKey(type)) {
|
||||
@ -53,13 +77,78 @@ public class EngineData {
|
||||
}
|
||||
}
|
||||
|
||||
public void loadData(File folder) throws IOException {
|
||||
public void loadData(File folder, PlatformNamespaceKey dimension) throws IOException {
|
||||
i("Loading Data in " + folder.getPath());
|
||||
for(File i : folder.listFiles()) {
|
||||
if(i.isDirectory()) {
|
||||
if(i.isDirectory() && i.getName().equals(dimension.getNamespace())) {
|
||||
loadDataNamespaced(i, i.getName());
|
||||
|
||||
if(getEngine().getConfiguration().isMutable()) {
|
||||
generateSchemas(new File(i, ".iris/schema"));
|
||||
i("Generated " + new File(i, ".iris/schema").listFiles().length + " Schemas");
|
||||
generateCodeWorkspace(new File(i, dimension.getNamespace() + ".code-workspace"));
|
||||
i("Generated Code Workspace");
|
||||
}
|
||||
}
|
||||
|
||||
else if(i.getName().equals(dimension.getNamespace() + ".dat")) {
|
||||
loadPakFile(folder, i.getName().split("\\Q.\\E")[0]);
|
||||
}
|
||||
}
|
||||
|
||||
IrisDimension dim = resolve(IrisDimension.class, dimension);
|
||||
|
||||
if(dim == null) {
|
||||
f("Failed to load dimension " + dimension);
|
||||
}
|
||||
}
|
||||
|
||||
private void generateCodeWorkspace(File file) throws IOException {
|
||||
file.getParentFile().mkdirs();
|
||||
JsonObject ws = new JsonObject();
|
||||
JsonArray folders = new JsonArray();
|
||||
JsonObject folder = new JsonObject();
|
||||
folder.add("path", new JsonPrimitive("."));
|
||||
folders.add(folder);
|
||||
ws.add("folders", folders);
|
||||
JsonObject settings = new JsonObject();
|
||||
settings.add("workbench.colorTheme", new JsonPrimitive("Monokai"));
|
||||
settings.add("workbench.preferredDarkColorTheme", new JsonPrimitive("Solarized Dark"));
|
||||
settings.add("workbench.tips.enabled", new JsonPrimitive(false));
|
||||
settings.add("workbench.tree.indent", new JsonPrimitive(24));
|
||||
settings.add("files.autoSave", new JsonPrimitive("onFocusChange"));
|
||||
JsonObject jc = new JsonObject();
|
||||
jc.add("editor.autoIndent", new JsonPrimitive("brackets"));
|
||||
jc.add("editor.acceptSuggestionOnEnter", new JsonPrimitive("smart"));
|
||||
jc.add("editor.cursorSmoothCaretAnimation", new JsonPrimitive(true));
|
||||
jc.add("editor.dragAndDrop", new JsonPrimitive(false));
|
||||
jc.add("files.trimTrailingWhitespace", new JsonPrimitive(true));
|
||||
jc.add("diffEditor.ignoreTrimWhitespace", new JsonPrimitive(true));
|
||||
jc.add("files.trimFinalNewlines", new JsonPrimitive(true));
|
||||
jc.add("editor.suggest.showKeywords", new JsonPrimitive(false));
|
||||
jc.add("editor.suggest.showSnippets", new JsonPrimitive(false));
|
||||
jc.add("editor.suggest.showWords", new JsonPrimitive(false));
|
||||
JsonObject st = new JsonObject();
|
||||
st.add("strings", new JsonPrimitive(true));
|
||||
jc.add("editor.quickSuggestions", st);
|
||||
jc.add("editor.suggest.insertMode", new JsonPrimitive("replace"));
|
||||
settings.add("[json]", jc);
|
||||
settings.add("json.maxItemsComputed", new JsonPrimitive(30000));
|
||||
JsonArray schemas = new JsonArray();
|
||||
|
||||
for(Resolvable i : resolvableTypes) {
|
||||
String id = i.entity().getId();
|
||||
JsonObject o = new JsonObject();
|
||||
JsonArray fileMatch = new JsonArray();
|
||||
fileMatch.add("/" + id + "/*.json");
|
||||
o.add("fileMatch", fileMatch);
|
||||
o.add("url", new JsonPrimitive(".iris/schema/" + id + ".json"));
|
||||
schemas.add(o);
|
||||
}
|
||||
|
||||
settings.add("json.schemas", schemas);
|
||||
ws.add("settings", settings);
|
||||
IO.writeAll(file, ws.toString());
|
||||
}
|
||||
|
||||
public void loadDataNamespaced(File folder, String namespace) throws IOException {
|
||||
@ -67,8 +156,7 @@ public class EngineData {
|
||||
for(Resolvable i : resolvableTypes)
|
||||
{
|
||||
new File(folder, i.entity().getId()).mkdirs();
|
||||
IO.writeAll(
|
||||
new File(new File(folder, i.entity().getId()), "example.json"), gson.toJson(i));
|
||||
IO.writeAll(new File(new File(folder, i.entity().getId()), "example.json"), gson.toJson(i));
|
||||
}
|
||||
|
||||
for(File i : folder.listFiles())
|
||||
@ -76,10 +164,6 @@ public class EngineData {
|
||||
if(i.isDirectory()) {
|
||||
loadDataFolder(i, namespace);
|
||||
}
|
||||
|
||||
else if(i.getName().endsWith(".dat")) {
|
||||
loadPakFile(folder, i.getName().split("\\Q.\\E")[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -114,4 +198,77 @@ public class EngineData {
|
||||
public void printResolvers() {
|
||||
resolvers.forEach((k, i) -> i.print(k.simpleName(), this));
|
||||
}
|
||||
|
||||
private <T> void writeSafeJson(TypeAdapter<T> delegate, JsonWriter out, T value) {
|
||||
try {
|
||||
delegate.write(out, value);
|
||||
} catch (IOException e) {
|
||||
try {
|
||||
delegate.write(out, null);
|
||||
} catch(IOException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
|
||||
final TypeAdapter<T> delegate = gson.getDelegateAdapter(this, type);
|
||||
|
||||
for(Resolvable i : resolvableTypes) {
|
||||
if(type.getRawType().equals(i.getClass())) {
|
||||
return new TypeAdapter<>() {
|
||||
public void write(JsonWriter out, T value) {writeSafeJson(delegate, out, value);}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public T read(JsonReader in) throws IOException {
|
||||
JsonToken token = in.peek();
|
||||
|
||||
if(token == JsonToken.STRING) {
|
||||
Resolver<?> resolver = getResolvers().get(i.getClass());
|
||||
String key = in.nextString();
|
||||
|
||||
if(resolver == null) {
|
||||
w("Unable to find a resolver for " + i.getClass() + " received " + key);
|
||||
return null;
|
||||
}
|
||||
|
||||
T t = (T) resolver.resolve(new NSK(key));
|
||||
|
||||
if(t == null) {
|
||||
w("Unable to resolve " + i.getClass() + " " + key);
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
return delegate.read(in);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public Resolvable getInstance(Class<?> type) {
|
||||
for(Resolvable i : resolvableTypes) {
|
||||
if(i.getClass().equals(type)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<PlatformNamespaceKey> getAllKeys(Class<?> type) {
|
||||
List<PlatformNamespaceKey> keys = new ArrayList<>();
|
||||
Resolver<?> resolver = resolvers.get(type);
|
||||
|
||||
if(resolver != null) {
|
||||
resolver.addAllKeys(keys);
|
||||
}
|
||||
|
||||
return keys;
|
||||
}
|
||||
}
|
||||
|
@ -28,10 +28,11 @@ import java.util.List;
|
||||
@NoArgsConstructor
|
||||
@EqualsAndHashCode(callSuper=false)
|
||||
@Accessors(fluent = true, chain = true)
|
||||
@Resolvable.Entity(id = "palette")
|
||||
@Resolvable.Entity(id = "palette", jsonTypes = {JsonToken.STRING, JsonToken.BEGIN_OBJECT})
|
||||
public class IrisPalette extends EngineResolvable implements TypeAdapterFactory {
|
||||
@Singular
|
||||
@PlatformType(PlatformBlock.class)
|
||||
@Type(String.class)
|
||||
@TokenConstructor(JsonToken.STRING)
|
||||
private List<String> blocks = new ArrayList<>();
|
||||
|
||||
|
@ -19,7 +19,7 @@ import java.util.List;
|
||||
@NoArgsConstructor
|
||||
@EqualsAndHashCode(callSuper=false)
|
||||
@Accessors(fluent = true, chain = true)
|
||||
@Resolvable.Entity(id = "surface-layer")
|
||||
@Resolvable.Entity(id = "surface")
|
||||
public class IrisSurface extends EngineResolvable {
|
||||
@Singular
|
||||
@Type(IrisSurfaceLayer.class)
|
||||
|
@ -5,6 +5,7 @@ import com.volmit.iris.platform.PlatformNamespaceKey;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
@ -62,4 +63,9 @@ public class CompositeResolver<T extends Resolvable> implements Resolver<T> {
|
||||
i.print(type, printer, indent + 2);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAllKeys(List<PlatformNamespaceKey> keys) {
|
||||
resolvers.forEach((k, v) -> v.addAllKeys(keys));
|
||||
}
|
||||
}
|
||||
|
@ -2,9 +2,11 @@ package com.volmit.iris.engine.resolver;
|
||||
|
||||
import art.arcane.amulet.format.Form;
|
||||
import com.volmit.iris.platform.PlatformNamespaceKey;
|
||||
import com.volmit.iris.util.NSK;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
@ -37,6 +39,11 @@ public class FrozenResolver<T extends Resolvable> implements Resolver<T> {
|
||||
printer.i(Form.repeat(" ", indent) + "Frozen[" + namespace + "] " + type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAllKeys(List<PlatformNamespaceKey> keys) {
|
||||
registry.keySet().forEach((k) -> keys.add(new NSK(getNamespace(), k)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Resolver<T> and(String namespace, Resolver<T> resolver) {
|
||||
if(!namespace.equals(getNamespace())) {
|
||||
|
@ -5,23 +5,29 @@ import com.github.benmanes.caffeine.cache.CacheLoader;
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||
import com.volmit.iris.platform.PlatformNamespaceKey;
|
||||
import com.volmit.iris.util.NSK;
|
||||
import lombok.Data;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Data
|
||||
public class HotResolver<T extends Resolvable> implements Resolver<T>, CacheLoader<String, T> {
|
||||
private final LoadingCache<String, T> cache;
|
||||
private final String namespace;
|
||||
private final Function<String, T> loader;
|
||||
private final Supplier<List<String>> keyGetter;
|
||||
|
||||
public HotResolver(String namespace, Function<String, T> loader)
|
||||
public HotResolver(String namespace, Function<String, T> loader, Supplier<List<String>> keyGetter)
|
||||
{
|
||||
this.namespace = namespace;
|
||||
this.keyGetter = keyGetter;
|
||||
this.loader = loader;
|
||||
cache = Caffeine.newBuilder().build(this);
|
||||
}
|
||||
@ -70,4 +76,9 @@ public class HotResolver<T extends Resolvable> implements Resolver<T>, CacheLoad
|
||||
public void print(String type, Object printer, int indent) {
|
||||
printer.i(Form.repeat(" ", indent) + "Hot[" + namespace + "] " + type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAllKeys(List<PlatformNamespaceKey> keys) {
|
||||
keys.addAll(keyGetter.get().stream().map(i -> new NSK(getNamespace(), i)).toList());
|
||||
}
|
||||
}
|
||||
|
@ -66,6 +66,11 @@ public class MergedNamespaceResolver<T extends Resolvable> implements Resolver<T
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAllKeys(List<PlatformNamespaceKey> keys) {
|
||||
resolvers.forEach(i -> i.addAllKeys(keys));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Resolver<T> and(String namespace, Resolver<T> resolver) {
|
||||
if(namespace.equals(getNamespace()))
|
||||
|
@ -1,12 +1,15 @@
|
||||
package com.volmit.iris.engine.resolver;
|
||||
|
||||
import art.arcane.amulet.concurrent.J;
|
||||
import art.arcane.amulet.format.Form;
|
||||
import art.arcane.cram.PakResource;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.TypeAdapter;
|
||||
import com.google.gson.TypeAdapterFactory;
|
||||
import com.google.gson.*;
|
||||
import com.google.gson.stream.JsonToken;
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
import com.volmit.iris.engine.EngineData;
|
||||
import com.volmit.iris.engine.dimension.IrisSeedSetMode;
|
||||
import com.volmit.iris.platform.PlatformBiome;
|
||||
import com.volmit.iris.platform.PlatformBlock;
|
||||
import com.volmit.iris.platform.PlatformNamespaced;
|
||||
import com.volmit.iris.platform.PlatformNamespacedMutable;
|
||||
import lombok.AllArgsConstructor;
|
||||
@ -16,8 +19,171 @@ import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public interface Resolvable extends PlatformNamespaced, PlatformNamespacedMutable, PakResource {
|
||||
String SCHEMA = "http://json-schema.org/draft-07/schema#";
|
||||
|
||||
default String getSchemaId() {
|
||||
return "https://art.arcane/iris/schemas/"+entity().getId()+".json";
|
||||
}
|
||||
|
||||
default String getSchemaRefId() {
|
||||
return entity().getId()+".json";
|
||||
}
|
||||
|
||||
default JsonObject generateSchema(EngineData data) {
|
||||
JsonObject object = new JsonObject();
|
||||
Entity.ResolverEntityData entity = entity();
|
||||
object.add("$schema", new JsonPrimitive(SCHEMA));
|
||||
object.add("$id", new JsonPrimitive(getSchemaId()));
|
||||
object.add("type", new JsonPrimitive("object"));
|
||||
object.add("description", new JsonPrimitive("No Description for " + entity.getName()));
|
||||
|
||||
JsonObject properties = new JsonObject();
|
||||
JsonObject definitions = new JsonObject();
|
||||
|
||||
for(Field i : getClass().getDeclaredFields()) {
|
||||
i.access();
|
||||
|
||||
if (Modifier.isStatic(i.getModifiers()) || Modifier.isTransient(i.getModifiers())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
properties.add(i.getName(), generateSchemaProperty(data, i.getName(), i.getType(), i.getDeclaredAnnotation(Type.class), i.getDeclaredAnnotation(PlatformType.class), definitions));
|
||||
}
|
||||
|
||||
object.add("properties", properties);
|
||||
object.add("definitions", definitions);
|
||||
return object;
|
||||
}
|
||||
|
||||
default String getSchemaDefinition(String name) {
|
||||
return "D" + name.hashCode();
|
||||
}
|
||||
|
||||
default JsonObject generateSchemaProperty(EngineData data, String name, Class<?> type, Type listType, PlatformType platformType, JsonObject definitions) {
|
||||
JsonObject main = new JsonObject();
|
||||
JsonArray anyOf = new JsonArray();
|
||||
JsonObject object = new JsonObject();
|
||||
anyOf.add(object);
|
||||
object.add("description", new JsonPrimitive("No Description for field " + name));
|
||||
|
||||
if(type.isAssignableFrom(Resolvable.class) || Resolvable.class.isAssignableFrom(type)) {
|
||||
Resolvable r = data.getInstance(type);
|
||||
|
||||
if(r != null) {
|
||||
String def = getSchemaDefinition(r.getClass().simpleName());
|
||||
object.add("$ref", new JsonPrimitive(r.getSchemaRefId()));
|
||||
JsonObject registry = new JsonObject();
|
||||
registry.add("description", new JsonPrimitive("No Description for field " + name));
|
||||
String defName = getSchemaDefinition("resolve" + type.getCanonicalName());
|
||||
registry.add("type", new JsonPrimitive("string"));
|
||||
registry.add("$ref", new JsonPrimitive("#/definitions/" + defName));
|
||||
|
||||
if(!definitions.has(defName)) {
|
||||
JsonObject enumDef = new JsonObject();
|
||||
JsonArray enums = new JsonArray();
|
||||
data.getAllKeys(type).forEach(i -> enums.add(i.toString()));
|
||||
enumDef.add("enum", enums);
|
||||
definitions.add(defName, enumDef);
|
||||
}
|
||||
|
||||
anyOf.add(registry);
|
||||
}
|
||||
}
|
||||
|
||||
else if(type.isAssignableFrom(List.class) || List.class.isAssignableFrom(type)) {
|
||||
if(listType != null) {
|
||||
JsonObject internal = generateSchemaProperty(data, "list", listType.value(), null, platformType, definitions);
|
||||
object.add("items", internal);
|
||||
}
|
||||
}
|
||||
|
||||
else if(type.isEnum()) {
|
||||
String defName = getSchemaDefinition(type.getCanonicalName());
|
||||
object.add("type", new JsonPrimitive("string"));
|
||||
object.add("$ref", new JsonPrimitive("#/definitions/" + defName));
|
||||
|
||||
if(!definitions.has(defName)) {
|
||||
try {
|
||||
JsonObject enumDef = new JsonObject();
|
||||
JsonArray enums = new JsonArray();
|
||||
Arrays.stream((Enum<?>[])type.getDeclaredMethod("values").invoke(null)).forEach(i -> enums.add(i.name()));
|
||||
enumDef.add("enum", enums);
|
||||
definitions.add(defName, enumDef);
|
||||
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if(type.equals(String.class)) {
|
||||
object.add("type", new JsonPrimitive("string"));
|
||||
|
||||
if(platformType != null) {
|
||||
String defName = getSchemaDefinition(platformType.value().getCanonicalName());
|
||||
object.add("$ref", new JsonPrimitive("#/definitions/" + defName));
|
||||
|
||||
if(!definitions.has(defName)) {
|
||||
JsonObject enumDef = new JsonObject();
|
||||
JsonArray enums = buildSchemaPlatformEnum(data, platformType.value());
|
||||
enumDef.add("enum", enums);
|
||||
definitions.add(defName, enumDef);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if(type.equals(int.class) || type.equals(Integer.class)
|
||||
|| type.equals(long.class) || type.equals(Long.class)
|
||||
|| type.equals(byte.class) || type.equals(Byte.class)
|
||||
|| type.equals(short.class) || type.equals(Short.class))
|
||||
{
|
||||
object.add("type", new JsonPrimitive("integer"));
|
||||
|
||||
if(type.equals(int.class) || type.equals(Integer.class)) {
|
||||
object.add("minimum", new JsonPrimitive(Integer.MIN_VALUE));
|
||||
object.add("maximum", new JsonPrimitive(Integer.MAX_VALUE));
|
||||
}
|
||||
|
||||
else if(type.equals(long.class) || type.equals(Long.class)) {
|
||||
object.add("minimum", new JsonPrimitive(Long.MIN_VALUE));
|
||||
object.add("maximum", new JsonPrimitive(Long.MAX_VALUE));
|
||||
}
|
||||
|
||||
else if(type.equals(short.class) || type.equals(Short.class)) {
|
||||
object.add("minimum", new JsonPrimitive(Short.MIN_VALUE));
|
||||
object.add("maximum", new JsonPrimitive(Short.MAX_VALUE));
|
||||
}
|
||||
|
||||
else {
|
||||
object.add("minimum", new JsonPrimitive(Byte.MIN_VALUE));
|
||||
object.add("maximum", new JsonPrimitive(Byte.MAX_VALUE));
|
||||
}
|
||||
}
|
||||
|
||||
main.add("anyOf", anyOf);
|
||||
return main;
|
||||
}
|
||||
|
||||
default JsonArray buildSchemaPlatformEnum(EngineData data, Class<? extends PlatformNamespaced> value) {
|
||||
JsonArray a = new JsonArray();
|
||||
|
||||
if(value.equals(PlatformBlock.class)) {
|
||||
data.getEngine().getPlatform().getBlocks().map(i -> i.getKey().toString()).forEach(a::add);
|
||||
}
|
||||
|
||||
else if(value.equals(PlatformBiome.class)) {
|
||||
data.getEngine().getPlatform().getBiomes().map(i -> i.getKey().toString()).forEach(a::add);
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
default void apply(GsonBuilder builder) {
|
||||
if(this instanceof TypeAdapterFactory f) {
|
||||
builder.registerTypeAdapterFactory(f);
|
||||
@ -77,7 +243,7 @@ public interface Resolvable extends PlatformNamespaced, PlatformNamespacedMutabl
|
||||
@Target({ElementType.FIELD, ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@interface Type {
|
||||
Class<? extends Resolvable> value();
|
||||
Class<?> value();
|
||||
}
|
||||
|
||||
@Target({ElementType.FIELD, ElementType.TYPE})
|
||||
|
@ -10,10 +10,14 @@ import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public interface Resolver<T extends Resolvable> {
|
||||
@SuppressWarnings("unchecked")
|
||||
@ -41,8 +45,8 @@ public interface Resolver<T extends Resolvable> {
|
||||
return new FrozenResolver<>(namespace, map);
|
||||
}
|
||||
|
||||
static <F extends Resolvable> Resolver<F> hot(String namespace, Function<String, F> loader) {
|
||||
return new HotResolver<>(namespace, loader);
|
||||
static <F extends Resolvable> Resolver<F> hot(String namespace, Function<String, F> loader, Supplier<List<String>> keyGetter) {
|
||||
return new HotResolver<>(namespace, loader, keyGetter);
|
||||
}
|
||||
|
||||
static <F extends Resolvable> Resolver<F> hotDirectoryJson(String namespace, Class<?> resolvableClass, File folder, Gson gson) {
|
||||
@ -68,6 +72,24 @@ public interface Resolver<T extends Resolvable> {
|
||||
}
|
||||
|
||||
return null;
|
||||
}, () -> {
|
||||
List<String> s = new ArrayList<>();
|
||||
|
||||
for(File i : folder.listFiles())
|
||||
{
|
||||
if(i.isFile()) {
|
||||
for(String j : extensions)
|
||||
{
|
||||
if(i.getName().endsWith(j))
|
||||
{
|
||||
s.add(i.getName().split("\\Q.\\E")[0]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return s;
|
||||
});
|
||||
}
|
||||
|
||||
@ -93,4 +115,6 @@ public interface Resolver<T extends Resolvable> {
|
||||
}
|
||||
|
||||
void print(String type, Object printer, int index);
|
||||
|
||||
void addAllKeys(List<PlatformNamespaceKey> keys);
|
||||
}
|
||||
|
@ -23,5 +23,7 @@ public interface IrisPlatform {
|
||||
return key("minecraft", nsk);
|
||||
}
|
||||
|
||||
File getStudioFolder();
|
||||
|
||||
File getStudioFolder(String dimension);
|
||||
}
|
||||
|
@ -25,4 +25,8 @@ public class NSK implements PlatformNamespaceKey {
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return namespace + ":" + key;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user