Skip to main content

steel_core/worldgen/structure/piece_placer/
swamp_hut.rs

1use std::sync::Arc;
2
3use glam::DVec3;
4use steel_registry::blocks::block_state_ext::BlockStateExt as _;
5use steel_registry::blocks::properties::{BlockStateProperties, StairsShape};
6use steel_registry::entity_type::EntityTypeRef;
7use steel_registry::{Registry, vanilla_blocks, vanilla_entities};
8use steel_utils::random::worldgen_random::WorldgenRandom;
9use steel_utils::{BlockStateId, BoundingBox, Direction};
10
11use crate::entity::{entities::RawEntity, next_entity_id};
12use crate::worldgen::region::WorldGenRegion;
13use steel_worldgen::structure::swamp_hut::SwampHutPieceData;
14
15use super::StructurePiecePlacer;
16use super::scattered_feature::ScatteredFeaturePlacer;
17
18impl StructurePiecePlacer {
19    pub(super) fn place_swamp_hut_piece(
20        region: &mut WorldGenRegion<'_>,
21        registry: &Registry,
22        bounding_box: &mut BoundingBox,
23        orientation: Option<Direction>,
24        data: &mut SwampHutPieceData,
25        clip: BoundingBox,
26        _random: &mut WorldgenRandom,
27    ) -> bool {
28        let mut placer =
29            ScatteredFeaturePlacer::new(region, registry, bounding_box, orientation, clip);
30        if !placer.update_average_ground_height(&mut data.height_position, 0) {
31            return false;
32        }
33
34        place_swamp_hut(&mut placer, data);
35        true
36    }
37}
38
39fn place_swamp_hut(placer: &mut ScatteredFeaturePlacer<'_, '_>, data: &mut SwampHutPieceData) {
40    let spruce_planks = vanilla_blocks::SPRUCE_PLANKS.default_state();
41    let oak_log = vanilla_blocks::OAK_LOG.default_state();
42    let oak_fence = vanilla_blocks::OAK_FENCE.default_state();
43    let air = vanilla_blocks::AIR.default_state();
44
45    placer.generate_box(1, 1, 1, 5, 1, 7, spruce_planks, spruce_planks, false);
46    placer.generate_box(1, 4, 2, 5, 4, 7, spruce_planks, spruce_planks, false);
47    placer.generate_box(2, 1, 0, 4, 1, 0, spruce_planks, spruce_planks, false);
48    placer.generate_box(2, 2, 2, 3, 3, 2, spruce_planks, spruce_planks, false);
49    placer.generate_box(1, 2, 3, 1, 3, 6, spruce_planks, spruce_planks, false);
50    placer.generate_box(5, 2, 3, 5, 3, 6, spruce_planks, spruce_planks, false);
51    placer.generate_box(2, 2, 7, 4, 3, 7, spruce_planks, spruce_planks, false);
52    placer.generate_box(1, 0, 2, 1, 3, 2, oak_log, oak_log, false);
53    placer.generate_box(5, 0, 2, 5, 3, 2, oak_log, oak_log, false);
54    placer.generate_box(1, 0, 7, 1, 3, 7, oak_log, oak_log, false);
55    placer.generate_box(5, 0, 7, 5, 3, 7, oak_log, oak_log, false);
56    placer.place_block(oak_fence, 2, 3, 2);
57    placer.place_block(oak_fence, 3, 3, 7);
58    placer.place_block(air, 1, 3, 4);
59    placer.place_block(air, 5, 3, 4);
60    placer.place_block(air, 5, 3, 5);
61    placer.place_block(vanilla_blocks::POTTED_RED_MUSHROOM.default_state(), 1, 3, 5);
62    placer.place_block(vanilla_blocks::CRAFTING_TABLE.default_state(), 3, 2, 6);
63    placer.place_block(vanilla_blocks::CAULDRON.default_state(), 4, 2, 6);
64    placer.place_block(oak_fence, 1, 2, 1);
65    placer.place_block(oak_fence, 5, 2, 1);
66
67    let north_stairs = stairs(Direction::North);
68    let east_stairs = stairs(Direction::East);
69    let west_stairs = stairs(Direction::West);
70    let south_stairs = stairs(Direction::South);
71    placer.generate_box(0, 4, 1, 6, 4, 1, north_stairs, north_stairs, false);
72    placer.generate_box(0, 4, 2, 0, 4, 7, east_stairs, east_stairs, false);
73    placer.generate_box(6, 4, 2, 6, 4, 7, west_stairs, west_stairs, false);
74    placer.generate_box(0, 4, 8, 6, 4, 8, south_stairs, south_stairs, false);
75    placer.place_block(stairs_shape(north_stairs, StairsShape::OuterRight), 0, 4, 1);
76    placer.place_block(stairs_shape(north_stairs, StairsShape::OuterLeft), 6, 4, 1);
77    placer.place_block(stairs_shape(south_stairs, StairsShape::OuterLeft), 0, 4, 8);
78    placer.place_block(stairs_shape(south_stairs, StairsShape::OuterRight), 6, 4, 8);
79
80    for z in [2, 7] {
81        for x in [1, 5] {
82            placer.fill_column_down(oak_log, x, -1, z);
83        }
84    }
85
86    spawn_swamp_hut_mob(placer, &mut data.spawned_witch, &vanilla_entities::WITCH);
87    spawn_swamp_hut_mob(placer, &mut data.spawned_cat, &vanilla_entities::CAT);
88}
89
90fn spawn_swamp_hut_mob(
91    placer: &mut ScatteredFeaturePlacer<'_, '_>,
92    spawned: &mut bool,
93    entity_type: EntityTypeRef,
94) {
95    if *spawned {
96        return;
97    }
98
99    let pos = placer.world_pos(2, 2, 5);
100    if !placer.clip().contains_blockpos(pos) {
101        return;
102    }
103
104    *spawned = true;
105    let entity = Arc::new(RawEntity::new(
106        next_entity_id(),
107        DVec3::new(
108            f64::from(pos.x()) + 0.5,
109            f64::from(pos.y()),
110            f64::from(pos.z()) + 0.5,
111        ),
112        placer.weak_world(),
113        entity_type,
114    ));
115    entity.set_persistence_required();
116    entity.snap_to(
117        DVec3::new(
118            f64::from(pos.x()) + 0.5,
119            f64::from(pos.y()),
120            f64::from(pos.z()) + 0.5,
121        ),
122        0.0,
123        0.0,
124    );
125    let _ = placer.add_fresh_entity(entity);
126}
127
128fn stairs(facing: Direction) -> BlockStateId {
129    vanilla_blocks::SPRUCE_STAIRS
130        .default_state()
131        .set_value(&BlockStateProperties::FACING, facing)
132}
133
134fn stairs_shape(state: BlockStateId, shape: StairsShape) -> BlockStateId {
135    state.set_value(&BlockStateProperties::STAIRS_SHAPE, shape)
136}