Skip to main content

steel_core/worldgen/feature/features/
underwater_magma.rs

1use super::super::prelude::*;
2use super::super::runner::FeatureDecorationRunner;
3
4impl FeatureDecorationRunner {
5    pub(in crate::worldgen::feature) fn place_underwater_magma_feature(
6        region: &mut WorldGenRegion<'_>,
7        random: &mut WorldgenRandom,
8        config: &UnderwaterMagmaConfiguration,
9        origin: BlockPos,
10    ) -> bool {
11        let Some(floor_y) = Self::underwater_magma_floor_y(region, origin, config) else {
12            return false;
13        };
14
15        let floor_pos = origin.at_y(floor_y);
16        let radius = config.placement_radius_around_floor;
17        let mut placed = false;
18
19        Self::for_each_vanilla_between_closed(
20            floor_pos.offset(-radius, -radius, -radius),
21            floor_pos.offset(radius, radius, radius),
22            |pos| {
23                if random.next_f32() < config.placement_probability_per_valid_position
24                    && Self::underwater_magma_valid_placement(region, pos)
25                {
26                    let did_place = region.set_block_state(
27                        pos,
28                        vanilla_blocks::MAGMA_BLOCK.default_state(),
29                        UpdateFlags::UPDATE_CLIENTS,
30                    );
31                    placed |= did_place;
32                }
33            },
34        );
35
36        placed
37    }
38
39    fn underwater_magma_floor_y(
40        region: &WorldGenRegion<'_>,
41        origin: BlockPos,
42        config: &UnderwaterMagmaConfiguration,
43    ) -> Option<i32> {
44        if region.block_state(origin).get_block() != &vanilla_blocks::WATER {
45            return None;
46        }
47
48        let mut pos = origin;
49        for _ in 1..config.floor_search_range {
50            if region.block_state(pos).get_block() != &vanilla_blocks::WATER {
51                break;
52            }
53            pos = pos.below();
54        }
55
56        if region.block_state(pos).get_block() == &vanilla_blocks::WATER {
57            return None;
58        }
59
60        Some(pos.y())
61    }
62
63    fn underwater_magma_valid_placement(region: &WorldGenRegion<'_>, pos: BlockPos) -> bool {
64        let state = region.block_state(pos);
65        if Self::underwater_magma_is_water_or_air(state)
66            || Self::underwater_magma_visible_from_outside(region, pos.below(), Direction::Up)
67        {
68            return false;
69        }
70
71        for direction in Self::VANILLA_HORIZONTAL_DIRECTIONS {
72            if Self::underwater_magma_visible_from_outside(
73                region,
74                pos.relative(direction),
75                direction.opposite(),
76            ) {
77                return false;
78            }
79        }
80
81        true
82    }
83
84    fn underwater_magma_is_water_or_air(state: BlockStateId) -> bool {
85        state.get_block() == &vanilla_blocks::WATER || state.is_air()
86    }
87
88    fn underwater_magma_visible_from_outside(
89        region: &WorldGenRegion<'_>,
90        pos: BlockPos,
91        covered_direction: Direction,
92    ) -> bool {
93        let state = region.block_state(pos);
94        let face_occlusion_shape = state.get_occlusion_shape();
95        face_occlusion_shape.is_empty()
96            || !shapes::is_face_full(face_occlusion_shape, covered_direction)
97    }
98}