@@ -8,9 +8,9 @@ pub struct DestroyStateChange(pub ValidBlockPosition, pub u8);
88
99use crate :: { entities:: player:: HotbarSlot , Game , Window , World } ;
1010
11- // Comparing to 0.7 ensures good feeling in the client
1211pub const BREAK_THRESHOLD : f32 = 0.7 ;
1312
13+ /// Handle a player's request to start digging the block at `position`. Adds an `ActiveBreaker` component to `player`.
1414pub fn start_digging (
1515 game : & mut Game ,
1616 player : Entity ,
@@ -30,6 +30,7 @@ pub fn start_digging(
3030 }
3131 Ok ( true )
3232}
33+ /// Handle a player's request to stop digging the block at `position`. Removes `ActiveBreaker` from `player`.
3334pub fn cancel_digging (
3435 game : & mut Game ,
3536 player : Entity ,
@@ -43,6 +44,10 @@ pub fn cancel_digging(
4344 . insert_entity_event ( player, DestroyStateChange ( position, 10 ) ) ?;
4445 Ok ( true )
4546}
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.
4651pub fn finish_digging (
4752 game : & mut Game ,
4853 player : Entity ,
@@ -65,6 +70,8 @@ pub fn finish_digging(
6570 . insert_entity_event ( player, DestroyStateChange ( position, 10 ) ) ?;
6671 Ok ( success)
6772}
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.
6875#[ derive( Clone ) ]
6976pub struct ActiveBreaker {
7077 pub position : ValidBlockPosition ,
@@ -73,6 +80,7 @@ pub struct ActiveBreaker {
7380 pub damage : f32 ,
7481}
7582impl ActiveBreaker {
83+ /// Advance block breaking by one tick.
7684 pub fn tick ( & mut self ) -> ( bool , bool ) {
7785 let before = self . destroy_stage ( ) ;
7886 self . progress += self . damage ;
@@ -85,19 +93,23 @@ impl ActiveBreaker {
8593 pub fn can_break ( & self ) -> bool {
8694 self . progress >= BREAK_THRESHOLD - self . damage / 2.0
8795 }
96+ /// Start breaking a block. Returns an error if the block at `block_pos` is unloaded or not diggable.
8897 pub fn new (
8998 world : & mut World ,
9099 block_pos : ValidBlockPosition ,
91100 equipped_item : Option < & ItemStack > ,
92- ) -> Option < Self > {
93- let block = world. block_at ( block_pos) ?. kind ( ) ;
101+ ) -> anyhow:: Result < Self > {
102+ let block = world
103+ . block_at ( block_pos)
104+ . context ( "Block is not loaded" ) ?
105+ . kind ( ) ;
94106 if !block. diggable ( ) || block == BlockKind :: Air {
95- return None ;
107+ anyhow :: bail! ( "Block is not diggable" )
96108 }
97109 let harvestable = match ( block. harvest_tools ( ) , equipped_item) {
98110 ( None , None | Some ( _) ) => true ,
99111 ( Some ( _) , None ) => false ,
100- ( Some ( tools ) , Some ( tool ) ) => tools . contains ( & tool . item ( ) ) ,
112+ ( Some ( valid_tools ) , Some ( equipped ) ) => valid_tools . contains ( & equipped . item ( ) ) ,
101113 } ;
102114 let dig_multiplier = block // TODO: calculate with Haste effect
103115 . dig_multipliers ( )
@@ -115,9 +127,9 @@ impl ActiveBreaker {
115127 } else {
116128 1.0 / block. hardness ( ) / 100.0
117129 } ;
118- Some ( Self {
130+ Ok ( Self {
119131 position : block_pos,
120- drop_item : true ,
132+ drop_item : harvestable ,
121133 progress : damage,
122134 damage,
123135 } )
0 commit comments