completely redo biome loading

This commit is contained in:
dfsek 2021-02-14 14:19:45 -07:00
parent 36db83b253
commit b6e414f944
21 changed files with 261 additions and 330 deletions

View File

@ -0,0 +1,6 @@
package com.dfsek.terra.api.util.seeded;
import com.dfsek.terra.biome.pipeline.source.BiomeSource;
public interface SourceSeeded extends SeededBuilder<BiomeSource> {
}

View File

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

View File

@ -2,7 +2,7 @@ package com.dfsek.terra.biome.pipeline;
import com.dfsek.terra.api.math.vector.Vector2;
import com.dfsek.terra.api.util.GlueList;
import com.dfsek.terra.api.util.seeded.SeededBuilder;
import com.dfsek.terra.api.util.seeded.StageSeeded;
import com.dfsek.terra.biome.pipeline.source.BiomeSource;
import com.dfsek.terra.biome.pipeline.stages.Stage;
@ -42,7 +42,7 @@ public class BiomePipeline {
public static final class BiomePipelineBuilder {
private final int init;
List<SeededBuilder<Stage>> stages = new GlueList<>();
List<StageSeeded> stages = new GlueList<>();
private int expand;
public BiomePipelineBuilder(int init) {
@ -60,7 +60,7 @@ public class BiomePipeline {
return new BiomePipeline(source, stagesBuilt, expand, init);
}
public BiomePipelineBuilder addStage(SeededBuilder<Stage> stage) {
public BiomePipelineBuilder addStage(StageSeeded stage) {
stages.add(stage);
return this;
}

View File

@ -23,4 +23,8 @@ public interface BiomeProvider {
interface BiomeProviderBuilder {
BiomeProvider build(long seed);
}
enum Type {
IMAGE, PIPELINE, SINGLE
}
}

View File

@ -1,10 +1,8 @@
package com.dfsek.terra.biome.provider;
import com.dfsek.tectonic.exception.ConfigException;
import com.dfsek.terra.api.core.TerraPlugin;
import com.dfsek.terra.api.math.noise.NoiseSampler;
import com.dfsek.terra.api.math.vector.Vector2;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.biome.TerraBiome;
import com.dfsek.terra.biome.pipeline.BiomeHolder;
import com.dfsek.terra.biome.pipeline.BiomePipeline;
@ -17,12 +15,13 @@ import org.jetbrains.annotations.NotNull;
public class StandardBiomeProvider implements BiomeProvider {
private final LoadingCache<Vector2, BiomeHolder> holderCache;
private final BiomePipeline pipeline;
private int resolution = 1;
private final int resolution;
private final NoiseSampler mutator;
private final double noiseAmp;
private final int seed;
protected StandardBiomeProvider(BiomePipeline pipeline, TerraPlugin main, NoiseSampler mutator, double noiseAmp, int seed) {
public StandardBiomeProvider(BiomePipeline pipeline, TerraPlugin main, int resolution, NoiseSampler mutator, double noiseAmp, int seed) {
this.resolution = resolution;
this.mutator = mutator;
this.noiseAmp = noiseAmp;
this.seed = seed;
@ -53,52 +52,4 @@ public class StandardBiomeProvider implements BiomeProvider {
int fdZ = FastMath.floorDiv(z, pipeline.getSize());
return holderCache.getUnchecked(new Vector2(fdX, fdZ)).getBiome(x - fdX * pipeline.getSize(), z - fdZ * pipeline.getSize());
}
public int getResolution() {
return resolution;
}
public void setResolution(int resolution) {
this.resolution = resolution;
}
public interface ExceptionalFunction<I, O> {
O apply(I in) throws ConfigException;
}
public static final class StandardBiomeProviderBuilder implements BiomeProviderBuilder {
private final ExceptionalFunction<Long, BiomePipeline> pipelineBuilder;
private final TerraPlugin main;
private int resolution = 1;
private double noiseAmp = 2;
private NoiseSeeded builder;
public StandardBiomeProviderBuilder(ExceptionalFunction<Long, BiomePipeline> pipelineBuilder, TerraPlugin main) {
this.pipelineBuilder = pipelineBuilder;
this.main = main;
}
public void setResolution(int resolution) {
this.resolution = resolution;
}
public void setBlender(NoiseSeeded builder) {
this.builder = builder;
}
public void setNoiseAmp(double noiseAmp) {
this.noiseAmp = noiseAmp;
}
@Override
public StandardBiomeProvider build(long seed) {
try {
StandardBiomeProvider provider = new StandardBiomeProvider(pipelineBuilder.apply(seed), main, builder.apply(seed), noiseAmp, (int) seed);
provider.setResolution(resolution);
return provider;
} catch(ConfigException e) {
throw new RuntimeException(e);
}
}
}
}

View File

@ -10,10 +10,14 @@ import com.dfsek.terra.api.math.noise.normalizer.Normalizer;
import com.dfsek.terra.api.math.noise.samplers.FastNoiseLite;
import com.dfsek.terra.api.math.noise.samplers.ImageSampler;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.api.util.seeded.SourceSeeded;
import com.dfsek.terra.api.util.seeded.StageSeeded;
import com.dfsek.terra.api.world.palette.holder.PaletteHolder;
import com.dfsek.terra.api.world.palette.holder.PaletteLayerHolder;
import com.dfsek.terra.biome.pipeline.stages.ExpanderStage;
import com.dfsek.terra.biome.pipeline.stages.MutatorStage;
import com.dfsek.terra.biome.provider.BiomeProvider;
import com.dfsek.terra.biome.provider.ImageBiomeProvider;
import com.dfsek.terra.carving.CarverPalette;
import com.dfsek.terra.config.loaders.LinkedHashMapLoader;
import com.dfsek.terra.config.loaders.MaterialSetLoader;
@ -24,6 +28,9 @@ import com.dfsek.terra.config.loaders.config.GridSpawnLoader;
import com.dfsek.terra.config.loaders.config.OreConfigLoader;
import com.dfsek.terra.config.loaders.config.OreHolderLoader;
import com.dfsek.terra.config.loaders.config.TreeLayerLoader;
import com.dfsek.terra.config.loaders.config.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.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;
@ -75,7 +82,6 @@ public class GenericLoaders implements LoaderRegistrar {
.registerLoader(DomainWarpTemplate.class, DomainWarpTemplate::new)
.registerLoader(LinearNormalizerTemplate.class, LinearNormalizerTemplate::new)
.registerLoader(NormalNormalizerTemplate.class, NormalNormalizerTemplate::new)
.registerLoader(FastNoiseTemplate.class, FastNoiseTemplate::new)
.registerLoader(NoiseSeeded.class, new NoiseSamplerBuilderLoader())
.registerLoader(ReplaceMutatorTemplate.class, ReplaceMutatorTemplate::new)
.registerLoader(ExpanderStageTemplate.class, ExpanderStageTemplate::new)
@ -86,7 +92,12 @@ public class GenericLoaders implements LoaderRegistrar {
.registerLoader(FunctionTemplate.class, FunctionTemplate::new)
.registerLoader(LinkedHashMap.class, new LinkedHashMapLoader())
.registerLoader(CarverPalette.class, new CarverPaletteLoader())
.registerLoader(SourceSeeded.class, new SourceBuilderLoader())
.registerLoader(StageSeeded.class, new StageBuilderLoader())
.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(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))
.registerLoader(FastNoiseLite.NoiseType.class, (t, object, cf) -> FastNoiseLite.NoiseType.valueOf((String) object))

View File

@ -3,88 +3,31 @@ package com.dfsek.terra.config.loaders.config.biome;
import com.dfsek.tectonic.exception.LoadException;
import com.dfsek.tectonic.loading.ConfigLoader;
import com.dfsek.tectonic.loading.TypeLoader;
import com.dfsek.terra.api.core.TerraPlugin;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.api.util.seeded.SeededBuilder;
import com.dfsek.terra.biome.TerraBiome;
import com.dfsek.terra.biome.pipeline.BiomePipeline;
import com.dfsek.terra.biome.pipeline.source.BiomeSource;
import com.dfsek.terra.biome.provider.BiomeProvider;
import com.dfsek.terra.biome.provider.ImageBiomeProvider;
import com.dfsek.terra.biome.provider.SingleBiomeProvider;
import com.dfsek.terra.biome.provider.StandardBiomeProvider;
import com.dfsek.terra.config.fileloaders.Loader;
import com.dfsek.terra.registry.TerraRegistry;
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 javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
@SuppressWarnings("unchecked")
public class BiomeProviderBuilderLoader implements TypeLoader<BiomeProvider.BiomeProviderBuilder> {
private final TerraPlugin main;
private final TerraRegistry<TerraBiome> biomeRegistry;
private final Loader fileLoader;
public BiomeProviderBuilderLoader(TerraPlugin main, TerraRegistry<TerraBiome> biomeRegistry, Loader fileLoader) {
this.main = main;
this.biomeRegistry = biomeRegistry;
this.fileLoader = fileLoader;
public BiomeProviderBuilderLoader() {
}
@Override
public BiomeProvider.BiomeProviderBuilder load(Type t, Object c, ConfigLoader loader) throws LoadException { // TODO: clean this up
Map<String, Object> map = (Map<String, Object>) c;
int resolution = (Integer) map.getOrDefault("resolution", 1);
if(map.get("type").equals("PIPELINE")) {
Map<String, Object> pipeline = (Map<String, Object>) map.get("pipeline");
List<Map<String, Object>> stages = (List<Map<String, Object>>) pipeline.get("stages");
if(stages == null) throw new LoadException("No pipeline stages defined!");
int init = (Integer) pipeline.getOrDefault("initial-size", 2);
StandardBiomeProvider.StandardBiomeProviderBuilder builder = new StandardBiomeProvider.StandardBiomeProviderBuilder(seed -> {
BiomePipeline.BiomePipelineBuilder pipelineBuilder = new BiomePipeline.BiomePipelineBuilder(init);
for(Map<String, Object> stage : stages) {
for(Map.Entry<String, Object> entry : stage.entrySet()) {
pipelineBuilder.addStage(new StageBuilderLoader().load(SeededBuilder.class, entry, loader));
}
}
if(!pipeline.containsKey("source")) throw new LoadException("Biome Source not defined!");
SeededBuilder<BiomeSource> source = new SourceBuilderLoader().load(BiomeSource.class, pipeline.get("source"), loader);
BiomePipeline biomePipeline = pipelineBuilder.build(source.apply(seed), seed);
main.getDebugLogger().info("Biome Pipeline scale factor: " + biomePipeline.getSize());
return biomePipeline;
}, main);
builder.setResolution(resolution);
if(map.containsKey("blend")) {
Map<String, Object> blend = (Map<String, Object>) map.get("blend");
if(blend.containsKey("amplitude")) builder.setNoiseAmp(Double.parseDouble(blend.get("amplitude").toString()));
if(blend.containsKey("noise"))
builder.setBlender(loader.loadClass(NoiseSeeded.class, blend.get("noise")));
}
return builder;
} else if(map.get("type").equals("IMAGE")) {
Map<String, Object> imageMap = (Map<String, Object>) map.get("image");
try {
main.getLogger().info("Using image " + imageMap.get("name") + " for biome distribution.");
BufferedImage image = ImageIO.read(fileLoader.get(imageMap.get("name").toString()));
return new ImageBiomeProvider(biomeRegistry, image, resolution, ImageBiomeProvider.Align.valueOf((String) imageMap.getOrDefault("align", "CENTER")));
} catch(IOException e) {
throw new LoadException("Failed to load image", e);
}
} else if(map.get("type").equals("SINGLE")) {
return new SingleBiomeProvider(loader.loadClass(TerraBiome.class, map.get("biome")));
switch(loader.loadClass(BiomeProvider.Type.class, map.get("type"))) {
case IMAGE:
return loader.loadClass(ImageProviderTemplate.class, map);
case PIPELINE:
return loader.loadClass(BiomePipelineTemplate.class, map);
case SINGLE:
return loader.loadClass(SingleBiomeProviderTemplate.class, map);
}
throw new LoadException("No such biome provider type: " + map.get("type"));

View File

@ -5,9 +5,8 @@ import com.dfsek.tectonic.loading.ConfigLoader;
import com.dfsek.tectonic.loading.TypeLoader;
import com.dfsek.terra.api.math.ProbabilityCollection;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.api.util.seeded.SeededBuilder;
import com.dfsek.terra.api.util.seeded.SourceSeeded;
import com.dfsek.terra.biome.TerraBiome;
import com.dfsek.terra.biome.pipeline.source.BiomeSource;
import com.dfsek.terra.biome.pipeline.source.RandomSource;
import com.dfsek.terra.config.loaders.Types;
@ -15,9 +14,9 @@ import java.lang.reflect.Type;
import java.util.Map;
@SuppressWarnings("unchecked")
public class SourceBuilderLoader implements TypeLoader<SeededBuilder<BiomeSource>> {
public class SourceBuilderLoader implements TypeLoader<SourceSeeded> {
@Override
public SeededBuilder<BiomeSource> load(Type t, Object c, ConfigLoader loader) throws LoadException {
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();

View File

@ -3,10 +3,9 @@ package com.dfsek.terra.config.loaders.config.biome;
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.SeededBuilder;
import com.dfsek.terra.api.util.seeded.StageSeeded;
import com.dfsek.terra.biome.pipeline.stages.ExpanderStage;
import com.dfsek.terra.biome.pipeline.stages.MutatorStage;
import com.dfsek.terra.biome.pipeline.stages.Stage;
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;
@ -18,33 +17,40 @@ import java.lang.reflect.Type;
import java.util.Map;
@SuppressWarnings("unchecked")
public class StageBuilderLoader implements TypeLoader<SeededBuilder<Stage>> {
public class StageBuilderLoader implements TypeLoader<StageSeeded> {
@Override
public SeededBuilder<Stage> load(Type t, Object c, ConfigLoader loader) throws LoadException {
Map.Entry<String, Object> entry = (Map.Entry<String, Object>) c;
public StageSeeded load(Type 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());
Map.Entry<String, Object> entry = null;
for(Map.Entry<String, Object> e : raw.entrySet()) {
entry = e;
}
Map<String, Object> mutator = (Map<String, Object>) entry.getValue();
if(entry.getKey().equals("expand")) {
ExpanderStage.Type stageType = loader.loadClass(ExpanderStage.Type.class, mutator.get("type"));
if(stageType.equals(ExpanderStage.Type.FRACTAL)) {
return loader.loadClass(ExpanderStageTemplate.class, mutator).get();
return loader.loadClass(ExpanderStageTemplate.class, mutator);
} else throw new LoadException("No such expander \"" + stageType + "\"");
} else if(entry.getKey().equals("mutate")) {
switch(loader.loadClass(MutatorStage.Type.class, mutator.get("type"))) {
case SMOOTH:
return loader.loadClass(SmoothMutatorTemplate.class, mutator).get();
return loader.loadClass(SmoothMutatorTemplate.class, mutator);
case REPLACE:
return loader.loadClass(ReplaceMutatorTemplate.class, mutator).get();
return loader.loadClass(ReplaceMutatorTemplate.class, mutator);
case REPLACE_LIST:
return loader.loadClass(ReplaceListMutatorTemplate.class, mutator).get();
return loader.loadClass(ReplaceListMutatorTemplate.class, mutator);
case BORDER:
return loader.loadClass(BorderMutatorTemplate.class, mutator).get();
return loader.loadClass(BorderMutatorTemplate.class, mutator);
case BORDER_LIST:
return loader.loadClass(BorderListMutatorTemplate.class, mutator).get();
return loader.loadClass(BorderListMutatorTemplate.class, mutator);
default:
throw new LoadException("No such mutator type \"" + mutator.get("type"));
}
}
throw new LoadException("No such mutator \"" + entry.getKey() + "\"");

View File

@ -0,0 +1,41 @@
package com.dfsek.terra.config.loaders.config.biome.templates.source;
import com.dfsek.tectonic.annotations.Default;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.api.core.TerraPlugin;
import com.dfsek.terra.api.util.seeded.SourceSeeded;
import com.dfsek.terra.api.util.seeded.StageSeeded;
import com.dfsek.terra.biome.pipeline.BiomePipeline;
import com.dfsek.terra.biome.provider.BiomeProvider;
import com.dfsek.terra.biome.provider.StandardBiomeProvider;
import com.dfsek.terra.registry.BiomeRegistry;
import java.util.List;
@SuppressWarnings({"FieldMayBeFinal", "unused"})
public class BiomePipelineTemplate extends BiomeProviderTemplate {
private final TerraPlugin main;
@Value("pipeline.initial-size")
@Default
private int initialSize = 2;
@Value("pipeline.stages")
private List<StageSeeded> stages;
@Value("pipeline.source")
private SourceSeeded source;
public BiomePipelineTemplate(BiomeRegistry registry, TerraPlugin main) {
super(registry);
this.main = main;
}
@Override
public BiomeProvider build(long seed) {
BiomePipeline.BiomePipelineBuilder biomePipelineBuilder = new BiomePipeline.BiomePipelineBuilder(initialSize);
System.out.println(stages);
stages.forEach(biomePipelineBuilder::addStage);
BiomePipeline pipeline = biomePipelineBuilder.build(source.apply(seed), seed);
return new StandardBiomeProvider(pipeline, main, resolution, blend.apply(seed), blendAmp, (int) seed);
}
}

View File

@ -0,0 +1,44 @@
package com.dfsek.terra.config.loaders.config.biome.templates.source;
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.ConstantSampler;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.biome.provider.BiomeProvider;
import com.dfsek.terra.registry.BiomeRegistry;
public abstract class BiomeProviderTemplate implements ObjectTemplate<BiomeProvider.BiomeProviderBuilder>, BiomeProvider.BiomeProviderBuilder {
protected final BiomeRegistry registry;
@Value("resolution")
@Default
protected int resolution = 1;
@Value("blend.noise")
@Default
protected NoiseSeeded blend = new NoiseSeeded() {
@Override
public NoiseSampler apply(Long seed) {
return new ConstantSampler(0);
}
@Override
public int getDimensions() {
return 2;
}
};
@Value("blend.amplitude")
@Default
protected double blendAmp = 0d;
@Value("type")
BiomeProvider.Type type;
protected BiomeProviderTemplate(BiomeRegistry registry) {
this.registry = registry;
}
@Override
public BiomeProvider.BiomeProviderBuilder get() {
return this;
}
}

View File

@ -0,0 +1,25 @@
package com.dfsek.terra.config.loaders.config.biome.templates.source;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.biome.provider.BiomeProvider;
import com.dfsek.terra.biome.provider.ImageBiomeProvider;
import com.dfsek.terra.registry.BiomeRegistry;
import java.awt.image.BufferedImage;
public class ImageProviderTemplate extends BiomeProviderTemplate {
@Value("image.name")
private BufferedImage image;
@Value("image.align")
private ImageBiomeProvider.Align align;
public ImageProviderTemplate(BiomeRegistry registry) {
super(registry);
}
@Override
public BiomeProvider build(long seed) {
return new ImageBiomeProvider(registry, image, resolution, align);
}
}

View File

@ -0,0 +1,21 @@
package com.dfsek.terra.config.loaders.config.biome.templates.source;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.biome.TerraBiome;
import com.dfsek.terra.biome.provider.BiomeProvider;
import com.dfsek.terra.biome.provider.SingleBiomeProvider;
import com.dfsek.terra.registry.BiomeRegistry;
public class SingleBiomeProviderTemplate extends BiomeProviderTemplate {
@Value("biome")
private TerraBiome biome;
public SingleBiomeProviderTemplate(BiomeRegistry registry) {
super(registry);
}
@Override
public BiomeProvider build(long seed) {
return new SingleBiomeProvider(biome);
}
}

View File

@ -4,14 +4,15 @@ import com.dfsek.tectonic.annotations.Value;
import com.dfsek.tectonic.loading.object.ObjectTemplate;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.api.util.seeded.SeededBuilder;
import com.dfsek.terra.api.util.seeded.StageSeeded;
import com.dfsek.terra.biome.pipeline.stages.Stage;
public abstract class StageTemplate implements ObjectTemplate<SeededBuilder<Stage>>, SeededBuilder<Stage> {
public abstract class StageTemplate implements ObjectTemplate<SeededBuilder<Stage>>, StageSeeded {
@Value("noise")
protected NoiseSeeded noise;
@Override
public SeededBuilder<Stage> get() {
public StageSeeded get() {
return this;
}
}

View File

@ -30,7 +30,10 @@ import com.dfsek.terra.config.fileloaders.Loader;
import com.dfsek.terra.config.fileloaders.ZIPLoader;
import com.dfsek.terra.config.lang.LangUtil;
import com.dfsek.terra.config.loaders.config.BufferedImageLoader;
import com.dfsek.terra.config.loaders.config.biome.BiomeProviderBuilderLoader;
import com.dfsek.terra.config.loaders.config.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.sampler.templates.ImageSamplerTemplate;
import com.dfsek.terra.config.templates.AbstractableTemplate;
import com.dfsek.terra.config.templates.BiomeTemplate;
import com.dfsek.terra.config.templates.CarverTemplate;
@ -97,6 +100,8 @@ public class ConfigPack implements LoaderRegistrar {
private final TerraPlugin main;
private final Loader loader;
private final BiomeProvider.BiomeProviderBuilder biomeProviderBuilder;
public ConfigPack(File folder, TerraPlugin main) throws ConfigException {
this.loader = new FolderLoader(folder.toPath());
@ -116,10 +121,14 @@ public class ConfigPack implements LoaderRegistrar {
try {
selfLoader.load(template, new FileInputStream(pack));
load(l, main);
ConfigPackPostTemplate packPostTemplate = new ConfigPackPostTemplate();
selfLoader.load(packPostTemplate, new FileInputStream(pack));
biomeProviderBuilder = packPostTemplate.getProviderBuilder();
biomeProviderBuilder.build(0); // Build dummy provider to catch errors at load time.
} catch(FileNotFoundException e) {
throw new FileMissingException("No pack.yml file found in " + folder.getAbsolutePath(), e);
}
load(l, main);
}
public ConfigPack(ZipFile file, TerraPlugin main) throws ConfigException {
@ -136,25 +145,33 @@ public class ConfigPack implements LoaderRegistrar {
main.register(selfLoader);
main.register(abstractConfigLoader);
InputStream stream = null;
try {
ZipEntry pack = null;
Enumeration<? extends ZipEntry> entries = file.entries();
while(entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
if(entry.getName().equals("pack.yml")) stream = file.getInputStream(entry);
if(entry.getName().equals("pack.yml")) pack = entry;
}
if(pack == null) throw new FileMissingException("No pack.yml file found in " + file.getName());
selfLoader.load(template, file.getInputStream(pack));
load(l, main);
ConfigPackPostTemplate packPostTemplate = new ConfigPackPostTemplate();
selfLoader.load(packPostTemplate, file.getInputStream(pack));
biomeProviderBuilder = packPostTemplate.getProviderBuilder();
biomeProviderBuilder.build(0); // Build dummy provider to catch errors at load time.
} catch(IOException e) {
throw new LoadException("Unable to load pack.yml from ZIP file", e);
}
if(stream == null) throw new FileMissingException("No pack.yml file found in " + file.getName());
}
selfLoader.load(template, stream);
load(l, main);
template.getProviderBuilder().build(0); // Build dummy provider to catch errors at load time.
public static <C extends AbstractableTemplate, O> void buildAll(TerraFactory<C, O> factory, TerraRegistry<O> registry, List<C> configTemplates, TerraPlugin main) throws LoadException {
for(C template : configTemplates) registry.add(template.getID(), factory.build(template, main));
}
private void load(long start, TerraPlugin main) throws ConfigException {
@ -197,10 +214,6 @@ public class ConfigPack implements LoaderRegistrar {
LangUtil.log("config-pack.loaded", Level.INFO, template.getID(), String.valueOf((System.nanoTime() - start) / 1000000D), template.getAuthor(), template.getVersion());
}
public static <C extends AbstractableTemplate, O> void buildAll(TerraFactory<C, O> factory, TerraRegistry<O> registry, List<C> configTemplates, TerraPlugin main) throws LoadException {
for(C template : configTemplates) registry.add(template.getID(), factory.build(template, main));
}
public TerraBiome getBiome(String id) {
return biomeRegistry.get(id);
}
@ -247,7 +260,9 @@ public class ConfigPack implements LoaderRegistrar {
.registerLoader(LootTable.class, lootRegistry)
.registerLoader(UserDefinedCarver.class, carverRegistry)
.registerLoader(BufferedImage.class, new BufferedImageLoader(loader))
.registerLoader(BiomeProvider.BiomeProviderBuilder.class, new BiomeProviderBuilderLoader(main, biomeRegistry, loader));
.registerLoader(SingleBiomeProviderTemplate.class, () -> new SingleBiomeProviderTemplate(biomeRegistry))
.registerLoader(BiomePipelineTemplate.class, () -> new BiomePipelineTemplate(biomeRegistry, main))
.registerLoader(ImageSamplerTemplate.class, () -> new ImageProviderTemplate(biomeRegistry));
}
public ScriptRegistry getScriptRegistry() {
@ -265,4 +280,8 @@ public class ConfigPack implements LoaderRegistrar {
public Set<UserDefinedCarver> getCarvers() {
return carverRegistry.entries();
}
public BiomeProvider.BiomeProviderBuilder getBiomeProviderBuilder() {
return biomeProviderBuilder;
}
}

View File

@ -0,0 +1,14 @@
package com.dfsek.terra.config.pack;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.tectonic.config.ConfigTemplate;
import com.dfsek.terra.biome.provider.BiomeProvider;
public class ConfigPackPostTemplate implements ConfigTemplate {
@Value("biomes")
private BiomeProvider.BiomeProviderBuilder providerBuilder;
public BiomeProvider.BiomeProviderBuilder getProviderBuilder() {
return providerBuilder;
}
}

View File

@ -4,7 +4,6 @@ import com.dfsek.tectonic.annotations.Default;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.tectonic.config.ConfigTemplate;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.biome.provider.BiomeProvider;
import com.dfsek.terra.config.loaders.config.function.FunctionTemplate;
import java.util.HashMap;
@ -67,13 +66,6 @@ public class ConfigPackTemplate implements ConfigTemplate {
@Default
private String version = "0.1.0";
@Value("biomes")
private BiomeProvider.BiomeProviderBuilder providerBuilder;
public BiomeProvider.BiomeProviderBuilder getProviderBuilder() {
return providerBuilder;
}
public Map<String, FunctionTemplate> getFunctions() {
return functions;
}

View File

@ -27,7 +27,7 @@ public class TerraWorld {
c.getBiomeRegistry().forEach(biome -> biome.getGenerator(w)); // Load all gens to cache
config = c;
profiler = new WorldProfiler(w);
this.provider = config.getTemplate().getProviderBuilder().build(w.getSeed());
this.provider = config.getBiomeProviderBuilder().build(w.getSeed());
this.world = w;
air = main.getWorldHandle().createBlockData("minecraft:air");
safe = true;

View File

@ -1,160 +0,0 @@
package biome;
import com.dfsek.terra.api.math.ProbabilityCollection;
import com.dfsek.terra.api.math.noise.NoiseSampler;
import com.dfsek.terra.api.math.noise.samplers.FastNoiseLite;
import com.dfsek.terra.api.platform.world.Biome;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.world.biome.Generator;
import com.dfsek.terra.biome.TerraBiome;
import com.dfsek.terra.biome.pipeline.BiomePipeline;
import com.dfsek.terra.biome.pipeline.expand.FractalExpander;
import com.dfsek.terra.biome.pipeline.mutator.BorderMutator;
import com.dfsek.terra.biome.pipeline.mutator.ReplaceMutator;
import com.dfsek.terra.biome.pipeline.mutator.SmoothMutator;
import com.dfsek.terra.biome.pipeline.source.BiomeSource;
import com.dfsek.terra.biome.pipeline.source.RandomSource;
import com.dfsek.terra.biome.pipeline.stages.ExpanderStage;
import com.dfsek.terra.biome.pipeline.stages.MutatorStage;
import com.dfsek.terra.biome.provider.BiomeProvider;
import com.dfsek.terra.biome.provider.StandardBiomeProvider;
import org.junit.jupiter.api.Test;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Arrays;
import java.util.Set;
import java.util.stream.Collectors;
public class BiomeTest {
@Test
public static void main(String... args) {
ProbabilityCollection<TerraBiome> oceanBiomes = new ProbabilityCollection<>();
ProbabilityCollection<TerraBiome> landBiomes = new ProbabilityCollection<>();
ProbabilityCollection<TerraBiome> beachBiomes = new ProbabilityCollection<>();
TestBiome ocean = new TestBiome(Color.BLUE, "OCEAN_TEMP");
TestBiome land = new TestBiome(Color.GREEN, "LAND_TEMP");
TestBiome beach = new TestBiome(Color.YELLOW, "BEACH");
beachBiomes.add(beach, 1);
ProbabilityCollection<TerraBiome> climate = new ProbabilityCollection<>();
climate.add(ocean, 1);
climate.add(land, 2);
oceanBiomes.add(new TestBiome(Color.BLUE, "OCEAN"), 10);
oceanBiomes.add(new TestBiome(Color.CYAN, "OCEAN"), 1);
landBiomes.add(new TestBiome(Color.GREEN, "LAND"), 8);
landBiomes.add(new TestBiome(Color.ORANGE, "LAND"), 5);
landBiomes.add(new TestBiome(Color.RED, "LAND"), 1);
landBiomes.add(new TestBiome(Color.GRAY, "LAND"), 1);
FastNoiseLite sourceSampler = new FastNoiseLite(123);
sourceSampler.setNoiseType(FastNoiseLite.NoiseType.WhiteNoise);
BiomeSource source = new RandomSource(climate, sourceSampler);
BiomeProvider provider = new StandardBiomeProvider.StandardBiomeProviderBuilder((seed) -> new BiomePipeline.BiomePipelineBuilder(2)
.addStage(s -> new MutatorStage(new ReplaceMutator("LAND_TEMP", landBiomes, whiteNoise(243))))
.addStage(s -> new ExpanderStage(new FractalExpander(whiteNoise(2))))
.addStage(s -> new MutatorStage(new ReplaceMutator("OCEAN_TEMP", oceanBiomes, whiteNoise(243))))
.addStage(s -> new ExpanderStage(new FractalExpander(whiteNoise(2))))
.addStage(s -> new ExpanderStage(new FractalExpander(whiteNoise(2))))
.addStage(s -> new MutatorStage(new SmoothMutator(whiteNoise(3))))
.addStage(s -> new ExpanderStage(new FractalExpander(whiteNoise(4))))
.addStage(s -> new MutatorStage(new SmoothMutator(whiteNoise(6))))
.addStage(s -> new ExpanderStage(new FractalExpander(whiteNoise(4))))
.addStage(s -> new ExpanderStage(new FractalExpander(whiteNoise(4))))
.addStage(s -> new MutatorStage(new BorderMutator("OCEAN", "LAND", whiteNoise(1234), beachBiomes)))
.addStage(s -> new ExpanderStage(new FractalExpander(whiteNoise(4))))
.addStage(s -> new MutatorStage(new SmoothMutator(whiteNoise(6))))
.addStage(s -> new MutatorStage(new SmoothMutator(whiteNoise(6))))
.build(source, seed), null).build(0);
int size = 1000;
BufferedImage image = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);
System.out.println(size);
long s = System.nanoTime();
for(int x = 0; x < size; x++) {
for(int z = 0; z < size; z++) {
image.setRGB(x, z, provider.getBiome(x, z).getColor());
}
}
long e = System.nanoTime();
double time = e - s;
time /= 1000000;
System.out.println(time + "ms for " + size + "x" + size);
JFrame frame = new JFrame("TerraBiome Viewer");
frame.setResizable(false);
frame.add(new JLabel(new ImageIcon(image)));
frame.pack();
System.out.println("Done");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setVisible(true);
}
private static NoiseSampler whiteNoise(int seed) {
FastNoiseLite noiseLite = new FastNoiseLite(seed);
noiseLite.setNoiseType(FastNoiseLite.NoiseType.WhiteNoise);
return noiseLite;
}
private final static class TestBiome implements TerraBiome {
private final Color color;
private final Set<String> tags;
private TestBiome(Color color, String... tags) {
this.color = color;
this.tags = Arrays.stream(tags).collect(Collectors.toSet());
}
@Override
public ProbabilityCollection<Biome> getVanillaBiomes() {
return null;
}
@Override
public Generator getGenerator(World w) {
return null;
}
@Override
public int getColor() {
return color.getRGB();
}
@Override
public Set<String> getTags() {
return tags;
}
@Override
public String getID() {
return null;
}
}
}

View File

@ -24,7 +24,11 @@ import com.dfsek.terra.config.PluginConfig;
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.sampler.NoiseSamplerBuilderLoader;
import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.config.templates.AbstractableTemplate;
@ -141,9 +145,13 @@ public class DistributionTest {
BiomeProviderTemplate template = new BiomeProviderTemplate();
ConfigLoader pipeLoader = new ConfigLoader()
.registerLoader(BiomeProvider.BiomeProviderBuilder.class, new BiomeProviderBuilderLoader(MAIN, biomeRegistry, folderLoader))
.registerLoader(BiomeProvider.BiomeProviderBuilder.class, new BiomeProviderBuilderLoader())
.registerLoader(ProbabilityCollection.class, new ProbabilityCollectionLoader())
.registerLoader(TerraBiome.class, biomeRegistry);
.registerLoader(TerraBiome.class, biomeRegistry)
.registerLoader(BufferedImage.class, new BufferedImageLoader(folderLoader))
.registerLoader(SingleBiomeProviderTemplate.class, () -> new SingleBiomeProviderTemplate(biomeRegistry))
.registerLoader(BiomePipelineTemplate.class, () -> new BiomePipelineTemplate(biomeRegistry, MAIN))
.registerLoader(ImageProviderTemplate.class, () -> new ImageProviderTemplate(biomeRegistry));
new GenericLoaders(null).register(pipeLoader);
pipeLoader.registerLoader(NoiseSeeded.class, new NoiseSamplerBuilderLoader());

View File

@ -34,7 +34,7 @@ public class TerraBiomeSource extends BiomeSource {
super(biomes.stream().collect(Collectors.toList()));
this.biomeRegistry = biomes;
this.seed = seed;
this.grid = pack.getTemplate().getProviderBuilder().build(seed);
this.grid = pack.getBiomeProviderBuilder().build(seed);
this.pack = pack;
}