steel_core/behavior/blocks/container/
beacon_block.rs1use std::sync::{Arc, Weak};
7
8use steel_macros::block_behavior;
9use steel_registry::block_entity_type::BlockEntityTypeRef;
10use steel_registry::blocks::BlockRef;
11use steel_registry::{DyeColor, vanilla_block_entity_types, vanilla_custom_stats};
12use steel_utils::{BlockPos, BlockStateId, Downcast as _, translations};
13use text_components::TextComponent;
14
15use crate::behavior::InventoryAccess;
16use crate::behavior::block::{BlockBehavior, BlockEntityCreation};
17use crate::behavior::context::{BlockHitResult, BlockPlaceContext, InteractionResult};
18use crate::block_entity::{BLOCK_ENTITIES, BlockEntityTicker, entities::BeaconBlockEntity};
19use crate::inventory::menu::kinds::beacon;
20use crate::player::Player;
21use crate::world::World;
22
23#[block_behavior]
25pub struct BeaconBlock {
26 block: BlockRef,
27}
28
29impl BeaconBlock {
30 #[must_use]
32 pub const fn new(block: BlockRef) -> Self {
33 Self { block }
34 }
35}
36
37impl BlockBehavior for BeaconBlock {
38 fn get_state_for_placement(&self, _context: &BlockPlaceContext<'_>) -> Option<BlockStateId> {
39 Some(self.block.default_state())
40 }
41
42 fn use_without_item(
43 &self,
44 _state: BlockStateId,
45 world: &Arc<World>,
46 pos: BlockPos,
47 player: &Player,
48 _hit_result: &BlockHitResult,
49 _inv: &mut InventoryAccess,
50 ) -> InteractionResult {
51 let Some(block_entity) = world.get_block_entity(pos) else {
52 return InteractionResult::Success;
53 };
54 let Some(beacon_entity) = block_entity.downcast_ref::<BeaconBlockEntity>() else {
55 return InteractionResult::Success;
56 };
57 let state = beacon_entity.state();
58 let base = beacon_entity.base_handle();
59
60 let inventory = player.inventory.clone();
61 let world = Arc::clone(world);
62 player.open_menu(
63 TextComponent::translated(translations::CONTAINER_BEACON.msg()),
64 move |context| beacon(inventory, context.container_id, pos, &world, state, base),
65 );
66
67 player.award_custom_stat(&vanilla_custom_stats::INTERACT_WITH_BEACON);
68 InteractionResult::Success
69 }
70
71 fn beacon_beam_color(&self, _state: BlockStateId) -> Option<DyeColor> {
74 Some(DyeColor::White)
75 }
76
77 fn new_block_entity(
78 &self,
79 level: Weak<World>,
80 pos: BlockPos,
81 state: BlockStateId,
82 ) -> BlockEntityCreation {
83 BlockEntityCreation::from_registered_factory(BLOCK_ENTITIES.create(
84 &vanilla_block_entity_types::BEACON,
85 level,
86 pos,
87 state,
88 ))
89 }
90
91 fn get_block_entity_ticker(
92 &self,
93 _world: &Arc<World>,
94 _state: BlockStateId,
95 block_entity_type: BlockEntityTypeRef,
96 ) -> Option<BlockEntityTicker> {
97 BlockEntityTicker::for_matching_entity_tick(
98 block_entity_type,
99 &vanilla_block_entity_types::BEACON,
100 )
101 }
102}