1use azalea_block::{BlockBehavior, BlockTrait};
2use azalea_inventory::{ItemStack, components::Tool};
3use azalea_registry::builtin::{BlockKind, MobEffect};
4
5use crate::{ActiveEffects, Attributes, FluidOnEyes, Physics};
6
7pub fn get_mine_progress(
18 block: &dyn BlockTrait,
19 held_item: &ItemStack,
20 fluid_on_eyes: &FluidOnEyes,
21 physics: &Physics,
22 attributes: &Attributes,
23 active_effects: &ActiveEffects,
24) -> f32 {
25 let block_behavior: BlockBehavior = block.behavior();
26
27 let destroy_time = block_behavior.destroy_time;
28 if destroy_time == -1. {
29 return 0.;
30 }
31 let divisor = if has_correct_tool_for_drops(block, held_item) {
32 30
33 } else {
34 100
35 };
36
37 let base_destroy_speed = destroy_speed(
38 block.as_registry_block(),
39 held_item,
40 fluid_on_eyes,
41 physics,
42 attributes,
43 active_effects,
44 );
45 (base_destroy_speed / destroy_time) / (divisor as f32)
46}
47
48fn has_correct_tool_for_drops(block: &dyn BlockTrait, item: &ItemStack) -> bool {
49 if !block.behavior().requires_correct_tool_for_drops {
50 return true;
51 }
52 let Some(tool) = item.get_component::<Tool>() else {
53 return false;
54 };
55 let registry_block = block.as_registry_block();
56 for rule in &tool.rules {
57 if let Some(correct) = rule.correct_for_drops
58 && rule.blocks.contains(registry_block)
59 {
60 return correct;
61 }
62 }
63
64 false
65}
66
67fn destroy_speed(
73 block: BlockKind,
74 tool: &ItemStack,
75 _fluid_on_eyes: &FluidOnEyes,
76 physics: &Physics,
77 attributes: &Attributes,
78 active_effects: &ActiveEffects,
79) -> f32 {
80 let mut speed = base_destroy_speed(block, tool);
81
82 if speed > 1. {
83 speed += attributes.mining_efficiency.calculate() as f32;
85 }
86
87 if let Some(dig_speed_amplifier) = active_effects.get_dig_speed_amplifier() {
88 speed *= 1. + (dig_speed_amplifier + 1) as f32 * 0.2;
89 }
90
91 if let Some(dig_slowdown) = active_effects.get_level(MobEffect::MiningFatigue) {
92 let multiplier = match dig_slowdown {
93 0 => 0.3,
94 1 => 0.09,
95 2 => 0.0027,
96 _ => 8.1E-4,
97 };
98 speed *= multiplier;
99 }
100
101 speed *= attributes.block_break_speed.calculate() as f32;
102
103 if !physics.on_ground {
112 speed /= 5.;
113 }
114
115 speed
116}
117
118fn base_destroy_speed(block: BlockKind, item: &ItemStack) -> f32 {
119 let tool = item.get_component::<Tool>();
120 let Some(tool) = tool else { return 1. };
121 for rule in &tool.rules {
122 if let Some(speed) = rule.speed
123 && rule.blocks.contains(block)
124 {
125 return speed;
126 }
127 }
128 tool.default_mining_speed
129}