@@ -8,9 +8,9 @@ pub struct DestroyStateChange(pub ValidBlockPosition, pub u8);
8
8
9
9
use crate :: { entities:: player:: HotbarSlot , Game , Window , World } ;
10
10
11
- // Comparing to 0.7 ensures good feeling in the client
12
11
pub const BREAK_THRESHOLD : f32 = 0.7 ;
13
12
13
+ /// Handle a player's request to start digging the block at `position`. Adds an `ActiveBreaker` component to `player`.
14
14
pub fn start_digging (
15
15
game : & mut Game ,
16
16
player : Entity ,
@@ -30,6 +30,7 @@ pub fn start_digging(
30
30
}
31
31
Ok ( true )
32
32
}
33
+ /// Handle a player's request to stop digging the block at `position`. Removes `ActiveBreaker` from `player`.
33
34
pub fn cancel_digging (
34
35
game : & mut Game ,
35
36
player : Entity ,
@@ -43,6 +44,10 @@ pub fn cancel_digging(
43
44
. insert_entity_event ( player, DestroyStateChange ( position, 10 ) ) ?;
44
45
Ok ( true )
45
46
}
47
+ /// Handle a player's request to finish digging the block at `position`.
48
+ /// This is called when the block breaking finishes at the player's side.
49
+ ///
50
+ /// Will return `false` if the system hasn't finished breaking the block yet.
46
51
pub fn finish_digging (
47
52
game : & mut Game ,
48
53
player : Entity ,
@@ -65,6 +70,8 @@ pub fn finish_digging(
65
70
. insert_entity_event ( player, DestroyStateChange ( position, 10 ) ) ?;
66
71
Ok ( success)
67
72
}
73
+ /// Main component for the block breaking system.
74
+ /// Tracks the position of the block being mined, whether it will drop an item and the current progress.
68
75
#[ derive( Clone ) ]
69
76
pub struct ActiveBreaker {
70
77
pub position : ValidBlockPosition ,
@@ -73,6 +80,7 @@ pub struct ActiveBreaker {
73
80
pub damage : f32 ,
74
81
}
75
82
impl ActiveBreaker {
83
+ /// Advance block breaking by one tick.
76
84
pub fn tick ( & mut self ) -> ( bool , bool ) {
77
85
let before = self . destroy_stage ( ) ;
78
86
self . progress += self . damage ;
@@ -85,19 +93,20 @@ impl ActiveBreaker {
85
93
pub fn can_break ( & self ) -> bool {
86
94
self . progress >= BREAK_THRESHOLD - self . damage / 2.0
87
95
}
96
+ /// Start breaking a block. Returns an error if the block at `block_pos` is unloaded or not diggable.
88
97
pub fn new (
89
98
world : & mut World ,
90
99
block_pos : ValidBlockPosition ,
91
100
equipped_item : Option < & ItemStack > ,
92
- ) -> Option < Self > {
93
- let block = world. block_at ( block_pos) ?. kind ( ) ;
101
+ ) -> anyhow :: Result < Self > {
102
+ let block = world. block_at ( block_pos) . context ( "Block is not loaded" ) ?. kind ( ) ;
94
103
if !block. diggable ( ) || block == BlockKind :: Air {
95
- return None ;
104
+ anyhow :: bail! ( "Block is not diggable" )
96
105
}
97
106
let harvestable = match ( block. harvest_tools ( ) , equipped_item) {
98
107
( None , None | Some ( _) ) => true ,
99
108
( Some ( _) , None ) => false ,
100
- ( Some ( tools ) , Some ( tool ) ) => tools . contains ( & tool . item ( ) ) ,
109
+ ( Some ( valid_tools ) , Some ( equipped ) ) => valid_tools . contains ( & equipped . item ( ) ) ,
101
110
} ;
102
111
let dig_multiplier = block // TODO: calculate with Haste effect
103
112
. dig_multipliers ( )
@@ -115,9 +124,9 @@ impl ActiveBreaker {
115
124
} else {
116
125
1.0 / block. hardness ( ) / 100.0
117
126
} ;
118
- Some ( Self {
127
+ Ok ( Self {
119
128
position : block_pos,
120
- drop_item : true ,
129
+ drop_item : harvestable ,
121
130
progress : damage,
122
131
damage,
123
132
} )
0 commit comments