9
0
mirror of https://github.com/VolmitSoftware/Iris.git synced 2025-12-25 18:19:14 +00:00

Resolvers

This commit is contained in:
cyberpwn
2022-06-30 19:31:13 -04:00
parent 0a2e3e5e88
commit 8b124bf298
28 changed files with 410 additions and 46 deletions

View File

@@ -1,5 +1,7 @@
package com.volmit.iris.engine;
import art.arcane.amulet.format.Form;
import art.arcane.amulet.metric.PrecisionStopwatch;
import com.volmit.iris.engine.feature.features.FeatureTerrain;
import com.volmit.iris.engine.pipeline.EnginePipeline;
import com.volmit.iris.engine.pipeline.EnginePlumbing;
@@ -30,17 +32,23 @@ public class Engine implements Closeable {
private final EngineExecutor executor;
private final EnginePlumbing plumbing;
private final EngineSeedManager seedManager;
private final EngineEditor editor;
public Engine(IrisPlatform platform, PlatformWorld world, EngineConfiguration configuration) {
PrecisionStopwatch p = PrecisionStopwatch.start();
this.configuration = configuration;
this.platform = platform;
this.world = world;
i("Initializing Iris Engine for " + platform.getPlatformName() + " in " + world.getName()
+ " with " + configuration.getThreads() + " priority " + configuration.getThreadPriority()
+ " threads in " + (configuration.isMutable() ? "edit mode" : "production mode"));
this.editor = configuration.isMutable() ? new EngineEditor(this) : null;
this.seedManager = getSeedManager();
this.registry = EngineRegistry.builder()
.blockRegistry(new PlatformRegistry<>(platform.getBlocks()))
.biomeRegistry(new PlatformRegistry<>(platform.getBiomes()))
.build();
this.blockCache = new EngineBlockCache(this);
this.registry = EngineRegistry.builder()
.blockRegistry(new PlatformRegistry<>("Block", platform.getBlocks()))
.biomeRegistry(new PlatformRegistry<>("Biome", platform.getBiomes()))
.build();
this.executor = new EngineExecutor(this);
this.plumbing = EnginePlumbing.builder().engine(this)
.pipeline(EnginePipeline.builder()

View File

@@ -0,0 +1,41 @@
package com.volmit.iris.engine;
import art.arcane.amulet.concurrent.J;
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 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<Mutated> mutatedTypes;
public EngineEditor(Engine engine)
{
this.engine = engine;
this.mutatedTypes = 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());
GsonBuilder gsonBuilder = new GsonBuilder();
mutatedTypes.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(gson.toJson(gson.fromJson("Noise.simplex(seed)", IrisGenerator.class)));
}
}

View File

@@ -1,5 +1,6 @@
package com.volmit.iris.engine;
import art.arcane.amulet.concurrent.J;
import lombok.Data;
import java.io.Closeable;
@@ -16,6 +17,7 @@ public class EngineExecutor implements ForkJoinPool.ForkJoinWorkerThreadFactory,
{
this.engine = engine;
forks = new ForkJoinPool(engine.getConfiguration().getThreads(), this, this, true);
i("Started Pool with " + engine.getConfiguration().getThreads() + " priority " + engine.getConfiguration().getThreadPriority() + " threads.");
}
@Override
@@ -32,6 +34,18 @@ public class EngineExecutor implements ForkJoinPool.ForkJoinWorkerThreadFactory,
@Override
public void close() throws IOException {
forks.shutdownNow().forEach(Runnable::run);
i("Shutting down generator pool");
forks.shutdownNow().forEach((i) -> {
try
{
i.run();
}
catch(Throwable e)
{
e.printStackTrace();
}
});
i("Generator pool shutdown");
}
}

View File

@@ -4,7 +4,13 @@ import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class EngineSeedManager {
private final Engine engine;
private final long worldSeed;
public EngineSeedManager(Engine engine)
{
this.engine = engine;
this.worldSeed = engine.getWorld().getSeed();
}
}

View File

@@ -0,0 +1,17 @@
package com.volmit.iris.engine.dimension;
import com.volmit.iris.engine.editor.Mutated;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
@Builder
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(fluent = true, chain = true)
public class IrisBiome implements Mutated {
private String name;
}

View File

@@ -1,29 +1,24 @@
package com.volmit.iris.engine.dimension;
import com.volmit.iris.engine.editor.Mutated;
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
public class IrisDimension
@NoArgsConstructor
@Builder
@AllArgsConstructor
@Accessors(fluent = true, chain = true)
public class IrisDimension implements Mutated
{
private String name;
@Data
public static class IrisDimensionMeta
{
private String name;
private String description;
private String version;
private List<IrisDimensionAuthor> authors = new ArrayList<>();
}
@Data
public static class IrisDimensionAuthor
{
private String name;
private Map<String, String> social;
}
@Builder.Default
private IrisDimensionMeta meta = new IrisDimensionMeta();
}

View File

@@ -0,0 +1,21 @@
package com.volmit.iris.engine.dimension;
import com.volmit.iris.engine.editor.Mutated;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.util.Map;
@Data
@NoArgsConstructor
@Builder
@AllArgsConstructor
@Accessors(fluent = true, chain = true)
public class IrisDimensionAuthor implements Mutated
{
private String name;
private Map<String, String> social;
}

View File

@@ -0,0 +1,26 @@
package com.volmit.iris.engine.dimension;
import com.volmit.iris.engine.editor.Mutated;
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;
@Data
@NoArgsConstructor
@Builder
@AllArgsConstructor
@Accessors(fluent = true, chain = true)
public class IrisDimensionMeta implements Mutated
{
private String name;
private String description;
private String version;
@Singular
private List<IrisDimensionAuthor> authors = new ArrayList<>();
}

View File

@@ -0,0 +1,75 @@
package com.volmit.iris.engine.dimension;
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 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 {
@Builder.Default
private String java = "art.arcane.source.api.util.NoisePreset.NATURAL.create(seed)";
@Builder.Default
private IrisSeedSet seed = new IrisSeedSet();
public NoisePlane getNoisePlane(long seed)
{
try {
return NoisePlaneConstructor.execute(seed, java);
} catch(ScriptException e) {
e.printStackTrace();
return NoisePreset.NATURAL.create(seed);
}
}
@Override
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
final TypeAdapter<T> delegate = gson.getDelegateAdapter(this, type);
if(!type.getRawType().equals(getClass())) {
return null;
}
return new TypeAdapter<>() {
public void write(JsonWriter out, T value) {writeSafeJson(delegate, out, value);}
public T read(JsonReader in) throws IOException {
JsonToken token = in.peek();
if(token == JsonToken.STRING)
{
return (T) IrisGenerator.builder().java(in.nextString()).build();
}
return delegate.read(in);
}
};
}
}

View File

@@ -0,0 +1,30 @@
package com.volmit.iris.engine.dimension;
import com.volmit.iris.engine.Engine;
import com.volmit.iris.engine.editor.Mutated;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(fluent = true, chain = true)
public class IrisSeedSet implements Mutated {
private IrisSeedSetMode mode = IrisSeedSetMode.LOCAL_OFFSET;
private long offset = 1337;
public double getSeed(Engine engine, long localSeed)
{
return switch(mode)
{
case WORLD -> engine.getSeedManager().getWorldSeed();
case LOCAL -> localSeed;
case LOCAL_OFFSET -> localSeed + offset;
case RAW -> offset;
case WORLD_OFFSET -> engine.getSeedManager().getWorldSeed() + offset;
case RANDOM -> (Math.random() * Long.MAX_VALUE) + (Math.random() * Long.MAX_VALUE);
};
}
}

View File

@@ -0,0 +1,11 @@
package com.volmit.iris.engine.dimension;
public enum IrisSeedSetMode
{
WORLD,
RAW,
WORLD_OFFSET,
LOCAL,
LOCAL_OFFSET,
RANDOM
}

View File

@@ -0,0 +1,28 @@
package com.volmit.iris.engine.editor;
import com.google.gson.GsonBuilder;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.stream.JsonWriter;
import java.io.IOException;
public interface Mutated {
default void apply(GsonBuilder builder) {
if(this instanceof TypeAdapterFactory f) {
builder.registerTypeAdapterFactory(f);
}
}
default <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);
}
}
}
}

View File

@@ -0,0 +1,18 @@
package com.volmit.iris.engine.editor;
import com.volmit.iris.platform.PlatformNamespaced;
import java.util.Map;
public class MutatedFrozenResolver<T extends Mutated> implements MutatedResolver<T> {
private final Map<PlatformNamespaced, T> registry;
public MutatedFrozenResolver(Map<PlatformNamespaced, T> registry)
{
this.registry = registry;
}
public T resolve(PlatformNamespaced key) {
return registry.get(key);
}
}

View File

@@ -0,0 +1,18 @@
package com.volmit.iris.engine.editor;
import com.volmit.iris.platform.PlatformNamespaced;
import java.util.Map;
public class MutatedLoadingResolver<T extends Mutated> implements MutatedResolver<T> {
private final Map<PlatformNamespaced, T> registry;
public MutatedLoadingResolver(Map<PlatformNamespaced, T> registry)
{
this.registry = registry;
}
public T resolve(PlatformNamespaced key) {
return registry.get(key);
}
}

View File

@@ -0,0 +1,8 @@
package com.volmit.iris.engine.editor;
import com.volmit.iris.platform.PlatformNamespaced;
@FunctionalInterface
public interface MutatedResolver<T extends Mutated> {
T resolve(PlatformNamespaced key);
}

View File

@@ -4,9 +4,9 @@ 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.Generator;
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;
import com.volmit.iris.engine.feature.IrisFeatureSizedTarget;
@@ -26,12 +26,7 @@ public class FeatureTerrain extends IrisFeature<PlatformBlock, FeatureTerrain.Te
{
super("terrain", engine);
stone = engine.block("stone");
Generator g = new Generator(new FractalFBMProvider((s) -> new CellularProvider(s), 1234));
g.scale(0.01);
this.generator = new StarcastInterpolator(new Generator(new SimplexProvider(engine.getWorld().getSeed()))
.maxOutput(64)
.minOutput(0)
.scale(0.01).warp(g), 8, 96);
this.generator = NoisePreset.NATURAL.create(1234).fit(0, 64).scale(0.2);
}
@Override

View File

@@ -1,19 +1,32 @@
package com.volmit.iris.platform;
import art.arcane.amulet.format.Form;
import lombok.Data;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@Data
public class PlatformRegistry<T extends PlatformNamespaced> {
private final Map<PlatformNamespaceKey, T> registry;
private final String name;
private final String namePlural;
public PlatformRegistry(Stream<T> stream) {
public PlatformRegistry(String name, String namePlural, Stream<T> stream) {
this.name = name;
this.namePlural = namePlural;
registry = Collections.unmodifiableMap(stream.collect(Collectors.toMap(PlatformNamespaced::getKey, (t) -> t)));
i("Registered " + Form.f(registry.size()) + " " + namePlural);
}
public PlatformRegistry(String name, Stream<T> stream) {
this(name, name + "s", stream);
}
public T get(PlatformNamespaceKey key) {
return registry.get(key);
}

View File

@@ -0,0 +1,28 @@
package com.volmit.iris.util;
import com.volmit.iris.platform.PlatformNamespaceKey;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class NSK implements PlatformNamespaceKey {
private final String namespace;
private final String key;
public NSK(String namespacedkey)
{
this(namespacedkey.contains(":") ? namespacedkey.split("\\Q:\\E")[0] : "minecraft",
namespacedkey.contains(":") ? namespacedkey.split("\\Q:\\E")[1] : namespacedkey);
}
@Override
public String getNamespace() {
return namespace;
}
@Override
public String getKey() {
return key;
}
}