fix(item): require a non-empty charged list to fire a crossbow (#2805)

Item::CROSSBOW ships a ChargedProjectiles component by default, carrying an empty
projectile list (crates/pumpkin-data/src/generated/item.rs, the CROSSBOW components
table). normal_use tested only for the presence of that component, which is therefore
true for every crossbow including a freshly crafted one.

The result is that the first right-click on an uncharged crossbow takes the fire branch,
fire_projectiles iterates an empty list and does nothing, and charging never starts, so
the crossbow cannot be used at all until something else happens to write a non-empty
patch.

Vanilla gates on the list being present AND non-empty:

    ChargedProjectiles chargedProjectiles = itemStack.get(DataComponents.CHARGED_PROJECTILES);
    if (chargedProjectiles != null && !chargedProjectiles.isEmpty()) {

(CrossbowItem.java:67-68, 26.2.) Matching that here restores the charge-then-fire cycle.

Test plan:
- cargo fmt --all
- RUSTFLAGS="-D warnings" cargo clippy -p pumpkin --all-targets
This commit is contained in:
Eshan I.
2026-08-09 09:59:09 -04:00
committed by GitHub
parent dedce1ce45
commit c75b89fd89

View File

@@ -34,9 +34,12 @@ impl ItemBehaviour for CrossbowItem {
let inventory = player.inventory();
let stack = inventory.held_item().await;
// Every crossbow carries a ChargedProjectiles component by default, so its mere
// presence does not mean the crossbow is loaded. Vanilla checks the list is also
// non-empty (CrossbowItem.java:68).
if stack
.get_data_component::<ChargedProjectilesImpl>()
.is_some()
.is_some_and(|charged| !charged.projectiles.is_empty())
{
Self::fire_projectiles(player).await;
return;