working flora populator impl

This commit is contained in:
dfsek
2021-07-14 10:27:14 -07:00
parent 7a38284158
commit 089af42623
20 changed files with 116 additions and 35 deletions

View File

@@ -33,6 +33,7 @@ public class NoiseChunkGenerator3D implements TerraChunkGenerator {
public NoiseChunkGenerator3D(ConfigPack c, TerraPlugin main) {
this.configPack = c;
this.main = main;
c.getStages().forEach(stage -> blockPopulators.add(stage.newInstance(c)));
}
@SuppressWarnings({"try"})
@@ -70,7 +71,6 @@ public class NoiseChunkGenerator3D implements TerraChunkGenerator {
TerraWorld tw = main.getWorld(world);
BiomeProvider grid = tw.getBiomeProvider();
if(!tw.isSafe()) return chunk;
int xOrig = (chunkX << 4);
int zOrig = (chunkZ << 4);

View File

@@ -34,7 +34,6 @@ public class CavePopulator implements TerraGenerationStage, Chunkified {
WorldHandle handle = main.getWorldHandle();
try(ProfileFrame ignore = main.getProfiler().profile("carving")) {
Random random = PopulationUtil.getRandom(chunk);
if(!tw.isSafe()) return;
WorldConfig config = tw.getConfig();
if(config.disableCarving()) return;

View File

@@ -1,6 +1,8 @@
package com.dfsek.terra.addons.flora;
import com.dfsek.terra.addons.flora.config.BlockLayerTemplate;
import com.dfsek.terra.addons.flora.flora.FloraLayer;
import com.dfsek.terra.addons.flora.flora.gen.BlockLayer;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.addon.TerraAddon;
import com.dfsek.terra.api.addon.annotations.Addon;
@@ -15,6 +17,7 @@ import com.dfsek.terra.api.util.seeded.BiomeBuilder;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.generator.GenerationStageProvider;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -31,7 +34,8 @@ public class FloraAddon extends TerraAddon implements EventListener {
@Override
public void initialize() {
main.getEventManager().registerListener(this, this);
main.applyLoader(FloraLayer.class, FloraLayerLoader::new);
main.applyLoader(FloraLayer.class, FloraLayerLoader::new)
.applyLoader(BlockLayer.class, BlockLayerTemplate::new);
}
public void onPackLoad(ConfigPackPreLoadEvent event) throws DuplicateEntryException {
@@ -46,6 +50,6 @@ public class FloraAddon extends TerraAddon implements EventListener {
}
public List<FloraLayer> getFlora(TerraBiome biome) {
return flora.get(biome.getID());
return flora.getOrDefault(biome.getID(), Collections.emptyList());
}
}

View File

@@ -8,10 +8,6 @@ import com.dfsek.terra.api.world.Flora;
public class FloraFactory implements ConfigFactory<FloraTemplate, Flora> {
@Override
public TerraFlora build(FloraTemplate config, TerraPlugin main) {
/*PaletteImpl palette = new NoisePalette(new WhiteNoiseSampler(2403), false);
for(PaletteLayerHolder layer : config.getFloraPalette()) {
palette.add(layer.getLayer(), layer.getSize(), layer.getSampler());
}*/
return new TerraFlora(null, config.doPhysics(), config.isCeiling(), config.getIrrigable(), config.getSpawnable(), config.getReplaceable(), config.getRotatable(), config.getMaxPlacements(), config.getSearch(), config.isSpawnBlacklist(), config.getIrrigableOffset(), 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));
}
}

View File

@@ -8,6 +8,7 @@ import com.dfsek.terra.api.vector.Vector2;
import com.dfsek.terra.api.world.Chunk;
import com.dfsek.terra.api.world.TerraWorld;
import com.dfsek.terra.api.world.World;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import com.dfsek.terra.api.world.generator.TerraGenerationStage;
import org.jetbrains.annotations.NotNull;
@@ -36,7 +37,6 @@ public class FloraPopulator implements TerraGenerationStage {
try(ProfileFrame ignore = main.getProfiler().profile("flora")) {
if(tw.getConfig().disableFlora()) return;
if(!tw.isSafe()) return;
BiomeProvider provider = tw.getBiomeProvider();
Map<Vector2, List<FloraLayer>> layers = new HashMap<>();
for(int x = 0; x < 16; x++) {

View File

@@ -4,8 +4,12 @@ import com.dfsek.tectonic.annotations.Default;
import com.dfsek.tectonic.annotations.Final;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.addons.flora.flora.TerraFlora;
import com.dfsek.terra.addons.flora.flora.gen.BlockLayer;
import com.dfsek.terra.api.config.AbstractableTemplate;
import com.dfsek.terra.api.util.collection.MaterialSet;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import java.util.List;
@SuppressWarnings({"FieldMayBeFinal", "unused"})
public class FloraTemplate implements AbstractableTemplate {
@@ -53,6 +57,20 @@ public class FloraTemplate implements AbstractableTemplate {
@Default
private int irrigableOffset;
@Value("layers")
private List<BlockLayer> layers;
@Value("layer-distribution")
private NoiseSeeded noiseDistribution;
public NoiseSeeded getNoiseDistribution() {
return noiseDistribution;
}
public List<BlockLayer> getLayers() {
return layers;
}
public int getIrrigableOffset() {
return irrigableOffset;
}

View File

@@ -0,0 +1,20 @@
package com.dfsek.terra.addons.flora.config;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.tectonic.loading.object.ObjectTemplate;
import com.dfsek.terra.addons.flora.flora.gen.BlockLayer;
import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.util.collection.ProbabilityCollection;
public class BlockLayerTemplate implements ObjectTemplate<BlockLayer> {
@Value("layers")
private int layers;
@Value("materials")
private ProbabilityCollection<BlockState> data;
@Override
public BlockLayer get() {
return new BlockLayer(layers, data);
}
}

View File

@@ -37,7 +37,9 @@ public class FloraLayer {
}
public void place(Chunk chunk, Vector2 coords) {
Flora item = layer.get(noise, (chunk.getX() << 4) + coords.getX(), (chunk.getZ() << 4) + coords.getZ());
item.getValidSpawnsAt(chunk, (int) coords.getX(), (int) coords.getZ(), level).forEach(block -> item.plant(block, chunk.getWorld()));
int cx = (chunk.getX() << 4);
int cz = (chunk.getZ() << 4);
Flora item = layer.get(noise, cx + coords.getX(), cz + coords.getZ());
item.getValidSpawnsAt(chunk, (int) coords.getX(), (int) coords.getZ(), level).forEach(block -> item.plant(block.add(cx, 0, cz), chunk.getWorld()));
}
}

View File

@@ -1,16 +1,18 @@
package com.dfsek.terra.addons.flora.flora;
import com.dfsek.terra.addons.flora.flora.gen.BlockLayer;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.block.state.properties.base.Properties;
import com.dfsek.terra.api.block.state.properties.enums.Direction;
import com.dfsek.terra.api.noise.NoiseSampler;
import com.dfsek.terra.api.util.Range;
import com.dfsek.terra.api.util.collection.MaterialSet;
import com.dfsek.terra.api.util.collection.ProbabilityCollection;
import com.dfsek.terra.api.vector.Vector3;
import com.dfsek.terra.api.world.Chunk;
import com.dfsek.terra.api.world.Flora;
import com.dfsek.terra.api.world.World;
import com.dfsek.terra.api.world.generator.Palette;
import net.jafama.FastMath;
import java.util.ArrayList;
@@ -19,7 +21,7 @@ import java.util.List;
import java.util.Random;
public class TerraFlora implements Flora {
private final Palette floraPalette;
private final List<ProbabilityCollection<BlockState>> layers;
private final boolean physics;
private final boolean ceiling;
@@ -40,8 +42,9 @@ public class TerraFlora implements Flora {
private final TerraPlugin main;
public TerraFlora(Palette floraPalette, boolean physics, boolean ceiling, MaterialSet irrigable, MaterialSet spawnable, MaterialSet replaceable, MaterialSet testRotation, int maxPlacements, Search search, boolean spawnBlacklist, int irrigableOffset, TerraPlugin main) {
this.floraPalette = floraPalette;
private final NoiseSampler distribution;
public TerraFlora(List<BlockLayer> layers, boolean physics, boolean ceiling, MaterialSet irrigable, MaterialSet spawnable, MaterialSet replaceable, MaterialSet testRotation, int maxPlacements, Search search, boolean spawnBlacklist, int irrigableOffset, TerraPlugin main, NoiseSampler distribution) {
this.physics = physics;
this.testRotation = testRotation;
this.spawnBlacklist = spawnBlacklist;
@@ -53,11 +56,19 @@ public class TerraFlora implements Flora {
this.search = search;
this.irrigableOffset = irrigableOffset;
this.main = main;
this.distribution = distribution;
this.layers = new ArrayList<>();
layers.forEach(layer -> {
for(int i = 0; i < layer.getLayers(); i++) {
this.layers.add(layer.getBlocks());
}
});
}
@Override
public List<Vector3> getValidSpawnsAt(Chunk chunk, int x, int z, Range range) {
int size = floraPalette.getSize();
int size = layers.size();
Vector3 current = new Vector3(x, search.equals(Search.UP) ? range.getMin() : range.getMax(), z);
List<Vector3> blocks = new ArrayList<>();
int cx = chunk.getX() << 4;
@@ -90,11 +101,14 @@ public class TerraFlora implements Flora {
|| irrigable.contains(world.getBlockData(b.getBlockX(), b.getBlockY(), b.getBlockZ() - 1).getBlockType());
}
private ProbabilityCollection<BlockState> getStateCollection(int layer) {
return layers.get(FastMath.max(FastMath.min(layer, layers.size()-1), 0));
}
@Override
public boolean plant(Vector3 location, World world) {
boolean doRotation = testRotation.size() > 0;
int size = floraPalette.getSize();
int size = layers.size();
int c = ceiling ? -1 : 1;
EnumSet<Direction> faces = doRotation ? getFaces(location.clone().add(0, c, 0), world) : EnumSet.noneOf(Direction.class);
@@ -102,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 = floraPalette.get((ceiling ? lvl : size - lvl - 1), location.getX(), location.getY(), location.getZ()).clone();
BlockState data = getStateCollection((ceiling ? lvl : size - lvl - 1)).get(distribution, location.getX(), location.getY(), location.getZ()).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,22 @@
package com.dfsek.terra.addons.flora.flora.gen;
import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.util.collection.ProbabilityCollection;
public class BlockLayer {
private final int layers;
private final ProbabilityCollection<BlockState> blocks;
public BlockLayer(int layers, ProbabilityCollection<BlockState> blocks) {
this.layers = layers;
this.blocks = blocks;
}
public int getLayers() {
return layers;
}
public ProbabilityCollection<BlockState> getBlocks() {
return blocks;
}
}

View File

@@ -26,7 +26,6 @@ public class OrePopulator implements TerraGenerationStage {
try(ProfileFrame ignore = main.getProfiler().profile("ore")) {
if(tw.getConfig().disableOres()) return;
if(!tw.isSafe()) return;
for(int cx = -1; cx <= 1; cx++) {
for(int cz = -1; cz <= 1; cz++) {
Random random = new Random(PopulationUtil.getCarverChunkSeed(chunk.getX() + cx, chunk.getZ() + cz, world.getSeed()));

View File

@@ -34,7 +34,6 @@ public class StructurePopulator implements TerraGenerationStage, Chunkified {
int cx = (chunk.getX() << 4);
int cz = (chunk.getZ() << 4);
if(!tw.isSafe()) return;
BiomeProvider provider = tw.getBiomeProvider();
WorldConfig config = tw.getConfig();
for(ConfiguredStructure conf : config.getRegistry(TerraStructure.class).entries()) {

View File

@@ -32,7 +32,6 @@ public class TreePopulator implements TerraGenerationStage {
try(ProfileFrame ignore = main.getProfiler().profile("tree")) {
if(tw.getConfig().disableTrees()) return;
if(!tw.isSafe()) return;
BiomeProvider provider = tw.getBiomeProvider();
Random random = PopulationUtil.getRandom(chunk);
for(int x = 0; x < 16; x += 2) {

View File

@@ -9,7 +9,9 @@ import com.dfsek.terra.api.tectonic.LoaderRegistrar;
import com.dfsek.terra.api.util.seeded.BiomeProviderBuilder;
import com.dfsek.terra.api.world.TerraWorld;
import com.dfsek.terra.api.world.generator.ChunkGeneratorProvider;
import com.dfsek.terra.api.world.generator.GenerationStageProvider;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -20,6 +22,8 @@ public interface ConfigPack extends LoaderRegistrar, LoaderHolder, RegistryHolde
WorldConfig toWorldConfig(TerraWorld world);
List<GenerationStageProvider> getStages();
void registerConfigType(ConfigType<?, ?> type, String id, int priority);
Loader getLoader();

View File

@@ -4,11 +4,12 @@ import com.dfsek.terra.api.registry.Registry;
import com.dfsek.terra.api.world.TerraWorld;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import com.dfsek.terra.api.world.generator.SamplerCache;
import com.dfsek.terra.api.world.generator.TerraGenerationStage;
import java.util.List;
import java.util.Map;
public interface WorldConfig {
@SuppressWarnings("unchecked")
<T> Registry<T> getRegistry(Class<T> clazz);
TerraWorld getWorld();

View File

@@ -12,8 +12,6 @@ public interface TerraWorld {
WorldConfig getConfig();
boolean isSafe();
/**
* Get a block at an ungenerated location
*

View File

@@ -30,6 +30,7 @@ import com.dfsek.terra.api.util.generic.pair.ImmutablePair;
import com.dfsek.terra.api.util.seeded.BiomeProviderBuilder;
import com.dfsek.terra.api.world.TerraWorld;
import com.dfsek.terra.api.world.generator.ChunkGeneratorProvider;
import com.dfsek.terra.api.world.generator.GenerationStageProvider;
import com.dfsek.terra.config.dummy.DummyWorld;
import com.dfsek.terra.config.fileloaders.FolderLoader;
import com.dfsek.terra.config.fileloaders.ZIPLoader;
@@ -243,7 +244,7 @@ public class ConfigPackImpl implements ConfigPack {
try {
Object loaded = ((ConfigFactory) configType.getFactory()).build(selfLoader.load(configType.getTemplate(this, main), config), main);
registry.register(config.getID(), loaded);
main.getEventManager().callEvent(new ConfigLoadEvent(this, config, template -> selfLoader.load(template, configuration), configType, loaded));
main.getEventManager().callEvent(new ConfigLoadEvent(this, config, template -> selfLoader.load(template, config), configType, loaded));
} catch(DuplicateEntryException e) {
throw new LoadException("Duplicate registry entry: ", e);
}
@@ -306,6 +307,11 @@ public class ConfigPackImpl implements ConfigPack {
return new WorldConfigImpl(world, this, main);
}
@Override
public List<GenerationStageProvider> getStages() {
return template.getStages();
}
@Override
public void registerConfigType(ConfigType<?, ?> type, String id, int priority) {
Set<String> contained = new HashSet<>();

View File

@@ -8,6 +8,7 @@ import com.dfsek.terra.api.world.generator.GenerationStageProvider;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@SuppressWarnings({"unused", "FieldMayBeFinal"})
@@ -56,7 +57,7 @@ public class ConfigPackTemplate implements ConfigTemplate {
private boolean disableSaplings = false;
@Value("stages")
private LinkedHashMap<String, GenerationStageProvider> stages;
private List<GenerationStageProvider> stages;
@Value("version")
@Default
@@ -89,7 +90,7 @@ public class ConfigPackTemplate implements ConfigTemplate {
return generatorProvider;
}
public LinkedHashMap<String, GenerationStageProvider> getStages() {
public List<GenerationStageProvider> getStages() {
return stages;
}

View File

@@ -8,12 +8,18 @@ import com.dfsek.terra.api.util.seeded.BiomeBuilder;
import com.dfsek.terra.api.world.TerraWorld;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import com.dfsek.terra.api.world.generator.GenerationStage;
import com.dfsek.terra.api.world.generator.GenerationStageProvider;
import com.dfsek.terra.api.world.generator.SamplerCache;
import com.dfsek.terra.api.world.generator.TerraGenerationStage;
import com.dfsek.terra.registry.LockedRegistryImpl;
import com.dfsek.terra.registry.OpenRegistryImpl;
import com.dfsek.terra.world.SamplerCacheImpl;
import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class WorldConfigImpl implements WorldConfig {

View File

@@ -17,7 +17,6 @@ import net.jafama.FastMath;
public class TerraWorldImpl implements TerraWorld {
private final BiomeProvider provider;
private final WorldConfigImpl config;
private final boolean safe;
private final World world;
private final BlockState air;
@@ -29,7 +28,6 @@ public class TerraWorldImpl implements TerraWorld {
this.provider = config.getProvider();
main.getEventManager().callEvent(new TerraWorldLoadEvent(this, c));
this.air = main.getWorldHandle().air();
safe = true;
}
@@ -49,11 +47,6 @@ public class TerraWorldImpl implements TerraWorld {
return config;
}
@Override
public boolean isSafe() {
return safe;
}
@Override
public BlockState getUngeneratedBlock(int x, int y, int z) {