From 27e31fef9fd9820a6b09ddb5d1a94c2c13351b90 Mon Sep 17 00:00:00 2001 From: dfsek Date: Thu, 3 Dec 2020 01:13:25 -0700 Subject: [PATCH] Improve flora placement algorithm --- .../terra/config/factories/FloraFactory.java | 2 +- .../terra/config/templates/FloraTemplate.java | 9 ++++++++ .../terra/generation/TerraChunkGenerator.java | 4 ++-- .../generation/items/flora/TerraFlora.java | 7 +++++-- .../terra/population/FloraPopulator.java | 21 ++++++++++++++++--- 5 files changed, 35 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/dfsek/terra/config/factories/FloraFactory.java b/src/main/java/com/dfsek/terra/config/factories/FloraFactory.java index e3401dea9..a9cd53d9a 100644 --- a/src/main/java/com/dfsek/terra/config/factories/FloraFactory.java +++ b/src/main/java/com/dfsek/terra/config/factories/FloraFactory.java @@ -16,6 +16,6 @@ public class FloraFactory implements TerraFactory { for(PaletteLayer layer : config.getFloraPalette()) { palette.add(layer.getLayer(), layer.getSize()); } - return new TerraFlora(palette, config.doPhysics(), config.isCeiling(), config.getIrrigable(), config.getSpawnable(), config.getReplaceable(), config.getMaxPlacements(), config.getSearch(), config.isSpawnBlacklist()); + return new TerraFlora(palette, config.doPhysics(), config.isCeiling(), config.getIrrigable(), config.getSpawnable(), config.getReplaceable(), config.getMaxPlacements(), config.getSearch(), config.isSpawnBlacklist(), config.getIrrigableOffset()); } } diff --git a/src/main/java/com/dfsek/terra/config/templates/FloraTemplate.java b/src/main/java/com/dfsek/terra/config/templates/FloraTemplate.java index c9c123fe0..a88ca7f51 100644 --- a/src/main/java/com/dfsek/terra/config/templates/FloraTemplate.java +++ b/src/main/java/com/dfsek/terra/config/templates/FloraTemplate.java @@ -59,6 +59,15 @@ public class FloraTemplate extends AbstractableTemplate { @Abstractable private int maxPlacements = -1; + @Value("irrigable-offset") + @Abstractable + @Default + private int irrigableOffset; + + public int getIrrigableOffset() { + return irrigableOffset; + } + public TerraFlora.Search getSearch() { return search; } diff --git a/src/main/java/com/dfsek/terra/generation/TerraChunkGenerator.java b/src/main/java/com/dfsek/terra/generation/TerraChunkGenerator.java index 8456291ff..06b857a6b 100644 --- a/src/main/java/com/dfsek/terra/generation/TerraChunkGenerator.java +++ b/src/main/java/com/dfsek/terra/generation/TerraChunkGenerator.java @@ -112,13 +112,13 @@ public class TerraChunkGenerator extends GaeaChunkGenerator { if(stairs != null) { Palette stairPalette = stairs.get(up.getMaterial()); if(stairPalette != null) { - BlockData stair = stairPalette.get(0, block.getBlockX(), block.getBlockZ()); + BlockData stair = stairPalette.get(0, block.getBlockX(), block.getBlockZ()).clone(); Stairs stairNew = (Stairs) stair.clone(); stairNew.setHalf(Bisected.Half.TOP); if(placePart(orig, chunk, block, thresh, sampler, stairNew)) return; } } - BlockData slab = slabs.getOrDefault(up.getMaterial(), DataUtil.BLANK_PALETTE).get(0, block.getBlockX(), block.getBlockZ()); + BlockData slab = slabs.getOrDefault(up.getMaterial(), DataUtil.BLANK_PALETTE).get(0, block.getBlockX(), block.getBlockZ()).clone(); if(slab instanceof Bisected) ((Bisected) slab).setHalf(Bisected.Half.TOP); if(slab instanceof Slab) ((Slab) slab).setType(Slab.Type.TOP); if(slab instanceof Waterlogged) { diff --git a/src/main/java/com/dfsek/terra/generation/items/flora/TerraFlora.java b/src/main/java/com/dfsek/terra/generation/items/flora/TerraFlora.java index fb1eef343..52915392f 100644 --- a/src/main/java/com/dfsek/terra/generation/items/flora/TerraFlora.java +++ b/src/main/java/com/dfsek/terra/generation/items/flora/TerraFlora.java @@ -30,7 +30,9 @@ public class TerraFlora implements Flora { private final boolean spawnBlacklist; - public TerraFlora(Palette floraPalette, boolean physics, boolean ceiling, MaterialSet irrigable, MaterialSet spawnable, MaterialSet replaceable, int maxPlacements, Search search, boolean spawnBlacklist) { + private final int irrigableOffset; + + public TerraFlora(Palette floraPalette, boolean physics, boolean ceiling, MaterialSet irrigable, MaterialSet spawnable, MaterialSet replaceable, int maxPlacements, Search search, boolean spawnBlacklist, int irrigableOffset) { this.floraPalette = floraPalette; this.physics = physics; this.spawnBlacklist = spawnBlacklist; @@ -40,6 +42,7 @@ public class TerraFlora implements Flora { this.replaceable = replaceable; this.maxPlacements = maxPlacements; this.search = search; + this.irrigableOffset = irrigableOffset; } @Override @@ -50,7 +53,7 @@ public class TerraFlora implements Flora { for(int y : range) { if(y > 255 || y < 0) continue; current = current.getRelative(search.equals(Search.UP) ? BlockFace.UP : BlockFace.DOWN); - if((spawnBlacklist != spawnable.contains(current.getType())) && isIrrigated(current) && valid(size, current)) { + if((spawnBlacklist != spawnable.contains(current.getType())) && isIrrigated(current.getRelative(BlockFace.UP, irrigableOffset)) && valid(size, current)) { blocks.add(current); if(maxPlacements > 0 && blocks.size() >= maxPlacements) break; } diff --git a/src/main/java/com/dfsek/terra/population/FloraPopulator.java b/src/main/java/com/dfsek/terra/population/FloraPopulator.java index 05a4a84c2..e8354175c 100644 --- a/src/main/java/com/dfsek/terra/population/FloraPopulator.java +++ b/src/main/java/com/dfsek/terra/population/FloraPopulator.java @@ -4,6 +4,7 @@ import com.dfsek.terra.TerraProfiler; import com.dfsek.terra.TerraWorld; import com.dfsek.terra.biome.UserDefinedBiome; import com.dfsek.terra.biome.grid.TerraBiomeGrid; +import com.dfsek.terra.generation.items.flora.FloraLayer; import com.dfsek.terra.procgen.math.Vector2; import org.bukkit.Chunk; import org.bukkit.World; @@ -12,6 +13,9 @@ import org.polydev.gaea.generation.GenerationPhase; import org.polydev.gaea.population.GaeaBlockPopulator; import org.polydev.gaea.profiler.ProfileFuture; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import java.util.Random; /** @@ -25,15 +29,26 @@ public class FloraPopulator extends GaeaBlockPopulator { TerraWorld tw = TerraWorld.getWorld(world); if(!tw.isSafe()) return; TerraBiomeGrid grid = tw.getGrid(); + Map> layers = new HashMap<>(); for(int x = 0; x < 16; x++) { for(int z = 0; z < 16; z++) { UserDefinedBiome biome = (UserDefinedBiome) grid.getBiome((chunk.getX() << 4) + x, (chunk.getZ() << 4) + z, GenerationPhase.POPULATE); Vector2 l = new Vector2(x, z); - biome.getConfig().getFlora().forEach(layer -> { - if(layer.getDensity() >= random.nextDouble() * 100D) layer.place(chunk, l, random); - }); + layers.put(l, biome.getConfig().getFlora()); } } + int iter = 0; + boolean finished = false; + while(!finished) { + finished = true; + for(Map.Entry> entry : layers.entrySet()) { + if(entry.getValue().size() <= iter) continue; + finished = false; + FloraLayer layer = entry.getValue().get(iter); + if(layer.getDensity() >= random.nextDouble() * 100D) layer.place(chunk, entry.getKey(), random); + } + iter++; + } } } }