diff --git a/src/main/java/net/minestom/server/entity/EquipmentSlot.java b/src/main/java/net/minestom/server/entity/EquipmentSlot.java index f72266a9c..39a5afa76 100644 --- a/src/main/java/net/minestom/server/entity/EquipmentSlot.java +++ b/src/main/java/net/minestom/server/entity/EquipmentSlot.java @@ -3,20 +3,34 @@ package net.minestom.server.entity; import net.minestom.server.item.attribute.AttributeSlot; import org.jetbrains.annotations.NotNull; +import static net.minestom.server.utils.inventory.PlayerInventoryUtils.*; + public enum EquipmentSlot { - MAIN_HAND, - OFF_HAND, - BOOTS, - LEGGINGS, - CHESTPLATE, - HELMET; + MAIN_HAND(false, -1), + OFF_HAND(false, -1), + BOOTS(true, BOOTS_SLOT), + LEGGINGS(true, LEGGINGS_SLOT), + CHESTPLATE(true, CHESTPLATE_SLOT), + HELMET(true, HELMET_SLOT); + + private final boolean armor; + private final int armorSlot; + + EquipmentSlot(boolean armor, int armorSlot) { + this.armor = armor; + this.armorSlot = armorSlot; + } public boolean isHand() { - return this == MAIN_HAND || this == OFF_HAND; + return !armor; } public boolean isArmor() { - return !isHand(); + return armor; + } + + public int armorSlot() { + return armorSlot; } public static EquipmentSlot fromAttributeSlot(@NotNull AttributeSlot attributeSlot) { diff --git a/src/main/java/net/minestom/server/inventory/click/InventoryClickProcessor.java b/src/main/java/net/minestom/server/inventory/click/InventoryClickProcessor.java index f0ece80b6..acc8ffa10 100644 --- a/src/main/java/net/minestom/server/inventory/click/InventoryClickProcessor.java +++ b/src/main/java/net/minestom/server/inventory/click/InventoryClickProcessor.java @@ -3,17 +3,16 @@ package net.minestom.server.inventory.click; import it.unimi.dsi.fastutil.ints.Int2ObjectFunction; import it.unimi.dsi.fastutil.ints.IntOpenHashSet; import it.unimi.dsi.fastutil.ints.IntSet; +import net.minestom.server.entity.EquipmentSlot; import net.minestom.server.entity.Player; import net.minestom.server.event.EventDispatcher; import net.minestom.server.event.inventory.InventoryClickEvent; import net.minestom.server.event.inventory.InventoryPreClickEvent; -import net.minestom.server.inventory.AbstractInventory; -import net.minestom.server.inventory.Inventory; -import net.minestom.server.inventory.TransactionOption; -import net.minestom.server.inventory.TransactionType; +import net.minestom.server.inventory.*; import net.minestom.server.inventory.condition.InventoryCondition; import net.minestom.server.inventory.condition.InventoryConditionResult; import net.minestom.server.item.ItemStack; +import net.minestom.server.item.Material; import net.minestom.server.item.StackingRule; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; @@ -126,6 +125,26 @@ public final class InventoryClickProcessor { InventoryClickResult clickResult = startCondition(player, inventory, slot, ClickType.START_SHIFT_CLICK, clicked, cursor); if (clickResult.isCancel()) return clickResult; if (clicked.isAir()) return clickResult.cancelled(); + + // Handle armor equip + if (inventory instanceof PlayerInventory && targetInventory instanceof PlayerInventory) { + final Material material = clicked.getMaterial(); + final EquipmentSlot equipmentSlot = material.registry().equipmentSlot(); + if (equipmentSlot != null) { + // Shift-click equip + final ItemStack currentArmor = player.getEquipment(equipmentSlot); + if (currentArmor.isAir()) { + final int armorSlot = equipmentSlot.armorSlot(); + InventoryClickResult result = startCondition(player, targetInventory, armorSlot, ClickType.SHIFT_CLICK, clicked, cursor); + if (result.isCancel()) return clickResult; + result.setClicked(ItemStack.AIR); + result.setCursor(cursor); + player.setEquipment(equipmentSlot, clicked); + return result; + } + } + } + final var pair = TransactionType.ADD.process(targetInventory, clicked, (index, itemStack) -> { if (inventory == targetInventory && index == slot) return false; // Prevent item lose/duplication