steel_core/behavior/blocks/container/
ender_chest_block.rs1use std::sync::{Arc, Weak};
4
5use steel_macros::block_behavior;
6use steel_registry::blocks::BlockRef;
7use steel_registry::blocks::block_state_ext::BlockStateExt;
8use steel_registry::blocks::properties::BlockStateProperties;
9use steel_registry::{vanilla_block_entity_types, vanilla_custom_stats};
10use steel_utils::{BlockPos, BlockStateId, translations};
11use text_components::TextComponent;
12
13use crate::behavior::InventoryAccess;
14use crate::behavior::block::{BlockBehavior, BlockEntityCreation};
15use crate::behavior::context::{BlockHitResult, BlockPlaceContext, InteractionResult};
16use crate::block_entity::BLOCK_ENTITIES;
17use crate::inventory::menu::kinds::ender_chest;
18use crate::player::Player;
19use crate::world::{World, is_redstone_conductor};
20
21#[block_behavior]
23pub struct EnderChestBlock {
24 block: BlockRef,
25}
26
27impl EnderChestBlock {
28 #[must_use]
30 pub const fn new(block: BlockRef) -> Self {
31 Self { block }
32 }
33}
34
35impl BlockBehavior for EnderChestBlock {
36 fn get_state_for_placement(&self, context: &BlockPlaceContext<'_>) -> Option<BlockStateId> {
37 let facing = context.horizontal_direction().opposite();
38
39 Some(
40 self.block
41 .default_state()
42 .set_value(&BlockStateProperties::FACING, facing)
43 .set_value(
44 &BlockStateProperties::WATERLOGGED,
45 context.is_water_source(),
46 ),
47 )
48 }
49
50 fn use_without_item(
51 &self,
52 _state: BlockStateId,
53 world: &Arc<World>,
54 pos: BlockPos,
55 player: &Player,
56 _hit_result: &BlockHitResult,
57 _inv: &mut InventoryAccess,
58 ) -> InteractionResult {
59 let Some(block_entity) = world.get_block_entity(pos) else {
60 return InteractionResult::Success;
61 };
62 if block_entity.get_type() != &vanilla_block_entity_types::ENDER_CHEST {
63 return InteractionResult::Success;
64 }
65
66 let above_pos = pos.above();
67 if is_redstone_conductor(world.as_ref(), world.get_block_state(above_pos), above_pos) {
68 return InteractionResult::Success;
69 }
70
71 let inventory = player.inventory.clone();
72 let container = player.ender_chest_inventory.clone();
73 let chest = Arc::downgrade(&block_entity);
74 player.open_menu(
75 TextComponent::translated(translations::CONTAINER_ENDERCHEST.msg()),
76 move |context| {
77 container.lock().set_active_chest(chest);
80 ender_chest(inventory, context.container_id, container)
81 },
82 );
83
84 player.award_custom_stat(&vanilla_custom_stats::OPEN_ENDERCHEST);
85 InteractionResult::Success
88 }
89
90 fn new_block_entity(
91 &self,
92 level: Weak<World>,
93 pos: BlockPos,
94 state: BlockStateId,
95 ) -> BlockEntityCreation {
96 BlockEntityCreation::from_registered_factory(BLOCK_ENTITIES.create(
97 &vanilla_block_entity_types::ENDER_CHEST,
98 level,
99 pos,
100 state,
101 ))
102 }
103}