1use azalea_block::{BlockBehavior, BlockTrait};
2use azalea_core::tier::get_item_tier;
3use azalea_registry::{self as registry, MobEffect};
4
5use crate::{ActiveEffects, FluidOnEyes, Physics};
6
7pub fn get_mine_progress(
18 block: &dyn BlockTrait,
19 held_item: registry::Item,
20 player_inventory: &azalea_inventory::Menu,
21 fluid_on_eyes: &FluidOnEyes,
22 physics: &Physics,
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 player_inventory,
41 fluid_on_eyes,
42 physics,
43 active_effects,
44 );
45 (base_destroy_speed / destroy_time) / divisor as f32
46}
47
48fn has_correct_tool_for_drops(block: &dyn BlockTrait, tool: registry::Item) -> bool {
49 if !block.behavior().requires_correct_tool_for_drops {
50 return true;
51 }
52 let registry_block = block.as_registry_block();
53 if tool == registry::Item::Shears {
54 matches!(
55 registry_block,
56 registry::Block::Cobweb | registry::Block::RedstoneWire | registry::Block::Tripwire
57 )
58 } else if registry::tags::items::SWORDS.contains(&tool) {
59 registry_block == registry::Block::Cobweb
60 } else if registry::tags::items::PICKAXES.contains(&tool)
61 || registry::tags::items::SHOVELS.contains(&tool)
62 || registry::tags::items::HOES.contains(&tool)
63 || registry::tags::items::AXES.contains(&tool)
64 {
65 let tier = get_item_tier(tool).expect("all pickaxes and shovels should be matched");
66 let tier_level = tier.level();
67 !((tier_level < 3 && registry::tags::blocks::NEEDS_DIAMOND_TOOL.contains(®istry_block))
68 || (tier_level < 2
69 && registry::tags::blocks::NEEDS_IRON_TOOL.contains(®istry_block))
70 || (tier_level < 1
71 && registry::tags::blocks::NEEDS_STONE_TOOL.contains(®istry_block)))
72 } else {
73 false
74 }
75}
76
77fn destroy_speed(
82 block: registry::Block,
83 tool: registry::Item,
84 _player_inventory: &azalea_inventory::Menu,
85 _fluid_on_eyes: &FluidOnEyes,
86 physics: &Physics,
87 active_effects: &ActiveEffects,
88) -> f32 {
89 let mut base_destroy_speed = base_destroy_speed(block, tool);
90
91 if let Some(dig_speed_amplifier) = active_effects.get_dig_speed_amplifier() {
102 base_destroy_speed *= 1. + (dig_speed_amplifier + 1) as f32 * 0.2;
103 }
104
105 if let Some(dig_slowdown) = active_effects.get_level(MobEffect::MiningFatigue) {
106 let multiplier = match dig_slowdown {
107 0 => 0.3,
108 1 => 0.09,
109 2 => 0.0027,
110 _ => 8.1E-4,
111 };
112 base_destroy_speed *= multiplier;
113 }
114
115 if !physics.on_ground {
124 base_destroy_speed /= 5.;
125 }
126
127 base_destroy_speed
128}
129
130fn base_destroy_speed(block: registry::Block, tool: registry::Item) -> f32 {
131 if tool == registry::Item::Shears {
132 if block == registry::Block::Cobweb || registry::tags::blocks::LEAVES.contains(&block) {
133 15.
134 } else if registry::tags::blocks::WOOL.contains(&block) {
135 5.
136 } else if matches!(block, registry::Block::Vine | registry::Block::GlowLichen) {
137 2.
138 } else {
139 1.
140 }
141 } else if registry::tags::items::SWORDS.contains(&tool) {
142 if block == registry::Block::Cobweb {
143 15.
144 } else if registry::tags::blocks::SWORD_EFFICIENT.contains(&block) {
145 1.5
146 } else {
147 1.
148 }
149 } else if registry::tags::items::PICKAXES.contains(&tool) {
150 if registry::tags::blocks::MINEABLE_PICKAXE.contains(&block) {
151 get_item_tier(tool).unwrap().speed()
152 } else {
153 1.
154 }
155 } else if registry::tags::items::SHOVELS.contains(&tool) {
156 if registry::tags::blocks::MINEABLE_SHOVEL.contains(&block) {
157 get_item_tier(tool).unwrap().speed()
158 } else {
159 1.
160 }
161 } else if registry::tags::items::HOES.contains(&tool) {
162 if registry::tags::blocks::MINEABLE_HOE.contains(&block) {
163 get_item_tier(tool).unwrap().speed()
164 } else {
165 1.
166 }
167 } else if registry::tags::items::AXES.contains(&tool) {
168 if registry::tags::blocks::MINEABLE_AXE.contains(&block) {
169 get_item_tier(tool).unwrap().speed()
170 } else {
171 1.
172 }
173 } else {
174 1.
175 }
176}