Skip to main content

steel_core/behavior/blocks/container/
anvil_block.rs

1use std::sync::Arc;
2
3use steel_macros::block_behavior;
4use steel_registry::{
5    blocks::{
6        BlockRef,
7        block_state_ext::BlockStateExt,
8        properties::{BlockStateProperties, EnumProperty},
9    },
10    items::item::BlockHitResult,
11    vanilla_blocks, vanilla_custom_stats,
12};
13use steel_utils::{BlockStateId, Direction, translations};
14use text_components::TextComponent;
15
16use crate::{
17    behavior::{BlockBehavior, BlockPlaceContext, InteractionResult, InventoryAccess},
18    inventory::menu::kinds::anvil,
19    player::Player,
20    world::World,
21};
22
23/// Behavior for Anvils
24#[block_behavior]
25pub struct AnvilBlock {
26    block: BlockRef,
27}
28
29const FACING: &EnumProperty<Direction> = &BlockStateProperties::FACING;
30const HORIZONTAL_FACING: &EnumProperty<Direction> = &BlockStateProperties::HORIZONTAL_FACING;
31
32impl AnvilBlock {
33    /// Creates a new Anvil Block Behavior
34    #[must_use]
35    pub const fn new(block: BlockRef) -> Self {
36        Self { block }
37    }
38
39    /// Returns the next damage level block state for anvil `BlockStates`
40    #[must_use]
41    pub fn damage(state: BlockStateId) -> Option<BlockStateId> {
42        let block = state.get_block();
43        if block == &vanilla_blocks::ANVIL {
44            Some(
45                vanilla_blocks::CHIPPED_ANVIL
46                    .default_state()
47                    .copy_value(FACING, &state),
48            )
49        } else if block == &vanilla_blocks::CHIPPED_ANVIL {
50            Some(
51                vanilla_blocks::DAMAGED_ANVIL
52                    .default_state()
53                    .copy_value(FACING, &state),
54            )
55        } else {
56            None
57        }
58    }
59}
60
61impl BlockBehavior for AnvilBlock {
62    fn get_state_for_placement(&self, context: &BlockPlaceContext<'_>) -> Option<BlockStateId> {
63        Some(self.block.default_state().set_value(
64            HORIZONTAL_FACING,
65            context.horizontal_direction().rotate_y_clockwise(),
66        ))
67    }
68
69    fn use_without_item(
70        &self,
71        _state: BlockStateId,
72        _world: &Arc<World>,
73        pos: steel_utils::BlockPos,
74        player: &Player,
75        _hit_result: &BlockHitResult,
76        _inv: &mut InventoryAccess,
77    ) -> InteractionResult {
78        let inventory = player.inventory.clone();
79        player.open_menu(
80            TextComponent::translated(translations::CONTAINER_REPAIR.msg()),
81            move |context| anvil(inventory, context.container_id, pos, context.world),
82        );
83        player.award_custom_stat(&vanilla_custom_stats::INTERACT_WITH_ANVIL);
84        InteractionResult::Success
85    }
86}