steel_core/behavior/items/
copper_chest_events.rs1use std::sync::Arc;
2
3use steel_registry::blocks::block_state_ext::BlockStateExt;
4use steel_registry::blocks::properties::{BlockStateProperties, ChestType};
5use steel_registry::vanilla_game_events;
6use steel_utils::{BlockPos, BlockStateId};
7
8use crate::{
9 entity::Entity,
10 player::Player,
11 world::{World, game_event::GameEventContext},
12};
13
14pub(super) fn emit_connected_chest_block_change(
16 world: &Arc<World>,
17 pos: BlockPos,
18 old_state: BlockStateId,
19 player: &Player,
20 level_event: Option<i32>,
21) {
22 let Some(neighbor_pos) = connected_chest_pos(pos, old_state) else {
23 return;
24 };
25
26 let neighbor_state = world.get_block_state(neighbor_pos);
27 world.game_event(
28 &vanilla_game_events::BLOCK_CHANGE,
29 neighbor_pos,
30 &GameEventContext::new(Some(player), Some(neighbor_state)),
31 );
32
33 if let Some(event) = level_event {
34 world.level_event(event, neighbor_pos, 0, Some(player.id()));
35 }
36}
37
38fn connected_chest_pos(pos: BlockPos, state: BlockStateId) -> Option<BlockPos> {
39 let chest_type = state.try_get_value(&BlockStateProperties::CHEST_TYPE)?;
40 if chest_type == ChestType::Single {
41 return None;
42 }
43
44 let facing = state.try_get_value(&BlockStateProperties::FACING)?;
45 let connected_direction = if chest_type == ChestType::Left {
46 facing.rotate_y_clockwise()
47 } else {
48 facing.rotate_y_counter_clockwise()
49 };
50
51 Some(pos.relative(connected_direction))
52}
53
54#[cfg(test)]
55mod tests {
56 use steel_registry::blocks::block_state_ext::BlockStateExt;
57 use steel_registry::blocks::properties::{BlockStateProperties, ChestType, Direction};
58 use steel_registry::init_vanilla_registry;
59 use steel_registry::vanilla_blocks;
60 use steel_utils::BlockPos;
61
62 use crate::behavior::items::copper_chest_events::connected_chest_pos;
63
64 #[test]
65 fn connected_chest_pos_matches_vanilla_left_and_right_offsets() {
66 init_vanilla_registry();
67
68 let pos = BlockPos::new(10, 64, 10);
69 let north_left = vanilla_blocks::COPPER_CHEST
70 .default_state()
71 .set_value(&BlockStateProperties::FACING, Direction::North)
72 .set_value(&BlockStateProperties::CHEST_TYPE, ChestType::Left);
73 let north_right = vanilla_blocks::COPPER_CHEST
74 .default_state()
75 .set_value(&BlockStateProperties::FACING, Direction::North)
76 .set_value(&BlockStateProperties::CHEST_TYPE, ChestType::Right);
77
78 assert_eq!(connected_chest_pos(pos, north_left), Some(pos.east()));
79 assert_eq!(connected_chest_pos(pos, north_right), Some(pos.west()));
80 }
81
82 #[test]
83 fn connected_chest_pos_ignores_single_chests() {
84 init_vanilla_registry();
85
86 let pos = BlockPos::new(10, 64, 10);
87 let single = vanilla_blocks::COPPER_CHEST
88 .default_state()
89 .set_value(&BlockStateProperties::CHEST_TYPE, ChestType::Single);
90
91 assert_eq!(connected_chest_pos(pos, single), None);
92 }
93}