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, sound_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 entity::Entity,
18 world::game_event::GameEventContext,
19};
20
21const FLATTENABLES: [&Block; 6] = [
22 &vanilla_blocks::GRASS_BLOCK,
23 &vanilla_blocks::DIRT,
24 &vanilla_blocks::PODZOL,
25 &vanilla_blocks::COARSE_DIRT,
26 &vanilla_blocks::MYCELIUM,
27 &vanilla_blocks::ROOTED_DIRT,
28];
29
30const LIT_PROPERTY: BoolProperty = BlockStateProperties::LIT;
31
32#[item_behavior]
34pub struct ShovelItem;
35
36impl ItemBehavior for ShovelItem {
37 fn use_on(&self, context: &mut UseOnContext) -> InteractionResult {
38 if context.hit_result.direction == Direction::Down {
39 return InteractionResult::Pass;
40 }
41
42 let block_state = context.world.get_block_state(context.hit_result.block_pos);
43 let block = block_state.get_block();
44
45 if FLATTENABLES.contains(&block) {
47 if !context
48 .world
49 .get_block_state(context.hit_result.block_pos.above())
50 .is_air()
51 {
52 return InteractionResult::Pass;
53 }
54 context.world.play_block_sound(
55 &sound_events::ITEM_SHOVEL_FLATTEN,
56 context.hit_result.block_pos,
57 1.0,
58 1.0,
59 Some(context.player.id()),
60 );
61 let infinite_materials = context.player.has_infinite_materials();
62 context
63 .inv
64 .with_item(|item| item.hurt_and_break(1, infinite_materials));
65 let updated_state = vanilla_blocks::DIRT_PATH.default_state();
66 context.world.set_block(
67 context.hit_result.block_pos,
68 updated_state,
69 UpdateFlags::UPDATE_ALL_IMMEDIATE,
70 );
71 context.world.game_event(
72 &vanilla_game_events::BLOCK_CHANGE,
73 context.hit_result.block_pos,
74 &GameEventContext::new(Some(context.player), Some(updated_state)),
75 );
76 return InteractionResult::Success;
77 }
78
79 if block.has_tag(&BlockTag::CAMPFIRES) {
81 if !block_state.get_value(&LIT_PROPERTY) {
82 return InteractionResult::Pass;
83 }
84 context.world.level_event(
85 level_events::SOUND_EXTINGUISH_FIRE,
86 context.hit_result.block_pos,
87 0,
88 None,
89 );
90 let updated_state = block_state.set_value(&LIT_PROPERTY, false);
91 context.world.set_block(
92 context.hit_result.block_pos,
93 updated_state,
94 UpdateFlags::UPDATE_ALL_IMMEDIATE,
95 );
96 context.world.game_event(
98 &vanilla_game_events::BLOCK_CHANGE,
99 context.hit_result.block_pos,
100 &GameEventContext::new(Some(context.player), Some(updated_state)),
101 );
102 return InteractionResult::Success;
103 }
104
105 InteractionResult::Pass
106 }
107}