From 88a68e0670816527000993014050bb0c620824c7 Mon Sep 17 00:00:00 2001 From: Alex 'mcmonkey' Goodwin Date: Thu, 20 May 2021 13:44:10 -0700 Subject: [PATCH] redesign input for attribute_modifiers --- .../entity/EntityAttributeModifiers.java | 79 +++++++++++++------ .../item/ItemAttributeModifiers.java | 9 +-- .../containers/core/ItemScriptContainer.java | 17 +++- 3 files changed, 69 insertions(+), 36 deletions(-) diff --git a/plugin/src/main/java/com/denizenscript/denizen/objects/properties/entity/EntityAttributeModifiers.java b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/entity/EntityAttributeModifiers.java index f6d597a045..eab196f57e 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/objects/properties/entity/EntityAttributeModifiers.java +++ b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/entity/EntityAttributeModifiers.java @@ -22,6 +22,7 @@ import java.util.List; import java.util.Map; import java.util.UUID; +import java.util.function.Consumer; public class EntityAttributeModifiers implements Property { @@ -194,6 +195,26 @@ public ObjectTag getObjectAttribute(Attribute attribute) { return null; } + public static void addAttributeModifiers(Consumer addModifier, org.bukkit.attribute.Attribute attr, ObjectTag subValue) { + if (subValue instanceof MapTag) { + MapTag attrMap = (MapTag) subValue; + List keys = new ArrayList<>(attrMap.map.keySet()); + keys.sort((k, k2) -> { + int a = Integer.parseInt(k.str); + int b = Integer.parseInt(k2.str); + return Integer.compare(a, b); + }); + for (StringHolder index : keys) { + addModifier.accept(modiferForMap(attr, (MapTag) attrMap.map.get(index))); + } + } + else { + for (ObjectTag listValue : (((ListTag) subValue).objectForms)) { + addModifier.accept(modiferForMap(attr, (MapTag) listValue)); + } + } + } + @Override public void adjust(Mechanism mechanism) { @@ -204,7 +225,7 @@ public void adjust(Mechanism mechanism) { // @description // Sets the attribute modifiers of an entity. // This is a SET operation, meaning pre-existing modifiers are removed. - // Specify a MapTag where the keys are attribute names, and values are a ListTag of modifiers, + // Specify a MapTag where the keys are attribute names, and values are a ListTag of modifiers (or a numbered-index MapTag), // where each modifier is itself a MapTag with required keys 'operation' and 'amount', and optional keys 'name', 'slot', and 'id'. // Valid operations: ADD_NUMBER, ADD_SCALAR, and MULTIPLY_SCALAR_1 // Valid slots: HAND, OFF_HAND, FEET, LEGS, CHEST, HEAD, ANY @@ -218,22 +239,25 @@ public void adjust(Mechanism mechanism) { // // --> if (mechanism.matches("attribute_modifiers") && mechanism.requireObject(MapTag.class)) { - MapTag input = mechanism.valueAsType(MapTag.class); - Attributable ent = (Attributable) entity.getBukkitEntity(); - for (Map.Entry subValue : input.map.entrySet()) { - org.bukkit.attribute.Attribute attr = org.bukkit.attribute.Attribute.valueOf(subValue.getKey().str.toUpperCase()); - AttributeInstance instance = ent.getAttribute(attr); - if (instance == null) { - mechanism.echoError("Attribute " + attr.name() + " is not applicable to entity of type " + entity.getBukkitEntity().getType().name()); - continue; - } - for (AttributeModifier modifier : instance.getModifiers()) { - instance.removeModifier(modifier); - } - for (ObjectTag listValue : (((ListTag) subValue.getValue()).objectForms)) { - instance.addModifier(modiferForMap(attr, (MapTag) listValue)); + try { + MapTag input = mechanism.valueAsType(MapTag.class); + Attributable ent = (Attributable) entity.getBukkitEntity(); + for (Map.Entry subValue : input.map.entrySet()) { + org.bukkit.attribute.Attribute attr = org.bukkit.attribute.Attribute.valueOf(subValue.getKey().str.toUpperCase()); + AttributeInstance instance = ent.getAttribute(attr); + if (instance == null) { + mechanism.echoError("Attribute " + attr.name() + " is not applicable to entity of type " + entity.getBukkitEntity().getType().name()); + continue; + } + for (AttributeModifier modifier : instance.getModifiers()) { + instance.removeModifier(modifier); + } + addAttributeModifiers(instance::addModifier, attr, subValue.getValue()); } } + catch (Throwable ex) { + Debug.echoError(ex); + } } // <--[mechanism] @@ -251,19 +275,22 @@ public void adjust(Mechanism mechanism) { // // --> if (mechanism.matches("add_attribute_modifiers") && mechanism.requireObject(MapTag.class)) { - MapTag input = mechanism.valueAsType(MapTag.class); - Attributable ent = (Attributable) entity.getBukkitEntity(); - for (Map.Entry subValue : input.map.entrySet()) { - org.bukkit.attribute.Attribute attr = org.bukkit.attribute.Attribute.valueOf(subValue.getKey().str.toUpperCase()); - AttributeInstance instance = ent.getAttribute(attr); - if (instance == null) { - mechanism.echoError("Attribute " + attr.name() + " is not applicable to entity of type " + entity.getBukkitEntity().getType().name()); - continue; - } - for (ObjectTag listValue : (((ListTag) subValue.getValue()).objectForms)) { - instance.addModifier(modiferForMap(attr, (MapTag) listValue)); + try { + MapTag input = mechanism.valueAsType(MapTag.class); + Attributable ent = (Attributable) entity.getBukkitEntity(); + for (Map.Entry subValue : input.map.entrySet()) { + org.bukkit.attribute.Attribute attr = org.bukkit.attribute.Attribute.valueOf(subValue.getKey().str.toUpperCase()); + AttributeInstance instance = ent.getAttribute(attr); + if (instance == null) { + mechanism.echoError("Attribute " + attr.name() + " is not applicable to entity of type " + entity.getBukkitEntity().getType().name()); + continue; + } + addAttributeModifiers(instance::addModifier, attr, subValue.getValue()); } } + catch (Throwable ex) { + Debug.echoError(ex); + } } // <--[mechanism] diff --git a/plugin/src/main/java/com/denizenscript/denizen/objects/properties/item/ItemAttributeModifiers.java b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/item/ItemAttributeModifiers.java index 889523115e..def4a384d5 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/objects/properties/item/ItemAttributeModifiers.java +++ b/plugin/src/main/java/com/denizenscript/denizen/objects/properties/item/ItemAttributeModifiers.java @@ -135,10 +135,7 @@ public void adjust(Mechanism mechanism) { MapTag map = mechanism.valueAsType(MapTag.class); for (Map.Entry mapEntry : map.map.entrySet()) { org.bukkit.attribute.Attribute attr = org.bukkit.attribute.Attribute.valueOf(mapEntry.getKey().str.toUpperCase()); - for (ObjectTag modifier : ((ListTag) mapEntry.getValue()).objectForms) { - AttributeModifier attrMod = EntityAttributeModifiers.modiferForMap(attr, (MapTag) modifier); - metaMap.put(attr, attrMod); - } + EntityAttributeModifiers.addAttributeModifiers((mod) -> metaMap.put(attr, mod), attr, mapEntry.getValue()); } ItemMeta meta = item.getItemMeta(); meta.setAttributeModifiers(metaMap); @@ -160,9 +157,7 @@ public void adjust(Mechanism mechanism) { MapTag input = mechanism.valueAsType(MapTag.class); for (Map.Entry subValue : input.map.entrySet()) { org.bukkit.attribute.Attribute attr = org.bukkit.attribute.Attribute.valueOf(subValue.getKey().str.toUpperCase()); - for (ObjectTag listValue : (((ListTag) subValue.getValue()).objectForms)) { - meta.addAttributeModifier(attr, EntityAttributeModifiers.modiferForMap(attr, (MapTag) listValue)); - } + EntityAttributeModifiers.addAttributeModifiers((mod) -> meta.addAttributeModifier(attr, mod), attr, subValue.getValue()); } item.setItemMeta(meta); } diff --git a/plugin/src/main/java/com/denizenscript/denizen/scripts/containers/core/ItemScriptContainer.java b/plugin/src/main/java/com/denizenscript/denizen/scripts/containers/core/ItemScriptContainer.java index 48d62dbf01..7257c967be 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/scripts/containers/core/ItemScriptContainer.java +++ b/plugin/src/main/java/com/denizenscript/denizen/scripts/containers/core/ItemScriptContainer.java @@ -58,10 +58,21 @@ public class ItemScriptContainer extends ScriptContainer { // unbreakable: true // # Other common example // custom_model_data: 5 - // # This mess demonstrates how to add a custom attribute modifier. + // # This demonstrates how to add a custom attribute modifier. // attribute_modifiers: + // # One subkey for each attribute you want to modify. // generic_armor: - // - + // # Each attribute can have a list of modifiers, using numbered keys. They will be applied in numeric order, low to high. + // 1: + // # Each modifier requires keys 'operation' and 'amount', and can optionally have keys 'name', 'slot', and 'id'. + // # Operations can be: ADD_NUMBER, ADD_SCALAR, and MULTIPLY_SCALAR_1 + // operation: add_number + // amount: 5 + // # Slots can be: HAND, OFF_HAND, FEET, LEGS, CHEST, HEAD, ANY + // slot: head + // # ID is a UUID used to uniquely identify modifiers. If unspecified the ID will be randomly generated. + // # Items with modifiers that lack IDs cannot be stacked due to the random generation. + // id: 10000000-1000-1000-1000-100000000000 // // # The 'custom name' can be anything you wish. Use color tags to make colored custom names. // # | Some item scripts should have this key! @@ -78,7 +89,7 @@ public class ItemScriptContainer extends ScriptContainer { // # | Most item scripts should exclude this key! // durability: 12 // - // # Each line must specify a valid Minecranft enchantment name. + // # Each line must specify a valid Minecraft enchantment name. // # | Some item scripts should have this key! // enchantments: // - enchantment_name:level