From 962554a0decbce39126c77e661834dddc74a6f1e Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Wed, 22 May 2024 10:00:19 -0700
Subject: [PATCH] Fix equipment slot and group API

Adds the following:
- Add missing 'body' slot group
- Expose LivingEntity#canUseSlot

Co-authored-by: SoSeDiK <mrsosedik@gmail.com>
---
 .../java/org/bukkit/attribute/AttributeModifier.java  |  1 +
 .../src/main/java/org/bukkit/entity/LivingEntity.java | 11 +++++++++++
 .../java/org/bukkit/inventory/EntityEquipment.java    |  8 +++++++-
 .../main/java/org/bukkit/inventory/EquipmentSlot.java |  2 +-
 .../java/org/bukkit/inventory/EquipmentSlotGroup.java |  3 ++-
 .../java/org/bukkit/inventory/PlayerInventory.java    |  4 ++++
 6 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/paper-api/src/main/java/org/bukkit/attribute/AttributeModifier.java b/paper-api/src/main/java/org/bukkit/attribute/AttributeModifier.java
index 4ad09a2673..c60f2170fb 100644
--- a/paper-api/src/main/java/org/bukkit/attribute/AttributeModifier.java
+++ b/paper-api/src/main/java/org/bukkit/attribute/AttributeModifier.java
@@ -130,6 +130,7 @@ public class AttributeModifier implements ConfigurationSerializable, Keyed {
      */
     @Nullable
     @Deprecated(since = "1.20.5")
+    @io.papermc.paper.annotation.DoNotUse // Paper
     public EquipmentSlot getSlot() {
         return slot == EquipmentSlotGroup.ANY ? null : slot.getExample();
     }
diff --git a/paper-api/src/main/java/org/bukkit/entity/LivingEntity.java b/paper-api/src/main/java/org/bukkit/entity/LivingEntity.java
index ac86962fa3..d21a228bbe 100644
--- a/paper-api/src/main/java/org/bukkit/entity/LivingEntity.java
+++ b/paper-api/src/main/java/org/bukkit/entity/LivingEntity.java
@@ -1457,4 +1457,15 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource
      */
     void setBodyYaw(float bodyYaw);
     // Paper end - body yaw API
+
+    // Paper start - Expose canUseSlot
+    /**
+     * Checks whether this entity can use the equipment slot.
+     * <br>For example, not all entities may have {@link org.bukkit.inventory.EquipmentSlot#BODY}.
+     *
+     * @param slot equipment slot
+     * @return whether this entity can use the equipment slot
+     */
+    boolean canUseEquipmentSlot(org.bukkit.inventory.@NotNull EquipmentSlot slot);
+    // Paper end - Expose canUseSlot
 }
diff --git a/paper-api/src/main/java/org/bukkit/inventory/EntityEquipment.java b/paper-api/src/main/java/org/bukkit/inventory/EntityEquipment.java
index 6a94bdba82..4264cf878c 100644
--- a/paper-api/src/main/java/org/bukkit/inventory/EntityEquipment.java
+++ b/paper-api/src/main/java/org/bukkit/inventory/EntityEquipment.java
@@ -15,6 +15,8 @@ public interface EntityEquipment {
      *
      * @param slot the slot to put the ItemStack
      * @param item the ItemStack to set
+     * @throws IllegalArgumentException if the slot is invalid for the entity
+     * @see org.bukkit.entity.LivingEntity#canUseEquipmentSlot(EquipmentSlot)
      */
     public void setItem(@NotNull EquipmentSlot slot, @Nullable ItemStack item);
 
@@ -23,7 +25,9 @@ public interface EntityEquipment {
      *
      * @param slot the slot to put the ItemStack
      * @param item the ItemStack to set
-     * @param silent whether or not the equip sound should be silenced
+     * @param silent whether the equip sound should be silenced
+     * @throws IllegalArgumentException if the slot is invalid for the entity
+     * @see org.bukkit.entity.LivingEntity#canUseEquipmentSlot(EquipmentSlot)
      */
     public void setItem(@NotNull EquipmentSlot slot, @Nullable ItemStack item, boolean silent);
 
@@ -32,6 +36,8 @@ public interface EntityEquipment {
      *
      * @param slot the slot to get the ItemStack
      * @return the ItemStack in the given slot
+     * @throws IllegalArgumentException if the slot is invalid for the entity
+     * @see org.bukkit.entity.LivingEntity#canUseEquipmentSlot(EquipmentSlot)
      */
     @NotNull
     public ItemStack getItem(@NotNull EquipmentSlot slot);
diff --git a/paper-api/src/main/java/org/bukkit/inventory/EquipmentSlot.java b/paper-api/src/main/java/org/bukkit/inventory/EquipmentSlot.java
index c1c69ba4c3..1bedf9b7ee 100644
--- a/paper-api/src/main/java/org/bukkit/inventory/EquipmentSlot.java
+++ b/paper-api/src/main/java/org/bukkit/inventory/EquipmentSlot.java
@@ -15,7 +15,7 @@ public enum EquipmentSlot {
     /**
      * Only for certain entities such as horses and wolves.
      */
-    BODY(() -> EquipmentSlotGroup.ARMOR);
+    BODY(() -> EquipmentSlotGroup.BODY); // Paper - add missing slot type
 
     private final Supplier<EquipmentSlotGroup> group; // Supplier because of class loading order, since EquipmentSlot and EquipmentSlotGroup reference each other on class init
 
diff --git a/paper-api/src/main/java/org/bukkit/inventory/EquipmentSlotGroup.java b/paper-api/src/main/java/org/bukkit/inventory/EquipmentSlotGroup.java
index 1a272fec57..2c4353e8fa 100644
--- a/paper-api/src/main/java/org/bukkit/inventory/EquipmentSlotGroup.java
+++ b/paper-api/src/main/java/org/bukkit/inventory/EquipmentSlotGroup.java
@@ -25,7 +25,8 @@ public final class EquipmentSlotGroup implements Predicate<EquipmentSlot> {
     public static final EquipmentSlotGroup LEGS = get("legs", EquipmentSlot.LEGS);
     public static final EquipmentSlotGroup CHEST = get("chest", EquipmentSlot.CHEST);
     public static final EquipmentSlotGroup HEAD = get("head", EquipmentSlot.HEAD);
-    public static final EquipmentSlotGroup ARMOR = get("armor", (test) -> test == EquipmentSlot.FEET || test == EquipmentSlot.LEGS || test == EquipmentSlot.CHEST || test == EquipmentSlot.HEAD, EquipmentSlot.CHEST);
+    public static final EquipmentSlotGroup ARMOR = get("armor", (test) -> test == EquipmentSlot.FEET || test == EquipmentSlot.LEGS || test == EquipmentSlot.CHEST || test == EquipmentSlot.HEAD || test == EquipmentSlot.BODY, EquipmentSlot.CHEST);  // Paper - add missing slot type
+    public static final EquipmentSlotGroup BODY = get("body", EquipmentSlot.BODY); // Paper - add missing slot group
     //
     private final String key;
     private final Predicate<EquipmentSlot> predicate;
diff --git a/paper-api/src/main/java/org/bukkit/inventory/PlayerInventory.java b/paper-api/src/main/java/org/bukkit/inventory/PlayerInventory.java
index 4294e9296f..58fcfaf2e3 100644
--- a/paper-api/src/main/java/org/bukkit/inventory/PlayerInventory.java
+++ b/paper-api/src/main/java/org/bukkit/inventory/PlayerInventory.java
@@ -95,6 +95,8 @@ public interface PlayerInventory extends Inventory {
      * @param slot the slot to put the ItemStack
      * @param item the ItemStack to set
      *
+     * @throws IllegalArgumentException if the slot is invalid for the player
+     * @see org.bukkit.entity.LivingEntity#canUseEquipmentSlot(EquipmentSlot)
      * @see #setItem(int, ItemStack)
      */
     public void setItem(@NotNull EquipmentSlot slot, @Nullable ItemStack item);
@@ -105,6 +107,8 @@ public interface PlayerInventory extends Inventory {
      * @param slot the slot to get the ItemStack
      *
      * @return the ItemStack in the given slot
+     * @throws IllegalArgumentException if the slot is invalid for the player
+     * @see org.bukkit.entity.LivingEntity#canUseEquipmentSlot(EquipmentSlot)
      */
     @NotNull // Paper
     public ItemStack getItem(@NotNull EquipmentSlot slot);