Skip to main content

steel_core/worldgen/generator/
mod.rs

1//! This module contains the `ChunkGenerator` trait, which is used to generate chunks.
2
3pub mod context;
4mod empty;
5mod flat;
6mod generation_chunk;
7pub mod registry;
8mod surface_biomes;
9pub(crate) mod vanilla;
10
11pub use empty::EmptyChunkGenerator;
12pub use flat::FlatChunkGenerator;
13#[cfg(feature = "benchmark-support")]
14pub use generation_chunk::benchmark_support as generation_benchmark_support;
15pub use generation_chunk::{GenerationChunk, TerrainPhase};
16pub use vanilla::{SteelPostNoiseState, VanillaGenerator, VanillaPostNoiseStateType};
17
18use enum_dispatch::enum_dispatch;
19use glam::IVec3;
20use steel_registry::biome::BiomeRef;
21use steel_utils::random::{
22    PositionalRandom as _, Random as _, RandomSource, RandomSplitter, name_hash::NameHash,
23    xoroshiro::Xoroshiro,
24};
25use steel_utils::{BlockPos, ChunkPos};
26
27use self::context::{ChunkGeneratorType, EndGenerator, NetherGenerator, OverworldGenerator};
28use crate::chunk::Chunk;
29use crate::worldgen::region::WorldGenRegion;
30use crate::worldgen::structure::StructureGenerator;
31use steel_worldgen::noise::Beardifier;
32
33/// A trait for generating chunks.
34#[enum_dispatch]
35pub trait ChunkGenerator: Send + Sync {
36    /// Returns the generator's minimum Y coordinate.
37    fn min_y(&self) -> i32;
38
39    /// Returns the generator's vertical generation depth in blocks.
40    fn gen_depth(&self) -> i32;
41
42    /// Returns the generator biome at one quart position without requiring a loaded chunk.
43    fn noise_biome(&self, quart_x: i32, quart_y: i32, quart_z: i32) -> BiomeRef;
44
45    /// Returns the climate-selected origin used by vanilla before searching for a safe spawn chunk.
46    fn initial_spawn_search_origin(&self) -> BlockPos {
47        BlockPos::new(0, 0, 0)
48    }
49
50    /// Returns the generator-provided spawn height used before falling back to the surface heightmap.
51    fn spawn_height(&self, min_y: i32, _height: i32) -> i32 {
52        let _ = min_y;
53        64
54    }
55
56    /// Returns the structure generator used for placement and locate queries.
57    fn structure_generator(&self) -> Option<&StructureGenerator> {
58        None
59    }
60
61    /// Creates the structures in a chunk.
62    fn create_structures(&self, chunk: &Chunk);
63
64    /// Creates the biomes in a chunk.
65    fn create_biomes(&self, chunk: &Chunk);
66
67    /// Builds vanilla's atomic Terrain generation step.
68    fn build_terrain(
69        &self,
70        chunk: GenerationChunk<'_, TerrainPhase>,
71        beardifier: Option<&Beardifier>,
72        neighbor_biomes: &dyn Fn(IVec3) -> u16,
73    ) {
74        self.fill_from_noise(chunk, beardifier);
75        self.build_surface(chunk, neighbor_biomes);
76        self.apply_carvers(chunk);
77        chunk.clear_post_noise_state();
78    }
79
80    /// Fills the chunk with noise as part of Terrain generation.
81    ///
82    /// `beardifier` carries pre-collected structure-piece terrain adaptation. The caller
83    /// (production: noise stage; tests: harness) is responsible for walking the chunk's
84    /// structure references and building the beardifier — this trait stays free of any
85    /// cross-chunk lookup. `None` skips the integration entirely (cheaper than passing
86    /// an empty beardifier).
87    fn fill_from_noise(
88        &self,
89        chunk: GenerationChunk<'_, TerrainPhase>,
90        beardifier: Option<&Beardifier>,
91    );
92
93    /// Builds the surface as part of Terrain generation.
94    ///
95    /// `neighbor_biomes` maps `(quart_x, quart_y, quart_z)` to a biome palette ID,
96    /// reading from neighbor chunk palettes for out-of-chunk biome lookups (matching
97    /// vanilla's `WorldGenRegion.getNoiseBiome`).
98    fn build_surface(
99        &self,
100        chunk: GenerationChunk<'_, TerrainPhase>,
101        neighbor_biomes: &dyn Fn(IVec3) -> u16,
102    );
103
104    /// Applies carvers as part of Terrain generation.
105    fn apply_carvers(&self, chunk: GenerationChunk<'_, TerrainPhase>);
106
107    /// Creates the per-region random source exposed by vanilla `WorldGenRegion.getRandom()`.
108    fn create_worldgen_region_random(&self, world_seed: i64, center: ChunkPos) -> RandomSource;
109
110    /// Applies structure piece placement and biome feature decorations.
111    fn apply_biome_decorations(&self, region: &mut WorldGenRegion<'_>);
112}
113
114pub(crate) fn worldgen_region_random_from_splitter(
115    splitter: &RandomSplitter,
116    center: ChunkPos,
117) -> RandomSource {
118    const WORLDGEN_REGION_RANDOM: NameHash = NameHash::new("minecraft:worldgen_region_random");
119
120    let mut named_random = splitter.with_hash_of(&WORLDGEN_REGION_RANDOM);
121    let region_factory = named_random.next_positional();
122    region_factory.at(center.0.x * 16, 0, center.0.y * 16)
123}
124
125pub(crate) fn xoroshiro_worldgen_region_random(world_seed: i64, center: ChunkPos) -> RandomSource {
126    let splitter = Xoroshiro::from_seed(world_seed as u64).next_positional();
127    worldgen_region_random_from_splitter(&splitter, center)
128}