Merge pull request #240 from PolyhedralDev/dev/features

Distributor/Locator addons + basic implementations, remove seed context
This commit is contained in:
dfsek
2021-07-19 23:21:00 -07:00
committed by GitHub
195 changed files with 1382 additions and 1100 deletions

View File

@@ -1,6 +1,5 @@
package com.dfsek.terra.addons.biome.image;
import com.dfsek.terra.api.util.seeded.BiomeProviderBuilder;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import net.jafama.FastMath;
@@ -11,7 +10,7 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class ImageBiomeProvider implements BiomeProvider, BiomeProviderBuilder { // This provider does not need a seed, so it is its own builder.
public class ImageBiomeProvider implements BiomeProvider {
private final Map<Color, TerraBiome> colorBiomeMap = new HashMap<>();
private final BufferedImage image;
private final int resolution;
@@ -29,7 +28,7 @@ public class ImageBiomeProvider implements BiomeProvider, BiomeProviderBuilder {
}
@Override
public TerraBiome getBiome(int x, int z) {
public TerraBiome getBiome(int x, int z, long seed) {
x /= resolution;
z /= resolution;
Color color = align.getColor(image, x, z);
@@ -40,11 +39,6 @@ public class ImageBiomeProvider implements BiomeProvider, BiomeProviderBuilder {
}));
}
@Override
public BiomeProvider build(long seed) {
return this;
}
public enum Align {
CENTER {
@Override

View File

@@ -2,14 +2,14 @@ package com.dfsek.terra.addons.biome.image;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.api.registry.Registry;
import com.dfsek.terra.api.util.seeded.BiomeBuilder;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import java.awt.image.BufferedImage;
import java.util.stream.Collectors;
import java.util.HashSet;
public class ImageProviderTemplate /*extends BiomeProviderTemplate */ {
private final Registry<BiomeBuilder> biomes;
private final Registry<TerraBiome> biomes;
@Value("image.name")
private BufferedImage image;
@@ -18,12 +18,12 @@ public class ImageProviderTemplate /*extends BiomeProviderTemplate */ {
private int resolution;
public ImageProviderTemplate(Registry<BiomeBuilder> set) {
public ImageProviderTemplate(Registry<TerraBiome> set) {
this.biomes = set;
}
//@Override
public BiomeProvider build(long seed) {
return new ImageBiomeProvider(biomes.entries().stream().map(biomeBuilder -> biomeBuilder.apply(seed)).collect(Collectors.toSet()), image, resolution, align);
public BiomeProvider build() {
return new ImageBiomeProvider(new HashSet<>(biomes.entries()), image, resolution, align);
}
}

View File

@@ -29,7 +29,7 @@ public class BiomeHolderImpl implements BiomeHolder {
}
@Override
public BiomeHolder expand(BiomeExpander expander) {
public BiomeHolder expand(BiomeExpander expander, long seed) {
TerraBiome[][] old = biomes;
int newWidth = width * 2 - 1;
@@ -39,31 +39,31 @@ public class BiomeHolderImpl implements BiomeHolder {
for(int z = 0; z < width; z++) {
biomes[x * 2][z * 2] = old[x][z];
if(z != width - 1)
biomes[x * 2][z * 2 + 1] = expander.getBetween(x + origin.getX(), z + 1 + origin.getZ(), old[x][z], old[x][z + 1]);
biomes[x * 2][z * 2 + 1] = expander.getBetween(x + origin.getX(), z + 1 + origin.getZ(), seed, old[x][z], old[x][z + 1]);
if(x != width - 1)
biomes[x * 2 + 1][z * 2] = expander.getBetween(x + 1 + origin.getX(), z + origin.getZ(), old[x][z], old[x + 1][z]);
biomes[x * 2 + 1][z * 2] = expander.getBetween(x + 1 + origin.getX(), z + origin.getZ(), seed, old[x][z], old[x + 1][z]);
if(x != width - 1 && z != width - 1)
biomes[x * 2 + 1][z * 2 + 1] = expander.getBetween(x + 1 + origin.getX(), z + 1 + origin.getZ(), old[x][z], old[x + 1][z + 1], old[x][z + 1], old[x + 1][z]);
biomes[x * 2 + 1][z * 2 + 1] = expander.getBetween(x + 1 + origin.getX(), z + 1 + origin.getZ(), seed, old[x][z], old[x + 1][z + 1], old[x][z + 1], old[x + 1][z]);
}
}
return new BiomeHolderImpl(biomes, origin.setX(origin.getX() * 2 - 1).setZ(origin.getZ() * 2 - 1), newWidth, offset);
}
@Override
public void mutate(BiomeMutator mutator) {
public void mutate(BiomeMutator mutator, long seed) {
for(int x = 0; x < width; x++) {
for(int z = 0; z < width; z++) {
BiomeMutator.ViewPoint viewPoint = new BiomeMutator.ViewPoint(this, x, z);
biomes[x][z] = mutator.mutate(viewPoint, x + origin.getX(), z + origin.getZ());
biomes[x][z] = mutator.mutate(viewPoint, x + origin.getX(), z + origin.getZ(), seed);
}
}
}
@Override
public void fill(BiomeSource source) {
public void fill(BiomeSource source, long seed) {
for(int x = 0; x < width; x++) {
for(int z = 0; z < width; z++) {
biomes[x][z] = source.getBiome(origin.getX() + x, origin.getZ() + z);
biomes[x][z] = source.getBiome(origin.getX() + x, origin.getZ() + z, seed);
}
}
}

View File

@@ -7,15 +7,14 @@ import com.dfsek.terra.api.world.biome.generation.pipeline.BiomeSource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class BiomePipelineImpl {
public class BiomePipeline {
private final BiomeSource source;
private final List<Stage> stages;
private final int size;
private final int init;
private BiomePipelineImpl(BiomeSource source, List<Stage> stages, int size, int init) {
private BiomePipeline(BiomeSource source, List<Stage> stages, int size, int init) {
this.source = source;
this.stages = stages;
this.size = size;
@@ -29,10 +28,10 @@ public class BiomePipelineImpl {
* @param z Chunk Z coord
* @return BiomeHolder containing biomes.
*/
public BiomeHolder getBiomes(int x, int z) {
public BiomeHolder getBiomes(int x, int z, long seed) {
BiomeHolder holder = new BiomeHolderImpl(init, new Vector2(x * (init - 1), z * (init - 1)));
holder.fill(source);
for(Stage stage : stages) holder = stage.apply(holder);
holder.fill(source, seed);
for(Stage stage : stages) holder = stage.apply(holder, seed);
return holder;
}
@@ -42,7 +41,7 @@ public class BiomePipelineImpl {
public static final class BiomePipelineBuilder {
private final int init;
List<StageSeeded> stages = new ArrayList<>();
List<Stage> stages = new ArrayList<>();
private int expand;
public BiomePipelineBuilder(int init) {
@@ -50,17 +49,15 @@ public class BiomePipelineImpl {
expand = init;
}
public BiomePipelineImpl build(BiomeSource source, long seed) {
List<Stage> stagesBuilt = stages.stream().map(stageBuilder -> stageBuilder.apply(seed)).collect(Collectors.toList());
for(Stage stage : stagesBuilt) {
public BiomePipeline build(BiomeSource source) {
for(Stage stage : stages) {
if(stage.isExpansion()) expand = expand * 2 - 1;
}
return new BiomePipelineImpl(source, stagesBuilt, expand, init);
return new BiomePipeline(source, stages, expand, init);
}
public BiomePipelineBuilder addStage(StageSeeded stage) {
public BiomePipelineBuilder addStage(Stage stage) {
stages.add(stage);
return this;
}

View File

@@ -1,16 +1,23 @@
package com.dfsek.terra.addons.biome.pipeline;
import com.dfsek.terra.addons.biome.pipeline.api.Stage;
import com.dfsek.terra.addons.biome.pipeline.config.BiomePipelineTemplate;
import com.dfsek.terra.addons.biome.pipeline.config.BiomeProviderBuilderLoader;
import com.dfsek.terra.addons.biome.pipeline.config.BiomeProviderLoader;
import com.dfsek.terra.addons.biome.pipeline.config.NoiseSourceTemplate;
import com.dfsek.terra.addons.biome.pipeline.config.SourceBuilderLoader;
import com.dfsek.terra.addons.biome.pipeline.config.stage.StageBuilderLoader;
import com.dfsek.terra.addons.biome.pipeline.config.SourceLoader;
import com.dfsek.terra.addons.biome.pipeline.config.stage.StageLoader;
import com.dfsek.terra.addons.biome.pipeline.config.stage.expander.ExpanderStageTemplate;
import com.dfsek.terra.addons.biome.pipeline.config.stage.mutator.BorderListMutatorTemplate;
import com.dfsek.terra.addons.biome.pipeline.config.stage.mutator.BorderMutatorTemplate;
import com.dfsek.terra.addons.biome.pipeline.config.stage.mutator.ReplaceListMutatorTemplate;
import com.dfsek.terra.addons.biome.pipeline.config.stage.mutator.ReplaceMutatorTemplate;
import com.dfsek.terra.addons.biome.pipeline.config.stage.mutator.SmoothMutatorTemplate;
import com.dfsek.terra.addons.biome.pipeline.mutator.BorderListMutator;
import com.dfsek.terra.addons.biome.pipeline.mutator.BorderMutator;
import com.dfsek.terra.addons.biome.pipeline.mutator.ReplaceListMutator;
import com.dfsek.terra.addons.biome.pipeline.mutator.ReplaceMutator;
import com.dfsek.terra.addons.biome.pipeline.mutator.SmoothMutator;
import com.dfsek.terra.addons.biome.pipeline.source.NoiseSource;
import com.dfsek.terra.addons.biome.pipeline.stages.ExpanderStage;
import com.dfsek.terra.addons.biome.pipeline.stages.MutatorStage;
import com.dfsek.terra.api.TerraPlugin;
@@ -21,10 +28,9 @@ import com.dfsek.terra.api.addon.annotations.Version;
import com.dfsek.terra.api.event.EventListener;
import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent;
import com.dfsek.terra.api.injection.annotations.Inject;
import com.dfsek.terra.api.util.seeded.BiomeProviderBuilder;
import com.dfsek.terra.api.util.seeded.SourceSeeded;
import java.lang.reflect.Type;
import com.dfsek.terra.api.util.reflection.TypeKey;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import com.dfsek.terra.api.world.biome.generation.pipeline.BiomeSource;
@Addon("biome-provider-pipeline")
@Author("Terra")
@@ -33,24 +39,27 @@ public class BiomePipelineAddon extends TerraAddon implements EventListener {
@Inject
private TerraPlugin main;
public static final TypeKey<BiomeProvider> BIOME_PROVIDER_BUILDER_TOKEN = new TypeKey<>(){};
public static final TypeKey<BiomeSource> BIOME_SOURCE_BUILDER_TOKEN = new TypeKey<>(){};
@Override
public void initialize() {
main.getEventManager().registerListener(this, this);
}
public void onPackLoad(ConfigPackPreLoadEvent event) {
event.getPack().applyLoader(SourceSeeded.class, new SourceBuilderLoader())
.applyLoader(StageSeeded.class, new StageBuilderLoader())
event.getPack().applyLoader(BIOME_SOURCE_BUILDER_TOKEN.getType(), new SourceLoader())
.applyLoader(Stage.class, new StageLoader())
.applyLoader(ExpanderStage.Type.class, (c, o, l) -> ExpanderStage.Type.valueOf((String) o))
.applyLoader(MutatorStage.Type.class, (c, o, l) -> MutatorStage.Type.valueOf((String) o))
.applyLoader(NoiseSourceTemplate.class, NoiseSourceTemplate::new)
.applyLoader(ReplaceMutatorTemplate.class, ReplaceMutatorTemplate::new)
.applyLoader(BorderMutatorTemplate.class, BorderMutatorTemplate::new)
.applyLoader(BorderListMutatorTemplate.class, BorderListMutatorTemplate::new)
.applyLoader(ReplaceListMutatorTemplate.class, ReplaceListMutatorTemplate::new)
.applyLoader(SmoothMutatorTemplate.class, SmoothMutatorTemplate::new)
.applyLoader(ExpanderStageTemplate.class, ExpanderStageTemplate::new)
.applyLoader((Type) BiomePipelineTemplate.class, () -> new BiomePipelineTemplate(main))
.applyLoader(BiomeProviderBuilder.class, new BiomeProviderBuilderLoader());
.applyLoader(NoiseSource.class, NoiseSourceTemplate::new)
.applyLoader(ReplaceMutator.class, ReplaceMutatorTemplate::new)
.applyLoader(BorderMutator.class, BorderMutatorTemplate::new)
.applyLoader(BorderListMutator.class, BorderListMutatorTemplate::new)
.applyLoader(ReplaceListMutator.class, ReplaceListMutatorTemplate::new)
.applyLoader(SmoothMutator.class, SmoothMutatorTemplate::new)
.applyLoader(ExpanderStage.class, ExpanderStageTemplate::new)
.applyLoader(BiomePipelineProvider.class, () -> new BiomePipelineTemplate(main))
.applyLoader(BIOME_PROVIDER_BUILDER_TOKEN.getType(), new BiomeProviderLoader());
}
}

View File

@@ -0,0 +1,81 @@
package com.dfsek.terra.addons.biome.pipeline;
import com.dfsek.terra.addons.biome.pipeline.api.BiomeHolder;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.noise.NoiseSampler;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import net.jafama.FastMath;
import org.jetbrains.annotations.NotNull;
public class BiomePipelineProvider implements BiomeProvider {
private final LoadingCache<SeededVector, BiomeHolder> holderCache;
private final BiomePipeline pipeline;
private final int resolution;
private final NoiseSampler mutator;
private final double noiseAmp;
public BiomePipelineProvider(BiomePipeline pipeline, TerraPlugin main, int resolution, NoiseSampler mutator, double noiseAmp) {
this.resolution = resolution;
this.mutator = mutator;
this.noiseAmp = noiseAmp;
holderCache = CacheBuilder.newBuilder()
.maximumSize(main == null ? 32 : main.getTerraConfig().getProviderCache())
.build(
new CacheLoader<SeededVector, BiomeHolder>() {
@Override
public BiomeHolder load(@NotNull SeededVector key) {
return pipeline.getBiomes(key.x, key.z, key.seed);
}
}
);
this.pipeline = pipeline;
}
@Override
public TerraBiome getBiome(int x, int z, long seed) {
x += mutator.getNoiseSeeded(seed + 1, x, z) * noiseAmp;
z += mutator.getNoiseSeeded(seed + 2, x, z) * noiseAmp;
x = FastMath.floorToInt(FastMath.floorDiv(x, resolution));
z = FastMath.floorToInt(FastMath.floorDiv(z, resolution));
int fdX = FastMath.floorDiv(x, pipeline.getSize());
int fdZ = FastMath.floorDiv(z, pipeline.getSize());
return holderCache.getUnchecked(new SeededVector(fdX, fdZ, seed)).getBiome(x - fdX * pipeline.getSize(), z - fdZ * pipeline.getSize());
}
private static final class SeededVector {
private final int x;
private final int z;
private final long seed;
private SeededVector(int x, int z, long seed) {
this.x = x;
this.z = z;
this.seed = seed;
}
@Override
public int hashCode() {
int result = 0;
result = 31 * result + ((int) (seed ^ (seed >>> 32)));
result = 31 * result + x;
result = 31 * result + z;
return result;
}
@Override
public boolean equals(Object obj) {
if(!(obj instanceof SeededVector)) return false;
SeededVector that = (SeededVector) obj;
return this.seed == that.seed && this.x == that.x && this.z == that.z;
}
}
}

View File

@@ -1,8 +0,0 @@
package com.dfsek.terra.addons.biome.pipeline;
import com.dfsek.terra.addons.biome.pipeline.api.Stage;
import com.dfsek.terra.api.util.seeded.SeededBuilder;
@FunctionalInterface
public interface StageSeeded extends SeededBuilder<Stage> {
}

View File

@@ -1,55 +0,0 @@
package com.dfsek.terra.addons.biome.pipeline;
import com.dfsek.terra.addons.biome.pipeline.api.BiomeHolder;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.noise.NoiseSampler;
import com.dfsek.terra.api.vector.Vector2;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import net.jafama.FastMath;
import org.jetbrains.annotations.NotNull;
public class StandardBiomeProvider implements BiomeProvider {
private final LoadingCache<Vector2, BiomeHolder> holderCache;
private final BiomePipelineImpl pipeline;
private final int resolution;
private final NoiseSampler mutator;
private final double noiseAmp;
private final int seed;
public StandardBiomeProvider(BiomePipelineImpl pipeline, TerraPlugin main, int resolution, NoiseSampler mutator, double noiseAmp, int seed) {
this.resolution = resolution;
this.mutator = mutator;
this.noiseAmp = noiseAmp;
this.seed = seed;
holderCache = CacheBuilder.newBuilder()
.maximumSize(main == null ? 32 : main.getTerraConfig().getProviderCache())
.build(
new CacheLoader<Vector2, BiomeHolder>() {
@Override
public BiomeHolder load(@NotNull Vector2 key) {
return pipeline.getBiomes(key.getBlockX(), key.getBlockZ());
}
}
);
this.pipeline = pipeline;
}
@Override
public TerraBiome getBiome(int x, int z) {
x += mutator.getNoiseSeeded(seed, x, z) * noiseAmp;
z += mutator.getNoiseSeeded(1 + seed, x, z) * noiseAmp;
x = FastMath.floorToInt(FastMath.floorDiv(x, resolution));
z = FastMath.floorToInt(FastMath.floorDiv(z, resolution));
int fdX = FastMath.floorDiv(x, pipeline.getSize());
int fdZ = FastMath.floorDiv(z, pipeline.getSize());
return holderCache.getUnchecked(new Vector2(fdX, fdZ)).getBiome(x - fdX * pipeline.getSize(), z - fdZ * pipeline.getSize());
}
}

View File

@@ -3,5 +3,5 @@ package com.dfsek.terra.addons.biome.pipeline.api;
import com.dfsek.terra.api.world.biome.TerraBiome;
public interface BiomeExpander {
TerraBiome getBetween(double x, double z, TerraBiome... others);
TerraBiome getBetween(double x, double z, long seed, TerraBiome... others);
}

View File

@@ -4,11 +4,11 @@ import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.generation.pipeline.BiomeSource;
public interface BiomeHolder {
BiomeHolder expand(BiomeExpander expander);
BiomeHolder expand(BiomeExpander expander, long seed);
void mutate(BiomeMutator mutator);
void mutate(BiomeMutator mutator, long seed);
void fill(BiomeSource source);
void fill(BiomeSource source, long seed);
TerraBiome getBiome(int x, int z);

View File

@@ -3,7 +3,7 @@ package com.dfsek.terra.addons.biome.pipeline.api;
import com.dfsek.terra.api.world.biome.TerraBiome;
public interface BiomeMutator {
TerraBiome mutate(ViewPoint viewPoint, double x, double z);
TerraBiome mutate(ViewPoint viewPoint, double x, double z, long seed);
class ViewPoint {
private final BiomeHolder biomes;

View File

@@ -3,6 +3,6 @@ package com.dfsek.terra.addons.biome.pipeline.api;
public interface Stage {
boolean isExpansion();
BiomeHolder apply(BiomeHolder in);
BiomeHolder apply(BiomeHolder in, long seed);
}

View File

@@ -2,12 +2,12 @@ package com.dfsek.terra.addons.biome.pipeline.config;
import com.dfsek.tectonic.annotations.Default;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.addons.biome.pipeline.BiomePipelineImpl;
import com.dfsek.terra.addons.biome.pipeline.StageSeeded;
import com.dfsek.terra.addons.biome.pipeline.StandardBiomeProvider;
import com.dfsek.terra.addons.biome.pipeline.BiomePipeline;
import com.dfsek.terra.addons.biome.pipeline.BiomePipelineProvider;
import com.dfsek.terra.addons.biome.pipeline.api.Stage;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.util.seeded.SourceSeeded;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import com.dfsek.terra.api.world.biome.generation.pipeline.BiomeSource;
import java.util.List;
@@ -19,20 +19,20 @@ public class BiomePipelineTemplate extends BiomeProviderTemplate {
private int initialSize = 2;
@Value("pipeline.stages")
private List<StageSeeded> stages;
private List<Stage> stages;
@Value("pipeline.source")
private SourceSeeded source;
private BiomeSource source;
public BiomePipelineTemplate(TerraPlugin main) {
this.main = main;
}
@Override
public BiomeProvider build(long seed) {
BiomePipelineImpl.BiomePipelineBuilder biomePipelineBuilder = new BiomePipelineImpl.BiomePipelineBuilder(initialSize);
public BiomeProvider get() {
BiomePipeline.BiomePipelineBuilder biomePipelineBuilder = new BiomePipeline.BiomePipelineBuilder(initialSize);
stages.forEach(biomePipelineBuilder::addStage);
BiomePipelineImpl pipeline = biomePipelineBuilder.build(source.apply(seed), seed);
return new StandardBiomeProvider(pipeline, main, resolution, blend.apply(seed), blendAmp, (int) seed);
BiomePipeline pipeline = biomePipelineBuilder.build(source);
return new BiomePipelineProvider(pipeline, main, resolution, blend, blendAmp);
}
}

View File

@@ -1,16 +0,0 @@
package com.dfsek.terra.addons.biome.pipeline.config;
import com.dfsek.tectonic.exception.LoadException;
import com.dfsek.tectonic.loading.ConfigLoader;
import com.dfsek.tectonic.loading.TypeLoader;
import com.dfsek.terra.api.util.seeded.BiomeProviderBuilder;
import java.lang.reflect.AnnotatedType;
import java.lang.reflect.Type;
public class BiomeProviderBuilderLoader implements TypeLoader<BiomeProviderBuilder> {
@Override
public BiomeProviderBuilder load(AnnotatedType t, Object c, ConfigLoader loader) throws LoadException {
return loader.loadType(BiomePipelineTemplate.class, c); // TODO: actually implement this lol
}
}

View File

@@ -0,0 +1,16 @@
package com.dfsek.terra.addons.biome.pipeline.config;
import com.dfsek.tectonic.exception.LoadException;
import com.dfsek.tectonic.loading.ConfigLoader;
import com.dfsek.tectonic.loading.TypeLoader;
import com.dfsek.terra.addons.biome.pipeline.BiomePipelineProvider;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import java.lang.reflect.AnnotatedType;
public class BiomeProviderLoader implements TypeLoader<BiomeProvider> {
@Override
public BiomeProvider load(AnnotatedType t, Object c, ConfigLoader loader) throws LoadException {
return loader.loadType(BiomePipelineProvider.class, c); // TODO: actually implement this lol
}
}

View File

@@ -3,22 +3,17 @@ package com.dfsek.terra.addons.biome.pipeline.config;
import com.dfsek.tectonic.annotations.Default;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.tectonic.loading.object.ObjectTemplate;
import com.dfsek.terra.api.util.seeded.BiomeProviderBuilder;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.api.noise.NoiseSampler;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
public abstract class BiomeProviderTemplate implements ObjectTemplate<BiomeProviderBuilder>, BiomeProviderBuilder {
public abstract class BiomeProviderTemplate implements ObjectTemplate<BiomeProvider> {
@Value("resolution")
@Default
protected int resolution = 1;
@Value("blend.noise")
@Default
protected NoiseSeeded blend = NoiseSeeded.zero(2);
protected NoiseSampler blend = NoiseSampler.zero();
@Value("blend.amplitude")
@Default
protected double blendAmp = 0d;
@Override
public BiomeProviderBuilder get() {
return this;
}
}

View File

@@ -1,21 +1,21 @@
package com.dfsek.terra.addons.biome.pipeline.config;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.addons.biome.pipeline.source.RandomSource;
import com.dfsek.terra.addons.biome.pipeline.source.NoiseSource;
import com.dfsek.terra.api.noise.NoiseSampler;
import com.dfsek.terra.api.util.collection.ProbabilityCollection;
import com.dfsek.terra.api.util.seeded.BiomeBuilder;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.generation.pipeline.BiomeSource;
public class NoiseSourceTemplate extends SourceTemplate {
@Value("noise")
private NoiseSeeded noise;
private NoiseSampler noise;
@Value("biomes")
private ProbabilityCollection<BiomeBuilder> biomes;
private ProbabilityCollection<TerraBiome> biomes;
@Override
public BiomeSource apply(Long seed) {
return new RandomSource(biomes.map((biome) -> biome.apply(seed), false), noise.apply(seed));
public BiomeSource get() {
return new NoiseSource(biomes, noise);
}
}

View File

@@ -3,23 +3,22 @@ package com.dfsek.terra.addons.biome.pipeline.config;
import com.dfsek.tectonic.exception.LoadException;
import com.dfsek.tectonic.loading.ConfigLoader;
import com.dfsek.tectonic.loading.TypeLoader;
import com.dfsek.terra.api.util.seeded.SourceSeeded;
import com.dfsek.terra.addons.biome.pipeline.source.NoiseSource;
import com.dfsek.terra.api.world.biome.generation.pipeline.BiomeSource;
import java.lang.reflect.AnnotatedType;
import java.lang.reflect.Type;
import java.util.Map;
@SuppressWarnings("unchecked")
public class SourceBuilderLoader implements TypeLoader<SourceSeeded> {
public class SourceLoader implements TypeLoader<BiomeSource> {
@Override
public SourceSeeded load(AnnotatedType t, Object c, ConfigLoader loader) throws LoadException {
public BiomeSource load(AnnotatedType t, Object c, ConfigLoader loader) throws LoadException {
Map<String, Object> source = (Map<String, Object>) c;
BiomeSource.Type type = loader.loadType(BiomeSource.Type.class, source.get("type"));
if(type == BiomeSource.Type.NOISE) {
return loader.loadType(NoiseSourceTemplate.class, source);
return loader.loadType(NoiseSource.class, source);
}
throw new LoadException("No such loader type: " + type);
}

View File

@@ -1,11 +1,8 @@
package com.dfsek.terra.addons.biome.pipeline.config;
import com.dfsek.tectonic.loading.object.ObjectTemplate;
import com.dfsek.terra.api.util.seeded.SourceSeeded;
import com.dfsek.terra.api.world.biome.generation.pipeline.BiomeSource;
public abstract class SourceTemplate implements ObjectTemplate<BiomeSource>{
public abstract class SourceTemplate implements ObjectTemplate<SourceSeeded>, SourceSeeded {
@Override
public SourceSeeded get() {
return this;
}
}

View File

@@ -3,24 +3,28 @@ package com.dfsek.terra.addons.biome.pipeline.config.stage;
import com.dfsek.tectonic.exception.LoadException;
import com.dfsek.tectonic.loading.ConfigLoader;
import com.dfsek.tectonic.loading.TypeLoader;
import com.dfsek.terra.addons.biome.pipeline.StageSeeded;
import com.dfsek.terra.addons.biome.pipeline.api.Stage;
import com.dfsek.terra.addons.biome.pipeline.config.stage.expander.ExpanderStageTemplate;
import com.dfsek.terra.addons.biome.pipeline.config.stage.mutator.BorderListMutatorTemplate;
import com.dfsek.terra.addons.biome.pipeline.config.stage.mutator.BorderMutatorTemplate;
import com.dfsek.terra.addons.biome.pipeline.config.stage.mutator.ReplaceListMutatorTemplate;
import com.dfsek.terra.addons.biome.pipeline.config.stage.mutator.ReplaceMutatorTemplate;
import com.dfsek.terra.addons.biome.pipeline.config.stage.mutator.SmoothMutatorTemplate;
import com.dfsek.terra.addons.biome.pipeline.mutator.BorderListMutator;
import com.dfsek.terra.addons.biome.pipeline.mutator.BorderMutator;
import com.dfsek.terra.addons.biome.pipeline.mutator.ReplaceListMutator;
import com.dfsek.terra.addons.biome.pipeline.mutator.ReplaceMutator;
import com.dfsek.terra.addons.biome.pipeline.mutator.SmoothMutator;
import com.dfsek.terra.addons.biome.pipeline.stages.ExpanderStage;
import com.dfsek.terra.addons.biome.pipeline.stages.MutatorStage;
import java.lang.reflect.AnnotatedType;
import java.lang.reflect.Type;
import java.util.Map;
@SuppressWarnings("unchecked")
public class StageBuilderLoader implements TypeLoader<StageSeeded> {
public class StageLoader implements TypeLoader<Stage> {
@Override
public StageSeeded load(AnnotatedType t, Object c, ConfigLoader loader) throws LoadException {
public Stage load(AnnotatedType t, Object c, ConfigLoader loader) throws LoadException {
Map<String, Object> raw = (Map<String, Object>) c;
if(raw.size() != 1) throw new LoadException("Illegal stage map size: " + raw.size());
@@ -36,20 +40,20 @@ public class StageBuilderLoader implements TypeLoader<StageSeeded> {
if(entry.getKey().equals("expand")) {
ExpanderStage.Type stageType = loader.loadType(ExpanderStage.Type.class, mutator.get("type"));
if(stageType.equals(ExpanderStage.Type.FRACTAL)) {
return loader.loadType(ExpanderStageTemplate.class, mutator);
return loader.loadType(ExpanderStage.class, mutator);
} else throw new LoadException("No such expander \"" + stageType + "\"");
} else if(entry.getKey().equals("mutate")) {
switch(loader.loadType(MutatorStage.Type.class, mutator.get("type"))) {
case SMOOTH:
return loader.loadType(SmoothMutatorTemplate.class, mutator);
return new MutatorStage(loader.loadType(SmoothMutator.class, mutator));
case REPLACE:
return loader.loadType(ReplaceMutatorTemplate.class, mutator);
return new MutatorStage(loader.loadType(ReplaceMutator.class, mutator));
case REPLACE_LIST:
return loader.loadType(ReplaceListMutatorTemplate.class, mutator);
return new MutatorStage(loader.loadType(ReplaceListMutator.class, mutator));
case BORDER:
return loader.loadType(BorderMutatorTemplate.class, mutator);
return new MutatorStage(loader.loadType(BorderMutator.class, mutator));
case BORDER_LIST:
return loader.loadType(BorderListMutatorTemplate.class, mutator);
return new MutatorStage(loader.loadType(BorderListMutator.class, mutator));
default:
throw new LoadException("No such mutator type \"" + mutator.get("type"));
}

View File

@@ -2,17 +2,10 @@ package com.dfsek.terra.addons.biome.pipeline.config.stage;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.tectonic.loading.object.ObjectTemplate;
import com.dfsek.terra.addons.biome.pipeline.StageSeeded;
import com.dfsek.terra.addons.biome.pipeline.api.Stage;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.api.util.seeded.SeededBuilder;
import com.dfsek.terra.api.noise.NoiseSampler;
public abstract class StageTemplate implements ObjectTemplate<SeededBuilder<Stage>>, StageSeeded {
public abstract class StageTemplate implements ObjectTemplate<Stage> {
@Value("noise")
protected NoiseSeeded noise;
@Override
public StageSeeded get() {
return this;
}
protected NoiseSampler noise;
}

View File

@@ -7,7 +7,7 @@ import com.dfsek.terra.addons.biome.pipeline.stages.ExpanderStage;
public class ExpanderStageTemplate extends StageTemplate {
@Override
public Stage apply(Long seed) {
return new ExpanderStage(new FractalExpander(noise.apply(seed)));
public Stage get() {
return new ExpanderStage(new FractalExpander(noise));
}
}

View File

@@ -4,10 +4,8 @@ import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.addons.biome.pipeline.api.BiomeMutator;
import com.dfsek.terra.addons.biome.pipeline.mutator.BorderListMutator;
import com.dfsek.terra.api.util.collection.ProbabilityCollection;
import com.dfsek.terra.api.util.seeded.BiomeBuilder;
import com.dfsek.terra.api.world.biome.TerraBiome;
import java.util.HashMap;
import java.util.Map;
@SuppressWarnings("unused")
@@ -19,18 +17,14 @@ public class BorderListMutatorTemplate extends MutatorStageTemplate {
private String defaultReplace;
@Value("default-to")
private ProbabilityCollection<BiomeBuilder> defaultTo;
private ProbabilityCollection<TerraBiome> defaultTo;
@Value("replace")
private Map<BiomeBuilder, ProbabilityCollection<BiomeBuilder>> replace;
private Map<TerraBiome, ProbabilityCollection<TerraBiome>> replace;
@Override
public BiomeMutator build(long seed) {
Map<TerraBiome, ProbabilityCollection<TerraBiome>> replaceMap = new HashMap<>();
replace.forEach((keyBuilder, replacements) -> replaceMap.put(keyBuilder.apply(seed), replacements.map(replacement -> replacement.apply(seed), true)));
return new BorderListMutator(replaceMap, from, defaultReplace, noise.apply(seed), defaultTo.map(biomeBuilder -> biomeBuilder.apply(seed), true));
public BiomeMutator get() {
return new BorderListMutator(replace, from, defaultReplace, noise, defaultTo);
}
}

View File

@@ -4,7 +4,7 @@ import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.addons.biome.pipeline.api.BiomeMutator;
import com.dfsek.terra.addons.biome.pipeline.mutator.BorderMutator;
import com.dfsek.terra.api.util.collection.ProbabilityCollection;
import com.dfsek.terra.api.util.seeded.BiomeBuilder;
import com.dfsek.terra.api.world.biome.TerraBiome;
@SuppressWarnings("unused")
public class BorderMutatorTemplate extends MutatorStageTemplate {
@@ -15,10 +15,10 @@ public class BorderMutatorTemplate extends MutatorStageTemplate {
private String replace;
@Value("to")
private ProbabilityCollection<BiomeBuilder> to;
private ProbabilityCollection<TerraBiome> to;
@Override
public BiomeMutator build(long seed) {
return new BorderMutator(from, replace, noise.apply(seed), to.map(biomeBuilder -> biomeBuilder.apply(seed), true));
public BiomeMutator get() {
return new BorderMutator(from, replace, noise, to);
}
}

View File

@@ -1,15 +1,15 @@
package com.dfsek.terra.addons.biome.pipeline.config.stage.mutator;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.tectonic.loading.object.ObjectTemplate;
import com.dfsek.terra.addons.biome.pipeline.api.BiomeMutator;
import com.dfsek.terra.addons.biome.pipeline.api.Stage;
import com.dfsek.terra.addons.biome.pipeline.config.stage.StageTemplate;
import com.dfsek.terra.addons.biome.pipeline.stages.MutatorStage;
import com.dfsek.terra.api.noise.NoiseSampler;
public abstract class MutatorStageTemplate extends StageTemplate {
public abstract BiomeMutator build(long seed);
public abstract class MutatorStageTemplate implements ObjectTemplate<BiomeMutator> {
@Value("noise")
protected NoiseSampler noise;
@Override
public Stage apply(Long seed) {
return new MutatorStage(build(seed));
}
public abstract BiomeMutator get();
}

View File

@@ -4,10 +4,8 @@ import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.addons.biome.pipeline.api.BiomeMutator;
import com.dfsek.terra.addons.biome.pipeline.mutator.ReplaceListMutator;
import com.dfsek.terra.api.util.collection.ProbabilityCollection;
import com.dfsek.terra.api.util.seeded.BiomeBuilder;
import com.dfsek.terra.api.world.biome.TerraBiome;
import java.util.HashMap;
import java.util.Map;
@SuppressWarnings("unused")
@@ -16,17 +14,13 @@ public class ReplaceListMutatorTemplate extends MutatorStageTemplate {
private String defaultFrom;
@Value("default-to")
private ProbabilityCollection<BiomeBuilder> defaultTo;
private ProbabilityCollection<TerraBiome> defaultTo;
@Value("to")
private Map<BiomeBuilder, ProbabilityCollection<BiomeBuilder>> replace;
private Map<TerraBiome, ProbabilityCollection<TerraBiome>> replace;
@Override
public BiomeMutator build(long seed) {
Map<TerraBiome, ProbabilityCollection<TerraBiome>> replaceMap = new HashMap<>();
replace.forEach((biomeBuilder, biomeBuilders) -> replaceMap.put(biomeBuilder.apply(seed), biomeBuilders.map(builder -> builder.apply(seed), true)));
return new ReplaceListMutator(replaceMap, defaultFrom, defaultTo.map(biomeBuilder -> biomeBuilder.apply(seed), true), noise.apply(seed));
public BiomeMutator get() {
return new ReplaceListMutator(replace, defaultFrom, defaultTo, noise);
}
}

View File

@@ -4,7 +4,7 @@ import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.addons.biome.pipeline.api.BiomeMutator;
import com.dfsek.terra.addons.biome.pipeline.mutator.ReplaceMutator;
import com.dfsek.terra.api.util.collection.ProbabilityCollection;
import com.dfsek.terra.api.util.seeded.BiomeBuilder;
import com.dfsek.terra.api.world.biome.TerraBiome;
@SuppressWarnings("unused")
public class ReplaceMutatorTemplate extends MutatorStageTemplate {
@@ -12,10 +12,10 @@ public class ReplaceMutatorTemplate extends MutatorStageTemplate {
private String from;
@Value("to")
private ProbabilityCollection<BiomeBuilder> to;
private ProbabilityCollection<TerraBiome> to;
@Override
public BiomeMutator build(long seed) {
return new ReplaceMutator(from, to.map(biomeBuilder -> biomeBuilder.apply(seed), true), noise.apply(seed));
public BiomeMutator get() {
return new ReplaceMutator(from, to, noise);
}
}

View File

@@ -5,7 +5,7 @@ import com.dfsek.terra.addons.biome.pipeline.mutator.SmoothMutator;
public class SmoothMutatorTemplate extends MutatorStageTemplate {
@Override
public BiomeMutator build(long seed) {
return new SmoothMutator(noise.apply(seed));
public BiomeMutator get() {
return new SmoothMutator(noise);
}
}

View File

@@ -13,7 +13,7 @@ public class FractalExpander implements BiomeExpander {
}
@Override
public TerraBiome getBetween(double x, double z, TerraBiome... others) {
return others[MathUtil.normalizeIndex(sampler.getNoise(x, z), others.length)];
public TerraBiome getBetween(double x, double z, long seed, TerraBiome... others) {
return others[MathUtil.normalizeIndex(sampler.getNoiseSeeded(seed, x, z), others.length)];
}
}

View File

@@ -23,7 +23,7 @@ public class BorderListMutator implements BiomeMutator {
}
@Override
public TerraBiome mutate(ViewPoint viewPoint, double x, double z) {
public TerraBiome mutate(ViewPoint viewPoint, double x, double z, long seed) {
TerraBiome origin = viewPoint.getBiome(0, 0);
if(origin.getTags().contains(defaultReplace)) {
for(int xi = -1; xi <= 1; xi++) {
@@ -33,10 +33,10 @@ public class BorderListMutator implements BiomeMutator {
if(current == null) continue;
if(current.getTags().contains(border)) {
if(replace.containsKey(origin)) {
TerraBiome biome = replace.get(origin).get(noiseSampler, x, z);
TerraBiome biome = replace.get(origin).get(noiseSampler, x, z, seed);
return biome == null ? origin : biome;
}
TerraBiome biome = replaceDefault.get(noiseSampler, x, z);
TerraBiome biome = replaceDefault.get(noiseSampler, x, z, seed);
return biome == null ? origin : biome;
}
}

View File

@@ -19,7 +19,7 @@ public class BorderMutator implements BiomeMutator {
}
@Override
public TerraBiome mutate(ViewPoint viewPoint, double x, double z) {
public TerraBiome mutate(ViewPoint viewPoint, double x, double z, long seed) {
TerraBiome origin = viewPoint.getBiome(0, 0);
if(origin.getTags().contains(replaceTag)) {
for(int xi = -1; xi <= 1; xi++) {
@@ -28,7 +28,7 @@ public class BorderMutator implements BiomeMutator {
TerraBiome current = viewPoint.getBiome(xi, zi);
if(current == null) continue;
if(current.getTags().contains(border)) {
TerraBiome biome = replace.get(noiseSampler, x, z);
TerraBiome biome = replace.get(noiseSampler, x, z, seed);
return biome == null ? origin : biome;
}
}

View File

@@ -21,14 +21,14 @@ public class ReplaceListMutator implements BiomeMutator {
}
@Override
public TerraBiome mutate(ViewPoint viewPoint, double x, double z) {
public TerraBiome mutate(ViewPoint viewPoint, double x, double z, long seed) {
TerraBiome center = viewPoint.getBiome(0, 0);
if(replace.containsKey(center)) {
TerraBiome biome = replace.get(center).get(sampler, x, z);
TerraBiome biome = replace.get(center).get(sampler, x, z, seed);
return biome == null ? viewPoint.getBiome(0, 0) : biome;
}
if(viewPoint.getBiome(0, 0).getTags().contains(defaultTag)) {
TerraBiome biome = replaceDefault.get(sampler, x, z);
TerraBiome biome = replaceDefault.get(sampler, x, z, seed);
return biome == null ? viewPoint.getBiome(0, 0) : biome;
}
return center;

View File

@@ -17,9 +17,9 @@ public class ReplaceMutator implements BiomeMutator {
}
@Override
public TerraBiome mutate(ViewPoint viewPoint, double x, double z) {
public TerraBiome mutate(ViewPoint viewPoint, double x, double z, long seed) {
if(viewPoint.getBiome(0, 0).getTags().contains(replaceableTag)) {
TerraBiome biome = replace.get(sampler, x, z);
TerraBiome biome = replace.get(sampler, x, z, seed);
return biome == null ? viewPoint.getBiome(0, 0) : biome;
}
return viewPoint.getBiome(0, 0);

View File

@@ -16,7 +16,7 @@ public class SmoothMutator implements BiomeMutator {
}
@Override
public TerraBiome mutate(ViewPoint viewPoint, double x, double z) {
public TerraBiome mutate(ViewPoint viewPoint, double x, double z, long seed) {
TerraBiome top = viewPoint.getBiome(1, 0);
TerraBiome bottom = viewPoint.getBiome(-1, 0);
TerraBiome left = viewPoint.getBiome(0, 1);
@@ -27,7 +27,7 @@ public class SmoothMutator implements BiomeMutator {
boolean horiz = Objects.equals(left, right) && left != null;
if(vert && horiz) {
return MathUtil.normalizeIndex(sampler.getNoise(x, z), 2) == 0 ? left : top;
return MathUtil.normalizeIndex(sampler.getNoiseSeeded(seed, x, z), 2) == 0 ? left : top;
}
if(vert) return top;

View File

@@ -5,17 +5,17 @@ import com.dfsek.terra.api.util.collection.ProbabilityCollection;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.generation.pipeline.BiomeSource;
public class RandomSource implements BiomeSource {
public class NoiseSource implements BiomeSource {
private final ProbabilityCollection<TerraBiome> biomes;
private final NoiseSampler sampler;
public RandomSource(ProbabilityCollection<TerraBiome> biomes, NoiseSampler sampler) {
public NoiseSource(ProbabilityCollection<TerraBiome> biomes, NoiseSampler sampler) {
this.biomes = biomes;
this.sampler = sampler;
}
@Override
public TerraBiome getBiome(double x, double z) {
return biomes.get(sampler, x, z);
public TerraBiome getBiome(double x, double z, long seed) {
return biomes.get(sampler, x, z, seed);
}
}

View File

@@ -17,8 +17,8 @@ public class ExpanderStage implements Stage {
}
@Override
public BiomeHolder apply(BiomeHolder in) {
return in.expand(expander);
public BiomeHolder apply(BiomeHolder in, long seed) {
return in.expand(expander, seed);
}
public enum Type {

View File

@@ -17,8 +17,8 @@ public class MutatorStage implements Stage {
}
@Override
public BiomeHolder apply(BiomeHolder in) {
in.mutate(mutator);
public BiomeHolder apply(BiomeHolder in, long seed) {
in.mutate(mutator, seed);
return in;
}

View File

@@ -1,10 +1,9 @@
package com.dfsek.terra.addons.biome.single;
import com.dfsek.terra.api.util.seeded.BiomeProviderBuilder;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
public class SingleBiomeProvider implements BiomeProvider, BiomeProviderBuilder {
public class SingleBiomeProvider implements BiomeProvider {
private final TerraBiome biome;
public SingleBiomeProvider(TerraBiome biome) {
@@ -12,12 +11,7 @@ public class SingleBiomeProvider implements BiomeProvider, BiomeProviderBuilder
}
@Override
public TerraBiome getBiome(int x, int z) {
public TerraBiome getBiome(int x, int z, long seed) {
return biome;
}
@Override
public BiomeProvider build(long seed) {
return this;
}
}

View File

@@ -2,21 +2,15 @@ package com.dfsek.terra.addons.biome.single;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.tectonic.loading.object.ObjectTemplate;
import com.dfsek.terra.api.util.seeded.BiomeBuilder;
import com.dfsek.terra.api.util.seeded.BiomeProviderBuilder;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
public class SingleBiomeProviderTemplate implements ObjectTemplate<BiomeProviderBuilder>, BiomeProviderBuilder {
public class SingleBiomeProviderTemplate implements ObjectTemplate<BiomeProvider> {
@Value("biome")
private BiomeBuilder biome;
private TerraBiome biome;
@Override
public BiomeProvider build(long seed) {
return new SingleBiomeProvider(biome.apply(seed));
}
@Override
public BiomeProviderBuilder get() {
return this;
public BiomeProvider get() {
return new SingleBiomeProvider(biome);
}
}

View File

@@ -15,7 +15,7 @@ import com.dfsek.terra.api.event.events.config.ConfigurationLoadEvent;
import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent;
import com.dfsek.terra.api.injection.annotations.Inject;
import com.dfsek.terra.api.registry.exception.DuplicateEntryException;
import com.dfsek.terra.api.util.seeded.BiomeBuilder;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.generator.ChunkGeneratorProvider;
@Addon("chunk-generator-noise-3d")
@@ -37,8 +37,8 @@ public class NoiseChunkGenerator3DAddon extends TerraAddon implements EventListe
}
public void onBiomeLoad(ConfigurationLoadEvent event) {
if(event.is(BiomeBuilder.class)) {
event.getLoadedObject(BiomeBuilder.class).getContext().put(event.load(new BiomePaletteTemplate()).get());
if(event.is(TerraBiome.class)) {
event.getLoadedObject(TerraBiome.class).getContext().put(event.load(new BiomePaletteTemplate()).get());
}
}
}

View File

@@ -47,14 +47,15 @@ public class NoiseChunkGenerator3D implements TerraChunkGenerator {
try(ProfileFrame ignore = main.getProfiler().profile("biomes")) {
int xOrig = (chunkX << 4);
int zOrig = (chunkZ << 4);
long seed = world.getSeed();
BiomeProvider grid = main.getWorld(world).getBiomeProvider();
for(int x = 0; x < 4; x++) {
for(int z = 0; z < 4; z++) {
int cx = xOrig + (x << 2);
int cz = zOrig + (z << 2);
TerraBiome b = grid.getBiome(cx, cz);
TerraBiome b = grid.getBiome(cx, cz, seed);
biome.setBiome(cx, cz, b.getVanillaBiomes().get(b.getGenerator(world).getBiomeNoise(), cx, 0, cz));
biome.setBiome(cx, cz, b.getVanillaBiomes().get(b.getGenerator(world).getBiomeNoise(), cx, 0, cz, world.getSeed()));
}
}
}
@@ -82,6 +83,8 @@ public class NoiseChunkGenerator3D implements TerraChunkGenerator {
Sampler sampler = tw.getConfig().getSamplerCache().getChunk(chunkX, chunkZ);
long seed = world.getSeed();
for(int x = 0; x < 16; x++) {
for(int z = 0; z < 16; z++) {
int paletteLevel = 0;
@@ -89,7 +92,7 @@ public class NoiseChunkGenerator3D implements TerraChunkGenerator {
int cx = xOrig + x;
int cz = zOrig + z;
TerraBiome biome = grid.getBiome(cx, cz);
TerraBiome biome = grid.getBiome(cx, cz, seed);
PaletteInfo paletteInfo = biome.getContext().get(PaletteInfo.class);
@@ -108,12 +111,12 @@ public class NoiseChunkGenerator3D implements TerraChunkGenerator {
if(sampler.sample(x, y, z) > 0) {
justSet = true;
data = PaletteUtil.getPalette(x, y, z, generator, sampler, paletteInfo).get(paletteLevel, cx, y, cz);
data = PaletteUtil.getPalette(x, y, z, generator, sampler, paletteInfo).get(paletteLevel, cx, y, cz, seed);
chunk.setBlock(x, y, z, data);
paletteLevel++;
} else if(y <= sea) {
chunk.setBlock(x, y, z, seaPalette.get(sea - y, x + xOrig, y, z + zOrig));
chunk.setBlock(x, y, z, seaPalette.get(sea - y, x + xOrig, y, z + zOrig, seed));
justSet = false;
paletteLevel = 0;
@@ -167,7 +170,7 @@ public class NoiseChunkGenerator3D implements TerraChunkGenerator {
public BlockState getBlock(World world, int x, int y, int z) {
TerraWorld terraWorld = main.getWorld(world);
BiomeProvider provider = terraWorld.getBiomeProvider();
TerraBiome biome = provider.getBiome(x, z);
TerraBiome biome = provider.getBiome(x, z, world.getSeed());
Sampler sampler = terraWorld.getConfig().getSamplerCache().get(x, z);
PaletteInfo paletteInfo = biome.getContext().get(PaletteInfo.class);
@@ -181,9 +184,9 @@ public class NoiseChunkGenerator3D implements TerraChunkGenerator {
if(sampler.sample(fdX, yi, fdZ) > 0) level++;
else level = 0;
}
return palette.get(level, x, y, z);
return palette.get(level, x, y, z, world.getSeed());
} else if(y <= paletteInfo.getSeaLevel()) {
return paletteInfo.getOcean().get(paletteInfo.getSeaLevel() - y, x, y, z);
return paletteInfo.getOcean().get(paletteInfo.getSeaLevel() - y, x, y, z, world.getSeed());
} else return air;
}
}

View File

@@ -32,11 +32,13 @@ public class ChunkInterpolator2D implements ChunkInterpolator {
int xOrigin = chunkX << 4;
int zOrigin = chunkZ << 4;
long seed = w.getSeed();
double[][] noiseStorage = new double[5][5];
for(int x = 0; x < 5; x++) {
for(int z = 0; z < 5; z++) {
Generator generator = provider.getBiome(xOrigin + (x << 2), zOrigin + (z << 2)).getGenerator(w);
Generator generator = provider.getBiome(xOrigin + (x << 2), zOrigin + (z << 2), seed).getGenerator(w);
Map<Generator, MutableInteger> genMap = new HashMap<>();
int step = generator.getBlendStep();
@@ -44,7 +46,7 @@ public class ChunkInterpolator2D implements ChunkInterpolator {
for(int xi = -blend; xi <= blend; xi++) {
for(int zi = -blend; zi <= blend; zi++) {
genMap.computeIfAbsent(provider.getBiome(xOrigin + (x << 2) + (xi * step), zOrigin + (z << 2) + (zi * step)).getGenerator(w), g -> new MutableInteger(0)).increment(); // Increment by 1
genMap.computeIfAbsent(provider.getBiome(xOrigin + (x << 2) + (xi * step), zOrigin + (z << 2) + (zi * step), seed).getGenerator(w), g -> new MutableInteger(0)).increment(); // Increment by 1
}
}

View File

@@ -45,9 +45,11 @@ public class ChunkInterpolator3D implements ChunkInterpolator {
double[][][] noiseStorage = new double[5][5][size + 1];
long seed = w.getSeed();
for(int x = 0; x < 5; x++) {
for(int z = 0; z < 5; z++) {
Generator generator = provider.getBiome(xOrigin + (x << 2), zOrigin + (z << 2)).getGenerator(w);
Generator generator = provider.getBiome(xOrigin + (x << 2), zOrigin + (z << 2), seed).getGenerator(w);
Map<Generator, MutableInteger> genMap = new HashMap<>();
int step = generator.getBlendStep();
@@ -55,7 +57,7 @@ public class ChunkInterpolator3D implements ChunkInterpolator {
for(int xi = -blend; xi <= blend; xi++) {
for(int zi = -blend; zi <= blend; zi++) {
genMap.computeIfAbsent(provider.getBiome(xOrigin + (x << 2) + (xi * step), zOrigin + (z << 2) + (zi * step)).getGenerator(w), g -> new MutableInteger(0)).increment(); // Increment by 1
genMap.computeIfAbsent(provider.getBiome(xOrigin + (x << 2) + (xi * step), zOrigin + (z << 2) + (zi * step), seed).getGenerator(w), g -> new MutableInteger(0)).increment(); // Increment by 1
}
}

View File

@@ -11,12 +11,14 @@ public class ElevationInterpolator {
int xOrigin = chunkX << 4;
int zOrigin = chunkZ << 4;
long seed = world.getSeed();
Generator[][] gens = new Generator[18 + 2 * smooth][18 + 2 * smooth];
// Precompute generators.
for(int x = -1 - smooth; x <= 16 + smooth; x++) {
for(int z = -1 - smooth; z <= 16 + smooth; z++) {
gens[x + 1 + smooth][z + 1 + smooth] = provider.getBiome(xOrigin + x, zOrigin + z).getGenerator(world);
gens[x + 1 + smooth][z + 1 + smooth] = provider.getBiome(xOrigin + x, zOrigin + z, seed).getGenerator(world);
}
}
@@ -27,7 +29,7 @@ public class ElevationInterpolator {
for(int xi = -smooth; xi <= smooth; xi++) {
for(int zi = -smooth; zi <= smooth; zi++) {
Generator gen = gens[x + 1 + smooth + xi][z + 1 + smooth + zi];
noise += gen.getElevationSampler().getNoise(xOrigin + x, zOrigin + z) * gen.getElevationWeight();
noise += gen.getElevationSampler().getNoiseSeeded(seed, xOrigin + x, zOrigin + z) * gen.getElevationWeight();
div += gen.getElevationWeight();
}
}

View File

@@ -12,7 +12,7 @@ public class Sampler3D implements Sampler {
private final ElevationInterpolator elevationInterpolator;
public Sampler3D(int x, int z, BiomeProvider provider, World world, int elevationSmooth) {
this.interpolator = new ChunkInterpolator3D(world, x, z, provider, (generator, coord) -> generator.getBaseSampler().getNoise(coord));
this.interpolator = new ChunkInterpolator3D(world, x, z, provider, (generator, coord) -> generator.getBaseSampler().getNoiseSeeded(coord, world.getSeed()));
this.elevationInterpolator = new ElevationInterpolator(world, x, z, provider, elevationSmooth);
}

View File

@@ -14,7 +14,7 @@ import com.dfsek.terra.api.injection.annotations.Inject;
@Addon("config-biome")
@Author("Terra")
@Version("1.0.0")
public class BiomeConfigAddon extends TerraAddon implements EventListener {
public class BiomeAddon extends TerraAddon implements EventListener {
@Inject
private TerraPlugin main;

View File

@@ -7,14 +7,17 @@ import com.dfsek.terra.api.config.ConfigFactory;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.config.ConfigType;
import com.dfsek.terra.api.registry.OpenRegistry;
import com.dfsek.terra.api.util.seeded.BiomeBuilder;
import com.dfsek.terra.api.util.reflection.TypeKey;
import com.dfsek.terra.api.world.biome.TerraBiome;
import java.util.function.Supplier;
public class BiomeConfigType implements ConfigType<BiomeTemplate, BiomeBuilder> {
public class BiomeConfigType implements ConfigType<BiomeTemplate, TerraBiome> {
private final ConfigPack pack;
private final BiomeFactory factory;
public static final TypeKey<TerraBiome> BIOME_TYPE_TOKEN = new TypeKey<>() {};
public BiomeConfigType(ConfigPack pack) {
this.pack = pack;
this.factory = new BiomeFactory(pack);
@@ -26,20 +29,20 @@ public class BiomeConfigType implements ConfigType<BiomeTemplate, BiomeBuilder>
}
@Override
public ConfigFactory<BiomeTemplate, BiomeBuilder> getFactory() {
public ConfigFactory<BiomeTemplate, TerraBiome> getFactory() {
return factory;
}
@Override
public Class<BiomeBuilder> getTypeClass() {
return BiomeBuilder.class;
public TypeKey<TerraBiome> getTypeClass() {
return BIOME_TYPE_TOKEN;
}
@Override
public Supplier<OpenRegistry<BiomeBuilder>> registrySupplier() {
return () -> pack.getRegistryFactory().create(registry -> (TypeLoader<BiomeBuilder>) (t, c, loader) -> {
public Supplier<OpenRegistry<TerraBiome>> registrySupplier() {
return () -> pack.getRegistryFactory().create(registry -> (TypeLoader<TerraBiome>) (t, c, loader) -> {
if(c.equals("SELF")) return null;
BiomeBuilder obj = registry.get((String) c);
TerraBiome obj = registry.get((String) c);
if(obj == null)
throw new LoadException("No such " + t.getType().getTypeName() + " matching \"" + c + "\" was found in this registry.");
return obj;

View File

@@ -3,9 +3,9 @@ package com.dfsek.terra.addons.biome;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.config.ConfigFactory;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.util.seeded.BiomeBuilder;
import com.dfsek.terra.api.world.biome.TerraBiome;
public class BiomeFactory implements ConfigFactory<BiomeTemplate, BiomeBuilder> {
public class BiomeFactory implements ConfigFactory<BiomeTemplate, TerraBiome> {
private final ConfigPack pack;
public BiomeFactory(ConfigPack pack) {
@@ -13,7 +13,9 @@ public class BiomeFactory implements ConfigFactory<BiomeTemplate, BiomeBuilder>
}
@Override
public BiomeBuilder build(BiomeTemplate template, TerraPlugin main) {
return new UserDefinedBiomeBuilder(template);
public TerraBiome build(BiomeTemplate template, TerraPlugin main) {
UserDefinedGenerator generator = new UserDefinedGenerator(template.getNoiseEquation(), template.getElevationEquation(), template.getCarvingEquation(), template.getBiomeNoise(), template.getElevationWeight(),
template.getBlendDistance(), template.getBlendStep(), template.getBlendWeight());
return new UserDefinedBiome(template.getVanilla(), generator, template);
}
}

View File

@@ -1,19 +1,16 @@
package com.dfsek.terra.addons.biome;
import com.dfsek.paralithic.eval.parser.Parser;
import com.dfsek.paralithic.eval.parser.Scope;
import com.dfsek.tectonic.annotations.Default;
import com.dfsek.tectonic.annotations.Final;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.tectonic.config.ValidatedConfigTemplate;
import com.dfsek.tectonic.exception.ValidationException;
import com.dfsek.terra.addons.biome.holder.PaletteHolder;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.block.BlockType;
import com.dfsek.terra.api.config.AbstractableTemplate;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.noise.NoiseSampler;
import com.dfsek.terra.api.util.collection.ProbabilityCollection;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.api.world.biome.Biome;
import com.dfsek.terra.api.world.generator.Palette;
@@ -43,14 +40,14 @@ public class BiomeTemplate implements AbstractableTemplate, ValidatedConfigTempl
@Value("beta.carving.equation")
@Default
private NoiseSeeded carvingEquation = NoiseSeeded.zero(3);
private NoiseSampler carvingEquation = NoiseSampler.zero();
@Value("vanilla")
private ProbabilityCollection<Biome> vanilla;
@Value("biome-noise")
@Default
private NoiseSeeded biomeNoise = NoiseSeeded.zero(2);
private NoiseSampler biomeNoise = NoiseSampler.zero();
@Value("blend.distance")
@Default
@@ -65,7 +62,7 @@ public class BiomeTemplate implements AbstractableTemplate, ValidatedConfigTempl
private int blendStep = 4;
@Value("noise")
private NoiseSeeded noiseEquation;
private NoiseSampler noiseEquation;
@Value("ocean.level")
@Default
@@ -73,7 +70,7 @@ public class BiomeTemplate implements AbstractableTemplate, ValidatedConfigTempl
@Value("elevation.equation")
@Default
private NoiseSeeded elevationEquation = NoiseSeeded.zero(2);
private NoiseSampler elevationEquation = NoiseSampler.zero();
@Value("elevation.weight")
@Default
@@ -160,15 +157,15 @@ public class BiomeTemplate implements AbstractableTemplate, ValidatedConfigTempl
return stairPalettes;
}
public NoiseSeeded getBiomeNoise() {
public NoiseSampler getBiomeNoise() {
return biomeNoise;
}
public NoiseSeeded getElevationEquation() {
public NoiseSampler getElevationEquation() {
return elevationEquation;
}
public NoiseSeeded getCarvingEquation() {
public NoiseSampler getCarvingEquation() {
return carvingEquation;
}
@@ -188,7 +185,7 @@ public class BiomeTemplate implements AbstractableTemplate, ValidatedConfigTempl
return vanilla;
}
public NoiseSeeded getNoiseEquation() {
public NoiseSampler getNoiseEquation() {
return noiseEquation;
}
@@ -207,36 +204,6 @@ public class BiomeTemplate implements AbstractableTemplate, ValidatedConfigTempl
@Override
public boolean validate() throws ValidationException {
color |= 0xff000000; // Alpha adjustment
Parser tester = new Parser();
Scope testScope = new Scope();
variables.forEach(testScope::create);
testScope.addInvocationVariable("x");
testScope.addInvocationVariable("y");
testScope.addInvocationVariable("z");
//pack.getTemplate().getNoiseBuilderMap().forEach((id, builder) -> tester.registerFunction(id, new BlankFunction(builder.getDimensions()))); // Register dummy functions
try {
noiseEquation.apply(0L);
} catch(Exception e) {
throw new ValidationException("Invalid noise sampler: ", e);
}
try {
carvingEquation.apply(0L);
} catch(Exception e) {
throw new ValidationException("Invalid carving sampler: ", e);
}
try {
elevationEquation.apply(0L);
} catch(Exception e) {
throw new ValidationException("Invalid elevation sampler: ", e);
}
return true;
}
}

View File

@@ -20,16 +20,15 @@ public class UserDefinedBiome implements TerraBiome {
private final int color;
private final Set<String> tags;
private final Context context;
private final Context context = new Context();
public UserDefinedBiome(ProbabilityCollection<Biome> vanilla, UserDefinedGenerator gen, BiomeTemplate config, Context context) {
public UserDefinedBiome(ProbabilityCollection<Biome> vanilla, UserDefinedGenerator gen, BiomeTemplate config) {
this.vanilla = vanilla;
this.gen = gen;
this.id = config.getID();
this.config = config;
this.color = config.getColor();
this.tags = config.getTags();
this.context = context;
tags.add("BIOME:" + id);
}

View File

@@ -1,43 +0,0 @@
package com.dfsek.terra.addons.biome;
import com.dfsek.terra.api.properties.Context;
import com.dfsek.terra.api.util.collection.ProbabilityCollection;
import com.dfsek.terra.api.util.seeded.BiomeBuilder;
import com.dfsek.terra.api.world.biome.Biome;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class UserDefinedBiomeBuilder implements BiomeBuilder {
private final BiomeTemplate template;
private final Context context = new Context();
private final Map<Long, UserDefinedBiome> biomeMap = new ConcurrentHashMap<>();
public UserDefinedBiomeBuilder(BiomeTemplate template) {
this.template = template;
}
@Override
public UserDefinedBiome apply(Long seed) {
synchronized(biomeMap) {
return biomeMap.computeIfAbsent(seed,
s -> {
UserDefinedGenerator generator = new UserDefinedGenerator(template.getNoiseEquation().apply(seed), template.getElevationEquation().apply(seed), template.getCarvingEquation().apply(seed), template.getBiomeNoise().apply(seed), template.getElevationWeight(),
template.getBlendDistance(), template.getBlendStep(), template.getBlendWeight());
return new UserDefinedBiome(template.getVanilla(), generator, template, context);
}
);
}
}
@Override
public ProbabilityCollection<Biome> getVanillaBiomes() {
return template.getVanilla();
}
@Override
public Context getContext() {
return context;
}
}

View File

@@ -46,7 +46,7 @@ public class AsyncBiomeFinder implements Runnable {
*/
public boolean isValid(int x, int z, TerraBiome target) {
int res = main.getTerraConfig().getBiomeSearchResolution();
return getProvider().getBiome(x * res, z * res).equals(target);
return getProvider().getBiome(x * res, z * res, world.getSeed()).equals(target);
}
public Vector3 finalizeVector(Vector3 orig) {

View File

@@ -38,7 +38,7 @@ public class BiomeCommand implements CommandTemplate {
Player player = (Player) sender;
BiomeProvider provider = main.getWorld(player.world()).getBiomeProvider();
UserDefinedBiome biome = (UserDefinedBiome) provider.getBiome(player.position());
UserDefinedBiome biome = (UserDefinedBiome) provider.getBiome(player.position(), player.world().getSeed());
sender.sendMessage("You are standing in " + biome.getID());
}
}

View File

@@ -9,11 +9,8 @@ import com.dfsek.terra.api.command.annotation.Argument;
import com.dfsek.terra.api.command.annotation.Command;
import com.dfsek.terra.api.command.annotation.inject.ArgumentTarget;
import com.dfsek.terra.api.entity.CommandSender;
import com.dfsek.terra.api.structure.ConfiguredStructure;
import com.dfsek.terra.api.world.biome.TerraBiome;
import java.util.List;
@Command(
arguments = {
@Argument(

View File

@@ -39,7 +39,7 @@ public class CarverCache {
List<Worm.WormPoint> points = new ArrayList<>();
for(int i = 0; i < carving.getLength(); i++) {
carving.step();
TerraBiome biome = provider.getBiome(carving.getRunning());
TerraBiome biome = provider.getBiome(carving.getRunning(), w.getSeed());
/*
if(!((UserDefinedBiome) biome).getConfig().getCarvers().containsKey(CarverCache.this.carver)) { // Stop if we enter a biome this carver is not present in
return Collections.emptyList();

View File

@@ -0,0 +1,37 @@
package com.dfsek.terra.addons.feature.distributor;
import com.dfsek.tectonic.loading.object.ObjectTemplate;
import com.dfsek.terra.addons.feature.distributor.config.NoiseDistributorTemplate;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.addon.TerraAddon;
import com.dfsek.terra.api.addon.annotations.Addon;
import com.dfsek.terra.api.addon.annotations.Author;
import com.dfsek.terra.api.addon.annotations.Version;
import com.dfsek.terra.api.event.EventListener;
import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent;
import com.dfsek.terra.api.injection.annotations.Inject;
import com.dfsek.terra.api.registry.CheckedRegistry;
import com.dfsek.terra.api.structure.feature.Distributor;
import com.dfsek.terra.api.util.reflection.TypeKey;
import java.util.function.Supplier;
@Addon("config-distributors")
@Version("1.0.0")
@Author("Terra")
public class DistributorAddon extends TerraAddon implements EventListener {
public static final TypeKey<Supplier<ObjectTemplate<Distributor>>> DISTRIBUTOR_TOKEN = new TypeKey<>() {};
@Inject
private TerraPlugin main;
@Override
public void initialize() {
main.getEventManager().registerListener(this, this);
}
public void packPreLoad(ConfigPackPreLoadEvent event) {
CheckedRegistry<Supplier<ObjectTemplate<Distributor>>> distributorRegistry = event.getPack().getOrCreateRegistry(DISTRIBUTOR_TOKEN);
distributorRegistry.register("NOISE", NoiseDistributorTemplate::new);
}
}

View File

@@ -0,0 +1,17 @@
package com.dfsek.terra.addons.feature.distributor.config;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.tectonic.loading.object.ObjectTemplate;
import com.dfsek.terra.addons.feature.distributor.distributors.NoiseDistributor;
import com.dfsek.terra.api.noise.NoiseSampler;
import com.dfsek.terra.api.structure.feature.Distributor;
public class NoiseDistributorTemplate implements ObjectTemplate<Distributor> {
@Value("distribution")
private NoiseSampler noise;
@Override
public Distributor get() {
return new NoiseDistributor(noise);
}
}

View File

@@ -0,0 +1,17 @@
package com.dfsek.terra.addons.feature.distributor.distributors;
import com.dfsek.terra.api.noise.NoiseSampler;
import com.dfsek.terra.api.structure.feature.Distributor;
public class NoiseDistributor implements Distributor {
private final NoiseSampler sampler;
public NoiseDistributor(NoiseSampler sampler) {
this.sampler = sampler;
}
@Override
public boolean matches(int x, int z, long seed) {
return sampler.getNoiseSeeded(seed, x, z) > 0;
}
}

View File

@@ -5,6 +5,7 @@ import com.dfsek.terra.api.config.ConfigFactory;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.config.ConfigType;
import com.dfsek.terra.api.registry.OpenRegistry;
import com.dfsek.terra.api.util.reflection.TypeKey;
import com.dfsek.terra.api.world.Flora;
import java.util.function.Supplier;
@@ -13,6 +14,8 @@ public class FloraConfigType implements ConfigType<FloraTemplate, Flora> {
private final FloraFactory factory = new FloraFactory();
private final ConfigPack pack;
public static final TypeKey<Flora> FLORA_TYPE_TOKEN = new TypeKey<>(){};
public FloraConfigType(ConfigPack pack) {
this.pack = pack;
}
@@ -28,8 +31,8 @@ public class FloraConfigType implements ConfigType<FloraTemplate, Flora> {
}
@Override
public Class<Flora> getTypeClass() {
return Flora.class;
public TypeKey<Flora> getTypeClass() {
return FLORA_TYPE_TOKEN;
}
@Override

View File

@@ -8,6 +8,6 @@ import com.dfsek.terra.api.world.Flora;
public class FloraFactory implements ConfigFactory<FloraTemplate, Flora> {
@Override
public TerraFlora build(FloraTemplate config, TerraPlugin main) {
return new TerraFlora(config.getLayers(), config.doPhysics(), config.isCeiling(), config.getIrrigable(), config.getSpawnable(), config.getReplaceable(), config.getRotatable(), config.getMaxPlacements(), config.getSearch(), config.isSpawnBlacklist(), config.getIrrigableOffset(), main, config.getNoiseDistribution().apply(2403L));
return new TerraFlora(config.getLayers(), config.doPhysics(), config.isCeiling(), config.getIrrigable(), config.getSpawnable(), config.getReplaceable(), config.getRotatable(), config.getMaxPlacements(), config.getSearch(), config.isSpawnBlacklist(), config.getIrrigableOffset(), main, config.getNoiseDistribution());
}
}

View File

@@ -6,8 +6,8 @@ import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.addons.flora.flora.gen.BlockLayer;
import com.dfsek.terra.addons.flora.flora.gen.TerraFlora;
import com.dfsek.terra.api.config.AbstractableTemplate;
import com.dfsek.terra.api.noise.NoiseSampler;
import com.dfsek.terra.api.util.collection.MaterialSet;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import java.util.List;
@@ -61,9 +61,9 @@ public class FloraTemplate implements AbstractableTemplate {
private List<BlockLayer> layers;
@Value("layer-distribution")
private NoiseSeeded noiseDistribution;
private NoiseSampler noiseDistribution;
public NoiseSeeded getNoiseDistribution() {
public NoiseSampler getNoiseDistribution() {
return noiseDistribution;
}

View File

@@ -116,7 +116,7 @@ public class TerraFlora implements Flora {
for(int i = 0; FastMath.abs(i) < size; i += c) { // Down if ceiling, up if floor
int lvl = (FastMath.abs(i));
BlockState data = getStateCollection((ceiling ? lvl : size - lvl - 1)).get(distribution, location.getX(), location.getY(), location.getZ()).clone();
BlockState data = getStateCollection((ceiling ? lvl : size - lvl - 1)).get(distribution, location.getX(), location.getY(), location.getZ(), world.getSeed()).clone();
if(doRotation) {
Direction oneFace = new ArrayList<>(faces).get(new Random(location.getBlockX() ^ location.getBlockZ()).nextInt(faces.size())); // Get random face.

View File

@@ -0,0 +1,45 @@
import com.dfsek.terra.configureCompilation
import com.dfsek.terra.configureDependencies
plugins {
`java-library`
`maven-publish`
idea
}
configureCompilation()
configureDependencies()
group = "com.dfsek.terra.common"
dependencies {
"shadedApi"(project(":common:api"))
"compileOnly"("com.google.guava:guava:30.0-jre")
"testImplementation"("com.google.guava:guava:30.0-jre")
}
publishing {
publications {
create<MavenPublication>("mavenJava") {
artifact(tasks["sourcesJar"])
artifact(tasks["jar"])
}
}
repositories {
val mavenUrl = "https://repo.codemc.io/repository/maven-releases/"
val mavenSnapshotUrl = "https://repo.codemc.io/repository/maven-snapshots/"
maven(mavenUrl) {
val mavenUsername: String? by project
val mavenPassword: String? by project
if (mavenUsername != null && mavenPassword != null) {
credentials {
username = mavenUsername
password = mavenPassword
}
}
}
}
}

View File

@@ -0,0 +1,37 @@
package com.dfsek.terra.addons.feature.locator;
import com.dfsek.tectonic.loading.object.ObjectTemplate;
import com.dfsek.terra.addons.feature.locator.config.SurfaceLocatorTemplate;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.addon.TerraAddon;
import com.dfsek.terra.api.addon.annotations.Addon;
import com.dfsek.terra.api.addon.annotations.Author;
import com.dfsek.terra.api.addon.annotations.Version;
import com.dfsek.terra.api.event.EventListener;
import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent;
import com.dfsek.terra.api.injection.annotations.Inject;
import com.dfsek.terra.api.registry.CheckedRegistry;
import com.dfsek.terra.api.structure.feature.Locator;
import com.dfsek.terra.api.util.reflection.TypeKey;
import java.util.function.Supplier;
@Addon("config-locators")
@Version("1.0.0")
@Author("Terra")
public class LocatorAddon extends TerraAddon implements EventListener {
public static final TypeKey<Supplier<ObjectTemplate<Locator>>> LOCATOR_TOKEN = new TypeKey<>() {};
@Inject
private TerraPlugin main;
@Override
public void initialize() {
main.getEventManager().registerListener(this, this);
}
public void onPackLoad(ConfigPackPreLoadEvent event) {
CheckedRegistry<Supplier<ObjectTemplate<Locator>>> locatorRegistry = event.getPack().getOrCreateRegistry(LOCATOR_TOKEN);
locatorRegistry.register("SURFACE", () -> new SurfaceLocatorTemplate(main));
}
}

View File

@@ -0,0 +1,24 @@
package com.dfsek.terra.addons.feature.locator.config;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.tectonic.loading.object.ObjectTemplate;
import com.dfsek.terra.addons.feature.locator.locators.SurfaceLocator;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.structure.feature.Locator;
import com.dfsek.terra.api.util.Range;
public class SurfaceLocatorTemplate implements ObjectTemplate<Locator> {
private final TerraPlugin main;
@Value("range")
private Range range;
public SurfaceLocatorTemplate(TerraPlugin main) {
this.main = main;
}
@Override
public Locator get() {
return new SurfaceLocator(range, main);
}
}

View File

@@ -0,0 +1,32 @@
package com.dfsek.terra.addons.feature.locator.locators;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.structure.feature.Locator;
import com.dfsek.terra.api.util.ConstantRange;
import com.dfsek.terra.api.util.Range;
import com.dfsek.terra.api.world.Column;
import java.util.Collections;
import java.util.List;
public class SurfaceLocator implements Locator {
private final Range search;
private final BlockState air;
public SurfaceLocator(Range search, TerraPlugin main) {
this.search = search;
this.air = main.getWorldHandle().air();
}
@Override
public List<Integer> getSuitableCoordinates(Column column) {
for(int y : search) {
if(column.getBlock(y).matches(air) && !column.getBlock(y-1).matches(air)) {
return Collections.singletonList(y);
}
}
return Collections.emptyList();
}
}

View File

@@ -1,6 +1,7 @@
package com.dfsek.terra.addons.noise;
import com.dfsek.tectonic.exception.ConfigException;
import com.dfsek.tectonic.loading.object.ObjectTemplate;
import com.dfsek.terra.addons.noise.config.DimensionApplicableNoiseSampler;
import com.dfsek.terra.addons.noise.config.NoiseSamplerBuilderLoader;
import com.dfsek.terra.addons.noise.config.templates.DomainWarpTemplate;
import com.dfsek.terra.addons.noise.config.templates.ImageSamplerTemplate;
@@ -16,7 +17,6 @@ import com.dfsek.terra.addons.noise.config.templates.noise.fractal.RidgedFractal
import com.dfsek.terra.addons.noise.config.templates.normalizer.ClampNormalizerTemplate;
import com.dfsek.terra.addons.noise.config.templates.normalizer.LinearNormalizerTemplate;
import com.dfsek.terra.addons.noise.config.templates.normalizer.NormalNormalizerTemplate;
import com.dfsek.terra.addons.noise.samplers.ImageSampler;
import com.dfsek.terra.addons.noise.samplers.noise.CellularSampler;
import com.dfsek.terra.addons.noise.samplers.noise.random.GaussianNoiseSampler;
import com.dfsek.terra.addons.noise.samplers.noise.random.WhiteNoiseSampler;
@@ -34,12 +34,13 @@ import com.dfsek.terra.api.addon.annotations.Version;
import com.dfsek.terra.api.event.EventListener;
import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent;
import com.dfsek.terra.api.injection.annotations.Inject;
import com.dfsek.terra.api.noise.NoiseSampler;
import com.dfsek.terra.api.registry.CheckedRegistry;
import com.dfsek.terra.api.util.seeded.NoiseProvider;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.api.util.reflection.TypeKey;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Supplier;
@Addon("config-noise-function")
@Author("Terra")
@@ -48,23 +49,25 @@ public class NoiseAddon extends TerraAddon implements EventListener {
@Inject
private TerraPlugin plugin;
public static final TypeKey<Supplier<ObjectTemplate<NoiseSampler>>> NOISE_SAMPLER_TOKEN = new TypeKey<>() {};
@Override
public void initialize() {
plugin.getEventManager().registerListener(this, this);
}
public void packPreLoad(ConfigPackPreLoadEvent event) {
CheckedRegistry<NoiseProvider> noiseRegistry = event.getPack().getOrCreateRegistry(NoiseProvider.class);
CheckedRegistry<Supplier<ObjectTemplate<NoiseSampler>>> noiseRegistry = event.getPack().getOrCreateRegistry(NOISE_SAMPLER_TOKEN);
event.getPack()
.applyLoader(NoiseSeeded.class, new NoiseSamplerBuilderLoader(noiseRegistry))
.applyLoader(NoiseSampler.class, new NoiseSamplerBuilderLoader(noiseRegistry))
.applyLoader(ImageSamplerTemplate.class, ImageSamplerTemplate::new)
.applyLoader(CellularSampler.DistanceFunction.class, (t, o, l) -> CellularSampler.DistanceFunction.valueOf((String) o))
.applyLoader(CellularSampler.ReturnType.class, (t, o, l) -> CellularSampler.ReturnType.valueOf((String) o))
.applyLoader(DomainWarpTemplate.class, DomainWarpTemplate::new)
.applyLoader(LinearNormalizerTemplate.class, LinearNormalizerTemplate::new)
.applyLoader(NormalNormalizerTemplate.class, NormalNormalizerTemplate::new)
.applyLoader(ImageSampler.Channel.class, (t, object, cf) -> ImageSampler.Channel.valueOf((String) object))
.applyLoader(ClampNormalizerTemplate.class, ClampNormalizerTemplate::new)
.applyLoader(CellularSampler.ReturnType.class, (t, object, cf) -> CellularSampler.ReturnType.valueOf((String) object))
.applyLoader(CellularSampler.DistanceFunction.class, (t, object, cf) -> CellularSampler.DistanceFunction.valueOf((String) object));
.applyLoader(DimensionApplicableNoiseSampler.class, DimensionApplicableNoiseSampler::new);
noiseRegistry.register("LINEAR", LinearNormalizerTemplate::new);
noiseRegistry.register("NORMAL", NormalNormalizerTemplate::new);
@@ -97,16 +100,12 @@ public class NoiseAddon extends TerraAddon implements EventListener {
noiseRegistry.register("KERNEL", KernelTemplate::new);
Map<String, NoiseSeeded> packFunctions = new HashMap<>();
Map<String, DimensionApplicableNoiseSampler> packFunctions = new HashMap<>();
noiseRegistry.register("EXPRESSION", () -> new ExpressionFunctionTemplate(packFunctions));
try {
NoiseConfigPackTemplate template = new NoiseConfigPackTemplate();
event.loadTemplate(template);
packFunctions.putAll(template.getNoiseBuilderMap());
} catch(ConfigException e) {
throw new RuntimeException(e);
}
NoiseConfigPackTemplate template = new NoiseConfigPackTemplate();
event.loadTemplate(template);
packFunctions.putAll(template.getNoiseBuilderMap());
}
}

View File

@@ -2,15 +2,15 @@ package com.dfsek.terra.addons.noise;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.tectonic.config.ConfigTemplate;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.addons.noise.config.DimensionApplicableNoiseSampler;
import java.util.Map;
public class NoiseConfigPackTemplate implements ConfigTemplate {
@Value("noise")
private Map<String, NoiseSeeded> noiseBuilderMap;
private Map<String, DimensionApplicableNoiseSampler> noiseBuilderMap;
public Map<String, NoiseSeeded> getNoiseBuilderMap() {
public Map<String, DimensionApplicableNoiseSampler> getNoiseBuilderMap() {
return noiseBuilderMap;
}
}

View File

@@ -0,0 +1,26 @@
package com.dfsek.terra.addons.noise.config;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.tectonic.loading.object.ObjectTemplate;
import com.dfsek.terra.api.noise.NoiseSampler;
public class DimensionApplicableNoiseSampler implements ObjectTemplate<DimensionApplicableNoiseSampler> {
@Value("dimensions")
private int dimensions;
@Value(".")
private NoiseSampler sampler;
public int getDimensions() {
return dimensions;
}
public NoiseSampler getSampler() {
return sampler;
}
@Override
public DimensionApplicableNoiseSampler get() {
return this;
}
}

View File

@@ -6,30 +6,29 @@ import com.dfsek.tectonic.exception.LoadException;
import com.dfsek.tectonic.loading.ConfigLoader;
import com.dfsek.tectonic.loading.TypeLoader;
import com.dfsek.tectonic.loading.object.ObjectTemplate;
import com.dfsek.terra.api.noise.NoiseSampler;
import com.dfsek.terra.api.registry.Registry;
import com.dfsek.terra.api.util.seeded.NoiseProvider;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import java.lang.reflect.AnnotatedType;
import java.util.Locale;
import java.util.Map;
import java.util.function.Supplier;
@SuppressWarnings("unchecked")
public class NoiseSamplerBuilderLoader implements TypeLoader<NoiseSeeded> {
private final Registry<NoiseProvider> noiseRegistry;
public class NoiseSamplerBuilderLoader implements TypeLoader<NoiseSampler> {
private final Registry<Supplier<ObjectTemplate<NoiseSampler>>> noiseRegistry;
public NoiseSamplerBuilderLoader(Registry<NoiseProvider> noiseRegistry) {
public NoiseSamplerBuilderLoader(Registry<Supplier<ObjectTemplate<NoiseSampler>>> noiseRegistry) {
this.noiseRegistry = noiseRegistry;
}
@Override
public NoiseSeeded load(AnnotatedType t, Object c, ConfigLoader loader) throws LoadException {
public NoiseSampler load(AnnotatedType t, Object c, ConfigLoader loader) throws LoadException {
Map<String, Object> map = (Map<String, Object>) c;
try {
if(!noiseRegistry.contains((String) map.get("type"))) {
throw new LoadException("No such noise function: " + map.get("type"));
}
ObjectTemplate<NoiseSeeded> normalizerTemplate = noiseRegistry.get(((String) map.get("type")).toUpperCase(Locale.ROOT)).get();
ObjectTemplate<NoiseSampler> normalizerTemplate = noiseRegistry.get(((String) map.get("type"))).get();
loader.load(normalizerTemplate, new MapConfiguration(map));
return normalizerTemplate.get();
} catch(ConfigException e) {

View File

@@ -4,15 +4,14 @@ import com.dfsek.tectonic.annotations.Default;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.addons.noise.samplers.DomainWarpedSampler;
import com.dfsek.terra.api.noise.NoiseSampler;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
@SuppressWarnings({"unused", "FieldMayBeFinal"})
public class DomainWarpTemplate extends SamplerTemplate<DomainWarpedSampler> {
@Value("warp")
private NoiseSeeded warp;
private NoiseSampler warp;
@Value("function")
private NoiseSeeded function;
private NoiseSampler function;
@Value("salt")
@Default
@@ -23,7 +22,7 @@ public class DomainWarpTemplate extends SamplerTemplate<DomainWarpedSampler> {
private double amplitude = 1;
@Override
public NoiseSampler apply(Long seed) {
return new DomainWarpedSampler(function.apply(seed), warp.apply(seed), (int) (seed + salt), amplitude);
public NoiseSampler get() {
return new DomainWarpedSampler(function, warp, amplitude);
}
}

View File

@@ -19,7 +19,7 @@ public class ImageSamplerTemplate extends SamplerTemplate<ImageSampler> {
private ImageSampler.Channel channel;
@Override
public NoiseSampler apply(Long seed) {
public NoiseSampler get() {
return new ImageSampler(image, channel, frequency);
}
}

View File

@@ -6,7 +6,6 @@ import com.dfsek.tectonic.config.ValidatedConfigTemplate;
import com.dfsek.tectonic.exception.ValidationException;
import com.dfsek.terra.addons.noise.samplers.KernelSampler;
import com.dfsek.terra.api.noise.NoiseSampler;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import java.util.List;
@@ -21,14 +20,14 @@ public class KernelTemplate extends SamplerTemplate<KernelSampler> implements Va
private double factor = 1;
@Value("function")
private NoiseSeeded function;
private NoiseSampler function;
@Value("frequency")
@Default
private double frequency = 1;
@Override
public NoiseSampler apply(Long seed) {
public NoiseSampler get() {
double[][] k = new double[kernel.size()][kernel.get(0).size()];
for(int x = 0; x < kernel.size(); x++) {
@@ -37,7 +36,7 @@ public class KernelTemplate extends SamplerTemplate<KernelSampler> implements Va
}
}
KernelSampler sampler = new KernelSampler(k, function.apply(seed));
KernelSampler sampler = new KernelSampler(k, function);
sampler.setFrequency(frequency);
return sampler;
}

View File

@@ -6,10 +6,9 @@ import com.dfsek.tectonic.config.ValidatedConfigTemplate;
import com.dfsek.tectonic.exception.ValidationException;
import com.dfsek.tectonic.loading.object.ObjectTemplate;
import com.dfsek.terra.api.noise.NoiseSampler;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
@SuppressWarnings("FieldMayBeFinal")
public abstract class SamplerTemplate<T extends NoiseSampler> implements ValidatedConfigTemplate, ObjectTemplate<NoiseSeeded>, NoiseSeeded {
public abstract class SamplerTemplate<T extends NoiseSampler> implements ValidatedConfigTemplate, ObjectTemplate<NoiseSampler> {
@Value("dimensions")
@Default
private int dimensions = 2;
@@ -23,9 +22,4 @@ public abstract class SamplerTemplate<T extends NoiseSampler> implements Validat
if(dimensions != 2 && dimensions != 3) throw new ValidationException("Illegal amount of dimensions: " + dimensions);
return true;
}
@Override
public NoiseSeeded get() {
return this;
}
}

View File

@@ -5,7 +5,6 @@ import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.addons.noise.samplers.noise.CellularSampler;
import com.dfsek.terra.addons.noise.samplers.noise.simplex.OpenSimplex2Sampler;
import com.dfsek.terra.api.noise.NoiseSampler;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
@SuppressWarnings("FieldMayBeFinal")
public class CellularNoiseTemplate extends NoiseTemplate<CellularSampler> {
@@ -24,23 +23,12 @@ public class CellularNoiseTemplate extends NoiseTemplate<CellularSampler> {
@Value("lookup")
@Default
private NoiseSeeded lookup = new NoiseSeeded() {
@Override
public NoiseSampler apply(Long seed) {
return new OpenSimplex2Sampler((int) (long) seed);
}
@Override
public int getDimensions() {
return 2;
}
};
private NoiseSampler lookup = new OpenSimplex2Sampler();
@Override
public NoiseSampler apply(Long seed) {
CellularSampler sampler = new CellularSampler((int) (long) seed + salt);
sampler.setNoiseLookup(lookup.apply(seed));
public NoiseSampler get() {
CellularSampler sampler = new CellularSampler();
sampler.setNoiseLookup(lookup);
sampler.setFrequency(frequency);
sampler.setJitterModifier(cellularJitter);
sampler.setReturnType(cellularReturnType);

View File

@@ -13,7 +13,7 @@ public class ConstantNoiseTemplate extends SamplerTemplate<ConstantSampler> {
private double value = 0d;
@Override
public NoiseSampler apply(Long seed) {
public NoiseSampler get() {
return new ConstantSampler(value);
}
}

View File

@@ -8,6 +8,7 @@ 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.terra.addons.noise.config.DimensionApplicableNoiseSampler;
import com.dfsek.terra.addons.noise.config.templates.FunctionTemplate;
import com.dfsek.terra.addons.noise.config.templates.SamplerTemplate;
import com.dfsek.terra.addons.noise.paralithic.defined.UserDefinedFunction;
@@ -15,7 +16,6 @@ import com.dfsek.terra.addons.noise.paralithic.noise.NoiseFunction2;
import com.dfsek.terra.addons.noise.paralithic.noise.NoiseFunction3;
import com.dfsek.terra.addons.noise.samplers.noise.ExpressionFunction;
import com.dfsek.terra.api.noise.NoiseSampler;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import java.util.HashMap;
import java.util.LinkedHashMap;
@@ -24,7 +24,7 @@ import java.util.Map;
@SuppressWarnings({"FieldMayBeFinal", "unused"})
public class ExpressionFunctionTemplate extends SamplerTemplate<ExpressionFunction> implements ValidatedConfigTemplate {
private final Map<String, NoiseSeeded> otherFunctions;
private final Map<String, DimensionApplicableNoiseSampler> otherFunctions;
@Value("variables")
@Default
private Map<String, Double> vars = new HashMap<>();
@@ -32,19 +32,19 @@ public class ExpressionFunctionTemplate extends SamplerTemplate<ExpressionFuncti
private String equation;
@Value("functions")
@Default
private LinkedHashMap<String, NoiseSeeded> functions = new LinkedHashMap<>();
private LinkedHashMap<String, DimensionApplicableNoiseSampler> functions = new LinkedHashMap<>();
@Value("expressions")
@Default
private LinkedHashMap<String, FunctionTemplate> expressions = new LinkedHashMap<>();
public ExpressionFunctionTemplate(Map<String, NoiseSeeded> otherFunctions) {
public ExpressionFunctionTemplate(Map<String, DimensionApplicableNoiseSampler> otherFunctions) {
this.otherFunctions = otherFunctions;
}
@Override
public NoiseSampler apply(Long seed) {
public NoiseSampler get() {
try {
Map<String, Function> noiseFunctionMap = generateFunctions(seed);
Map<String, Function> noiseFunctionMap = generateFunctions();
return new ExpressionFunction(noiseFunctionMap, equation, vars);
} catch(ParseException e) {
throw new IllegalStateException(e);
@@ -54,7 +54,7 @@ public class ExpressionFunctionTemplate extends SamplerTemplate<ExpressionFuncti
@Override
public boolean validate() throws ValidationException {
try {
Map<String, Function> noiseFunctionMap = generateFunctions(0L);
Map<String, Function> noiseFunctionMap = generateFunctions();
new ExpressionFunction(noiseFunctionMap, equation, vars);
} catch(ParseException e) {
throw new ValidationException("Errors occurred while parsing noise equation: ", e);
@@ -62,7 +62,7 @@ public class ExpressionFunctionTemplate extends SamplerTemplate<ExpressionFuncti
return super.validate();
}
private Map<String, Function> generateFunctions(Long seed) throws ParseException {
private Map<String, Function> generateFunctions() throws ParseException {
Map<String, Function> noiseFunctionMap = new HashMap<>();
for(Map.Entry<String, FunctionTemplate> entry : expressions.entrySet()) {
@@ -71,14 +71,14 @@ public class ExpressionFunctionTemplate extends SamplerTemplate<ExpressionFuncti
otherFunctions.forEach((id, function) -> {
if(function.getDimensions() == 2) {
noiseFunctionMap.put(id, new NoiseFunction2(function.apply(seed)));
} else noiseFunctionMap.put(id, new NoiseFunction3(function.apply(seed)));
noiseFunctionMap.put(id, new NoiseFunction2(function.getSampler()));
} else noiseFunctionMap.put(id, new NoiseFunction3(function.getSampler()));
});
functions.forEach((id, function) -> {
if(function.getDimensions() == 2) {
noiseFunctionMap.put(id, new NoiseFunction2(function.apply(seed)));
} else noiseFunctionMap.put(id, new NoiseFunction3(function.apply(seed)));
noiseFunctionMap.put(id, new NoiseFunction2(function.getSampler()));
} else noiseFunctionMap.put(id, new NoiseFunction3(function.getSampler()));
});
return noiseFunctionMap;

View File

@@ -27,8 +27,8 @@ public class GaborNoiseTemplate extends NoiseTemplate<GaborNoiseSampler> {
private double f0 = 0.625;
@Override
public NoiseSampler apply(Long seed) {
GaborNoiseSampler gaborNoiseSampler = new GaborNoiseSampler((int) (long) seed + salt);
public NoiseSampler get() {
GaborNoiseSampler gaborNoiseSampler = new GaborNoiseSampler();
gaborNoiseSampler.setFrequency(frequency);
gaborNoiseSampler.setRotation(rotation);
gaborNoiseSampler.setIsotropic(isotropic);

View File

@@ -4,17 +4,18 @@ import com.dfsek.terra.addons.noise.samplers.noise.NoiseFunction;
import com.dfsek.terra.api.noise.NoiseSampler;
import java.util.function.Function;
import java.util.function.Supplier;
public class SimpleNoiseTemplate extends NoiseTemplate<NoiseFunction> {
private final Function<Integer, NoiseFunction> samplerSupplier;
private final Supplier<NoiseFunction> samplerSupplier;
public SimpleNoiseTemplate(Function<Integer, NoiseFunction> samplerSupplier) {
public SimpleNoiseTemplate(Supplier<NoiseFunction> samplerSupplier) {
this.samplerSupplier = samplerSupplier;
}
@Override
public NoiseSampler apply(Long seed) {
NoiseFunction sampler = samplerSupplier.apply((int) (long) seed + salt);
public NoiseSampler get() {
NoiseFunction sampler = samplerSupplier.get();
sampler.setFrequency(frequency);
return sampler;
}

View File

@@ -5,8 +5,8 @@ import com.dfsek.terra.api.noise.NoiseSampler;
public class BrownianMotionTemplate extends FractalTemplate<BrownianMotionSampler> {
@Override
public NoiseSampler apply(Long seed) {
BrownianMotionSampler sampler = new BrownianMotionSampler((int) (long) seed, function.apply(seed));
public NoiseSampler get() {
BrownianMotionSampler sampler = new BrownianMotionSampler(function);
sampler.setGain(fractalGain);
sampler.setLacunarity(fractalLacunarity);
sampler.setOctaves(octaves);

View File

@@ -4,7 +4,7 @@ import com.dfsek.tectonic.annotations.Default;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.addons.noise.config.templates.SamplerTemplate;
import com.dfsek.terra.addons.noise.samplers.noise.fractal.FractalNoiseFunction;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.api.noise.NoiseSampler;
public abstract class FractalTemplate<T extends FractalNoiseFunction> extends SamplerTemplate<T> {
@Value("octaves")
@@ -24,5 +24,5 @@ public abstract class FractalTemplate<T extends FractalNoiseFunction> extends Sa
protected double weightedStrength = 0.0D;
@Value("function")
protected NoiseSeeded function;
protected NoiseSampler function;
}

View File

@@ -12,8 +12,8 @@ public class PingPongTemplate extends FractalTemplate<PingPongSampler> {
private double pingPong = 2.0D;
@Override
public NoiseSampler apply(Long seed) {
PingPongSampler sampler = new PingPongSampler((int) (long) seed, function.apply(seed));
public NoiseSampler get() {
PingPongSampler sampler = new PingPongSampler(function);
sampler.setGain(fractalGain);
sampler.setLacunarity(fractalLacunarity);
sampler.setOctaves(octaves);

View File

@@ -5,8 +5,8 @@ import com.dfsek.terra.api.noise.NoiseSampler;
public class RidgedFractalTemplate extends FractalTemplate<RidgedFractalSampler> {
@Override
public NoiseSampler apply(Long seed) {
RidgedFractalSampler sampler = new RidgedFractalSampler((int) (long) seed, function.apply(seed));
public NoiseSampler get() {
RidgedFractalSampler sampler = new RidgedFractalSampler(function);
sampler.setGain(fractalGain);
sampler.setLacunarity(fractalLacunarity);
sampler.setOctaves(octaves);

View File

@@ -13,7 +13,7 @@ public class ClampNormalizerTemplate extends NormalizerTemplate<ClampNormalizer>
private double min;
@Override
public NoiseSampler apply(Long seed) {
return new ClampNormalizer(function.apply(seed), min, max);
public NoiseSampler get() {
return new ClampNormalizer(function, min, max);
}
}

View File

@@ -13,7 +13,7 @@ public class LinearNormalizerTemplate extends NormalizerTemplate<LinearNormalize
private double min;
@Override
public NoiseSampler apply(Long seed) {
return new LinearNormalizer(function.apply(seed), min, max);
public NoiseSampler get() {
return new LinearNormalizer(function, min, max);
}
}

View File

@@ -18,7 +18,7 @@ public class NormalNormalizerTemplate extends NormalizerTemplate<NormalNormalize
private int groups = 16384;
@Override
public NoiseSampler apply(Long seed) {
return new NormalNormalizer(function.apply(seed), groups, mean, stdDev);
public NoiseSampler get() {
return new NormalNormalizer(function, groups, mean, stdDev);
}
}

View File

@@ -3,9 +3,9 @@ package com.dfsek.terra.addons.noise.config.templates.normalizer;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.addons.noise.config.templates.SamplerTemplate;
import com.dfsek.terra.addons.noise.normalizer.Normalizer;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.api.noise.NoiseSampler;
public abstract class NormalizerTemplate<T extends Normalizer> extends SamplerTemplate<T> {
@Value("function")
protected NoiseSeeded function;
protected NoiseSampler function;
}

View File

@@ -12,22 +12,12 @@ public abstract class Normalizer implements NoiseSampler {
public abstract double normalize(double in);
@Override
public double getNoise(double x, double y) {
return normalize(sampler.getNoise(x, y));
}
@Override
public double getNoise(double x, double y, double z) {
return normalize(sampler.getNoise(x, y, z));
}
@Override
public double getNoiseSeeded(int seed, double x, double y) {
public double getNoiseSeeded(long seed, double x, double y) {
return normalize(sampler.getNoiseSeeded(seed, x, y));
}
@Override
public double getNoiseSeeded(int seed, double x, double y, double z) {
public double getNoiseSeeded(long seed, double x, double y, double z) {
return normalize(sampler.getNoiseSeeded(seed, x, y, z));
}
}

View File

@@ -4,6 +4,7 @@ import com.dfsek.paralithic.Expression;
import com.dfsek.paralithic.eval.parser.Parser;
import com.dfsek.paralithic.eval.parser.Scope;
import com.dfsek.paralithic.eval.tokenizer.ParseException;
import com.dfsek.paralithic.functions.dynamic.Context;
import com.dfsek.paralithic.functions.dynamic.DynamicFunction;
import com.dfsek.terra.addons.noise.config.templates.FunctionTemplate;
@@ -31,6 +32,11 @@ public class UserDefinedFunction implements DynamicFunction {
return expression.evaluate(args);
}
@Override
public double eval(Context context, double... args) {
return expression.evaluate(context, args);
}
@Override
public boolean isStateless() {
return true;

View File

@@ -1,7 +0,0 @@
package com.dfsek.terra.addons.noise.paralithic.noise;
import com.dfsek.paralithic.functions.dynamic.DynamicFunction;
public interface NoiseFunction extends DynamicFunction {
}

View File

@@ -1,12 +1,13 @@
package com.dfsek.terra.addons.noise.paralithic.noise;
import com.dfsek.paralithic.functions.dynamic.Context;
import com.dfsek.paralithic.functions.dynamic.DynamicFunction;
import com.dfsek.terra.addons.noise.util.HashMapDoubleDouble;
import com.dfsek.terra.api.noise.NoiseSampler;
public class NoiseFunction2 implements NoiseFunction {
public class NoiseFunction2 implements DynamicFunction {
private final NoiseSampler gen;
private final Cache cache = new Cache();
public NoiseFunction2(NoiseSampler gen) {
this.gen = gen;
@@ -19,36 +20,16 @@ public class NoiseFunction2 implements NoiseFunction {
@Override
public double eval(double... args) {
return cache.get(gen, args[0], args[1]);
throw new UnsupportedOperationException("Cannot evaluate seeded function without seed context.");
}
@Override
public double eval(Context context, double... args) {
return gen.getNoiseSeeded(((SeedContext) context).getSeed(), args[0], args[1]);
}
@Override
public boolean isStateless() {
return true;
}
private static class Cache extends HashMapDoubleDouble {
private static final long serialVersionUID = 8915092734723467010L;
private static final int cacheSize = 384;
public Cache() {
super(cacheSize);
}
public double get(NoiseSampler noise, double x, double z) {
double xx = x >= 0 ? x * 2 : x * -2 - 1;
double zz = z >= 0 ? z * 2 : z * -2 - 1;
double key = (xx >= zz) ? (xx * xx + xx + zz) : (zz * zz + xx);
double value = this.get(key);
if(this.size() > cacheSize) {
this.clear();
}
return (value == 4.9E-324D ? addAndReturn(noise.getNoise(x, z), key) : value);
}
private synchronized double addAndReturn(double value, double key) {
this.put(key, value);
return value;
}
return false;
}
}

View File

@@ -1,8 +1,10 @@
package com.dfsek.terra.addons.noise.paralithic.noise;
import com.dfsek.paralithic.functions.dynamic.Context;
import com.dfsek.paralithic.functions.dynamic.DynamicFunction;
import com.dfsek.terra.api.noise.NoiseSampler;
public class NoiseFunction3 implements NoiseFunction {
public class NoiseFunction3 implements DynamicFunction {
private final NoiseSampler gen;
public NoiseFunction3(NoiseSampler gen) {
@@ -16,11 +18,16 @@ public class NoiseFunction3 implements NoiseFunction {
@Override
public double eval(double... args) {
return gen.getNoise(args[0], args[1], args[2]);
throw new UnsupportedOperationException("Cannot evaluate seeded function without seed context.");
}
@Override
public double eval(Context context, double... args) {
return gen.getNoiseSeeded(((SeedContext) context).getSeed(), args[0], args[1], args[2]);
}
@Override
public boolean isStateless() {
return true;
return false;
}
}

View File

@@ -0,0 +1,15 @@
package com.dfsek.terra.addons.noise.paralithic.noise;
import com.dfsek.paralithic.functions.dynamic.Context;
public class SeedContext implements Context {
private final long seed;
public SeedContext(long seed) {
this.seed = seed;
}
public long getSeed() {
return seed;
}
}

View File

@@ -5,40 +5,28 @@ import com.dfsek.terra.api.noise.NoiseSampler;
public class DomainWarpedSampler implements NoiseSampler {
private final NoiseSampler function;
private final NoiseSampler warp;
private final int seed;
private final double amplitude;
public DomainWarpedSampler(NoiseSampler function, NoiseSampler warp, int seed, double amplitude) {
public DomainWarpedSampler(NoiseSampler function, NoiseSampler warp, double amplitude) {
this.function = function;
this.warp = warp;
this.seed = seed;
this.amplitude = amplitude;
}
@Override
public double getNoise(double x, double y) {
return getNoiseSeeded(seed, x, y);
}
@Override
public double getNoise(double x, double y, double z) {
return getNoiseSeeded(seed, x, y, z);
}
@Override
public double getNoiseSeeded(int seed, double x, double y) {
return function.getNoise(
x + warp.getNoiseSeeded(seed, x, y) * amplitude,
y + warp.getNoiseSeeded(seed + 1, x, y) * amplitude
public double getNoiseSeeded(long seed, double x, double y) {
return function.getNoiseSeeded(seed++,
x + warp.getNoiseSeeded(seed++, x, y) * amplitude,
y + warp.getNoiseSeeded(seed, x, y) * amplitude
);
}
@Override
public double getNoiseSeeded(int seed, double x, double y, double z) {
return function.getNoise(
x + warp.getNoiseSeeded(seed, x, y, z) * amplitude,
y + warp.getNoiseSeeded(seed + 1, x, y, z) * amplitude,
z + warp.getNoiseSeeded(seed + 2, x, y, z) * amplitude
public double getNoiseSeeded(long seed, double x, double y, double z) {
return function.getNoiseSeeded(seed++,
x + warp.getNoiseSeeded(seed++, x, y, z) * amplitude,
y + warp.getNoiseSeeded(seed++, x, y, z) * amplitude,
z + warp.getNoiseSeeded(seed, x, y, z) * amplitude
);
}
}

View File

@@ -1,67 +0,0 @@
package com.dfsek.terra.addons.noise.samplers;
import com.dfsek.paralithic.Expression;
import com.dfsek.paralithic.eval.parser.Parser;
import com.dfsek.paralithic.eval.parser.Scope;
import com.dfsek.paralithic.eval.tokenizer.ParseException;
import com.dfsek.terra.addons.noise.config.templates.FunctionTemplate;
import com.dfsek.terra.addons.noise.paralithic.defined.UserDefinedFunction;
import com.dfsek.terra.addons.noise.paralithic.noise.NoiseFunction2;
import com.dfsek.terra.addons.noise.paralithic.noise.NoiseFunction3;
import com.dfsek.terra.api.noise.NoiseSampler;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import java.util.Map;
/**
* Sampler3D implementation using Paralithic expression
*/
public class ExpressionSampler implements NoiseSampler {
private final Expression expression;
public ExpressionSampler(String equation, Scope parent, long seed, Map<String, NoiseSeeded> functions, Map<String, FunctionTemplate> definedFunctions) throws ParseException {
Parser parser = new Parser();
Scope scope = new Scope().withParent(parent);
scope.addInvocationVariable("x");
scope.addInvocationVariable("y");
scope.addInvocationVariable("z");
functions.forEach((id, noise) -> {
switch(noise.getDimensions()) {
case 2:
parser.registerFunction(id, new NoiseFunction2(noise.apply(seed)));
break;
case 3:
parser.registerFunction(id, new NoiseFunction3(noise.apply(seed)));
break;
}
});
for(Map.Entry<String, FunctionTemplate> entry : definedFunctions.entrySet()) {
parser.registerFunction(entry.getKey(), UserDefinedFunction.newInstance(entry.getValue(), parser, parent));
}
this.expression = parser.parse(equation, scope);
}
@Override
public double getNoise(double x, double y) {
return getNoise(x, 0, y);
}
@Override
public double getNoise(double x, double y, double z) {
return expression.evaluate(x, y, z);
}
@Override
public double getNoiseSeeded(int seed, double x, double y) {
return getNoise(x, y);
}
@Override
public double getNoiseSeeded(int seed, double x, double y, double z) {
return getNoise(x, y, z);
}
}

View File

@@ -18,23 +18,13 @@ public class ImageSampler implements NoiseSampler {
}
@Override
public double getNoise(double x, double y) {
public double getNoiseSeeded(long seed, double x, double y) {
return ((channel.getChannel(image.getRGB(FastMath.floorMod(FastMath.floorToInt(x * frequency), image.getWidth()), FastMath.floorMod(FastMath.floorToInt(y * frequency), image.getHeight()))) / 255D) - 0.5) * 2;
}
@Override
public double getNoise(double x, double y, double z) {
return getNoise(x, y);
}
@Override
public double getNoiseSeeded(int seed, double x, double y) {
return getNoise(x, y);
}
@Override
public double getNoiseSeeded(int seed, double x, double y, double z) {
return getNoise(x, y, z);
public double getNoiseSeeded(long seed, double x, double y, double z) {
return getNoiseSeeded(seed, x, y);
}
public enum Channel {

View File

@@ -13,24 +13,14 @@ public class KernelSampler implements NoiseSampler {
}
@Override
public double getNoise(double x, double y) {
return getNoiseSeeded(0, x, y);
}
@Override
public double getNoise(double x, double y, double z) {
return getNoiseSeeded(0, x, y, z);
}
@Override
public double getNoiseSeeded(int seed, double x, double y) {
public double getNoiseSeeded(long seed, double x, double y) {
x *= frequency;
y *= frequency;
double accumulator = 0;
for(int kx = 0; kx < kernel.length; kx++) {
for(int ky = 0; ky < kernel[kx].length; ky++) {
accumulator += in.getNoise(x + kx, y + ky) * kernel[kx][ky];
accumulator += in.getNoiseSeeded(seed, x + kx, y + ky) * kernel[kx][ky];
}
}
@@ -38,7 +28,7 @@ public class KernelSampler implements NoiseSampler {
}
@Override
public double getNoiseSeeded(int seed, double x, double y, double z) {
public double getNoiseSeeded(long seed, double x, double y, double z) {
x *= frequency;
y *= frequency;
z *= frequency;
@@ -46,7 +36,7 @@ public class KernelSampler implements NoiseSampler {
for(int kx = 0; kx < kernel.length; kx++) {
for(int ky = 0; ky < kernel[kx].length; ky++) {
accumulator += in.getNoise(x + kx, y, z + ky) * kernel[kx][ky];
accumulator += in.getNoiseSeeded(seed, x + kx, y, z + ky) * kernel[kx][ky];
}
}

View File

@@ -192,9 +192,8 @@ public class CellularSampler extends NoiseFunction {
private NoiseSampler noiseLookup;
public CellularSampler(int seed) {
super(seed);
noiseLookup = new OpenSimplex2Sampler(seed);
public CellularSampler() {
noiseLookup = new OpenSimplex2Sampler();
}
public void setDistanceFunction(DistanceFunction distanceFunction) {
@@ -214,7 +213,8 @@ public class CellularSampler extends NoiseFunction {
}
@Override
public double getNoiseRaw(int seed, double x, double y) {
public double getNoiseRaw(long sl, double x, double y) {
int seed = (int) sl;
int xr = fastRound(x);
int yr = fastRound(y);
@@ -349,7 +349,7 @@ public class CellularSampler extends NoiseFunction {
case Distance2Div:
return distance0 / distance1 - 1;
case NoiseLookup:
return noiseLookup.getNoise(center.getX(), center.getZ());
return noiseLookup.getNoiseSeeded(sl, center.getX(), center.getZ());
case Distance3:
return distance2 - 1;
case Distance3Add:
@@ -366,7 +366,8 @@ public class CellularSampler extends NoiseFunction {
}
@Override
public double getNoiseRaw(int seed, double x, double y, double z) {
public double getNoiseRaw(long sl, double x, double y, double z) {
int seed = (int) sl;
int xr = fastRound(x);
int yr = fastRound(y);
int zr = fastRound(z);
@@ -523,7 +524,7 @@ public class CellularSampler extends NoiseFunction {
case Distance2Div:
return distance0 / distance1 - 1;
case NoiseLookup:
return noiseLookup.getNoise(center.getX(), center.getY(), center.getZ());
return noiseLookup.getNoiseSeeded(sl, center.getX(), center.getY(), center.getZ());
case Distance3:
return distance2 - 1;
case Distance3Add:

View File

@@ -7,17 +7,16 @@ public class ConstantSampler extends NoiseFunction {
private final double constant;
public ConstantSampler(double constant) {
super(0);
this.constant = constant;
}
@Override
public double getNoiseRaw(int seed, double x, double y) {
public double getNoiseRaw(long seed, double x, double y) {
return constant;
}
@Override
public double getNoiseRaw(int seed, double x, double y, double z) {
public double getNoiseRaw(long seed, double x, double y, double z) {
return constant;
}
}

Some files were not shown because too many files have changed in this diff Show More