From 24d9dbdc6b1528dad9794f9bf8956ac9c4e325c3 Mon Sep 17 00:00:00 2001 From: QiuHu <74653499+2982136527@users.noreply.github.com> Date: Thu, 13 Aug 2026 20:23:58 +0800 Subject: [PATCH] fix(inventory): decode block-placement and swing hands via from_packet_id (#2876) The placement and swing packet 'hand' fields use 0 = main hand, but they were decoded with TryFrom, which maps 0 -> Hand::Left (that conversion is for the client's dominant-hand setting). Hand::Left means off-hand in the inventory API, so the decremented stack was written back to the off-hand instead of the main hand, causing non-consumed placement and duplication into the off-hand. Use Hand::from_packet_id for these packet fields and read the item via inventory.get_stack_in_hand, matching the existing use_item handler. --- crates/pumpkin/src/net/java/play.rs | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/crates/pumpkin/src/net/java/play.rs b/crates/pumpkin/src/net/java/play.rs index f19c6cf10..e5beac5ea 100644 --- a/crates/pumpkin/src/net/java/play.rs +++ b/crates/pumpkin/src/net/java/play.rs @@ -1354,7 +1354,7 @@ impl JavaClient { swing_arm: SSwingArm, ) { player.update_last_action_time(); - let Ok(hand) = Hand::try_from(swing_arm.hand.0) else { + let Ok(hand) = Hand::from_packet_id(swing_arm.hand.0) else { self.kick(TextComponent::text("Invalid hand")).await; return; }; @@ -2284,7 +2284,7 @@ impl JavaClient { return Err(BlockPlacingError::InvalidBlockFace); }; - let Ok(hand) = Hand::try_from(use_item_on.hand.0) else { + let Ok(hand) = Hand::from_packet_id(use_item_on.hand.0) else { return Err(BlockPlacingError::InvalidHand); }; @@ -2299,11 +2299,8 @@ impl JavaClient { let held_item_empty = held_item.is_empty(); let off_hand_item_empty = off_hand_item.is_empty(); - let item_id = if matches!(hand, Hand::Left) { - held_item.item.id - } else { - off_hand_item.item.id - }; + let mut item = inventory.get_stack_in_hand(hand).await; + let item_id = item.item.id; player .increment_stat(StatisticCategory::Used, item_id as i32, 1) .await; @@ -2333,12 +2330,7 @@ impl JavaClient { } }} - let mut item = if matches!(hand, Hand::Left) { - held_item - } else { - off_hand_item - }; - let equipment_slot = if matches!(hand, Hand::Left) { + let equipment_slot = if matches!(hand, Hand::Right) { EquipmentSlot::MAIN_HAND } else { EquipmentSlot::OFF_HAND @@ -2371,7 +2363,7 @@ impl JavaClient { } } - let slot_index = if matches!(hand, Hand::Left) { + let slot_index = if matches!(hand, Hand::Right) { inventory.get_selected_slot() as usize } else { PlayerInventory::OFF_HAND_SLOT