diff --git a/build.gradle b/build.gradle index 45ff2cbf5..fcbf46b04 100644 --- a/build.gradle +++ b/build.gradle @@ -25,6 +25,7 @@ allprojects { annotationProcessor 'org.projectlombok:lombok:1.18.24' implementation 'art.arcane.source:Source:22.6.9' implementation 'art.arcane:Amulet:22.6.9' + implementation 'com.github.ben-manes.caffeine:caffeine:3.0.6' annotationProcessor 'systems.manifold:manifold-ext:2022.1.18' testAnnotationProcessor 'systems.manifold:manifold-ext:2022.1.18' implementation 'systems.manifold:manifold-rt:2022.1.18' diff --git a/bukkit/src/main/resources/plugin.yml b/bukkit/src/main/resources/plugin.yml index c30fd7bce..116e58960 100644 --- a/bukkit/src/main/resources/plugin.yml +++ b/bukkit/src/main/resources/plugin.yml @@ -4,4 +4,5 @@ version: 1.0.0 api-version: 1.19 libraries: - org.apache-extras.beanshell:bsh:2.0b6 -- com.google.code.gson:gson:2.8.9 \ No newline at end of file +- com.google.code.gson:gson:2.8.9 +- com.github.ben-manes.caffeine:caffeine:3.0.6 \ No newline at end of file diff --git a/engine/src/main/java/com/volmit/iris/engine/EngineEditor.java b/engine/src/main/java/com/volmit/iris/engine/EngineEditor.java index 34fcd463a..8933a663e 100644 --- a/engine/src/main/java/com/volmit/iris/engine/EngineEditor.java +++ b/engine/src/main/java/com/volmit/iris/engine/EngineEditor.java @@ -5,36 +5,31 @@ import art.arcane.amulet.io.JarLoader; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.TypeAdapterFactory; -import com.volmit.iris.engine.dimension.IrisBiome; -import com.volmit.iris.engine.dimension.IrisDimension; import com.volmit.iris.engine.dimension.IrisGenerator; -import com.volmit.iris.engine.dimension.IrisSeedSet; -import com.volmit.iris.engine.editor.Mutated; +import com.volmit.iris.engine.editor.Resolvable; import lombok.Data; -import java.lang.reflect.InvocationTargetException; import java.util.List; import java.util.Objects; -import java.util.stream.Collectors; @Data public class EngineEditor { private final Engine engine; private final Gson gson; - private List mutatedTypes; + private List resolvableTypes; public EngineEditor(Engine engine) { this.engine = engine; - this.mutatedTypes = J.attempt(() -> new JarLoader(getClass()).all().parallel() + this.resolvableTypes = J.attempt(() -> new JarLoader(getClass()).all().parallel() .filter(Objects::nonNull) .filter(i -> !i.isInterface() && !i.isEnum()) - .filter(i -> i.isAssignableFrom(Mutated.class) || Mutated.class.isAssignableFrom(i)) - .map(i -> J.attempt(() -> (Mutated) i.getDeclaredConstructor().newInstance(), null)).toList(), List.of()); + .filter(i -> i.isAssignableFrom(Resolvable.class) || Resolvable.class.isAssignableFrom(i)) + .map(i -> J.attempt(() -> (Resolvable) i.getDeclaredConstructor().newInstance(), null)).toList(), List.of()); GsonBuilder gsonBuilder = new GsonBuilder(); - mutatedTypes.forEach(i -> i.apply(gsonBuilder)); + resolvableTypes.forEach(i -> i.apply(gsonBuilder)); this.gson = gsonBuilder.setPrettyPrinting().create(); - i("Registered " + mutatedTypes.size() + " Mutators with " + mutatedTypes.stream().filter(i -> i instanceof TypeAdapterFactory).count() + " Type Adapter Factories"); + i("Registered " + resolvableTypes.size() + " Mutators with " + resolvableTypes.stream().filter(i -> i instanceof TypeAdapterFactory).count() + " Type Adapter Factories"); i(gson.toJson(gson.fromJson("Noise.simplex(seed)", IrisGenerator.class))); } diff --git a/engine/src/main/java/com/volmit/iris/engine/dimension/IrisBiome.java b/engine/src/main/java/com/volmit/iris/engine/dimension/IrisBiome.java index 9782e1474..637228585 100644 --- a/engine/src/main/java/com/volmit/iris/engine/dimension/IrisBiome.java +++ b/engine/src/main/java/com/volmit/iris/engine/dimension/IrisBiome.java @@ -1,6 +1,6 @@ package com.volmit.iris.engine.dimension; -import com.volmit.iris.engine.editor.Mutated; +import com.volmit.iris.engine.editor.Resolvable; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -12,6 +12,6 @@ import lombok.experimental.Accessors; @AllArgsConstructor @NoArgsConstructor @Accessors(fluent = true, chain = true) -public class IrisBiome implements Mutated { +public class IrisBiome implements Resolvable { private String name; } diff --git a/engine/src/main/java/com/volmit/iris/engine/dimension/IrisDimension.java b/engine/src/main/java/com/volmit/iris/engine/dimension/IrisDimension.java index 0a01b841c..8a4467aeb 100644 --- a/engine/src/main/java/com/volmit/iris/engine/dimension/IrisDimension.java +++ b/engine/src/main/java/com/volmit/iris/engine/dimension/IrisDimension.java @@ -1,23 +1,18 @@ package com.volmit.iris.engine.dimension; -import com.volmit.iris.engine.editor.Mutated; +import com.volmit.iris.engine.editor.Resolvable; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; -import lombok.Singular; import lombok.experimental.Accessors; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - @Data @NoArgsConstructor @Builder @AllArgsConstructor @Accessors(fluent = true, chain = true) -public class IrisDimension implements Mutated +public class IrisDimension implements Resolvable { @Builder.Default private IrisDimensionMeta meta = new IrisDimensionMeta(); diff --git a/engine/src/main/java/com/volmit/iris/engine/dimension/IrisDimensionAuthor.java b/engine/src/main/java/com/volmit/iris/engine/dimension/IrisDimensionAuthor.java index acd5110df..617bd2741 100644 --- a/engine/src/main/java/com/volmit/iris/engine/dimension/IrisDimensionAuthor.java +++ b/engine/src/main/java/com/volmit/iris/engine/dimension/IrisDimensionAuthor.java @@ -1,6 +1,6 @@ package com.volmit.iris.engine.dimension; -import com.volmit.iris.engine.editor.Mutated; +import com.volmit.iris.engine.editor.Resolvable; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -14,7 +14,7 @@ import java.util.Map; @Builder @AllArgsConstructor @Accessors(fluent = true, chain = true) -public class IrisDimensionAuthor implements Mutated +public class IrisDimensionAuthor implements Resolvable { private String name; private Map social; diff --git a/engine/src/main/java/com/volmit/iris/engine/dimension/IrisDimensionMeta.java b/engine/src/main/java/com/volmit/iris/engine/dimension/IrisDimensionMeta.java index 99a9cdd3e..4105606c8 100644 --- a/engine/src/main/java/com/volmit/iris/engine/dimension/IrisDimensionMeta.java +++ b/engine/src/main/java/com/volmit/iris/engine/dimension/IrisDimensionMeta.java @@ -1,6 +1,6 @@ package com.volmit.iris.engine.dimension; -import com.volmit.iris.engine.editor.Mutated; +import com.volmit.iris.engine.editor.Resolvable; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -16,7 +16,7 @@ import java.util.List; @Builder @AllArgsConstructor @Accessors(fluent = true, chain = true) -public class IrisDimensionMeta implements Mutated +public class IrisDimensionMeta implements Resolvable { private String name; private String description; diff --git a/engine/src/main/java/com/volmit/iris/engine/dimension/IrisGenerator.java b/engine/src/main/java/com/volmit/iris/engine/dimension/IrisGenerator.java index ecc5ec827..047a0b3ca 100644 --- a/engine/src/main/java/com/volmit/iris/engine/dimension/IrisGenerator.java +++ b/engine/src/main/java/com/volmit/iris/engine/dimension/IrisGenerator.java @@ -4,35 +4,28 @@ import art.arcane.source.api.NoisePlane; import art.arcane.source.api.script.NoisePlaneConstructor; import art.arcane.source.api.util.NoisePreset; import com.google.gson.Gson; -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonDeserializer; -import com.google.gson.JsonElement; -import com.google.gson.JsonParseException; -import com.google.gson.JsonSyntaxException; import com.google.gson.TypeAdapter; import com.google.gson.TypeAdapterFactory; 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.editor.Mutated; +import com.volmit.iris.engine.editor.Resolvable; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import lombok.experimental.Accessors; -import lombok.extern.java.Log; import javax.script.ScriptException; import java.io.IOException; -import java.lang.reflect.Type; @Data @NoArgsConstructor @Builder @AllArgsConstructor @Accessors(fluent = true, chain = true) -public class IrisGenerator implements Mutated, TypeAdapterFactory { +public class IrisGenerator implements Resolvable, TypeAdapterFactory { @Builder.Default private String java = "art.arcane.source.api.util.NoisePreset.NATURAL.create(seed)"; diff --git a/engine/src/main/java/com/volmit/iris/engine/dimension/IrisSeedSet.java b/engine/src/main/java/com/volmit/iris/engine/dimension/IrisSeedSet.java index 33d630eb2..806de23de 100644 --- a/engine/src/main/java/com/volmit/iris/engine/dimension/IrisSeedSet.java +++ b/engine/src/main/java/com/volmit/iris/engine/dimension/IrisSeedSet.java @@ -1,7 +1,7 @@ package com.volmit.iris.engine.dimension; import com.volmit.iris.engine.Engine; -import com.volmit.iris.engine.editor.Mutated; +import com.volmit.iris.engine.editor.Resolvable; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @@ -11,7 +11,7 @@ import lombok.experimental.Accessors; @NoArgsConstructor @AllArgsConstructor @Accessors(fluent = true, chain = true) -public class IrisSeedSet implements Mutated { +public class IrisSeedSet implements Resolvable { private IrisSeedSetMode mode = IrisSeedSetMode.LOCAL_OFFSET; private long offset = 1337; diff --git a/engine/src/main/java/com/volmit/iris/engine/editor/MutatedFrozenResolver.java b/engine/src/main/java/com/volmit/iris/engine/editor/MutatedFrozenResolver.java deleted file mode 100644 index bffd345a7..000000000 --- a/engine/src/main/java/com/volmit/iris/engine/editor/MutatedFrozenResolver.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.volmit.iris.engine.editor; - -import com.volmit.iris.platform.PlatformNamespaced; - -import java.util.Map; - -public class MutatedFrozenResolver implements MutatedResolver { - private final Map registry; - - public MutatedFrozenResolver(Map registry) - { - this.registry = registry; - } - - public T resolve(PlatformNamespaced key) { - return registry.get(key); - } -} diff --git a/engine/src/main/java/com/volmit/iris/engine/editor/MutatedLoadingResolver.java b/engine/src/main/java/com/volmit/iris/engine/editor/MutatedLoadingResolver.java deleted file mode 100644 index d39a027d7..000000000 --- a/engine/src/main/java/com/volmit/iris/engine/editor/MutatedLoadingResolver.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.volmit.iris.engine.editor; - -import com.volmit.iris.platform.PlatformNamespaced; - -import java.util.Map; - -public class MutatedLoadingResolver implements MutatedResolver { - private final Map registry; - - public MutatedLoadingResolver(Map registry) - { - this.registry = registry; - } - - public T resolve(PlatformNamespaced key) { - return registry.get(key); - } -} diff --git a/engine/src/main/java/com/volmit/iris/engine/editor/MutatedResolver.java b/engine/src/main/java/com/volmit/iris/engine/editor/MutatedResolver.java deleted file mode 100644 index 45b93033b..000000000 --- a/engine/src/main/java/com/volmit/iris/engine/editor/MutatedResolver.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.volmit.iris.engine.editor; - -import com.volmit.iris.platform.PlatformNamespaced; - -@FunctionalInterface -public interface MutatedResolver { - T resolve(PlatformNamespaced key); -} diff --git a/engine/src/main/java/com/volmit/iris/engine/editor/Mutated.java b/engine/src/main/java/com/volmit/iris/engine/editor/Resolvable.java similarity index 96% rename from engine/src/main/java/com/volmit/iris/engine/editor/Mutated.java rename to engine/src/main/java/com/volmit/iris/engine/editor/Resolvable.java index 0c49eeeb5..dad8476b4 100644 --- a/engine/src/main/java/com/volmit/iris/engine/editor/Mutated.java +++ b/engine/src/main/java/com/volmit/iris/engine/editor/Resolvable.java @@ -7,7 +7,7 @@ import com.google.gson.stream.JsonWriter; import java.io.IOException; -public interface Mutated { +public interface Resolvable { default void apply(GsonBuilder builder) { if(this instanceof TypeAdapterFactory f) { builder.registerTypeAdapterFactory(f); diff --git a/engine/src/main/java/com/volmit/iris/engine/editor/resolver/CompositeResolver.java b/engine/src/main/java/com/volmit/iris/engine/editor/resolver/CompositeResolver.java new file mode 100644 index 000000000..25a832016 --- /dev/null +++ b/engine/src/main/java/com/volmit/iris/engine/editor/resolver/CompositeResolver.java @@ -0,0 +1,40 @@ +package com.volmit.iris.engine.editor.resolver; + +import com.volmit.iris.engine.editor.Resolvable; +import com.volmit.iris.platform.PlatformNamespaceKey; +import lombok.Data; + +import java.util.Map; + +@Data +public class CompositeResolver implements Resolver { + private final Map> resolvers; + private final String[] namespaces; + + public CompositeResolver(Map> resolvers) + { + this.resolvers = resolvers; + this.namespaces = resolvers.keySet().toArray(new String[0]); + } + + @Override + public boolean hasNamespace(String namespace) { + return resolvers.containsKey(namespace); + } + + @Override + public T resolve(PlatformNamespaceKey key) { + return resolvers.get(key.getNamespace()).resolve(key); + } + + @Override + public T resolve(String key) { + for(String i : getNamespaces()) { + if(resolvers.get(i).contains(i, key)) { + return resolvers.get(i).resolve(key); + } + } + + return null; + } +} diff --git a/engine/src/main/java/com/volmit/iris/engine/editor/resolver/FrozenResolver.java b/engine/src/main/java/com/volmit/iris/engine/editor/resolver/FrozenResolver.java new file mode 100644 index 000000000..cf7a228ea --- /dev/null +++ b/engine/src/main/java/com/volmit/iris/engine/editor/resolver/FrozenResolver.java @@ -0,0 +1,34 @@ +package com.volmit.iris.engine.editor.resolver; + +import com.volmit.iris.engine.editor.Resolvable; +import com.volmit.iris.platform.PlatformNamespaceKey; +import lombok.Data; + +import java.util.Collections; +import java.util.Map; + +@Data +public class FrozenResolver implements Resolver { + private final Map registry; + private final String namespace; + + public FrozenResolver(String namespace, Map registry) + { + this.registry = Collections.unmodifiableMap(registry); + this.namespace = namespace; + } + + @Override + public boolean hasNamespace(String namespace) { + return this.namespace.equals(namespace); + } + + public T resolve(PlatformNamespaceKey key) { + return registry.get(key.getKey()); + } + + @Override + public T resolve(String key) { + return registry.get(key); + } +} diff --git a/engine/src/main/java/com/volmit/iris/engine/editor/resolver/HotResolver.java b/engine/src/main/java/com/volmit/iris/engine/editor/resolver/HotResolver.java new file mode 100644 index 000000000..3a7ba5a03 --- /dev/null +++ b/engine/src/main/java/com/volmit/iris/engine/editor/resolver/HotResolver.java @@ -0,0 +1,59 @@ +package com.volmit.iris.engine.editor.resolver; + +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.engine.editor.Resolvable; +import com.volmit.iris.platform.PlatformNamespaceKey; +import lombok.Data; +import org.checkerframework.checker.nullness.qual.Nullable; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Function; + +@Data +public class HotResolver implements Resolver, CacheLoader { + private final LoadingCache cache; + private final String namespace; + private final Function loader; + + public HotResolver(String namespace, Function loader) + { + this.namespace = namespace; + this.loader = loader; + cache = Caffeine.newBuilder().build(this); + } + + public T resolve(PlatformNamespaceKey key) { + return cache.get(key.getKey()); + } + + @Override + public T resolve(String key) { + return cache.get(key); + } + + public boolean hasNamespace(String namespace) { + return this.namespace.equals(namespace); + } + + public FrozenResolver freeze() + { + cache.cleanUp(); + Map map = new HashMap<>((int) cache.estimatedSize()); + Map view = cache.asMap(); + + for(String i : view.keySet()) { + map.put(i, view.get(i)); + } + + return new FrozenResolver<>(getNamespace(), Collections.unmodifiableMap(map)); + } + + @Override + public @Nullable T load(String key) { + return loader.apply(key); + } +} diff --git a/engine/src/main/java/com/volmit/iris/engine/editor/resolver/Resolver.java b/engine/src/main/java/com/volmit/iris/engine/editor/resolver/Resolver.java new file mode 100644 index 000000000..2d1e567e0 --- /dev/null +++ b/engine/src/main/java/com/volmit/iris/engine/editor/resolver/Resolver.java @@ -0,0 +1,64 @@ +package com.volmit.iris.engine.editor.resolver; + +import com.google.gson.Gson; +import com.volmit.iris.engine.Engine; +import com.volmit.iris.engine.editor.Resolvable; +import com.volmit.iris.platform.PlatformNamespaceKey; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.Map; +import java.util.function.Function; + +public interface Resolver { + static Resolver frozen(String namespace, Map map) { + return new FrozenResolver<>(namespace, map); + } + + static Resolver hot(String namespace, Function loader) { + return new HotResolver<>(namespace, loader); + } + + static Resolver hotDirectoryJson(String namespace, Class resolvableClass, File folder, Gson gson) { + return hotDirectory(namespace, (in) -> (F) gson.fromJson(new InputStreamReader(in), resolvableClass), folder, "json"); + } + + static Resolver hotDirectory(String namespace, Function loader, File folder, String... extensions) { + return new HotResolver<>(namespace, (key) -> { + for(String i : extensions) + { + File f = new File(folder, key + "." + i); + if(f.exists()) + { + try { + FileInputStream in = new FileInputStream(f); + F ff = loader.apply(in); + in.close(); + return ff; + } catch(IOException e) { + throw new RuntimeException(e); + } + } + } + + return null; + }); + } + + boolean hasNamespace(String namespace); + + T resolve(PlatformNamespaceKey key); + + T resolve(String key); + + default boolean contains(String namespace, String key) { + return hasNamespace(namespace) && resolve(key) != null; + } + + default boolean contains(PlatformNamespaceKey key){ + return hasNamespace(key.getNamespace()) && resolve(key) != null; + } +} diff --git a/engine/src/main/java/com/volmit/iris/engine/feature/IrisPreparedFeature.java b/engine/src/main/java/com/volmit/iris/engine/feature/IrisPreparedFeature.java index 9d36b4d3c..5b17c3b60 100644 --- a/engine/src/main/java/com/volmit/iris/engine/feature/IrisPreparedFeature.java +++ b/engine/src/main/java/com/volmit/iris/engine/feature/IrisPreparedFeature.java @@ -17,7 +17,6 @@ public class IrisPreparedFeature target = size.hunked(origin); feature.generate(engine, state, target); - return target; } } diff --git a/engine/src/main/java/com/volmit/iris/engine/feature/features/FeatureTerrain.java b/engine/src/main/java/com/volmit/iris/engine/feature/features/FeatureTerrain.java index f447ad792..e373959dc 100644 --- a/engine/src/main/java/com/volmit/iris/engine/feature/features/FeatureTerrain.java +++ b/engine/src/main/java/com/volmit/iris/engine/feature/features/FeatureTerrain.java @@ -2,10 +2,6 @@ package com.volmit.iris.engine.feature.features; import art.arcane.amulet.range.IntegerRange; import art.arcane.source.api.NoisePlane; -import art.arcane.source.api.fractal.FractalFBMProvider; -import art.arcane.source.api.interpolator.StarcastInterpolator; -import art.arcane.source.api.noise.provider.CellularProvider; -import art.arcane.source.api.noise.provider.SimplexProvider; import art.arcane.source.api.util.NoisePreset; import com.volmit.iris.engine.Engine; import com.volmit.iris.engine.feature.IrisFeature;