Skip to main content

steel_core/worldgen/feature/features/
bonus_chest.rs

1use super::super::prelude::*;
2use super::super::runner::FeatureDecorationRunner;
3use steel_registry::vanilla_block_entity_types;
4
5const SPAWN_BONUS_CHEST: &str = "minecraft:chests/spawn_bonus_chest";
6
7impl FeatureDecorationRunner {
8    pub(in crate::worldgen::feature) fn place_bonus_chest_feature(
9        region: &WorldGenRegion<'_>,
10        random: &mut WorldgenRandom,
11        origin: BlockPos,
12    ) -> bool {
13        let chunk_x = SectionPos::block_to_section_coord(origin.x());
14        let chunk_z = SectionPos::block_to_section_coord(origin.z());
15        let mut x_positions =
16            Self::shuffled_inclusive_range(chunk_x << 4, (chunk_x << 4) + 15, random);
17        let z_positions = Self::shuffled_inclusive_range(chunk_z << 4, (chunk_z << 4) + 15, random);
18        let chest = vanilla_blocks::CHEST.default_state();
19        let torch = vanilla_blocks::TORCH.default_state();
20
21        for x in x_positions.drain(..) {
22            for &z in &z_positions {
23                let y = region.height_at(HeightmapType::MotionBlockingNoLeaves, x, z);
24                let chest_pos = BlockPos::new(x, y, z);
25                let state = region.block_state(chest_pos);
26                if state.is_air() || state.get_collision_shape_at(chest_pos).is_empty() {
27                    let _ = region.set_block_state(chest_pos, chest, UpdateFlags::UPDATE_CLIENTS);
28                    Self::set_loot_table_block_entity(
29                        region,
30                        chest_pos,
31                        &vanilla_block_entity_types::CHEST,
32                        chest,
33                        SPAWN_BONUS_CHEST,
34                        random.next_i64(),
35                    );
36
37                    let torch_behavior = BLOCK_BEHAVIORS.get_behavior(torch.get_block());
38                    for direction in Self::VANILLA_HORIZONTAL_DIRECTIONS {
39                        let torch_pos = chest_pos.relative(direction);
40                        if torch_behavior.can_survive(torch, region, torch_pos) {
41                            let _ = region.set_block_state(
42                                torch_pos,
43                                torch,
44                                UpdateFlags::UPDATE_CLIENTS,
45                            );
46                        }
47                    }
48
49                    return true;
50                }
51            }
52        }
53
54        false
55    }
56
57    fn shuffled_inclusive_range(start: i32, end: i32, random: &mut WorldgenRandom) -> Vec<i32> {
58        let mut values: Vec<i32> = (start..=end).collect();
59        for i in (1..values.len()).rev() {
60            let bound = (i + 1) as i32;
61            let j = random.next_i32_bounded(bound) as usize;
62            values.swap(i, j);
63        }
64        values
65    }
66}