From af248ee14a2874913a0f8c4701a5b98a087fdbe6 Mon Sep 17 00:00:00 2001 From: dfsek Date: Sat, 30 Jan 2021 03:22:13 -0700 Subject: [PATCH] begin refactoring with Tectonic Object Templates --- common/build.gradle.kts | 2 +- .../dfsek/terra/config/GenericLoaders.java | 9 + .../config/loaders/MaterialSetLoader.java | 2 +- .../loaders/config/BufferedImageLoader.java | 28 +++ .../loaders/config/FloraLayerLoader.java | 10 +- .../loaders/config/OreHolderLoader.java | 2 +- .../loaders/config/TreeLayerLoader.java | 10 +- .../biome/BiomeProviderBuilderLoader.java | 4 +- .../config/biome/SourceBuilderLoader.java | 2 +- .../config/biome/StageBuilderLoader.java | 6 +- .../sampler/NoiseSamplerBuilderLoader.java | 170 ++++++++---------- .../sampler/templates/FastNoiseTemplate.java} | 37 ++-- .../templates/ImageSamplerTemplate.java | 24 +++ .../sampler/templates/SamplerTemplate.java | 30 ++++ .../loaders/palette/PaletteLayerLoader.java | 2 +- .../dfsek/terra/config/pack/ConfigPack.java | 8 +- .../terra/config/templates/BiomeTemplate.java | 6 +- .../config/templates/PaletteTemplate.java | 6 +- .../src/test/java/biome/DistributionTest.java | 6 +- common/src/test/java/noise/NoiseTool.java | 5 +- 20 files changed, 224 insertions(+), 145 deletions(-) create mode 100644 common/src/main/java/com/dfsek/terra/config/loaders/config/BufferedImageLoader.java rename common/src/main/java/com/dfsek/terra/{world/generation/config/NoiseBuilder.java => config/loaders/config/sampler/templates/FastNoiseTemplate.java} (80%) create mode 100644 common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/ImageSamplerTemplate.java create mode 100644 common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/SamplerTemplate.java diff --git a/common/build.gradle.kts b/common/build.gradle.kts index bc7c7d3d8..94fec69e3 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -14,7 +14,7 @@ dependencies { "shadedApi"("commons-io:commons-io:2.4") "shadedApi"("com.scireum:parsii:1.2.1") - "shadedApi"("com.dfsek:Tectonic:1.1.0") + "shadedApi"("com.dfsek:Tectonic:1.2.3") "shadedApi"("net.jafama:jafama:2.3.2") "shadedApi"("org.yaml:snakeyaml:1.27") diff --git a/common/src/main/java/com/dfsek/terra/config/GenericLoaders.java b/common/src/main/java/com/dfsek/terra/config/GenericLoaders.java index c2999609d..3bb8610fd 100644 --- a/common/src/main/java/com/dfsek/terra/config/GenericLoaders.java +++ b/common/src/main/java/com/dfsek/terra/config/GenericLoaders.java @@ -8,6 +8,8 @@ import com.dfsek.terra.api.math.ProbabilityCollection; import com.dfsek.terra.api.math.Range; import com.dfsek.terra.api.math.noise.normalizer.Normalizer; import com.dfsek.terra.api.math.noise.samplers.FastNoiseLite; +import com.dfsek.terra.api.math.noise.samplers.ImageSampler; +import com.dfsek.terra.api.util.seeded.NoiseSeeded; import com.dfsek.terra.api.world.palette.holder.PaletteHolder; import com.dfsek.terra.api.world.palette.holder.PaletteLayerHolder; import com.dfsek.terra.config.loaders.MaterialSetLoader; @@ -18,6 +20,9 @@ import com.dfsek.terra.config.loaders.config.GridSpawnLoader; import com.dfsek.terra.config.loaders.config.OreConfigLoader; import com.dfsek.terra.config.loaders.config.OreHolderLoader; import com.dfsek.terra.config.loaders.config.TreeLayerLoader; +import com.dfsek.terra.config.loaders.config.sampler.NoiseSamplerBuilderLoader; +import com.dfsek.terra.config.loaders.config.sampler.templates.FastNoiseTemplate; +import com.dfsek.terra.config.loaders.config.sampler.templates.ImageSamplerTemplate; import com.dfsek.terra.config.loaders.palette.PaletteHolderLoader; import com.dfsek.terra.config.loaders.palette.PaletteLayerLoader; import com.dfsek.terra.util.MaterialSet; @@ -48,6 +53,10 @@ public class GenericLoaders implements LoaderRegistrar { .registerLoader(TreeLayer.class, new TreeLayerLoader()) .registerLoader(MaterialSet.class, new MaterialSetLoader()) .registerLoader(OreHolder.class, new OreHolderLoader()) + .registerLoader(FastNoiseTemplate.class, FastNoiseTemplate::new) + .registerLoader(ImageSamplerTemplate.class, ImageSamplerTemplate::new) + .registerLoader(NoiseSeeded.class, new NoiseSamplerBuilderLoader()) + .registerLoader(ImageSampler.Channel.class, (t, object, cf) -> ImageSampler.Channel.valueOf((String) object)) .registerLoader(FastNoiseLite.NoiseType.class, (t, object, cf) -> FastNoiseLite.NoiseType.valueOf((String) object)) .registerLoader(FastNoiseLite.FractalType.class, (t, object, cf) -> FastNoiseLite.FractalType.valueOf((String) object)) .registerLoader(FastNoiseLite.DomainWarpType.class, (t, object, cf) -> FastNoiseLite.DomainWarpType.valueOf((String) object)) diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/MaterialSetLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/MaterialSetLoader.java index 53ec78a2b..c06333917 100644 --- a/common/src/main/java/com/dfsek/terra/config/loaders/MaterialSetLoader.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/MaterialSetLoader.java @@ -18,7 +18,7 @@ public class MaterialSetLoader implements TypeLoader { for(String string : stringData) { try { - set.add((MaterialData) configLoader.loadType(MaterialData.class, string)); + set.add(configLoader.loadClass(MaterialData.class, string)); } catch(NullPointerException e) { throw new LoadException("Invalid data identifier \"" + string + "\"", e); } diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/BufferedImageLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/BufferedImageLoader.java new file mode 100644 index 000000000..191477d4c --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/BufferedImageLoader.java @@ -0,0 +1,28 @@ +package com.dfsek.terra.config.loaders.config; + +import com.dfsek.tectonic.exception.LoadException; +import com.dfsek.tectonic.loading.ConfigLoader; +import com.dfsek.tectonic.loading.TypeLoader; +import com.dfsek.terra.config.fileloaders.Loader; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.lang.reflect.Type; + +public class BufferedImageLoader implements TypeLoader { + private final Loader files; + + public BufferedImageLoader(Loader files) { + this.files = files; + } + + @Override + public BufferedImage load(Type t, Object c, ConfigLoader loader) throws LoadException { + try { + return ImageIO.read(files.get((String) c)); + } catch(IOException e) { + throw new LoadException("Unable to load image", e); + } + } +} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/FloraLayerLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/FloraLayerLoader.java index bd519f505..b02a20b98 100644 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/FloraLayerLoader.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/FloraLayerLoader.java @@ -10,7 +10,7 @@ import com.dfsek.terra.api.math.noise.samplers.FastNoiseLite; import com.dfsek.terra.api.util.seeded.NoiseSeeded; import com.dfsek.terra.api.world.flora.Flora; import com.dfsek.terra.config.loaders.Types; -import com.dfsek.terra.world.generation.config.NoiseBuilder; +import com.dfsek.terra.config.loaders.config.sampler.templates.FastNoiseTemplate; import com.dfsek.terra.world.population.items.flora.FloraLayer; import java.lang.reflect.Type; @@ -22,23 +22,23 @@ public class FloraLayerLoader implements TypeLoader { public FloraLayer load(Type type, Object o, ConfigLoader configLoader) throws LoadException { Map map = (Map) o; double density = ((Number) map.get("density")).doubleValue(); - Range range = (Range) configLoader.loadType(Range.class, map.get("y")); + Range range = configLoader.loadClass(Range.class, map.get("y")); if(range == null) throw new LoadException("Flora range unspecified"); ProbabilityCollection items = (ProbabilityCollection) configLoader.loadType(Types.FLORA_PROBABILITY_COLLECTION_TYPE, map.get("items")); NoiseSeeded sampler; if(map.containsKey("distribution")) { try { - sampler = (NoiseSeeded) configLoader.loadType(NoiseSeeded.class, map.get("distribution")); + sampler = configLoader.loadClass(NoiseSeeded.class, map.get("distribution")); } catch(ConfigException e) { throw new LoadException("Unable to load noise", e); } return new FloraLayer(density, range, items, sampler.apply(2403L)); } - NoiseBuilder def = new NoiseBuilder(); + FastNoiseTemplate def = new FastNoiseTemplate(); def.setType(FastNoiseLite.NoiseType.WhiteNoise); def.setDimensions(3); - return new FloraLayer(density, range, items, def.build(2403)); + return new FloraLayer(density, range, items, def.apply(2403L)); } } diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/OreHolderLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/OreHolderLoader.java index 7f66ee778..71b021fa3 100644 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/OreHolderLoader.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/OreHolderLoader.java @@ -18,7 +18,7 @@ public class OreHolderLoader implements TypeLoader { Map map = (Map) o; for(Map.Entry entry : map.entrySet()) { - holder.add((Ore) configLoader.loadType(Ore.class, entry.getKey()), (OreConfig) configLoader.loadType(OreConfig.class, entry.getValue())); + holder.add(configLoader.loadClass(Ore.class, entry.getKey()), (OreConfig) configLoader.loadType(OreConfig.class, entry.getValue())); } return holder; diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/TreeLayerLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/TreeLayerLoader.java index 40e0c646c..eac525bbd 100644 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/TreeLayerLoader.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/TreeLayerLoader.java @@ -10,7 +10,7 @@ import com.dfsek.terra.api.math.Range; import com.dfsek.terra.api.math.noise.samplers.FastNoiseLite; import com.dfsek.terra.api.world.tree.Tree; import com.dfsek.terra.config.loaders.Types; -import com.dfsek.terra.world.generation.config.NoiseBuilder; +import com.dfsek.terra.config.loaders.config.sampler.templates.FastNoiseTemplate; import com.dfsek.terra.world.population.items.tree.TreeLayer; import java.lang.reflect.Type; @@ -22,23 +22,23 @@ public class TreeLayerLoader implements TypeLoader { public TreeLayer load(Type type, Object o, ConfigLoader configLoader) throws LoadException { Map map = (Map) o; double density = ((Number) map.get("density")).doubleValue(); - Range range = (Range) configLoader.loadType(Range.class, map.get("y")); + Range range = configLoader.loadClass(Range.class, map.get("y")); if(range == null) throw new LoadException("Tree range unspecified"); ProbabilityCollection items = (ProbabilityCollection) configLoader.loadType(Types.TREE_PROBABILITY_COLLECTION_TYPE, map.get("items")); - NoiseBuilder sampler = new NoiseBuilder(); + FastNoiseTemplate sampler = new FastNoiseTemplate(); if(map.containsKey("distribution")) { try { configLoader.load(sampler, new Configuration((Map) map.get("distribution"))); } catch(ConfigException e) { throw new LoadException("Unable to load noise", e); } - return new TreeLayer(density, range, items, sampler.build(2403)); + return new TreeLayer(density, range, items, sampler.apply(2403L)); } sampler.setType(FastNoiseLite.NoiseType.WhiteNoise); sampler.setDimensions(3); - return new TreeLayer(density, range, items, sampler.build(2403)); + return new TreeLayer(density, range, items, sampler.apply(2403L)); } } diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/BiomeProviderBuilderLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/BiomeProviderBuilderLoader.java index 506f21270..122b7c683 100644 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/BiomeProviderBuilderLoader.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/BiomeProviderBuilderLoader.java @@ -71,7 +71,7 @@ public class BiomeProviderBuilderLoader implements TypeLoader blend = (Map) map.get("blend"); if(blend.containsKey("amplitude")) builder.setNoiseAmp(Integer.parseInt(blend.get("amplitude").toString())); if(blend.containsKey("noise")) - builder.setBlender((NoiseSeeded) loader.loadType(NoiseSeeded.class, blend.get("noise"))); + builder.setBlender(loader.loadClass(NoiseSeeded.class, blend.get("noise"))); } return builder; } else if(map.get("type").equals("IMAGE")) { @@ -86,7 +86,7 @@ public class BiomeProviderBuilderLoader implements TypeLoader { try { - return new SingleBiomeProvider((TerraBiome) loader.loadType(TerraBiome.class, map.get("biome"))); + return new SingleBiomeProvider(loader.loadClass(TerraBiome.class, map.get("biome"))); } catch(LoadException e) { throw new RuntimeException(e); } diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/SourceBuilderLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/SourceBuilderLoader.java index aba25694e..871cbb9f1 100644 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/SourceBuilderLoader.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/SourceBuilderLoader.java @@ -24,7 +24,7 @@ public class SourceBuilderLoader implements TypeLoader sourceBiomes = (ProbabilityCollection) loader.loadType(Types.TERRA_BIOME_PROBABILITY_COLLECTION_TYPE, source.get("biomes")); - NoiseSeeded sourceNoise = (NoiseSeeded) loader.loadType(NoiseSeeded.class, source.get("noise")); + NoiseSeeded sourceNoise = loader.loadClass(NoiseSeeded.class, source.get("noise")); return seed -> new RandomSource(sourceBiomes, sourceNoise.apply(seed)); } throw new LoadException("No such loader type: " + type); diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/StageBuilderLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/StageBuilderLoader.java index 94bb954b4..253044fee 100644 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/StageBuilderLoader.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/StageBuilderLoader.java @@ -30,7 +30,7 @@ public class StageBuilderLoader implements TypeLoader> { Map.Entry entry = (Map.Entry) c; Map mutator = (Map) entry.getValue(); - NoiseSeeded mutatorNoise = (NoiseSeeded) loader.loadType(NoiseSeeded.class, mutator.get("noise")); + NoiseSeeded mutatorNoise = loader.loadClass(NoiseSeeded.class, mutator.get("noise")); if(entry.getKey().equals("expand")) { if(mutator.get("type").equals("FRACTAL")) @@ -54,7 +54,7 @@ public class StageBuilderLoader implements TypeLoader> { Map> replace = new HashMap<>(); for(Map.Entry e : ((Map) mutator.get("to")).entrySet()) { - replace.put((TerraBiome) loader.loadType(TerraBiome.class, e.getKey()), new SelfProbabilityCollectionLoader().load(Types.TERRA_BIOME_PROBABILITY_COLLECTION_TYPE, e.getValue(), loader)); + replace.put(loader.loadClass(TerraBiome.class, e.getKey()), new SelfProbabilityCollectionLoader().load(Types.TERRA_BIOME_PROBABILITY_COLLECTION_TYPE, e.getValue(), loader)); } return seed -> new MutatorStage(new ReplaceListMutator(replace, fromTag, replaceBiomes, mutatorNoise.apply(seed))); @@ -73,7 +73,7 @@ public class StageBuilderLoader implements TypeLoader> { Map> replace = new HashMap<>(); for(Map.Entry e : ((Map) mutator.get("replace")).entrySet()) { - replace.put((TerraBiome) loader.loadType(TerraBiome.class, e.getKey()), new SelfProbabilityCollectionLoader().load(Types.TERRA_BIOME_PROBABILITY_COLLECTION_TYPE, e.getValue(), loader)); + replace.put(loader.loadClass(TerraBiome.class, e.getKey()), new SelfProbabilityCollectionLoader().load(Types.TERRA_BIOME_PROBABILITY_COLLECTION_TYPE, e.getValue(), loader)); } return seed -> new MutatorStage(new BorderListMutator(replace, fromTag, replaceTag, mutatorNoise.apply(seed), replaceBiomes)); diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/NoiseSamplerBuilderLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/NoiseSamplerBuilderLoader.java index 041f6289c..bb78827e6 100644 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/NoiseSamplerBuilderLoader.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/NoiseSamplerBuilderLoader.java @@ -10,24 +10,15 @@ import com.dfsek.terra.api.math.noise.normalizer.LinearNormalizer; import com.dfsek.terra.api.math.noise.normalizer.NormalNormalizer; import com.dfsek.terra.api.math.noise.normalizer.Normalizer; import com.dfsek.terra.api.math.noise.samplers.DomainWarpedSampler; -import com.dfsek.terra.api.math.noise.samplers.ImageSampler; import com.dfsek.terra.api.util.seeded.NoiseSeeded; -import com.dfsek.terra.config.fileloaders.Loader; -import com.dfsek.terra.world.generation.config.NoiseBuilder; +import com.dfsek.terra.config.loaders.config.sampler.templates.FastNoiseTemplate; +import com.dfsek.terra.config.loaders.config.sampler.templates.ImageSamplerTemplate; -import javax.imageio.ImageIO; -import java.awt.image.BufferedImage; -import java.io.IOException; import java.lang.reflect.Type; import java.util.Map; @SuppressWarnings("unchecked") public class NoiseSamplerBuilderLoader implements TypeLoader { - private final Loader fileAccess; - - public NoiseSamplerBuilderLoader(Loader fileAccess) { - this.fileAccess = fileAccess; - } @Override public NoiseSeeded load(Type t, Object c, ConfigLoader loader) throws LoadException { @@ -43,79 +34,18 @@ public class NoiseSamplerBuilderLoader implements TypeLoader { samplerType = map.get("sampler-type").toString(); } - if(samplerType.equals("NOISE")) { - NoiseBuilder builder = new NoiseBuilder(); - try { - loader.load(builder, new Configuration(map)); - } catch(ConfigException e) { - throw new LoadException("Failed to load noise function", e); - } - return new NoiseSeeded() { - @Override - public NoiseSampler apply(Long seed) { - return builder.build(seed); + switch(samplerType) { + case "NOISE": + FastNoiseTemplate builder = new FastNoiseTemplate(); + try { + loader.load(builder, new Configuration(map)); + } catch(ConfigException e) { + throw new LoadException("Failed to load noise function", e); } - - @Override - public int getDimensions() { - return dimensions; - } - }; - } else if(samplerType.equals("NORMALIZER")) { - Normalizer.NormalType normalType = (Normalizer.NormalType) loader.loadType(Normalizer.NormalType.class, map.get("type")); - - NoiseSeeded noise = (NoiseSeeded) loader.loadType(NoiseSeeded.class, map.get("function")); - - switch(normalType) { - case LINEAR: { - if(!map.containsKey("max")) throw new LoadException("Max unspecified."); - if(!map.containsKey("min")) throw new LoadException("Min unspecified."); - - - int min = Integer.parseInt(map.get("min").toString()); - int max = Integer.parseInt(map.get("max").toString()); - return new NoiseSeeded() { - @Override - public NoiseSampler apply(Long seed) { - return new LinearNormalizer(noise.apply(seed), min, max); - } - - @Override - public int getDimensions() { - return dimensions; - } - }; - } - case NORMAL: { - if(!map.containsKey("mean")) throw new LoadException("Mean unspecified."); - if(!map.containsKey("standard-deviation")) throw new LoadException("Standard Deviation unspecified."); - if(!map.containsKey("groups")) throw new LoadException("Groups unspecified."); - - double mean = Double.parseDouble(map.get("mean").toString()); - double stdDev = Double.parseDouble(map.get("standard-deviation").toString()); - int groups = Integer.parseInt(map.get("groups").toString()); - return new NoiseSeeded() { - @Override - public NoiseSampler apply(Long seed) { - return new NormalNormalizer(noise.apply(seed), groups, mean, stdDev); - } - - @Override - public int getDimensions() { - return dimensions; - } - }; - } - } - } else if(samplerType.equals("IMAGE")) { - try { - BufferedImage image = ImageIO.read(fileAccess.get(map.get("image").toString())); - ImageSampler.Channel channel = ImageSampler.Channel.valueOf(map.get("channel").toString()); - double frequency = Double.parseDouble(map.get("frequency").toString()); return new NoiseSeeded() { @Override public NoiseSampler apply(Long seed) { - return new ImageSampler(image, channel, frequency); + return builder.apply(seed); } @Override @@ -123,25 +53,71 @@ public class NoiseSamplerBuilderLoader implements TypeLoader { return dimensions; } }; - } catch(IOException | NullPointerException e) { - throw new LoadException("Failed to load image", e); - } - } else if(samplerType.equals("DOMAIN_WARP")) { - NoiseSeeded warp = (NoiseSeeded) loader.loadType(NoiseSeeded.class, map.get("warp")); - NoiseSeeded target = (NoiseSeeded) loader.loadType(NoiseSeeded.class, map.get("function")); - double amplitude = ((Number) map.getOrDefault("amplitude", 1)).doubleValue(); - int salt = (Integer) map.getOrDefault("salt", 0); - return new NoiseSeeded() { - @Override - public NoiseSampler apply(Long seed) { - return new DomainWarpedSampler(target.apply(seed), warp.apply(seed), (int) (seed + salt), amplitude); - } + case "NORMALIZER": + Normalizer.NormalType normalType = loader.loadClass(Normalizer.NormalType.class, map.get("type")); - @Override - public int getDimensions() { - return dimensions; + NoiseSeeded noise = loader.loadClass(NoiseSeeded.class, map.get("function")); + + switch(normalType) { + case LINEAR: { + if(!map.containsKey("max")) throw new LoadException("Max unspecified."); + if(!map.containsKey("min")) throw new LoadException("Min unspecified."); + + + int min = Integer.parseInt(map.get("min").toString()); + int max = Integer.parseInt(map.get("max").toString()); + return new NoiseSeeded() { + @Override + public NoiseSampler apply(Long seed) { + return new LinearNormalizer(noise.apply(seed), min, max); + } + + @Override + public int getDimensions() { + return dimensions; + } + }; + } + case NORMAL: { + if(!map.containsKey("mean")) throw new LoadException("Mean unspecified."); + if(!map.containsKey("standard-deviation")) throw new LoadException("Standard Deviation unspecified."); + if(!map.containsKey("groups")) throw new LoadException("Groups unspecified."); + + double mean = Double.parseDouble(map.get("mean").toString()); + double stdDev = Double.parseDouble(map.get("standard-deviation").toString()); + int groups = Integer.parseInt(map.get("groups").toString()); + return new NoiseSeeded() { + @Override + public NoiseSampler apply(Long seed) { + return new NormalNormalizer(noise.apply(seed), groups, mean, stdDev); + } + + @Override + public int getDimensions() { + return dimensions; + } + }; + } } - }; + case "IMAGE": { + return loader.loadClass(ImageSamplerTemplate.class, map).get(); + } + case "DOMAIN_WARP": + NoiseSeeded warp = loader.loadClass(NoiseSeeded.class, map.get("warp")); + NoiseSeeded target = loader.loadClass(NoiseSeeded.class, map.get("function")); + double amplitude = ((Number) map.getOrDefault("amplitude", 1)).doubleValue(); + int salt = (Integer) map.getOrDefault("salt", 0); + return new NoiseSeeded() { + @Override + public NoiseSampler apply(Long seed) { + return new DomainWarpedSampler(target.apply(seed), warp.apply(seed), (int) (seed + salt), amplitude); + } + + @Override + public int getDimensions() { + return dimensions; + } + }; } throw new LoadException("No such noise sampler type \"" + samplerType + "\""); diff --git a/common/src/main/java/com/dfsek/terra/world/generation/config/NoiseBuilder.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/FastNoiseTemplate.java similarity index 80% rename from common/src/main/java/com/dfsek/terra/world/generation/config/NoiseBuilder.java rename to common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/FastNoiseTemplate.java index f772f8e97..9da5a2f0e 100644 --- a/common/src/main/java/com/dfsek/terra/world/generation/config/NoiseBuilder.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/FastNoiseTemplate.java @@ -1,14 +1,13 @@ -package com.dfsek.terra.world.generation.config; +package com.dfsek.terra.config.loaders.config.sampler.templates; import com.dfsek.tectonic.annotations.Default; import com.dfsek.tectonic.annotations.Value; -import com.dfsek.tectonic.config.ConfigTemplate; import com.dfsek.terra.api.math.noise.NoiseSampler; import com.dfsek.terra.api.math.noise.samplers.FastNoiseLite; import com.dfsek.terra.api.util.seeded.NoiseSeeded; @SuppressWarnings("FieldMayBeFinal") -public class NoiseBuilder implements ConfigTemplate { +public class FastNoiseTemplate extends SamplerTemplate implements NoiseSeeded { @Value("type") @Default private FastNoiseLite.NoiseType type = FastNoiseLite.NoiseType.OpenSimplex2; @@ -70,7 +69,8 @@ public class NoiseBuilder implements ConfigTemplate { private NoiseSeeded lookup; - public NoiseSampler build(long seed) { + @Override + public NoiseSampler apply(Long seed) { FastNoiseLite noise = new FastNoiseLite((int) (seed + seedOffset)); if(!fractalType.equals(FastNoiseLite.FractalType.None)) { noise.setFractalType(fractalType); @@ -99,7 +99,7 @@ public class NoiseBuilder implements ConfigTemplate { return type; } - public NoiseBuilder setType(FastNoiseLite.NoiseType type) { + public FastNoiseTemplate setType(FastNoiseLite.NoiseType type) { this.type = type; return this; } @@ -116,7 +116,7 @@ public class NoiseBuilder implements ConfigTemplate { return cellularDistanceFunction; } - public NoiseBuilder setCellularDistanceFunction(FastNoiseLite.CellularDistanceFunction cellularDistanceFunction) { + public FastNoiseTemplate setCellularDistanceFunction(FastNoiseLite.CellularDistanceFunction cellularDistanceFunction) { this.cellularDistanceFunction = cellularDistanceFunction; return this; } @@ -125,7 +125,7 @@ public class NoiseBuilder implements ConfigTemplate { return cellularReturnType; } - public NoiseBuilder setCellularReturnType(FastNoiseLite.CellularReturnType cellularReturnType) { + public FastNoiseTemplate setCellularReturnType(FastNoiseLite.CellularReturnType cellularReturnType) { this.cellularReturnType = cellularReturnType; return this; } @@ -134,7 +134,7 @@ public class NoiseBuilder implements ConfigTemplate { return cellularJitter; } - public NoiseBuilder setCellularJitter(double cellularJitter) { + public FastNoiseTemplate setCellularJitter(double cellularJitter) { this.cellularJitter = cellularJitter; return this; } @@ -143,7 +143,7 @@ public class NoiseBuilder implements ConfigTemplate { return fractalGain; } - public NoiseBuilder setFractalGain(double fractalGain) { + public FastNoiseTemplate setFractalGain(double fractalGain) { this.fractalGain = fractalGain; return this; } @@ -152,7 +152,7 @@ public class NoiseBuilder implements ConfigTemplate { return fractalLacunarity; } - public NoiseBuilder setFractalLacunarity(double fractalLacunarity) { + public FastNoiseTemplate setFractalLacunarity(double fractalLacunarity) { this.fractalLacunarity = fractalLacunarity; return this; } @@ -161,7 +161,7 @@ public class NoiseBuilder implements ConfigTemplate { return frequency; } - public NoiseBuilder setFrequency(double frequency) { + public FastNoiseTemplate setFrequency(double frequency) { this.frequency = frequency; return this; } @@ -170,7 +170,7 @@ public class NoiseBuilder implements ConfigTemplate { return pingPong; } - public NoiseBuilder setPingPong(double pingPong) { + public FastNoiseTemplate setPingPong(double pingPong) { this.pingPong = pingPong; return this; } @@ -179,7 +179,7 @@ public class NoiseBuilder implements ConfigTemplate { return weightedStrength; } - public NoiseBuilder setWeightedStrength(double weightedStrength) { + public FastNoiseTemplate setWeightedStrength(double weightedStrength) { this.weightedStrength = weightedStrength; return this; } @@ -188,7 +188,7 @@ public class NoiseBuilder implements ConfigTemplate { return octaves; } - public NoiseBuilder setOctaves(int octaves) { + public FastNoiseTemplate setOctaves(int octaves) { this.octaves = octaves; return this; } @@ -197,7 +197,7 @@ public class NoiseBuilder implements ConfigTemplate { return fractalType; } - public NoiseBuilder setFractalType(FastNoiseLite.FractalType fractalType) { + public FastNoiseTemplate setFractalType(FastNoiseLite.FractalType fractalType) { this.fractalType = fractalType; return this; } @@ -206,7 +206,7 @@ public class NoiseBuilder implements ConfigTemplate { return rotationType3D; } - public NoiseBuilder setRotationType3D(FastNoiseLite.RotationType3D rotationType3D) { + public FastNoiseTemplate setRotationType3D(FastNoiseLite.RotationType3D rotationType3D) { this.rotationType3D = rotationType3D; return this; } @@ -218,5 +218,10 @@ public class NoiseBuilder implements ConfigTemplate { public void setDimensions(int dimensions) { this.dimensions = dimensions; } + + @Override + public NoiseSeeded get() { + return this; + } } diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/ImageSamplerTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/ImageSamplerTemplate.java new file mode 100644 index 000000000..98dd43504 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/ImageSamplerTemplate.java @@ -0,0 +1,24 @@ +package com.dfsek.terra.config.loaders.config.sampler.templates; + +import com.dfsek.tectonic.annotations.Value; +import com.dfsek.terra.api.math.noise.NoiseSampler; +import com.dfsek.terra.api.math.noise.samplers.ImageSampler; + +import java.awt.image.BufferedImage; + +public class ImageSamplerTemplate extends SamplerTemplate { + + @Value("image") + private BufferedImage image; + + @Value("frequency") + private double frequency; + + @Value("channel") + private ImageSampler.Channel channel; + + @Override + public NoiseSampler apply(Long seed) { + return new ImageSampler(image, channel, frequency); + } +} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/SamplerTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/SamplerTemplate.java new file mode 100644 index 000000000..af38ce9b9 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/SamplerTemplate.java @@ -0,0 +1,30 @@ +package com.dfsek.terra.config.loaders.config.sampler.templates; + +import com.dfsek.tectonic.annotations.Default; +import com.dfsek.tectonic.annotations.Value; +import com.dfsek.tectonic.config.ValidatedConfigTemplate; +import com.dfsek.tectonic.exception.ValidationException; +import com.dfsek.tectonic.loading.object.ObjectTemplate; +import com.dfsek.terra.api.math.noise.NoiseSampler; +import com.dfsek.terra.api.util.seeded.NoiseSeeded; + +public abstract class SamplerTemplate implements ValidatedConfigTemplate, ObjectTemplate, NoiseSeeded { + @Value("dimensions") + @Default + private int dimensions = 2; + + public int getDimensions() { + return dimensions; + } + + @Override + public boolean validate() throws ValidationException { + if(dimensions != 2 && dimensions != 3) throw new ValidationException("Illegal amount of dimensions: " + dimensions); + return true; + } + + @Override + public NoiseSeeded get() { + return this; + } +} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/palette/PaletteLayerLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/palette/PaletteLayerLoader.java index 59e38f15c..12c32224c 100644 --- a/common/src/main/java/com/dfsek/terra/config/loaders/palette/PaletteLayerLoader.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/palette/PaletteLayerLoader.java @@ -22,7 +22,7 @@ public class PaletteLayerLoader implements TypeLoader { NoiseSampler sampler = null; if(map.containsKey("noise")) { - sampler = ((NoiseSeeded) configLoader.loadType(NoiseSeeded.class, map.get("noise"))).apply(2403L); + sampler = configLoader.loadClass(NoiseSeeded.class, map.get("noise")).apply(2403L); } if(collection == null) throw new LoadException("Collection is null: " + map.get("materials")); diff --git a/common/src/main/java/com/dfsek/terra/config/pack/ConfigPack.java b/common/src/main/java/com/dfsek/terra/config/pack/ConfigPack.java index ff4f5d4fc..6b587e8bc 100644 --- a/common/src/main/java/com/dfsek/terra/config/pack/ConfigPack.java +++ b/common/src/main/java/com/dfsek/terra/config/pack/ConfigPack.java @@ -9,7 +9,6 @@ import com.dfsek.terra.api.LoaderRegistrar; import com.dfsek.terra.api.core.TerraPlugin; import com.dfsek.terra.api.structures.loot.LootTable; import com.dfsek.terra.api.structures.script.StructureScript; -import com.dfsek.terra.api.util.seeded.NoiseSeeded; import com.dfsek.terra.api.world.flora.Flora; import com.dfsek.terra.api.world.palette.Palette; import com.dfsek.terra.api.world.tree.Tree; @@ -27,8 +26,8 @@ import com.dfsek.terra.config.fileloaders.FolderLoader; import com.dfsek.terra.config.fileloaders.Loader; import com.dfsek.terra.config.fileloaders.ZIPLoader; import com.dfsek.terra.config.lang.LangUtil; +import com.dfsek.terra.config.loaders.config.BufferedImageLoader; import com.dfsek.terra.config.loaders.config.biome.BiomeProviderBuilderLoader; -import com.dfsek.terra.config.loaders.config.sampler.NoiseSamplerBuilderLoader; import com.dfsek.terra.config.templates.AbstractableTemplate; import com.dfsek.terra.config.templates.BiomeTemplate; import com.dfsek.terra.config.templates.FloraTemplate; @@ -52,6 +51,7 @@ import org.apache.commons.io.IOUtils; import org.json.simple.parser.ParseException; import parsii.eval.Scope; +import java.awt.image.BufferedImage; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; @@ -240,8 +240,8 @@ public class ConfigPack implements LoaderRegistrar { .registerLoader(StructureScript.class, scriptRegistry) .registerLoader(TerraStructure.class, structureRegistry) .registerLoader(LootTable.class, lootRegistry) - .registerLoader(BiomeProvider.BiomeProviderBuilder.class, new BiomeProviderBuilderLoader(main, biomeRegistry, loader)) - .registerLoader(NoiseSeeded.class, new NoiseSamplerBuilderLoader(loader)); + .registerLoader(BufferedImage.class, new BufferedImageLoader(loader)) + .registerLoader(BiomeProvider.BiomeProviderBuilder.class, new BiomeProviderBuilderLoader(main, biomeRegistry, loader)); } public ScriptRegistry getScriptRegistry() { diff --git a/common/src/main/java/com/dfsek/terra/config/templates/BiomeTemplate.java b/common/src/main/java/com/dfsek/terra/config/templates/BiomeTemplate.java index a437ff791..dd9244657 100644 --- a/common/src/main/java/com/dfsek/terra/config/templates/BiomeTemplate.java +++ b/common/src/main/java/com/dfsek/terra/config/templates/BiomeTemplate.java @@ -18,8 +18,8 @@ import com.dfsek.terra.api.util.seeded.NoiseSeeded; import com.dfsek.terra.api.world.palette.Palette; import com.dfsek.terra.api.world.palette.SinglePalette; import com.dfsek.terra.api.world.palette.holder.PaletteHolder; +import com.dfsek.terra.config.loaders.config.sampler.templates.FastNoiseTemplate; import com.dfsek.terra.config.pack.ConfigPack; -import com.dfsek.terra.world.generation.config.NoiseBuilder; import com.dfsek.terra.world.population.items.TerraStructure; import com.dfsek.terra.world.population.items.flora.FloraLayer; import com.dfsek.terra.world.population.items.ores.OreHolder; @@ -226,12 +226,12 @@ public class BiomeTemplate extends AbstractableTemplate implements ValidatedConf public BiomeTemplate(ConfigPack pack, TerraPlugin main) { this.pack = pack; - NoiseBuilder builder = new NoiseBuilder(); + FastNoiseTemplate builder = new FastNoiseTemplate(); builder.setType(FastNoiseLite.NoiseType.Constant); biomeNoise = new NoiseSeeded() { @Override public NoiseSampler apply(Long seed) { - return builder.build(seed); + return builder.apply(seed); } @Override diff --git a/common/src/main/java/com/dfsek/terra/config/templates/PaletteTemplate.java b/common/src/main/java/com/dfsek/terra/config/templates/PaletteTemplate.java index 64a55cb27..35d385d7f 100644 --- a/common/src/main/java/com/dfsek/terra/config/templates/PaletteTemplate.java +++ b/common/src/main/java/com/dfsek/terra/config/templates/PaletteTemplate.java @@ -7,7 +7,7 @@ import com.dfsek.terra.api.math.noise.NoiseSampler; import com.dfsek.terra.api.math.noise.samplers.FastNoiseLite; import com.dfsek.terra.api.util.seeded.NoiseSeeded; import com.dfsek.terra.api.world.palette.holder.PaletteLayerHolder; -import com.dfsek.terra.world.generation.config.NoiseBuilder; +import com.dfsek.terra.config.loaders.config.sampler.templates.FastNoiseTemplate; import java.util.List; @@ -26,13 +26,13 @@ public class PaletteTemplate extends AbstractableTemplate { private List palette; public PaletteTemplate() { - NoiseBuilder builder = new NoiseBuilder(); + FastNoiseTemplate builder = new FastNoiseTemplate(); builder.setType(FastNoiseLite.NoiseType.WhiteNoise); builder.setDimensions(3); this.noise = new NoiseSeeded() { @Override public NoiseSampler apply(Long seed) { - return builder.build(seed); + return builder.apply(seed); } @Override diff --git a/common/src/test/java/biome/DistributionTest.java b/common/src/test/java/biome/DistributionTest.java index 169ba500c..56dbfd48f 100644 --- a/common/src/test/java/biome/DistributionTest.java +++ b/common/src/test/java/biome/DistributionTest.java @@ -145,7 +145,7 @@ public class DistributionTest { .registerLoader(ProbabilityCollection.class, new ProbabilityCollectionLoader()) .registerLoader(TerraBiome.class, biomeRegistry); new GenericLoaders(null).register(pipeLoader); - pipeLoader.registerLoader(NoiseSeeded.class, new NoiseSamplerBuilderLoader(folderLoader)); + pipeLoader.registerLoader(NoiseSeeded.class, new NoiseSamplerBuilderLoader()); pipeLoader.load(template, folderLoader.get("pack.yml")); return template.getBiomeProviderBuilder().build(seed); @@ -214,6 +214,7 @@ public class DistributionTest { @Override public void keyTyped(KeyEvent e) { if(e.getKeyChar() == 's') { + long l = System.nanoTime(); try { provider[0] = getProvider(ThreadLocalRandom.current().nextLong()); } catch(ConfigException | IOException configException) { @@ -225,6 +226,9 @@ public class DistributionTest { image[0].setRGB(x, z, provider[0].getBiome(x, z).getColor()); } } + long n = System.nanoTime(); + double t = n - l; + System.out.println("Time: " + t / 1000000 + "ms"); img.setIcon(new ImageIcon(image[0])); } } diff --git a/common/src/test/java/noise/NoiseTool.java b/common/src/test/java/noise/NoiseTool.java index 7c36ea488..07c9e2c0e 100644 --- a/common/src/test/java/noise/NoiseTool.java +++ b/common/src/test/java/noise/NoiseTool.java @@ -8,6 +8,7 @@ import com.dfsek.terra.api.util.seeded.NoiseSeeded; import com.dfsek.terra.config.GenericLoaders; import com.dfsek.terra.config.fileloaders.FolderLoader; import com.dfsek.terra.config.loaders.ProbabilityCollectionLoader; +import com.dfsek.terra.config.loaders.config.BufferedImageLoader; import com.dfsek.terra.config.loaders.config.sampler.NoiseSamplerBuilderLoader; import org.apache.commons.io.FileUtils; @@ -95,7 +96,8 @@ public class NoiseTool { FolderLoader folderLoader = new FolderLoader(Paths.get("./")); ConfigLoader loader = new ConfigLoader(); - loader.registerLoader(NoiseSeeded.class, new NoiseSamplerBuilderLoader(folderLoader)) + loader.registerLoader(NoiseSeeded.class, new NoiseSamplerBuilderLoader()) + .registerLoader(BufferedImage.class, new BufferedImageLoader(folderLoader)) .registerLoader(ProbabilityCollection.class, new ProbabilityCollectionLoader()); new GenericLoaders(null).register(loader); @@ -124,6 +126,7 @@ public class NoiseTool { ProbabilityCollection colorCollection = color.getColors(); loader.load(template, new FileInputStream(file)); + System.out.println(template.getBuilder().getDimensions()); NoiseSampler noise = template.getBuilder().apply((long) seed); int size = 1024;