steel_core/worldgen/generator/context.rs
1//! This module contains the `WorldGenContext` struct, which is used to provide context for chunk generation.
2
3use std::sync::{Arc, Weak};
4
5use enum_dispatch::enum_dispatch;
6use steel_worldgen::density_functions::{
7 end::EndNoises, nether::NetherNoises, overworld::OverworldNoises,
8};
9
10use crate::world::World;
11use crate::worldgen::generator::{
12 ChunkGenerator, EmptyChunkGenerator, FlatChunkGenerator, VanillaGenerator,
13};
14
15/// Type alias for overworld generator.
16pub type OverworldGenerator = VanillaGenerator<OverworldNoises>;
17
18/// Type alias for nether generator.
19pub type NetherGenerator = VanillaGenerator<NetherNoises>;
20
21/// Type alias for end generator.
22pub type EndGenerator = VanillaGenerator<EndNoises>;
23
24#[expect(
25 missing_docs,
26 reason = "variants are named after their dimension; self-explanatory"
27)]
28#[enum_dispatch(ChunkGenerator)]
29pub enum ChunkGeneratorType {
30 Flat(FlatChunkGenerator),
31 Empty(EmptyChunkGenerator),
32 Overworld(OverworldGenerator),
33 Nether(NetherGenerator),
34 End(EndGenerator),
35 //Custom(Box<dyn ChunkGenerator>),
36}
37
38/// Context for world generation.
39///
40/// Similar to vanilla's `WorldGenContext`, this provides access to the level/dimension
41/// and generation infrastructure.
42pub struct WorldGenContext {
43 /// The chunk generator to use.
44 pub generator: Arc<ChunkGeneratorType>,
45 /// Weak reference to the world (to avoid circular Arc reference).
46 /// Use `world()` to get a strong reference when needed.
47 world: Weak<World>,
48 /// Cached dimension minimum build Y. Immutable for the world's lifetime;
49 /// cached here so per-block queries avoid a `Weak<World>::upgrade` (a
50 /// cross-thread atomic refcount round-trip) on every call.
51 min_y: i32,
52 /// Cached dimension build height. See [`Self::min_y`].
53 height: i32,
54 /// Cached dimension sea level. Immutable for the world's lifetime. Read
55 /// per-column by the `freeze_top_layer` feature (snow/ice placement);
56 /// cached here so it avoids a `Weak<World>::upgrade` (cross-thread atomic
57 /// on the shared `Arc<World>`) on every column. See [`Self::min_y`].
58 sea_level: i32,
59}
60
61impl WorldGenContext {
62 /// Creates a new `WorldGenContext`.
63 ///
64 /// `min_y`/`height` are the dimension's build bounds (`DimensionType::min_y`
65 /// / `::height`); they are cached rather than read from the world per call.
66 #[must_use]
67 pub const fn new(
68 generator: Arc<ChunkGeneratorType>,
69 world: Weak<World>,
70 min_y: i32,
71 height: i32,
72 sea_level: i32,
73 ) -> Self {
74 Self {
75 generator,
76 world,
77 min_y,
78 height,
79 sea_level,
80 }
81 }
82
83 /// Returns the dimension's sea level (cached; see [`Self::min_y`]).
84 #[must_use]
85 pub const fn sea_level(&self) -> i32 {
86 self.sea_level
87 }
88
89 /// Gets a strong reference to the world.
90 ///
91 /// # Panics
92 /// Panics if the world has been dropped.
93 #[must_use]
94 pub fn world(&self) -> Arc<World> {
95 self.world.upgrade().expect("World has been dropped")
96 }
97
98 /// Gets a weak reference to the world.
99 ///
100 /// This is useful for passing to chunks without creating a strong reference cycle.
101 #[must_use]
102 pub fn weak_world(&self) -> Weak<World> {
103 self.world.clone()
104 }
105
106 /// Returns the minimum Y coordinate of the world.
107 #[must_use]
108 pub const fn min_y(&self) -> i32 {
109 self.min_y
110 }
111
112 /// Returns the total height of the world in blocks.
113 #[must_use]
114 pub const fn height(&self) -> i32 {
115 self.height
116 }
117
118 /// Returns the minimum Y coordinate used by `WorldGenerationContext`.
119 #[must_use]
120 pub fn generation_min_y(&self) -> i32 {
121 self.min_y.max(self.generator.min_y())
122 }
123
124 /// Returns the height used by `WorldGenerationContext`.
125 #[must_use]
126 pub fn generation_height(&self) -> i32 {
127 self.height.min(self.generator.gen_depth())
128 }
129
130 #[must_use]
131 /// How many sections this dimension has
132 pub const fn section_count(&self) -> usize {
133 (self.height / 16) as usize
134 }
135}