steel_worldgen/structure/
jungle_temple.rs1use steel_registry::structure::StructureData;
4use steel_utils::random::legacy_random::LegacyRandom;
5use steel_utils::{Direction, Identifier};
6
7use crate::structure::{
8 GenerationStub, ProceduralPieceData, Structure, StructureGenerationContext, StructurePiece,
9 StructurePiecePayload, make_oriented_piece_bounding_box, random_horizontal_direction,
10};
11
12pub(crate) const JUNGLE_TEMPLE_WIDTH: i32 = 12;
13pub(crate) const JUNGLE_TEMPLE_HEIGHT: i32 = 10;
14pub(crate) const JUNGLE_TEMPLE_DEPTH: i32 = 15;
15
16#[derive(Debug, Clone, Default)]
18pub struct JungleTemplePieceData {
19 pub height_position: Option<i32>,
21 pub placed_main_chest: bool,
23 pub placed_hidden_chest: bool,
25 pub placed_trap1: bool,
27 pub placed_trap2: bool,
29}
30
31impl JungleTemplePieceData {
32 #[must_use]
34 pub const fn new() -> Self {
35 Self {
36 height_position: None,
37 placed_main_chest: false,
38 placed_hidden_chest: false,
39 placed_trap1: false,
40 placed_trap2: false,
41 }
42 }
43}
44
45pub struct JungleTempleStructure;
47
48const fn jungle_temple_piece(west: i32, north: i32, orientation: Direction) -> StructurePiece {
49 StructurePiece {
50 piece_type: Identifier::new_static("minecraft", "tejp"),
51 bounding_box: make_oriented_piece_bounding_box(
52 west,
53 64,
54 north,
55 orientation,
56 JUNGLE_TEMPLE_WIDTH,
57 JUNGLE_TEMPLE_HEIGHT,
58 JUNGLE_TEMPLE_DEPTH,
59 ),
60 gen_depth: 0,
61 orientation: Some(orientation),
62 payload: StructurePiecePayload::Procedural(ProceduralPieceData::JungleTemple(
63 JungleTemplePieceData::new(),
64 )),
65 ground_level_delta: 0,
66 junctions: Vec::new(),
67 projection: None,
68 }
69}
70
71impl Structure for JungleTempleStructure {
72 fn find_generation_point(
73 &self,
74 ctx: &mut dyn StructureGenerationContext,
75 structure: &StructureData,
76 rng: &mut LegacyRandom,
77 ) -> Option<GenerationStub> {
78 let x0 = ctx.chunk_min_x();
79 let z0 = ctx.chunk_min_z();
80 let h0 = ctx.base_height(x0, z0, false) - 1;
81 let h1 = ctx.base_height(x0, z0 + JUNGLE_TEMPLE_DEPTH, false) - 1;
82 let h2 = ctx.base_height(x0 + JUNGLE_TEMPLE_WIDTH, z0, false) - 1;
83 let h3 = ctx.base_height(x0 + JUNGLE_TEMPLE_WIDTH, z0 + JUNGLE_TEMPLE_DEPTH, false) - 1;
84 if h0.min(h1).min(h2).min(h3) < ctx.sea_level() {
85 return None;
86 }
87
88 let center_y = ctx.base_height(ctx.center_block_x(), ctx.center_block_z(), false) - 1;
89 let biome = ctx.biome_at(ctx.center_block_x(), center_y, ctx.center_block_z());
90 if !structure.allowed_biomes.contains(&biome.key) {
91 return None;
92 }
93
94 let orientation = random_horizontal_direction(rng);
95 Some(GenerationStub {
96 position: (ctx.center_block_x(), center_y, ctx.center_block_z()),
97 pieces: vec![jungle_temple_piece(
98 ctx.chunk_min_x(),
99 ctx.chunk_min_z(),
100 orientation,
101 )],
102 })
103 }
104}
105
106#[cfg(test)]
107mod tests {
108 use super::*;
109
110 #[test]
111 fn jungle_temple_piece_uses_full_procedural_payload() {
112 let piece = jungle_temple_piece(16, 32, Direction::South);
113
114 assert_eq!(
115 piece.piece_type,
116 Identifier::new_static("minecraft", "tejp")
117 );
118 assert_eq!(piece.gen_depth, 0);
119 assert_eq!(piece.orientation, Some(Direction::South));
120 let StructurePiecePayload::Procedural(ProceduralPieceData::JungleTemple(data)) =
121 piece.payload
122 else {
123 panic!("jungle temple piece should use procedural payload");
124 };
125 assert_eq!(data.height_position, None);
126 assert!(!data.placed_main_chest);
127 assert!(!data.placed_hidden_chest);
128 assert!(!data.placed_trap1);
129 assert!(!data.placed_trap2);
130 }
131}