Skip to content

Commit

Permalink
Fix tool rules: Ensure get_speed and is_correct_for_drops check for t…
Browse files Browse the repository at this point in the history
…ags (#566)

* fix(tool-rules): ensure `get_speed` and `is_correct_for_drops` check for tags

Both functions were ignoring tags (`#tag`), causing incorrect default values.
- Now correctly checks tags before returning speed or drop validity.
- Ensures tool rules work as expected for both direct and tagged block matches.

* Make Clippy happy and use strip_prefix

replace manual stripping with strip_prefix

* Make clippy happy and use strip_prefix

Make clippy happy and use strip_prefix instead of manual stripping. Also removing unnecessary reference

* cargo: fmt

---------

Co-authored-by: Alexander Medvedev <lilalexmed@proton.me>
  • Loading branch information
Jayryn and Snowiiii authored Feb 22, 2025
1 parent 2af2fbb commit 0fb1b76
Showing 1 changed file with 58 additions and 12 deletions.
70 changes: 58 additions & 12 deletions pumpkin-world/src/item/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use pumpkin_data::item::Item;
use pumpkin_data::tag::{RegistryKey, get_tag_values};

mod categories;
#[derive(serde::Deserialize, Debug, Clone, PartialEq, Eq)]
Expand Down Expand Up @@ -28,26 +29,71 @@ impl ItemStack {
Self { item_count, item }
}

/// Determines the mining speed for a block based on tool rules.
/// Direct matches return immediately, tagged blocks are checked separately.
/// If no match is found, returns the tool's default mining speed or `1.0`.
pub fn get_speed(&self, block: &str) -> f32 {
if let Some(tool) = self.item.components.tool {
for rule in tool.rules {
if rule.speed.is_none() || !rule.blocks.contains(&block) {
continue;
// No tool? Use default speed
let Some(tool) = &self.item.components.tool else {
return 1.0;
};

for rule in tool.rules {
// Skip if speed is not set
let Some(speed) = rule.speed else {
continue;
};

for entry in rule.blocks {
if entry.eq(&block) {
return speed;
}

if entry.starts_with('#') {
// Check if block is in the tag group
if let Some(blocks) =
get_tag_values(RegistryKey::Block, entry.strip_prefix('#').unwrap())
{
if blocks.iter().flatten().any(|s| s == block) {
return speed;
}
}
}
return rule.speed.unwrap();
}
return tool.default_mining_speed.unwrap_or(1.0);
}
1.0
// Return default mining speed if no match is found
tool.default_mining_speed.unwrap_or(1.0)
}

/// Determines if a tool is valid for block drops based on tool rules.
/// Direct matches return immediately, while tagged blocks are checked separately.
pub fn is_correct_for_drops(&self, block: &str) -> bool {
if let Some(tool) = self.item.components.tool {
for rule in tool.rules {
if rule.correct_for_drops.is_none() || !rule.blocks.contains(&block) {
continue;
// Return false if no tool component exists
let Some(tool) = &self.item.components.tool else {
return false;
};

for rule in tool.rules {
// Skip rules without a drop condition
let Some(correct_for_drops) = rule.correct_for_drops else {
continue;
};

for entry in rule.blocks {
if entry.eq(&block) {
return correct_for_drops;
}

if entry.starts_with('#') {
// Check if block exists within the tag group
if let Some(blocks) =
get_tag_values(RegistryKey::Block, entry.strip_prefix('#').unwrap())
{
if blocks.iter().flatten().any(|s| s == block) {
return correct_for_drops;
}
}
}
return rule.correct_for_drops.unwrap();
}
}
false
Expand Down

0 comments on commit 0fb1b76

Please sign in to comment.