diff --git a/common/src/main/java/com/dfsek/terra/api/world/generation/Chunkified.java b/common/src/main/java/com/dfsek/terra/api/world/generation/Chunkified.java new file mode 100644 index 000000000..3b9925d46 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/world/generation/Chunkified.java @@ -0,0 +1,7 @@ +package com.dfsek.terra.api.world.generation; + +/** + * Marker interface that marks a feature as "chunkified" (only modifying one chunk at a time) + */ +public interface Chunkified { +} diff --git a/common/src/main/java/com/dfsek/terra/api/world/generation/GenerationPhase.java b/common/src/main/java/com/dfsek/terra/api/world/generation/GenerationPhase.java deleted file mode 100644 index 6dfee8985..000000000 --- a/common/src/main/java/com/dfsek/terra/api/world/generation/GenerationPhase.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.dfsek.terra.api.world.generation; - -/** - * The phase of terrain generation. Used for modifying values based on the phase of generation. - */ -public enum GenerationPhase { - BASE, POPULATE, GENERATION_POPULATE, PALETTE_APPLY, POST_GEN -} diff --git a/common/src/main/java/com/dfsek/terra/api/world/generation/TerraChunkGenerator.java b/common/src/main/java/com/dfsek/terra/api/world/generation/TerraChunkGenerator.java index 280ee8f96..345e32c61 100644 --- a/common/src/main/java/com/dfsek/terra/api/world/generation/TerraChunkGenerator.java +++ b/common/src/main/java/com/dfsek/terra/api/world/generation/TerraChunkGenerator.java @@ -6,10 +6,10 @@ import com.dfsek.terra.api.platform.world.World; import com.dfsek.terra.api.platform.world.generator.ChunkData; import com.dfsek.terra.api.world.biome.provider.BiomeProvider; import com.dfsek.terra.config.pack.ConfigPack; -import com.dfsek.terra.world.generation.math.SamplerCache; import com.dfsek.terra.world.generation.math.samplers.Sampler; import org.jetbrains.annotations.NotNull; +import java.util.List; import java.util.Random; public interface TerraChunkGenerator { @@ -32,4 +32,6 @@ public interface TerraChunkGenerator { TerraPlugin getMain(); Sampler createSampler(int chunkX, int chunkZ, BiomeProvider provider, World world, int elevationSmooth); + + List getPopulators(); } diff --git a/common/src/main/java/com/dfsek/terra/world/generation/generators/DefaultChunkGenerator2D.java b/common/src/main/java/com/dfsek/terra/world/generation/generators/DefaultChunkGenerator2D.java index ed93986bc..c4f384b07 100644 --- a/common/src/main/java/com/dfsek/terra/world/generation/generators/DefaultChunkGenerator2D.java +++ b/common/src/main/java/com/dfsek/terra/world/generation/generators/DefaultChunkGenerator2D.java @@ -10,6 +10,7 @@ import com.dfsek.terra.api.util.world.PaletteUtil; import com.dfsek.terra.api.world.biome.TerraBiome; import com.dfsek.terra.api.world.biome.UserDefinedBiome; import com.dfsek.terra.api.world.biome.provider.BiomeProvider; +import com.dfsek.terra.api.world.generation.TerraBlockPopulator; import com.dfsek.terra.api.world.generation.TerraChunkGenerator; import com.dfsek.terra.api.world.palette.Palette; import com.dfsek.terra.config.pack.ConfigPack; @@ -21,9 +22,15 @@ 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.Sampler2D; +import com.dfsek.terra.world.population.CavePopulator; +import com.dfsek.terra.world.population.OrePopulator; +import com.dfsek.terra.world.population.StructurePopulator; +import com.dfsek.terra.world.population.TreePopulator; import net.jafama.FastMath; import org.jetbrains.annotations.NotNull; +import java.util.ArrayList; +import java.util.List; import java.util.Random; public class DefaultChunkGenerator2D implements TerraChunkGenerator { @@ -31,12 +38,18 @@ public class DefaultChunkGenerator2D implements TerraChunkGenerator { private final TerraPlugin main; private final Carver carver; + private final List blockPopulators = new ArrayList<>(); private final SamplerCache cache; public DefaultChunkGenerator2D(ConfigPack c, TerraPlugin main, SamplerCache cache) { this.configPack = c; this.main = main; + blockPopulators.add(new CavePopulator(main)); + blockPopulators.add(new StructurePopulator(main)); + blockPopulators.add(new OrePopulator(main)); + blockPopulators.add(new TreePopulator(main)); + blockPopulators.add(new TreePopulator(main)); carver = new NoiseCarver(new Range(0, 255), main.getWorldHandle().createBlockData("minecraft:air"), main); this.cache = cache; } @@ -125,4 +138,9 @@ public class DefaultChunkGenerator2D implements TerraChunkGenerator { public Sampler createSampler(int chunkX, int chunkZ, BiomeProvider provider, World world, int elevationSmooth) { return new Sampler2D(chunkX, chunkZ, provider, world, elevationSmooth); } + + @Override + public List getPopulators() { + return blockPopulators; + } } diff --git a/common/src/main/java/com/dfsek/terra/world/generation/generators/DefaultChunkGenerator3D.java b/common/src/main/java/com/dfsek/terra/world/generation/generators/DefaultChunkGenerator3D.java index af656ac84..f63676161 100644 --- a/common/src/main/java/com/dfsek/terra/world/generation/generators/DefaultChunkGenerator3D.java +++ b/common/src/main/java/com/dfsek/terra/world/generation/generators/DefaultChunkGenerator3D.java @@ -17,6 +17,7 @@ import com.dfsek.terra.api.util.world.PaletteUtil; import com.dfsek.terra.api.world.biome.TerraBiome; import com.dfsek.terra.api.world.biome.UserDefinedBiome; import com.dfsek.terra.api.world.biome.provider.BiomeProvider; +import com.dfsek.terra.api.world.generation.TerraBlockPopulator; import com.dfsek.terra.api.world.generation.TerraChunkGenerator; import com.dfsek.terra.api.world.palette.Palette; import com.dfsek.terra.api.world.palette.SinglePalette; @@ -28,8 +29,15 @@ import com.dfsek.terra.world.TerraWorld; import com.dfsek.terra.world.carving.NoiseCarver; import com.dfsek.terra.world.generation.math.samplers.Sampler; import com.dfsek.terra.world.generation.math.samplers.Sampler3D; +import com.dfsek.terra.world.population.CavePopulator; +import com.dfsek.terra.world.population.FloraPopulator; +import com.dfsek.terra.world.population.OrePopulator; +import com.dfsek.terra.world.population.StructurePopulator; +import com.dfsek.terra.world.population.TreePopulator; import org.jetbrains.annotations.NotNull; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.Random; @@ -38,14 +46,21 @@ public class DefaultChunkGenerator3D implements TerraChunkGenerator { private final TerraPlugin main; private final BlockType water; private final SinglePalette blank; + private final List blockPopulators = new ArrayList<>(); private final Carver carver; - public DefaultChunkGenerator3D(ConfigPack c, TerraPlugin main) { this.configPack = c; this.main = main; + + blockPopulators.add(new CavePopulator(main)); + blockPopulators.add(new StructurePopulator(main)); + blockPopulators.add(new OrePopulator(main)); + blockPopulators.add(new TreePopulator(main)); + blockPopulators.add(new FloraPopulator(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")); @@ -236,4 +251,9 @@ public class DefaultChunkGenerator3D implements TerraChunkGenerator { public Sampler createSampler(int chunkX, int chunkZ, BiomeProvider provider, World world, int elevationSmooth) { return new Sampler3D(chunkX, chunkZ, provider, world, elevationSmooth); } + + @Override + public List getPopulators() { + return blockPopulators; + } } diff --git a/common/src/main/java/com/dfsek/terra/world/population/CavePopulator.java b/common/src/main/java/com/dfsek/terra/world/population/CavePopulator.java index 15d386ca9..53bd28d13 100644 --- a/common/src/main/java/com/dfsek/terra/world/population/CavePopulator.java +++ b/common/src/main/java/com/dfsek/terra/world/population/CavePopulator.java @@ -9,6 +9,7 @@ import com.dfsek.terra.api.platform.handle.WorldHandle; import com.dfsek.terra.api.platform.world.Chunk; import com.dfsek.terra.api.platform.world.World; import com.dfsek.terra.api.util.world.PopulationUtil; +import com.dfsek.terra.api.world.generation.Chunkified; import com.dfsek.terra.api.world.generation.TerraBlockPopulator; import com.dfsek.terra.carving.UserDefinedCarver; import com.dfsek.terra.config.pack.WorldConfig; @@ -23,7 +24,7 @@ import java.util.Map; import java.util.Random; import java.util.Set; -public class CavePopulator implements TerraBlockPopulator { +public class CavePopulator implements TerraBlockPopulator, Chunkified { private static final Map shiftStorage = new HashMap<>(); // Persist BlockData created for shifts, to avoid re-calculating each time. private final TerraPlugin main; diff --git a/common/src/main/java/com/dfsek/terra/world/population/StructurePopulator.java b/common/src/main/java/com/dfsek/terra/world/population/StructurePopulator.java index 17bb41221..6dc3f3379 100644 --- a/common/src/main/java/com/dfsek/terra/world/population/StructurePopulator.java +++ b/common/src/main/java/com/dfsek/terra/world/population/StructurePopulator.java @@ -9,6 +9,7 @@ import com.dfsek.terra.api.structures.structure.Rotation; import com.dfsek.terra.api.util.FastRandom; import com.dfsek.terra.api.world.biome.UserDefinedBiome; import com.dfsek.terra.api.world.biome.provider.BiomeProvider; +import com.dfsek.terra.api.world.generation.Chunkified; import com.dfsek.terra.api.world.generation.TerraBlockPopulator; import com.dfsek.terra.config.pack.ConfigPack; import com.dfsek.terra.config.pack.WorldConfig; @@ -20,7 +21,7 @@ import org.jetbrains.annotations.NotNull; import java.util.Random; -public class StructurePopulator implements TerraBlockPopulator { +public class StructurePopulator implements TerraBlockPopulator, Chunkified { private final TerraPlugin main; public StructurePopulator(TerraPlugin main) { diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/generator/BukkitChunkGeneratorWrapper.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/generator/BukkitChunkGeneratorWrapper.java index 092b486f2..96ae67747 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/generator/BukkitChunkGeneratorWrapper.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/generator/BukkitChunkGeneratorWrapper.java @@ -23,6 +23,8 @@ import org.jetbrains.annotations.NotNull; import java.io.FileNotFoundException; import java.io.IOException; +import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.LinkedList; import java.util.List; @@ -40,20 +42,13 @@ public class BukkitChunkGeneratorWrapper extends ChunkGenerator implements Gener private final TerraPlugin main; - private final List populators = new LinkedList<>(); - private boolean needsLoad = true; public BukkitChunkGeneratorWrapper(TerraChunkGenerator delegate) { this.delegate = delegate; this.main = delegate.getMain(); - popMan = new PopulationManager(main); - popMan.attach(new OrePopulator(main)); - popMan.attach(new TreePopulator(main)); - popMan.attach(new FloraPopulator(main)); - populators.add(new CavePopulator(main)); - populators.add(new StructurePopulator(main)); - populators.add(popMan); + this.popMan = new PopulationManager(delegate, main); + } @@ -96,7 +91,7 @@ public class BukkitChunkGeneratorWrapper extends ChunkGenerator implements Gener @Override public @NotNull List getDefaultPopulators(@NotNull World world) { - return populators.stream().map(BukkitPopulatorWrapper::new).collect(Collectors.toList()); + return Arrays.asList(popMan, new BukkitPopulatorWrapper(delegate)); } @Override diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/generator/BukkitPopulator.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/generator/BukkitPopulator.java deleted file mode 100644 index fabb1d53c..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/generator/BukkitPopulator.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.dfsek.terra.bukkit.generator; - -import com.dfsek.terra.api.platform.world.Chunk; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.platform.world.generator.BlockPopulator; -import com.dfsek.terra.bukkit.world.BukkitChunk; -import com.dfsek.terra.bukkit.world.BukkitWorld; - -import java.util.Random; - -public class BukkitPopulator implements BlockPopulator { - private final org.bukkit.generator.BlockPopulator handle; - - public BukkitPopulator(org.bukkit.generator.BlockPopulator handle) { - this.handle = handle; - } - - @Override - public void populate(World world, Random random, Chunk chunk) { - handle.populate(((BukkitWorld) world).getHandle(), random, ((BukkitChunk) chunk).getHandle()); - } - - @Override - public org.bukkit.generator.BlockPopulator getHandle() { - return handle; - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/generator/BukkitPopulatorWrapper.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/generator/BukkitPopulatorWrapper.java index 22b1a2a53..eb57cb2dc 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/generator/BukkitPopulatorWrapper.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/generator/BukkitPopulatorWrapper.java @@ -1,6 +1,8 @@ package com.dfsek.terra.bukkit.generator; +import com.dfsek.terra.api.world.generation.Chunkified; import com.dfsek.terra.api.world.generation.TerraBlockPopulator; +import com.dfsek.terra.api.world.generation.TerraChunkGenerator; import com.dfsek.terra.bukkit.world.BukkitAdapter; import org.bukkit.Chunk; import org.bukkit.World; @@ -10,14 +12,18 @@ import org.jetbrains.annotations.NotNull; import java.util.Random; public class BukkitPopulatorWrapper extends BlockPopulator { - private final TerraBlockPopulator delegate; + private final TerraChunkGenerator delegate; - public BukkitPopulatorWrapper(TerraBlockPopulator delegate) { + public BukkitPopulatorWrapper(TerraChunkGenerator delegate) { this.delegate = delegate; } @Override public void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk source) { - delegate.populate(BukkitAdapter.adapt(world), BukkitAdapter.adapt(source)); + delegate.getPopulators().forEach(populator -> { + if(populator instanceof Chunkified) { + populator.populate(BukkitAdapter.adapt(world), BukkitAdapter.adapt(source)); + } + }); } } diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/population/PopulationManager.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/population/PopulationManager.java index 34ec49d68..9b9c7a100 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/population/PopulationManager.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/population/PopulationManager.java @@ -4,54 +4,35 @@ import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.platform.world.Chunk; import com.dfsek.terra.api.platform.world.World; import com.dfsek.terra.api.util.FastRandom; -import com.dfsek.terra.api.util.GlueList; +import com.dfsek.terra.api.world.generation.Chunkified; import com.dfsek.terra.api.world.generation.TerraBlockPopulator; +import com.dfsek.terra.api.world.generation.TerraChunkGenerator; import com.dfsek.terra.bukkit.TerraBukkitPlugin; +import com.dfsek.terra.bukkit.world.BukkitAdapter; import com.dfsek.terra.profiler.ProfileFuture; import com.dfsek.terra.profiler.WorldProfiler; +import org.bukkit.generator.BlockPopulator; import org.jetbrains.annotations.NotNull; import java.io.File; import java.io.IOException; import java.util.HashSet; -import java.util.List; import java.util.Random; /** * Cursed management class for the horrors of Bukkit population */ -public class PopulationManager implements TerraBlockPopulator { - private final List attachedPopulators = new GlueList<>(); +public class PopulationManager extends BlockPopulator { + private final TerraChunkGenerator generator; private final HashSet needsPop = new HashSet<>(); private final TerraPlugin main; private WorldProfiler profiler; - public PopulationManager(TerraPlugin main) { + public PopulationManager(TerraChunkGenerator generator, TerraPlugin main) { + this.generator = generator; this.main = main; } - public void attach(TerraBlockPopulator populator) { - this.attachedPopulators.add(populator); - } - - @Override - @SuppressWarnings("try") - public void populate(@NotNull World world, @NotNull Chunk chunk) { - try(ProfileFuture ignored = measure()) { - needsPop.add(new ChunkCoordinate(chunk)); - int x = chunk.getX(); - int z = chunk.getZ(); - if(((TerraBukkitPlugin) main).isEnabled()) { - for(int xi = -1; xi <= 1; xi++) { - for(int zi = -1; zi <= 1; zi++) { - if(xi == 0 && zi == 0) continue; - if(world.isChunkGenerated(xi + x, zi + z)) checkNeighbors(xi + x, zi + z, world); - } - } - } - } - } - private ProfileFuture measure() { if(profiler != null) return profiler.measure("PopulationManagerTime"); return null; @@ -87,10 +68,30 @@ public class PopulationManager implements TerraBlockPopulator { long zRand = (random.nextLong() / 2L << 1L) + 1L; random.setSeed((long) x * xRand + (long) z * zRand ^ w.getSeed()); Chunk currentChunk = w.getChunkAt(x, z); - for(TerraBlockPopulator r : attachedPopulators) { - r.populate(w, currentChunk); - } + generator.getPopulators().forEach(populator -> { + if(!(populator instanceof Chunkified)) { + populator.populate(w, currentChunk); + } + }); needsPop.remove(c); } } + + @Override + public void populate(org.bukkit.@NotNull World world, @NotNull Random random, org.bukkit.@NotNull Chunk source) { + try(ProfileFuture ignored = measure()) { + Chunk chunk = BukkitAdapter.adapt(source); + needsPop.add(new ChunkCoordinate(chunk)); + int x = chunk.getX(); + int z = chunk.getZ(); + if(((TerraBukkitPlugin) main).isEnabled()) { + for(int xi = -1; xi <= 1; xi++) { + for(int zi = -1; zi <= 1; zi++) { + if(xi == 0 && zi == 0) continue; + if(world.isChunkGenerated(xi + x, zi + z)) checkNeighbors(xi + x, zi + z, BukkitAdapter.adapt(world)); + } + } + } + } + } } \ No newline at end of file diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/features/PopulatorFeature.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/features/PopulatorFeature.java index fdb39fe78..b284acd43 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/features/PopulatorFeature.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/features/PopulatorFeature.java @@ -27,11 +27,7 @@ public class PopulatorFeature extends Feature { FabricChunkGeneratorWrapper gen = (FabricChunkGeneratorWrapper) chunkGenerator; FabricChunkWorldAccess chunk = new FabricChunkWorldAccess(world, pos.getX() >> 4, pos.getZ() >> 4); FabricWorld world1 = new FabricWorld(world.toServerWorld(), new FabricChunkGenerator(chunkGenerator)); - gen.getCavePopulator().populate(new FabricWorldAccess(world), chunk); - gen.getStructurePopulator().populate(new FabricWorldAccess(world), chunk); - gen.getOrePopulator().populate(world1, chunk); - gen.getTreePopulator().populate(world1, chunk); - gen.getFloraPopulator().populate(world1, chunk); + gen.getHandle().getPopulators().forEach(populator -> populator.populate(world1, chunk)); return true; } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/generator/FabricChunkGeneratorWrapper.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/generator/FabricChunkGeneratorWrapper.java index cb7ebe8b8..a15267e2d 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/generator/FabricChunkGeneratorWrapper.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/generator/FabricChunkGeneratorWrapper.java @@ -50,32 +50,6 @@ public class FabricChunkGeneratorWrapper extends ChunkGenerator implements Gener return pack; } - private final FloraPopulator floraPopulator = new FloraPopulator(TerraFabricPlugin.getInstance()); - private final OrePopulator orePopulator = new OrePopulator(TerraFabricPlugin.getInstance()); - private final TreePopulator treePopulator = new TreePopulator(TerraFabricPlugin.getInstance()); - private final StructurePopulator structurePopulator = new StructurePopulator(TerraFabricPlugin.getInstance()); - private final CavePopulator cavePopulator = new CavePopulator(TerraFabricPlugin.getInstance()); - - public TreePopulator getTreePopulator() { - return treePopulator; - } - - public OrePopulator getOrePopulator() { - return orePopulator; - } - - public FloraPopulator getFloraPopulator() { - return floraPopulator; - } - - public StructurePopulator getStructurePopulator() { - return structurePopulator; - } - - public CavePopulator getCavePopulator() { - return cavePopulator; - } - public FabricChunkGeneratorWrapper(TerraBiomeSource biomeSource, long seed, ConfigPack configPack) { super(biomeSource, new StructuresConfig(false)); this.pack = configPack; @@ -124,6 +98,8 @@ public class FabricChunkGeneratorWrapper extends ChunkGenerator implements Gener } + + @Override public boolean isStrongholdStartingChunk(ChunkPos chunkPos) { return false;