steel_core/worldgen/feature/features/
underwater_magma.rs1use 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}