fixes "none armor items in armor slots #996" (#1008)

* fixes #996

* fmt

* code review changes

* added skulls and pumpkin as allowed helmets

* shift + left click moves items to armor slots

* shift + left click moves items to armor slots

* reformatted

* linter

* handles moving stack bigger than 1 item
This commit is contained in:
Damian Lesiuk
2025-07-10 11:37:18 +02:00
committed by GitHub
parent 49a15c6031
commit a378e48a04
3 changed files with 60 additions and 10 deletions

View File

@@ -75,6 +75,42 @@ impl PlayerScreenHandler {
player_screen_handler
}
async fn try_move_one_to_armor_slot(&mut self, stack: &ItemStack) -> bool {
if stack.item_count == 0 {
return false;
}
let one_item = stack.copy_with_count(1);
for armor_slot_index in 5..9 {
let armor_slot = self.get_slot(armor_slot_index).await;
if !armor_slot.has_stack().await && armor_slot.can_insert(&one_item).await {
armor_slot.set_stack(one_item).await;
return true;
}
}
false
}
async fn handle_inventory_move(&mut self, slot_index: i32, slot_stack: &mut ItemStack) -> bool {
if !slot_stack.is_empty() && self.try_move_one_to_armor_slot(slot_stack).await {
slot_stack.item_count -= 1;
if slot_stack.item_count == 0 {
*slot_stack = ItemStack::EMPTY;
}
}
if slot_stack.is_empty() {
true
} else {
match slot_index {
9..=35 => self.insert_item(slot_stack, 36, 45, false).await, // Main → Hotbar
36..=44 => self.insert_item(slot_stack, 9, 36, false).await, // Hotbar → Main
_ => false,
}
}
}
}
#[async_trait]
@@ -127,12 +163,11 @@ impl ScreenHandler for PlayerScreenHandler {
if !self.insert_item(&mut slot_stack, 9, 45, false).await {
return ItemStack::EMPTY;
}
} else if (9..36).contains(&slot_index) {
if !self.insert_item(&mut slot_stack, 36, 45, false).await {
return ItemStack::EMPTY;
}
} else if (36..45).contains(&slot_index) {
if !self.insert_item(&mut slot_stack, 9, 36, false).await {
} else if (9..45).contains(&slot_index) {
if !self
.handle_inventory_move(slot_index, &mut slot_stack)
.await
{
return ItemStack::EMPTY;
}
} else if !self.insert_item(&mut slot_stack, 9, 45, false).await {

View File

@@ -6,6 +6,7 @@ use std::{
};
use async_trait::async_trait;
use pumpkin_data::item::Item;
use pumpkin_world::inventory::Inventory;
use pumpkin_world::item::ItemStack;
use tokio::{sync::Mutex, time::timeout};
@@ -271,11 +272,17 @@ impl Slot for ArmorSlot {
self.set_stack_no_callbacks(stack).await;
}
async fn can_insert(&self, _stack: &ItemStack) -> bool {
// TODO: return this.entity.canEquip(stack, this.equipmentSlot);
true
async fn can_insert(&self, stack: &ItemStack) -> bool {
match self.equipment_slot {
EquipmentSlot::Head(_) => {
stack.is_helmet() || stack.is_skull() || stack.item == &Item::CARVED_PUMPKIN
}
EquipmentSlot::Chest(_) => stack.is_chestplate() || stack.item == &Item::ELYTRA,
EquipmentSlot::Legs(_) => stack.is_leggings(),
EquipmentSlot::Feet(_) => stack.is_boots(),
_ => true,
}
}
async fn can_take_items(&self, _player: &dyn InventoryPlayer) -> bool {
// TODO: Check enchantments
true

View File

@@ -4,6 +4,7 @@ use crate::item::ItemStack;
const SWORDS_TAG: &str = "#minecraft:swords";
const HEAD_ARMOR_TAG: &str = "#minecraft:head_armor";
const SKULL_TAG: &str = "#minecraft:skulls";
const CHEST_ARMOR_TAG: &str = "#minecraft:chest_armor";
const LEG_ARMOR_TAG: &str = "#minecraft:leg_armor";
const FOOT_ARMOR_TAG: &str = "#minecraft:foot_armor";
@@ -23,6 +24,13 @@ impl ItemStack {
)
}
#[inline]
pub fn is_skull(&self) -> bool {
self.item.is_tagged_with(SKULL_TAG).expect(
"This is a default minecraft tag that should have been gotten from the extractor",
)
}
#[inline]
pub fn is_chestplate(&self) -> bool {
self.item.is_tagged_with(CHEST_ARMOR_TAG).expect(