Skip to main content

steel_core/worldgen/feature/features/
block_entities.rs

1use simdnbt::owned::{NbtCompound, NbtList, NbtTag};
2use steel_registry::block_entity_type::BlockEntityTypeRef;
3use steel_registry::vanilla_block_entity_types;
4use steel_registry::vanilla_block_tags::BlockTag;
5use steel_utils::PackedBlockPos;
6
7use super::super::prelude::*;
8use super::super::runner::FeatureDecorationRunner;
9
10impl FeatureDecorationRunner {
11    pub(in crate::worldgen::feature) fn set_loot_table_block_entity(
12        region: &WorldGenRegion<'_>,
13        pos: BlockPos,
14        block_entity_type: BlockEntityTypeRef,
15        state: BlockStateId,
16        loot_table: &'static str,
17        seed: i64,
18    ) {
19        let mut nbt = NbtCompound::new();
20        nbt.insert("LootTable", loot_table);
21        if seed != 0 {
22            nbt.insert("LootTableSeed", seed);
23        }
24        let _ = region.set_block_entity_data(pos, block_entity_type, state, nbt);
25    }
26
27    pub(in crate::worldgen::feature) fn set_empty_block_entity(
28        region: &WorldGenRegion<'_>,
29        pos: BlockPos,
30        block_entity_type: BlockEntityTypeRef,
31        state: BlockStateId,
32    ) {
33        let _ = region.set_block_entity_data(pos, block_entity_type, state, NbtCompound::new());
34    }
35
36    pub(in crate::worldgen::feature) fn set_brushable_loot_table(
37        region: &WorldGenRegion<'_>,
38        pos: BlockPos,
39        state: BlockStateId,
40        loot_table: &'static str,
41    ) {
42        let seed = PackedBlockPos::from(pos).as_raw();
43        Self::set_loot_table_block_entity(
44            region,
45            pos,
46            &vanilla_block_entity_types::BRUSHABLE_BLOCK,
47            state,
48            loot_table,
49            seed,
50        );
51    }
52
53    pub(in crate::worldgen::feature) fn set_spawner_entity(
54        region: &WorldGenRegion<'_>,
55        pos: BlockPos,
56        state: BlockStateId,
57        entity_id: &'static str,
58    ) {
59        let mut entity = NbtCompound::new();
60        entity.insert("id", entity_id);
61
62        let mut spawn_data = NbtCompound::new();
63        spawn_data.insert("entity", NbtTag::Compound(entity));
64
65        let mut nbt = NbtCompound::new();
66        nbt.insert("Delay", 20_i16);
67        nbt.insert("MinSpawnDelay", 200_i16);
68        nbt.insert("MaxSpawnDelay", 800_i16);
69        nbt.insert("SpawnCount", 4_i16);
70        nbt.insert("MaxNearbyEntities", 6_i16);
71        nbt.insert("RequiredPlayerRange", 16_i16);
72        nbt.insert("SpawnRange", 4_i16);
73        nbt.insert("SpawnData", NbtTag::Compound(spawn_data));
74        nbt.insert(
75            "SpawnPotentials",
76            NbtTag::List(NbtList::Compound(Vec::new())),
77        );
78
79        let _ =
80            region.set_block_entity_data(pos, &vanilla_block_entity_types::MOB_SPAWNER, state, nbt);
81    }
82
83    pub(in crate::worldgen::feature) fn set_end_gateway_block_entity(
84        region: &WorldGenRegion<'_>,
85        pos: BlockPos,
86        state: BlockStateId,
87        exit: Option<BlockPos>,
88        exact: bool,
89    ) {
90        let mut nbt = NbtCompound::new();
91        nbt.insert("Age", 0_i64);
92        if let Some(exit) = exit {
93            nbt.insert(
94                "exit_portal",
95                NbtTag::IntArray(vec![exit.x(), exit.y(), exit.z()]),
96            );
97        }
98        if exact {
99            nbt.insert("ExactTeleport", 1_i8);
100        }
101        let _ =
102            region.set_block_entity_data(pos, &vanilla_block_entity_types::END_GATEWAY, state, nbt);
103    }
104
105    pub(in crate::worldgen::feature) fn safe_set_feature_block(
106        region: &WorldGenRegion<'_>,
107        pos: BlockPos,
108        state: BlockStateId,
109    ) -> bool {
110        if Self::feature_can_replace(region.block_state(pos)) {
111            region.set_block_state(pos, state, UpdateFlags::UPDATE_CLIENTS)
112        } else {
113            false
114        }
115    }
116
117    pub(in crate::worldgen::feature) fn feature_can_replace(state: BlockStateId) -> bool {
118        !state
119            .get_block()
120            .has_tag(&BlockTag::FEATURES_CANNOT_REPLACE)
121    }
122}