steel_core/behavior/items/
shovel.rs1use steel_macros::item_behavior;
2use steel_registry::{
3 blocks::{
4 Block,
5 block_state_ext::BlockStateExt,
6 properties::{BlockStateProperties, BoolProperty},
7 },
8 level_events,
9 vanilla_block_tags::BlockTag,
10 vanilla_blocks, vanilla_game_events,
11};
12use steel_utils::Direction;
13use steel_utils::types::UpdateFlags;
14
15use crate::{
16 behavior::{InteractionResult, ItemBehavior, UseOnContext},
17 world::game_event::GameEventContext,
18};
19
20const FLATTENABLES: [&Block; 6] = [
21 &vanilla_blocks::GRASS_BLOCK,
22 &vanilla_blocks::DIRT,
23 &vanilla_blocks::PODZOL,
24 &vanilla_blocks::COARSE_DIRT,
25 &vanilla_blocks::MYCELIUM,
26 &vanilla_blocks::ROOTED_DIRT,
27];
28
29const LIT_PROPERTY: BoolProperty = BlockStateProperties::LIT;
30
31#[item_behavior]
33pub struct ShovelItem;
34
35impl ItemBehavior for ShovelItem {
36 fn use_on(&self, context: &mut UseOnContext) -> InteractionResult {
37 if context.hit_result.direction == Direction::Down {
38 return InteractionResult::Pass;
39 }
40
41 let block_state = context.world.get_block_state(context.hit_result.block_pos);
42 let block = block_state.get_block();
43
44 if FLATTENABLES.contains(&block) {
46 if !context
47 .world
48 .get_block_state(context.hit_result.block_pos.above())
49 .is_air()
50 {
51 return InteractionResult::Pass;
52 }
53 let infinite_materials = context.player.has_infinite_materials();
55 context
56 .inv
57 .with_item(|item| item.hurt_and_break(1, infinite_materials));
58 let updated_state = vanilla_blocks::DIRT_PATH.default_state();
59 context.world.set_block(
60 context.hit_result.block_pos,
61 updated_state,
62 UpdateFlags::UPDATE_ALL_IMMEDIATE,
63 );
64 context.world.game_event(
65 &vanilla_game_events::BLOCK_CHANGE,
66 context.hit_result.block_pos,
67 &GameEventContext::new(Some(context.player), Some(updated_state)),
68 );
69 return InteractionResult::Success;
70 }
71
72 if block.has_tag(&BlockTag::CAMPFIRES) {
74 if !block_state.get_value(&LIT_PROPERTY) {
75 return InteractionResult::Pass;
76 }
77 context.world.level_event(
78 level_events::SOUND_EXTINGUISH_FIRE,
79 context.hit_result.block_pos,
80 0,
81 None,
82 );
83 let updated_state = block_state.set_value(&LIT_PROPERTY, false);
85 context.world.set_block(
86 context.hit_result.block_pos,
87 updated_state,
88 UpdateFlags::UPDATE_ALL_IMMEDIATE,
89 );
90 context.world.game_event(
92 &vanilla_game_events::BLOCK_CHANGE,
93 context.hit_result.block_pos,
94 &GameEventContext::new(Some(context.player), Some(updated_state)),
95 );
96 return InteractionResult::Success;
97 }
98
99 InteractionResult::Pass
100 }
101}