From bbe01377d51feeca0cc8d4fc92ade51be73f2b9c Mon Sep 17 00:00:00 2001 From: Jake Potrebic Date: Thu, 23 May 2024 11:44:07 -0700 Subject: [PATCH] Improve default item attributes API (#10765) --- .../Attributes-API-for-item-defaults.patch | 35 ------- .../Improve-item-default-attribute-API.patch | 99 +++++++++++++++++++ .../Fix-item-default-attributes-API.patch | 47 --------- .../Improve-item-default-attribute-API.patch | 92 +++++++++++++++++ 4 files changed, 191 insertions(+), 82 deletions(-) delete mode 100644 patches/api/Attributes-API-for-item-defaults.patch create mode 100644 patches/api/Improve-item-default-attribute-API.patch delete mode 100644 patches/server/Fix-item-default-attributes-API.patch create mode 100644 patches/server/Improve-item-default-attribute-API.patch diff --git a/patches/api/Attributes-API-for-item-defaults.patch b/patches/api/Attributes-API-for-item-defaults.patch deleted file mode 100644 index af19eb5dcf..0000000000 --- a/patches/api/Attributes-API-for-item-defaults.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sat, 8 May 2021 15:02:00 -0700 -Subject: [PATCH] Attributes API for item defaults - -(Now replaced by upstream's API) - -diff --git a/src/main/java/org/bukkit/Material.java b/src/main/java/org/bukkit/Material.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/Material.java -+++ b/src/main/java/org/bukkit/Material.java -@@ -0,0 +0,0 @@ public enum Material implements Keyed, Translatable, net.kyori.adventure.transla - } - // Paper end - item rarity API - -+ // Paper start - item default attributes API -+ /** -+ * Returns an immutable multimap of attributes for the slot. -+ * {@link #isItem()} must be true for this material. -+ * -+ * @param equipmentSlot the slot to get the attributes for -+ * @throws IllegalArgumentException if {@link #isItem()} is false -+ * @return an immutable multimap of attributes -+ * @deprecated use {@link #getDefaultAttributeModifiers(EquipmentSlot)} -+ */ -+ @NotNull -+ @Deprecated(forRemoval = true, since = "1.20.5") -+ public Multimap getItemAttributes(@NotNull EquipmentSlot equipmentSlot) { -+ return this.getDefaultAttributeModifiers(equipmentSlot); -+ } -+ // Paper end - item default attributes API -+ - /** - * Do not use for any reason. - * diff --git a/patches/api/Improve-item-default-attribute-API.patch b/patches/api/Improve-item-default-attribute-API.patch new file mode 100644 index 0000000000..8a3c5fc9b8 --- /dev/null +++ b/patches/api/Improve-item-default-attribute-API.patch @@ -0,0 +1,99 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sat, 8 May 2021 15:02:00 -0700 +Subject: [PATCH] Improve item default attribute API + + +diff --git a/src/main/java/org/bukkit/Material.java b/src/main/java/org/bukkit/Material.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/Material.java ++++ b/src/main/java/org/bukkit/Material.java +@@ -0,0 +0,0 @@ public enum Material implements Keyed, Translatable, net.kyori.adventure.transla + } + // Paper end - item rarity API + ++ // Paper start - item default attributes API ++ /** ++ * Returns an immutable multimap of attributes for the slot. ++ * {@link #isItem()} must be true for this material. ++ * ++ * @param equipmentSlot the slot to get the attributes for ++ * @throws IllegalArgumentException if {@link #isItem()} is false ++ * @return an immutable multimap of attributes ++ * @deprecated use {@link #getDefaultAttributeModifiers(EquipmentSlot)} ++ */ ++ @NotNull ++ @Deprecated(forRemoval = true, since = "1.20.5") ++ public Multimap getItemAttributes(@NotNull EquipmentSlot equipmentSlot) { ++ return this.getDefaultAttributeModifiers(equipmentSlot); ++ } ++ // Paper end - item default attributes API ++ + /** + * Do not use for any reason. + * +@@ -0,0 +0,0 @@ public enum Material implements Keyed, Translatable, net.kyori.adventure.transla + } + } + ++ // Paper start - improve default item attribute API ++ /** ++ * Return an immutable copy of all default {@link Attribute}s and their {@link AttributeModifier}s. ++ *

++ * Default attributes are those that are always preset on some items, unless ++ * they are specifically overridden on that {@link ItemStack}. Examples include ++ * the attack damage on weapons or the armor value on armor. ++ *

++ * Only available when {@link #isItem()} is true. ++ * ++ * @return the immutable {@link Multimap} with the respective default ++ * Attributes and modifiers, or an empty map if no attributes are set. ++ */ ++ public @NotNull @org.jetbrains.annotations.Unmodifiable Multimap getDefaultAttributeModifiers() { ++ final ItemType type = this.asItemType(); ++ Preconditions.checkArgument(type != null, "The Material is not an item!"); ++ return type.getDefaultAttributeModifiers(); ++ } ++ // Paper end - improve default item attribute API ++ + /** + * Return an immutable copy of all default {@link Attribute}s and their + * {@link AttributeModifier}s for a given {@link EquipmentSlot}. +- * +- * Default attributes are those that are always preset on some items, such +- * as the attack damage on weapons or the armor value on armor. +- * ++ *

++ * Default attributes are those that are always preset on some items, unless ++ * they are specifically overridden on that {@link ItemStack}. Examples include ++ * the attack damage on weapons or the armor value on armor. ++ *

+ * Only available when {@link #isItem()} is true. + * + * @param slot the {@link EquipmentSlot} to check +diff --git a/src/main/java/org/bukkit/inventory/ItemType.java b/src/main/java/org/bukkit/inventory/ItemType.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/inventory/ItemType.java ++++ b/src/main/java/org/bukkit/inventory/ItemType.java +@@ -0,0 +0,0 @@ public interface ItemType extends Keyed, Translatable, net.kyori.adventure.trans + // @NotNull + // EquipmentSlot getEquipmentSlot(); + ++ // Paper start - improve default item attribute API ++ /** ++ * Return an immutable copy of all default {@link Attribute}s and their ++ * {@link AttributeModifier}s. ++ *

++ * Default attributes are those that are always preset on some items, unless ++ * they are specifically overridden on that {@link ItemStack}. Examples include ++ * the attack damage on weapons or the armor value on armor. ++ * ++ * @return the immutable {@link Multimap} with the respective default ++ * Attributes and modifiers, or an empty map if no attributes are set. ++ */ ++ @NotNull @org.jetbrains.annotations.Unmodifiable Multimap getDefaultAttributeModifiers(); ++ // Paper end - improve default item attribute API ++ + /** + * Return an immutable copy of all default {@link Attribute}s and their + * {@link AttributeModifier}s for a given {@link EquipmentSlot}. diff --git a/patches/server/Fix-item-default-attributes-API.patch b/patches/server/Fix-item-default-attributes-API.patch deleted file mode 100644 index 6a2da937f4..0000000000 --- a/patches/server/Fix-item-default-attributes-API.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sat, 8 May 2021 15:01:54 -0700 -Subject: [PATCH] Fix item default attributes API - -(previously added this API but upstream also added it) - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemType.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemType.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemType.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemType.java -@@ -0,0 +0,0 @@ public class CraftItemType implements ItemType.Typed, Han - - @Override - public Multimap getDefaultAttributeModifiers(EquipmentSlot slot) { -- ImmutableMultimap.Builder defaultAttributes = ImmutableMultimap.builder(); -- -- ItemAttributeModifiers nmsDefaultAttributes = this.item.getDefaultAttributeModifiers(); -+ // Paper start - fix item default attribute API -+ final ImmutableMultimap.Builder defaultAttributes = ImmutableMultimap.builder(); -+ ItemAttributeModifiers nmsDefaultAttributes = this.item.components().getOrDefault(DataComponents.ATTRIBUTE_MODIFIERS, ItemAttributeModifiers.EMPTY); -+ // Paper end - fix item default attribute API - nmsDefaultAttributes.forEach(CraftEquipmentSlot.getNMS(slot), (key, value) -> { - Attribute attribute = CraftAttribute.minecraftToBukkit(key.value()); - defaultAttributes.put(attribute, CraftAttributeInstance.convert(value, slot)); -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -0,0 +0,0 @@ public final class CraftMagicNumbers implements UnsafeValues { - - @Override - public Multimap getDefaultAttributeModifiers(Material material, EquipmentSlot slot) { -- ImmutableMultimap.Builder defaultAttributes = ImmutableMultimap.builder(); -- -- ItemAttributeModifiers nmsDefaultAttributes = CraftMagicNumbers.getItem(material).getDefaultAttributeModifiers(); -+ // Paper start - fix item default attribute API -+ final Item item = CraftMagicNumbers.getItem(material); -+ if (item == null) { -+ throw new IllegalArgumentException(material + " is not an item and therefore does not have attributes"); -+ } -+ final ImmutableMultimap.Builder defaultAttributes = ImmutableMultimap.builder(); -+ ItemAttributeModifiers nmsDefaultAttributes = item.components().getOrDefault(net.minecraft.core.component.DataComponents.ATTRIBUTE_MODIFIERS, ItemAttributeModifiers.EMPTY); -+ // Paper end - fix item default attribute API - nmsDefaultAttributes.forEach(CraftEquipmentSlot.getNMS(slot), (key, value) -> { - Attribute attribute = CraftAttribute.minecraftToBukkit(key.value()); - defaultAttributes.put(attribute, CraftAttributeInstance.convert(value, slot)); diff --git a/patches/server/Improve-item-default-attribute-API.patch b/patches/server/Improve-item-default-attribute-API.patch new file mode 100644 index 0000000000..57ab200db8 --- /dev/null +++ b/patches/server/Improve-item-default-attribute-API.patch @@ -0,0 +1,92 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Sat, 8 May 2021 15:01:54 -0700 +Subject: [PATCH] Improve item default attribute API + +Also fixes an issue where upstream isn't +actually getting the correct default attributes + +diff --git a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeInstance.java b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeInstance.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeInstance.java ++++ b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeInstance.java +@@ -0,0 +0,0 @@ public class CraftAttributeInstance implements AttributeInstance { + return new AttributeModifier(nms.id(), nms.name, nms.amount(), AttributeModifier.Operation.values()[nms.operation().ordinal()]); + } + +- public static AttributeModifier convert(net.minecraft.world.entity.ai.attributes.AttributeModifier nms, EquipmentSlot slot) { +- return new AttributeModifier(nms.id(), nms.name, nms.amount(), AttributeModifier.Operation.values()[nms.operation().ordinal()], slot); ++ public static AttributeModifier convert(net.minecraft.world.entity.ai.attributes.AttributeModifier nms, net.minecraft.world.entity.EquipmentSlotGroup slot) { // Paper ++ return new AttributeModifier(nms.id(), nms.name, nms.amount(), AttributeModifier.Operation.values()[nms.operation().ordinal()], org.bukkit.craftbukkit.CraftEquipmentSlot.getSlot(slot)); // Paper + } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemType.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemType.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemType.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemType.java +@@ -0,0 +0,0 @@ public class CraftItemType implements ItemType.Typed, Han + // return CraftEquipmentSlot.getSlot(EntityInsentient.getEquipmentSlotForItem(CraftItemStack.asNMSCopy(ItemStack.of(this)))); + // } + ++ // Paper start - improve default attribute API ++ @Override ++ public @NotNull Multimap getDefaultAttributeModifiers() { ++ return this.getDefaultAttributeModifiers(sg -> true); ++ } ++ // Paper end - improve default attribute API ++ + @Override + public Multimap getDefaultAttributeModifiers(EquipmentSlot slot) { +- ImmutableMultimap.Builder defaultAttributes = ImmutableMultimap.builder(); ++ // Paper start - improve/fix item default attribute API ++ final net.minecraft.world.entity.EquipmentSlot nmsSlot = CraftEquipmentSlot.getNMS(slot); ++ return this.getDefaultAttributeModifiers(sg -> sg.test(nmsSlot)); ++ } + +- ItemAttributeModifiers nmsDefaultAttributes = this.item.getDefaultAttributeModifiers(); +- nmsDefaultAttributes.forEach(CraftEquipmentSlot.getNMS(slot), (key, value) -> { +- Attribute attribute = CraftAttribute.minecraftToBukkit(key.value()); +- defaultAttributes.put(attribute, CraftAttributeInstance.convert(value, slot)); +- }); ++ private Multimap getDefaultAttributeModifiers(final java.util.function.Predicate slotPredicate) { ++ final ImmutableMultimap.Builder defaultAttributes = ImmutableMultimap.builder(); ++ ItemAttributeModifiers nmsDefaultAttributes = this.item.components().getOrDefault(DataComponents.ATTRIBUTE_MODIFIERS, ItemAttributeModifiers.EMPTY); ++ if (nmsDefaultAttributes.modifiers().isEmpty()) { ++ // we have to check both places cause for some reason vanilla puts default modifiers for armor in a different place ++ nmsDefaultAttributes = this.item.getDefaultAttributeModifiers(); ++ } ++ for (final net.minecraft.world.item.component.ItemAttributeModifiers.Entry entry : nmsDefaultAttributes.modifiers()) { ++ if (!slotPredicate.test(entry.slot())) continue; ++ final Attribute attribute = CraftAttribute.minecraftHolderToBukkit(entry.attribute()); ++ final AttributeModifier modifier = CraftAttributeInstance.convert(entry.modifier(), entry.slot()); ++ defaultAttributes.put(attribute, modifier); ++ } ++ // Paper end - improve/fix item default attribute API + + return defaultAttributes.build(); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -0,0 +0,0 @@ public final class CraftMagicNumbers implements UnsafeValues { + + @Override + public Multimap getDefaultAttributeModifiers(Material material, EquipmentSlot slot) { +- ImmutableMultimap.Builder defaultAttributes = ImmutableMultimap.builder(); +- +- ItemAttributeModifiers nmsDefaultAttributes = CraftMagicNumbers.getItem(material).getDefaultAttributeModifiers(); +- nmsDefaultAttributes.forEach(CraftEquipmentSlot.getNMS(slot), (key, value) -> { +- Attribute attribute = CraftAttribute.minecraftToBukkit(key.value()); +- defaultAttributes.put(attribute, CraftAttributeInstance.convert(value, slot)); +- }); +- +- return defaultAttributes.build(); ++ // Paper start - delegate to method on ItemType ++ final org.bukkit.inventory.ItemType item = material.asItemType(); ++ Preconditions.checkArgument(item != null, material + " is not an item and does not have default attributes"); ++ return item.getDefaultAttributeModifiers(slot); ++ // Paper end - delegate to method on ItemType + } + + @Override