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 x_positions = Self::shuffled_inclusive_range(chunk_x << 4, (chunk_x << 4) + 15, random);
16        let z_positions = Self::shuffled_inclusive_range(chunk_z << 4, (chunk_z << 4) + 15, random);
17        let chest = vanilla_blocks::CHEST.default_state();
18        let torch = vanilla_blocks::TORCH.default_state();
19
20        for x in x_positions {
21            for &z in &z_positions {
22                let y = region.height_at(HeightmapType::MotionBlockingNoLeaves, x, z);
23                let chest_pos = BlockPos::new(x, y, z);
24                let state = region.block_state(chest_pos);
25                if state.is_air() || state.get_collision_shape_at(chest_pos).is_empty() {
26                    let _ = region.set_block_state(chest_pos, chest, UpdateFlags::UPDATE_CLIENTS);
27                    Self::set_loot_table_block_entity(
28                        region,
29                        chest_pos,
30                        &vanilla_block_entity_types::CHEST,
31                        chest,
32                        SPAWN_BONUS_CHEST,
33                        random.next_i64(),
34                    );
35
36                    let torch_behavior = BLOCK_BEHAVIORS.get_behavior(torch.get_block());
37                    for direction in Self::VANILLA_HORIZONTAL_DIRECTIONS {
38                        let torch_pos = chest_pos.relative(direction);
39                        if torch_behavior.can_survive(torch, region, torch_pos) {
40                            let _ = region.set_block_state(
41                                torch_pos,
42                                torch,
43                                UpdateFlags::UPDATE_CLIENTS,
44                            );
45                        }
46                    }
47
48                    return true;
49                }
50            }
51        }
52
53        false
54    }
55
56    fn shuffled_inclusive_range(start: i32, end: i32, random: &mut WorldgenRandom) -> Vec<i32> {
57        let mut values: Vec<i32> = (start..=end).collect();
58        for i in (1..values.len()).rev() {
59            let bound = (i + 1) as i32;
60            let j = random.next_i32_bounded(bound) as usize;
61            values.swap(i, j);
62        }
63        values
64    }
65}