working WorldConfig impl

This commit is contained in:
dfsek
2021-03-01 15:20:09 -07:00
parent 5a6b7ac4c1
commit a28f3fa660
44 changed files with 246 additions and 180 deletions

View File

@@ -10,6 +10,7 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.Random;
import java.util.Set;
import java.util.function.Function;
@SuppressWarnings("unchecked")
public class ProbabilityCollection<E> implements Collection<E> {
@@ -43,6 +44,17 @@ public class ProbabilityCollection<E> implements Collection<E> {
return (E) array[MathUtil.normalizeIndex(n.getNoise(x, z), array.length)];
}
public <T> ProbabilityCollection<T> map(Function<E, T> mapper, boolean carryNull) {
ProbabilityCollection<T> newCollection = new ProbabilityCollection<>();
newCollection.array = new Object[array.length];
for(int i = 0; i < array.length; i++) {
if(carryNull && array[i] == null) continue;
newCollection.array[i] = mapper.apply((E) array[i]);
}
return newCollection;
}
public int getTotalProbability() {
return array.length;
}

View File

@@ -4,4 +4,8 @@ import com.dfsek.terra.api.world.biome.TerraBiome;
public interface BiomeSource {
TerraBiome getBiome(double x, double z);
enum Type {
NOISE
}
}

View File

@@ -9,6 +9,7 @@ import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class ImageBiomeProvider implements BiomeProvider, BiomeProvider.BiomeProviderBuilder { // This provider does not need a seed, so it is its own builder.
private final Map<Color, TerraBiome> colorBiomeMap = new HashMap<>();
@@ -16,7 +17,7 @@ public class ImageBiomeProvider implements BiomeProvider, BiomeProvider.BiomePro
private final int resolution;
private final Align align;
public ImageBiomeProvider(Registry<TerraBiome> registry, BufferedImage image, int resolution, Align align) {
public ImageBiomeProvider(Set<TerraBiome> registry, BufferedImage image, int resolution, Align align) {
this.image = image;
this.resolution = resolution;
this.align = align;

View File

@@ -31,7 +31,5 @@ public interface TerraChunkGenerator {
TerraPlugin getMain();
SamplerCache getCache();
Sampler createSampler(int chunkX, int chunkZ, BiomeProvider provider, World world, int elevationSmooth);
}

View File

@@ -13,6 +13,7 @@ import com.dfsek.terra.api.util.collections.MaterialSet;
import com.dfsek.terra.api.util.collections.ProbabilityCollection;
import com.dfsek.terra.api.util.seeded.SourceSeeded;
import com.dfsek.terra.api.util.seeded.StageSeeded;
import com.dfsek.terra.api.world.biome.pipeline.source.BiomeSource;
import com.dfsek.terra.api.world.biome.pipeline.stages.ExpanderStage;
import com.dfsek.terra.api.world.biome.pipeline.stages.MutatorStage;
import com.dfsek.terra.api.world.biome.provider.BiomeProvider;
@@ -32,6 +33,7 @@ import com.dfsek.terra.config.loaders.config.TreeLayerLoader;
import com.dfsek.terra.config.loaders.config.biome.BiomeProviderBuilderLoader;
import com.dfsek.terra.config.loaders.config.biome.SourceBuilderLoader;
import com.dfsek.terra.config.loaders.config.biome.StageBuilderLoader;
import com.dfsek.terra.config.loaders.config.biome.templates.source.NoiseSourceTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.stage.expander.ExpanderStageTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator.BorderListMutatorTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator.BorderMutatorTemplate;
@@ -87,6 +89,7 @@ public class GenericLoaders implements LoaderRegistrar {
.registerLoader(ReplaceListMutatorTemplate.class, ReplaceListMutatorTemplate::new)
.registerLoader(BorderMutatorTemplate.class, BorderMutatorTemplate::new)
.registerLoader(BorderListMutatorTemplate.class, BorderListMutatorTemplate::new)
.registerLoader(NoiseSourceTemplate.class, NoiseSourceTemplate::new)
.registerLoader(FunctionTemplate.class, FunctionTemplate::new)
.registerLoader(LinkedHashMap.class, new LinkedHashMapLoader())
.registerLoader(CarverPalette.class, new CarverPaletteLoader())
@@ -97,6 +100,7 @@ public class GenericLoaders implements LoaderRegistrar {
.registerLoader(BiomeProvider.BiomeProviderBuilder.class, new BiomeProviderBuilderLoader())
.registerLoader(ImageSampler.Channel.class, (t, object, cf) -> ImageSampler.Channel.valueOf((String) object))
.registerLoader(BiomeProvider.Type.class, (t, object, cf) -> BiomeProvider.Type.valueOf((String) object))
.registerLoader(BiomeSource.Type.class, (t, object, cf) -> BiomeSource.Type.valueOf((String) object))
.registerLoader(ImageBiomeProvider.Align.class, (t, object, cf) -> ImageBiomeProvider.Align.valueOf((String) object))
.registerLoader(ExpanderStage.Type.class, (t, object, cf) -> ExpanderStage.Type.valueOf((String) object))
.registerLoader(MutatorStage.Type.class, (t, object, cf) -> MutatorStage.Type.valueOf((String) object))

View File

@@ -1,57 +1,12 @@
package com.dfsek.terra.config.builder;
import com.dfsek.paralithic.eval.parser.Scope;
import com.dfsek.paralithic.eval.tokenizer.ParseException;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.math.noise.NoiseSampler;
import com.dfsek.terra.api.math.noise.samplers.ExpressionSampler;
import com.dfsek.terra.api.math.noise.samplers.noise.ConstantSampler;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.api.platform.world.Biome;
import com.dfsek.terra.api.util.collections.ProbabilityCollection;
import com.dfsek.terra.api.util.seeded.SeededBuilder;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.UserDefinedBiome;
import com.dfsek.terra.config.loaders.config.function.FunctionTemplate;
import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.config.templates.BiomeTemplate;
import com.dfsek.terra.world.TerraWorld;
import com.dfsek.terra.world.generation.WorldGenerator;
import java.util.HashMap;
import java.util.Map;
public class BiomeBuilder implements ConfigBuilder<TerraBiome> {
private final BiomeTemplate template;
private final ConfigPack pack;
public BiomeBuilder(BiomeTemplate template, ConfigPack pack) {
this.template = template;
this.pack = pack;
}
@Override
public TerraBiome build(TerraWorld world, TerraPlugin main) {
NoiseSampler noise;
NoiseSampler elevation;
NoiseSampler carving;
Scope varScope = new Scope().withParent(pack.getVarScope());
template.getVariables().forEach(varScope::create);
Map<String, NoiseSeeded> noiseBuilderMap = pack.getTemplate().getNoiseBuilderMap();
Map<String, FunctionTemplate> functionTemplateMap = new HashMap<>(template.getFunctions());
functionTemplateMap.putAll(template.getFunctions());
long seed = world.getWorld().getSeed();
try {
noise = new ExpressionSampler(template.getNoiseEquation(), varScope, seed, noiseBuilderMap, functionTemplateMap);
elevation = template.getElevationEquation() == null ? new ConstantSampler(0) : new ExpressionSampler(template.getElevationEquation(), varScope, seed, noiseBuilderMap, functionTemplateMap);
carving = new ExpressionSampler(template.getCarvingEquation(), varScope, seed, noiseBuilderMap, functionTemplateMap);
} catch(ParseException e) {
throw new RuntimeException(e);
}
WorldGenerator generator = new WorldGenerator(template.getPalette(), template.getSlantPalette(), noise, elevation, carving, template.getBiomeNoise().apply(seed), template.getElevationWeight(),
template.getBlendDistance(), template.getBlendStep(), template.getBlendWeight());
return new UserDefinedBiome(template.getVanilla(), generator, template);
}
public interface BiomeBuilder<O extends TerraBiome> extends SeededBuilder<O> {
ProbabilityCollection<Biome> getVanillaBiomes();
}

View File

@@ -1,8 +0,0 @@
package com.dfsek.terra.config.builder;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.world.TerraWorld;
public interface ConfigBuilder<O> {
O build(TerraWorld world, TerraPlugin main);
}

View File

@@ -1,12 +0,0 @@
package com.dfsek.terra.config.builder;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.structures.script.StructureScript;
import com.dfsek.terra.world.TerraWorld;
public class ScriptBuilder implements ConfigBuilder<StructureScript> {
@Override
public StructureScript build(TerraWorld world, TerraPlugin main) {
return null;
}
}

View File

@@ -0,0 +1,60 @@
package com.dfsek.terra.config.builder;
import com.dfsek.paralithic.eval.parser.Scope;
import com.dfsek.paralithic.eval.tokenizer.ParseException;
import com.dfsek.terra.api.math.noise.NoiseSampler;
import com.dfsek.terra.api.math.noise.samplers.ExpressionSampler;
import com.dfsek.terra.api.math.noise.samplers.noise.ConstantSampler;
import com.dfsek.terra.api.platform.world.Biome;
import com.dfsek.terra.api.util.collections.ProbabilityCollection;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.api.world.biome.UserDefinedBiome;
import com.dfsek.terra.config.loaders.config.function.FunctionTemplate;
import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.config.templates.BiomeTemplate;
import com.dfsek.terra.world.generation.WorldGenerator;
import java.util.HashMap;
import java.util.Map;
public class UserDefinedBiomeBuilder implements BiomeBuilder<UserDefinedBiome> {
private final BiomeTemplate template;
private final ConfigPack pack;
public UserDefinedBiomeBuilder(BiomeTemplate template, ConfigPack pack) {
this.template = template;
this.pack = pack;
}
@Override
public UserDefinedBiome apply(Long seed) {
NoiseSampler noise;
NoiseSampler elevation;
NoiseSampler carving;
Scope varScope = new Scope().withParent(pack.getVarScope());
template.getVariables().forEach(varScope::create);
Map<String, NoiseSeeded> noiseBuilderMap = pack.getTemplate().getNoiseBuilderMap();
Map<String, FunctionTemplate> functionTemplateMap = new HashMap<>(template.getFunctions());
functionTemplateMap.putAll(template.getFunctions());
try {
noise = new ExpressionSampler(template.getNoiseEquation(), varScope, seed, noiseBuilderMap, functionTemplateMap);
elevation = template.getElevationEquation() == null ? new ConstantSampler(0) : new ExpressionSampler(template.getElevationEquation(), varScope, seed, noiseBuilderMap, functionTemplateMap);
carving = new ExpressionSampler(template.getCarvingEquation(), varScope, seed, noiseBuilderMap, functionTemplateMap);
} catch(ParseException e) {
throw new RuntimeException(e);
}
WorldGenerator generator = new WorldGenerator(template.getPalette(), template.getSlantPalette(), noise, elevation, carving, template.getBiomeNoise().apply(seed), template.getElevationWeight(),
template.getBlendDistance(), template.getBlendStep(), template.getBlendWeight());
return new UserDefinedBiome(template.getVanilla(), generator, template);
}
@Override
public ProbabilityCollection<Biome> getVanillaBiomes() {
return template.getVanilla();
}
}

View File

@@ -29,7 +29,7 @@ public class DummyWorld implements World {
@Override
public ChunkGenerator getGenerator() {
throw new UnsupportedOperationException("Cannot get generator of DummyWorld");
return () -> (ChunkGenerator) () -> null;
}
@Override

View File

@@ -2,12 +2,12 @@ package com.dfsek.terra.config.factories;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.config.builder.UserDefinedBiomeBuilder;
import com.dfsek.terra.config.builder.BiomeBuilder;
import com.dfsek.terra.config.builder.ConfigBuilder;
import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.config.templates.BiomeTemplate;
public class BiomeFactory implements ConfigFactory<BiomeTemplate, ConfigBuilder<TerraBiome>> {
public class BiomeFactory implements ConfigFactory<BiomeTemplate, BiomeBuilder<? extends TerraBiome>> {
private final ConfigPack pack;
public BiomeFactory(ConfigPack pack) {
@@ -15,7 +15,7 @@ public class BiomeFactory implements ConfigFactory<BiomeTemplate, ConfigBuilder<
}
@Override
public BiomeBuilder build(BiomeTemplate template, TerraPlugin main) {
return new BiomeBuilder(template, pack);
public BiomeBuilder<? extends TerraBiome> build(BiomeTemplate template, TerraPlugin main) {
return new UserDefinedBiomeBuilder(template, pack);
}
}

View File

@@ -4,9 +4,9 @@ import com.dfsek.tectonic.exception.LoadException;
import com.dfsek.tectonic.loading.ConfigLoader;
import com.dfsek.tectonic.loading.TypeLoader;
import com.dfsek.terra.api.world.biome.provider.BiomeProvider;
import com.dfsek.terra.config.loaders.config.biome.templates.source.BiomePipelineTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.source.ImageProviderTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.source.SingleBiomeProviderTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.provider.BiomePipelineTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.provider.ImageProviderTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.provider.SingleBiomeProviderTemplate;
import java.lang.reflect.Type;
import java.util.Map;

View File

@@ -7,8 +7,10 @@ import com.dfsek.terra.api.util.collections.ProbabilityCollection;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.api.util.seeded.SourceSeeded;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.pipeline.source.BiomeSource;
import com.dfsek.terra.api.world.biome.pipeline.source.RandomSource;
import com.dfsek.terra.config.loaders.Types;
import com.dfsek.terra.config.loaders.config.biome.templates.source.NoiseSourceTemplate;
import java.lang.reflect.Type;
import java.util.Map;
@@ -19,12 +21,10 @@ public class SourceBuilderLoader implements TypeLoader<SourceSeeded> {
public SourceSeeded load(Type t, Object c, ConfigLoader loader) throws LoadException {
Map<String, Object> source = (Map<String, Object>) c;
String type = source.get("type").toString();
BiomeSource.Type type = loader.loadClass(BiomeSource.Type.class, source.get("type"));
if("NOISE".equals(type)) {
ProbabilityCollection<TerraBiome> sourceBiomes = (ProbabilityCollection<TerraBiome>) loader.loadType(Types.TERRA_BIOME_PROBABILITY_COLLECTION_TYPE, source.get("biomes"));
NoiseSeeded sourceNoise = loader.loadClass(NoiseSeeded.class, source.get("noise"));
return seed -> new RandomSource(sourceBiomes, sourceNoise.apply(seed));
if(type == BiomeSource.Type.NOISE) {
return loader.loadClass(NoiseSourceTemplate.class, source);
}
throw new LoadException("No such loader type: " + type);
}

View File

@@ -1,4 +1,4 @@
package com.dfsek.terra.config.loaders.config.biome.templates.source;
package com.dfsek.terra.config.loaders.config.biome.templates.provider;
import com.dfsek.tectonic.annotations.Default;
import com.dfsek.tectonic.annotations.Value;
@@ -8,7 +8,6 @@ import com.dfsek.terra.api.util.seeded.StageSeeded;
import com.dfsek.terra.api.world.biome.pipeline.BiomePipeline;
import com.dfsek.terra.api.world.biome.provider.BiomeProvider;
import com.dfsek.terra.api.world.biome.provider.StandardBiomeProvider;
import com.dfsek.terra.registry.config.BiomeRegistry;
import java.util.List;
@@ -25,8 +24,7 @@ public class BiomePipelineTemplate extends BiomeProviderTemplate {
@Value("pipeline.source")
private SourceSeeded source;
public BiomePipelineTemplate(BiomeRegistry registry, TerraPlugin main) {
super(registry);
public BiomePipelineTemplate(TerraPlugin main) {
this.main = main;
}

View File

@@ -1,18 +1,14 @@
package com.dfsek.terra.config.loaders.config.biome.templates.source;
package com.dfsek.terra.config.loaders.config.biome.templates.provider;
import com.dfsek.tectonic.annotations.Default;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.tectonic.loading.object.ObjectTemplate;
import com.dfsek.terra.api.math.noise.NoiseSampler;
import com.dfsek.terra.api.math.noise.samplers.noise.ConstantSampler;
import com.dfsek.terra.api.registry.Registry;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.provider.BiomeProvider;
import com.dfsek.terra.registry.config.BiomeRegistry;
public abstract class BiomeProviderTemplate implements ObjectTemplate<BiomeProvider.BiomeProviderBuilder>, BiomeProvider.BiomeProviderBuilder {
protected final Registry<TerraBiome> registry;
@Value("resolution")
@Default
protected int resolution = 1;
@@ -35,10 +31,6 @@ public abstract class BiomeProviderTemplate implements ObjectTemplate<BiomeProvi
@Value("type")
BiomeProvider.Type type;
protected BiomeProviderTemplate(Registry<TerraBiome> registry) {
this.registry = registry;
}
@Override
public BiomeProvider.BiomeProviderBuilder get() {
return this;

View File

@@ -1,27 +1,29 @@
package com.dfsek.terra.config.loaders.config.biome.templates.source;
package com.dfsek.terra.config.loaders.config.biome.templates.provider;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.api.registry.Registry;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.provider.BiomeProvider;
import com.dfsek.terra.api.world.biome.provider.ImageBiomeProvider;
import com.dfsek.terra.registry.config.BiomeRegistry;
import com.dfsek.terra.config.builder.BiomeBuilder;
import java.awt.image.BufferedImage;
import java.util.stream.Collectors;
public class ImageProviderTemplate extends BiomeProviderTemplate {
private final Registry<BiomeBuilder<? extends TerraBiome>> biomes;
@Value("image.name")
private BufferedImage image;
@Value("image.align")
private ImageBiomeProvider.Align align;
public ImageProviderTemplate(Registry<TerraBiome> registry) {
super(registry);
public ImageProviderTemplate(Registry<BiomeBuilder<? extends TerraBiome>> set) {
this.biomes = set;
}
@Override
public BiomeProvider build(long seed) {
return new ImageBiomeProvider(registry, image, resolution, align);
return new ImageBiomeProvider(biomes.entries().stream().map(biomeBuilder -> biomeBuilder.apply(seed)).collect(Collectors.toSet()), image, resolution, align);
}
}

View File

@@ -1,17 +1,15 @@
package com.dfsek.terra.config.loaders.config.biome.templates.source;
package com.dfsek.terra.config.loaders.config.biome.templates.provider;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.provider.BiomeProvider;
import com.dfsek.terra.api.world.biome.provider.SingleBiomeProvider;
import com.dfsek.terra.registry.config.BiomeRegistry;
public class SingleBiomeProviderTemplate extends BiomeProviderTemplate {
@Value("biome")
private TerraBiome biome;
public SingleBiomeProviderTemplate(BiomeRegistry registry) {
super(registry);
public SingleBiomeProviderTemplate() {
}
@Override

View File

@@ -0,0 +1,22 @@
package com.dfsek.terra.config.loaders.config.biome.templates.source;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.api.util.collections.ProbabilityCollection;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.pipeline.source.BiomeSource;
import com.dfsek.terra.api.world.biome.pipeline.source.RandomSource;
import com.dfsek.terra.config.builder.BiomeBuilder;
public class NoiseSourceTemplate extends SourceTemplate {
@Value("noise")
private NoiseSeeded noise;
@Value("biomes")
private ProbabilityCollection<BiomeBuilder<? extends TerraBiome>> biomes;
@Override
public BiomeSource apply(Long seed) {
return new RandomSource(biomes.map((biome) -> biome.apply(seed), false), noise.apply(seed));
}
}

View File

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

View File

@@ -5,7 +5,10 @@ import com.dfsek.terra.api.util.collections.ProbabilityCollection;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.pipeline.mutator.BiomeMutator;
import com.dfsek.terra.api.world.biome.pipeline.mutator.BorderListMutator;
import com.dfsek.terra.config.builder.BiomeBuilder;
import com.dfsek.terra.config.builder.UserDefinedBiomeBuilder;
import java.util.HashMap;
import java.util.Map;
public class BorderListMutatorTemplate extends MutatorStageTemplate {
@@ -16,14 +19,18 @@ public class BorderListMutatorTemplate extends MutatorStageTemplate {
private String defaultReplace;
@Value("default-to")
private ProbabilityCollection<TerraBiome> defaultTo;
private ProbabilityCollection<UserDefinedBiomeBuilder> defaultTo;
@Value("replace")
private Map<TerraBiome, ProbabilityCollection<TerraBiome>> replace;
private Map<BiomeBuilder<? extends TerraBiome>, ProbabilityCollection<BiomeBuilder<? extends TerraBiome>>> replace;
@Override
public BiomeMutator build(long seed) {
return new BorderListMutator(replace, from, defaultReplace, noise.apply(seed), defaultTo);
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 BorderListMutator(replaceMap, from, defaultReplace, noise.apply(seed), defaultTo.map(biomeBuilder -> biomeBuilder.apply(seed), true));
}
}

View File

@@ -5,6 +5,8 @@ import com.dfsek.terra.api.util.collections.ProbabilityCollection;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.pipeline.mutator.BiomeMutator;
import com.dfsek.terra.api.world.biome.pipeline.mutator.BorderMutator;
import com.dfsek.terra.config.builder.BiomeBuilder;
import com.dfsek.terra.config.builder.UserDefinedBiomeBuilder;
@SuppressWarnings("unused")
public class BorderMutatorTemplate extends MutatorStageTemplate {
@@ -15,10 +17,10 @@ public class BorderMutatorTemplate extends MutatorStageTemplate {
private String replace;
@Value("to")
private ProbabilityCollection<TerraBiome> to;
private ProbabilityCollection<BiomeBuilder<? extends TerraBiome>> to;
@Override
public BiomeMutator build(long seed) {
return new BorderMutator(from, replace, noise.apply(seed), to);
return new BorderMutator(from, replace, noise.apply(seed), to.map(biomeBuilder -> biomeBuilder.apply(seed), true));
}
}

View File

@@ -5,7 +5,10 @@ import com.dfsek.terra.api.util.collections.ProbabilityCollection;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.pipeline.mutator.BiomeMutator;
import com.dfsek.terra.api.world.biome.pipeline.mutator.ReplaceListMutator;
import com.dfsek.terra.config.builder.BiomeBuilder;
import com.dfsek.terra.config.builder.UserDefinedBiomeBuilder;
import java.util.HashMap;
import java.util.Map;
@SuppressWarnings("unused")
@@ -14,13 +17,17 @@ public class ReplaceListMutatorTemplate extends MutatorStageTemplate {
private String defaultFrom;
@Value("default-to")
private ProbabilityCollection<TerraBiome> defaultTo;
private ProbabilityCollection<BiomeBuilder<? extends TerraBiome>> defaultTo;
@Value("to")
private Map<TerraBiome, ProbabilityCollection<TerraBiome>> replace;
private Map<BiomeBuilder<? extends TerraBiome>, ProbabilityCollection<BiomeBuilder<? extends TerraBiome>>> replace;
@Override
public BiomeMutator build(long seed) {
return new ReplaceListMutator(replace, defaultFrom, defaultTo, noise.apply(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));
}
}

View File

@@ -5,6 +5,8 @@ import com.dfsek.terra.api.util.collections.ProbabilityCollection;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.pipeline.mutator.BiomeMutator;
import com.dfsek.terra.api.world.biome.pipeline.mutator.ReplaceMutator;
import com.dfsek.terra.config.builder.BiomeBuilder;
import com.dfsek.terra.config.builder.UserDefinedBiomeBuilder;
@SuppressWarnings("unused")
public class ReplaceMutatorTemplate extends MutatorStageTemplate {
@@ -12,10 +14,10 @@ public class ReplaceMutatorTemplate extends MutatorStageTemplate {
private String from;
@Value("to")
private ProbabilityCollection<TerraBiome> to;
private ProbabilityCollection<BiomeBuilder<? extends TerraBiome>> to;
@Override
public BiomeMutator build(long seed) {
return new ReplaceMutator(from, to, noise.apply(seed));
return new ReplaceMutator(from, to.map(biomeBuilder -> biomeBuilder.apply(seed), true), noise.apply(seed));
}
}

View File

@@ -23,7 +23,8 @@ import com.dfsek.terra.api.world.flora.Flora;
import com.dfsek.terra.api.world.palette.Palette;
import com.dfsek.terra.api.world.tree.Tree;
import com.dfsek.terra.carving.UserDefinedCarver;
import com.dfsek.terra.config.builder.ConfigBuilder;
import com.dfsek.terra.config.builder.UserDefinedBiomeBuilder;
import com.dfsek.terra.config.builder.BiomeBuilder;
import com.dfsek.terra.config.dummy.DummyWorld;
import com.dfsek.terra.config.factories.BiomeFactory;
import com.dfsek.terra.config.factories.CarverFactory;
@@ -37,9 +38,9 @@ import com.dfsek.terra.config.fileloaders.FolderLoader;
import com.dfsek.terra.config.fileloaders.Loader;
import com.dfsek.terra.config.fileloaders.ZIPLoader;
import com.dfsek.terra.config.loaders.config.BufferedImageLoader;
import com.dfsek.terra.config.loaders.config.biome.templates.source.BiomePipelineTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.source.ImageProviderTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.source.SingleBiomeProviderTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.provider.BiomePipelineTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.provider.ImageProviderTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.provider.SingleBiomeProviderTemplate;
import com.dfsek.terra.config.loaders.config.sampler.NoiseSamplerBuilderLoader;
import com.dfsek.terra.config.loaders.config.sampler.templates.ImageSamplerTemplate;
import com.dfsek.terra.config.templates.AbstractableTemplate;
@@ -263,7 +264,7 @@ public class ConfigPack implements LoaderRegistrar {
public void register(TypeRegistry registry) {
registry
.registerLoader(Palette.class, paletteRegistry)
.registerLoader(TerraBiome.class, biomeRegistry)
.registerLoader(BiomeBuilder.class, biomeRegistry)
.registerLoader(Flora.class, floraRegistry)
.registerLoader(Ore.class, oreRegistry)
.registerLoader(Tree.class, treeRegistry)
@@ -273,8 +274,8 @@ public class ConfigPack implements LoaderRegistrar {
.registerLoader(UserDefinedCarver.class, carverRegistry)
.registerLoader(BufferedImage.class, new BufferedImageLoader(loader))
.registerLoader(NoiseSeeded.class, new NoiseSamplerBuilderLoader(noiseRegistry))
.registerLoader(SingleBiomeProviderTemplate.class, () -> new SingleBiomeProviderTemplate(biomeRegistry))
.registerLoader(BiomePipelineTemplate.class, () -> new BiomePipelineTemplate(biomeRegistry, main))
.registerLoader(SingleBiomeProviderTemplate.class, SingleBiomeProviderTemplate::new)
.registerLoader(BiomePipelineTemplate.class, () -> new BiomePipelineTemplate(main))
.registerLoader(ImageSamplerTemplate.class, () -> new ImageProviderTemplate(biomeRegistry));
}
@@ -290,7 +291,7 @@ public class ConfigPack implements LoaderRegistrar {
return new CheckedRegistry<>(scriptRegistry);
}
public CheckedRegistry<ConfigBuilder<TerraBiome>> getBiomeRegistry() {
public CheckedRegistry<BiomeBuilder<? extends TerraBiome>> getBiomeRegistry() {
return new CheckedRegistry<>(biomeRegistry);
}

View File

@@ -48,7 +48,7 @@ public class WorldConfig {
this.scriptRegistry = new LockedRegistry<>(pack.getScriptRegistry());
OpenRegistry<TerraBiome> biomeOpenRegistry = new OpenRegistry<>();
pack.getBiomeRegistry().forEach((id, biome) -> biomeOpenRegistry.add(id, biome.build(world, main)));
pack.getBiomeRegistry().forEach((id, biome) -> biomeOpenRegistry.add(id, biome.apply(world.getWorld().getSeed())));
this.biomeRegistry = new LockedRegistry<>(biomeOpenRegistry);
this.carverRegistry = new LockedRegistry<>(pack.getCarverRegistry());

View File

@@ -3,16 +3,16 @@ package com.dfsek.terra.registry.config;
import com.dfsek.tectonic.exception.LoadException;
import com.dfsek.tectonic.loading.ConfigLoader;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.config.builder.ConfigBuilder;
import com.dfsek.terra.config.builder.BiomeBuilder;
import com.dfsek.terra.registry.OpenRegistry;
import java.lang.reflect.Type;
public class BiomeRegistry extends OpenRegistry<ConfigBuilder<TerraBiome>> {
public class BiomeRegistry extends OpenRegistry<BiomeBuilder<? extends TerraBiome>> {
@Override
public ConfigBuilder<TerraBiome> load(Type type, Object o, ConfigLoader configLoader) throws LoadException {
public BiomeBuilder<? extends TerraBiome> load(Type type, Object o, ConfigLoader configLoader) throws LoadException {
if(o.equals("SELF")) return null;
ConfigBuilder<TerraBiome> biome = get((String) o);
BiomeBuilder<? extends TerraBiome> biome = get((String) o);
if(biome == null)
throw new LoadException("No such " + type.getTypeName() + " matching \"" + o + "\" was found in this registry.");
return biome;

View File

@@ -28,10 +28,10 @@ public class TerraWorld {
public TerraWorld(World w, ConfigPack c, TerraPlugin main) {
if(!isTerraWorld(w)) throw new IllegalArgumentException("World " + w + " is not a Terra World!");
config = c.toWorldConfig(this);
profiler = new WorldProfiler(w);
this.provider = config.getProvider();
this.world = w;
config = c.toWorldConfig(this);
this.provider = config.getProvider();
profiler = new WorldProfiler(w);
air = main.getWorldHandle().createBlockData("minecraft:air");
main.getEventManager().callEvent(new TerraWorldLoadEvent(this));
safe = true;

View File

@@ -121,11 +121,6 @@ public class DefaultChunkGenerator2D implements TerraChunkGenerator {
DefaultChunkGenerator3D.biomes(world, chunkX, chunkZ, biome, main);
}
@Override
public SamplerCache getCache() {
return cache;
}
@Override
public Sampler createSampler(int chunkX, int chunkZ, BiomeProvider provider, World world, int elevationSmooth) {
return new Sampler2D(chunkX, chunkZ, provider, world, elevationSmooth);

View File

@@ -26,7 +26,6 @@ import com.dfsek.terra.profiler.ProfileFuture;
import com.dfsek.terra.world.Carver;
import com.dfsek.terra.world.TerraWorld;
import com.dfsek.terra.world.carving.NoiseCarver;
import com.dfsek.terra.world.generation.math.SamplerCache;
import com.dfsek.terra.world.generation.math.samplers.Sampler;
import com.dfsek.terra.world.generation.math.samplers.Sampler3D;
import org.jetbrains.annotations.NotNull;
@@ -42,16 +41,14 @@ public class DefaultChunkGenerator3D implements TerraChunkGenerator {
private final Carver carver;
private final SamplerCache cache;
public DefaultChunkGenerator3D(ConfigPack c, TerraPlugin main, SamplerCache cache) {
public DefaultChunkGenerator3D(ConfigPack c, TerraPlugin main) {
this.configPack = c;
this.main = main;
carver = new NoiseCarver(new Range(0, 255), main.getWorldHandle().createBlockData("minecraft:air"), main);
water = main.getWorldHandle().createBlockData("minecraft:water").getBlockType();
blank = new SinglePalette<>(main.getWorldHandle().createBlockData("minecraft:air"));
this.cache = cache;
}
@Override
@@ -99,7 +96,7 @@ public class DefaultChunkGenerator3D implements TerraChunkGenerator {
int xOrig = (chunkX << 4);
int zOrig = (chunkZ << 4);
Sampler sampler = cache.getChunk(chunkX, chunkZ);
Sampler sampler = tw.getConfig().getSamplerCache().getChunk(chunkX, chunkZ);
for(int x = 0; x < 16; x++) {
for(int z = 0; z < 16; z++) {
@@ -235,11 +232,6 @@ public class DefaultChunkGenerator3D implements TerraChunkGenerator {
biomes(world, chunkX, chunkZ, biome, main);
}
@Override
public SamplerCache getCache() {
return cache;
}
@Override
public Sampler createSampler(int chunkX, int chunkZ, BiomeProvider provider, World world, int elevationSmooth) {
return new Sampler3D(chunkX, chunkZ, provider, world, elevationSmooth);

View File

@@ -40,4 +40,9 @@ public class SamplerCache {
long key = MathUtil.squash(cx, cz);
return cache.getUnchecked(key);
}
public void clear() {
cache.invalidateAll();
cache.cleanUp();
}
}

View File

@@ -27,14 +27,15 @@ import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.provider.BiomeProvider;
import com.dfsek.terra.config.GenericLoaders;
import com.dfsek.terra.config.PluginConfig;
import com.dfsek.terra.config.builder.BiomeBuilder;
import com.dfsek.terra.config.fileloaders.FolderLoader;
import com.dfsek.terra.config.lang.Language;
import com.dfsek.terra.config.loaders.ProbabilityCollectionLoader;
import com.dfsek.terra.config.loaders.config.BufferedImageLoader;
import com.dfsek.terra.config.loaders.config.biome.BiomeProviderBuilderLoader;
import com.dfsek.terra.config.loaders.config.biome.templates.source.BiomePipelineTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.source.ImageProviderTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.source.SingleBiomeProviderTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.provider.BiomePipelineTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.provider.ImageProviderTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.provider.SingleBiomeProviderTemplate;
import com.dfsek.terra.config.loaders.config.sampler.NoiseSamplerBuilderLoader;
import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.config.templates.AbstractableTemplate;
@@ -157,10 +158,10 @@ public class DistributionTest {
ConfigLoader pipeLoader = new ConfigLoader()
.registerLoader(BiomeProvider.BiomeProviderBuilder.class, new BiomeProviderBuilderLoader())
.registerLoader(ProbabilityCollection.class, new ProbabilityCollectionLoader())
.registerLoader(TerraBiome.class, biomeRegistry)
.registerLoader(BiomeBuilder.class, biomeRegistry)
.registerLoader(BufferedImage.class, new BufferedImageLoader(folderLoader))
.registerLoader(SingleBiomeProviderTemplate.class, () -> new SingleBiomeProviderTemplate(biomeRegistry))
.registerLoader(BiomePipelineTemplate.class, () -> new BiomePipelineTemplate(biomeRegistry, MAIN))
.registerLoader(SingleBiomeProviderTemplate.class, SingleBiomeProviderTemplate::new)
.registerLoader(BiomePipelineTemplate.class, () -> new BiomePipelineTemplate(MAIN))
.registerLoader(ImageProviderTemplate.class, () -> new ImageProviderTemplate(biomeRegistry));
new GenericLoaders(null).register(pipeLoader);
@@ -285,7 +286,7 @@ public class DistributionTest {
}
}
private static final class TestBiome extends AbstractableTemplate implements TerraBiome, ValidatedConfigTemplate {
private static final class TestBiome extends AbstractableTemplate implements TerraBiome, ValidatedConfigTemplate, BiomeBuilder<TestBiome> {
@Value("color")
@Default
@@ -336,5 +337,10 @@ public class DistributionTest {
public String toString() {
return id;
}
@Override
public TestBiome apply(Long aLong) {
return this;
}
}
}

View File

@@ -48,7 +48,7 @@ public class ImageTest {
};
folderLoader.open("biomes", ".yml").then(inputStreams -> ConfigPack.buildAll((template, main) -> template, biomeRegistry, loader.load(inputStreams, TestBiome::new), null));
return new ImageBiomeProvider(biomeRegistry, ImageIO.read(ImageTest.class.getResourceAsStream("/map.jpg")), 1, ImageBiomeProvider.Align.CENTER);
return new ImageBiomeProvider(biomeRegistry.entries(), ImageIO.read(ImageTest.class.getResourceAsStream("/map.jpg")), 1, ImageBiomeProvider.Align.CENTER);
}
@Test