<commit_before>package com.elmakers.mine.bukkit.magic;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.ListIterator;
import java.util.Set;
import java.util.logging.Level;
import javax.annotation.Nullable;

import org.bukkit.attribute.Attribute;
import org.bukkit.attribute.AttributeInstance;
import org.bukkit.attribute.AttributeModifier;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;

import com.elmakers.mine.bukkit.api.magic.MagicPropertyType;
import com.elmakers.mine.bukkit.api.magic.Trigger;
import com.elmakers.mine.bukkit.api.spell.CooldownReducer;
import com.elmakers.mine.bukkit.api.spell.CostReducer;
import com.elmakers.mine.bukkit.api.spell.Spell;
import com.elmakers.mine.bukkit.spell.TriggeredSpell;
import com.elmakers.mine.bukkit.wand.Wand;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap;

public class BaseMageModifier extends ParentedProperties implements CostReducer, CooldownReducer {
    public static final ImmutableSet<String> PROPERTY_KEYS = new ImmutableSet.Builder<String>()
        .addAll(BaseMagicProperties.PROPERTY_KEYS)
        .add("craftable", "useable", "health_scale", "entity_attributes", "triggers").build();

    private List<EntityAttributeModifier> attributeModifiers;
    private boolean checkedAttributes = false;
    protected @Nullable
    Multimap<String, CustomTrigger> triggers;
    protected final Multimap<String, TriggeredSpell> spellTriggers = ArrayListMultimap.create();

    protected final Mage mage;

    public BaseMageModifier(Mage mage, MagicPropertyType type, @Nullable TemplateProperties template) {
        super(type, mage.getController(), template);
        this.mage = mage;
    }

    @Override
    public Mage getMage() {
        return mage;
    }

    @Override
    public boolean isPlayer() {
        return mage.isPlayer();
    }

    @Nullable
    @Override
    public Player getPlayer() {
        return mage.getPlayer();
    }

    @Override
    public void updated() {
        super.updated();
        Mage mage = getMage();
        if (mage == null) return;
        updateMaxMana(mage);
        Wand activeWand = mage.getActiveWand();
        if (activeWand != null) {
            activeWand.updated();
        }
        if (!isLocked()) {
            deactivate();
            activate();
        }
        mage.updatePassiveEffects();
    }

    public void activate() {
        activateAttributes();
        trigger("join");
    }

    protected void activateAttributes() {
        double healthScale = getDouble("health_scale");
        if (healthScale > 0) {
            Player player = mage.getPlayer();
            if (player != null) {
                player.setHealthScale(healthScale);
            }
        }

        Collection<EntityAttributeModifier> modifiers = getAttributeModifiers();
        if (modifiers == null) return;
        LivingEntity entity = mage.getLivingEntity();
        if (entity == null) return;

        for (EntityAttributeModifier modifier : modifiers) {
            AttributeInstance attribute = entity.getAttribute(modifier.attribute);
            if (attribute == null) continue;

            if (modifier.modifier != null) {
                if (!checkedAttributes) {
                    // Only do this once, it's really here to clean up attributes that may have gotten stuck on server crash
                    Collection<AttributeModifier> existingModifiers = attribute.getModifiers();
                    for (AttributeModifier existing : existingModifiers) {
                        if (existing.getName().equalsIgnoreCase(modifier.modifier.getName())) {
                            mage.getController().getLogger().warning("Removed duplicate attribute modifier " + modifier.modifier.getName() + ", was this leftover from a server crash?");
                            attribute.removeModifier(existing);
                            break;
                        }
                    }
                }
                try {
                    attribute.addModifier(modifier.modifier);
                } catch (Exception ex) {
                    controller.getLogger().log(Level.WARNING, "Error adding vanilla attribute modifier: " + modifier.modifier.getName() + " from class/modifier " + getKey(), ex);
                }
            }

            if (modifier.base != null) {
                modifier.previous = attribute.getBaseValue();
                attribute.setBaseValue(modifier.base);
            }
        }

        checkedAttributes = true;
    }

    public void deactivate() {
        deactivateAttributes();
        cancelTrigger("join");
    }

    protected void deactivateAttributes() {
        double healthScale = getDouble("health_scale");
        if (healthScale > 0) {
            Player player = mage.getPlayer();
            if (player != null) {
                player.setHealthScaled(false);
            }
        }

        if (attributeModifiers == null) return;
        LivingEntity entity = mage.getLivingEntity();
        if (entity == null) return;

        // Remove in reverse-order in case a base attribute was changed twice
        ListIterator<EntityAttributeModifier> it = attributeModifiers.listIterator(attributeModifiers.size());
        while (it.hasPrevious()) {
            EntityAttributeModifier modifier = it.previous();
            AttributeInstance attribute = entity.getAttribute(modifier.attribute);
            if (modifier.modifier != null) {
                attribute.removeModifier(modifier.modifier);
            }
            if (modifier.previous != null) {
                attribute.setBaseValue(modifier.previous);
            }
        }
        attributeModifiers = null;
    }

    @Nullable
    public Collection<EntityAttributeModifier> getAttributeModifiers() {
        if (attributeModifiers != null) {
            return attributeModifiers;
        }

        ConfigurationSection config = getConfigurationSection("entity_attributes");
        if (config == null) return null;<commit_msg>Fix another error trying to apply attribute modifiers to an entity that does not have the specified attribute<commit_after>package com.elmakers.mine.bukkit.magic;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.ListIterator;
import java.util.Set;
import java.util.logging.Level;
import javax.annotation.Nullable;

import org.bukkit.attribute.Attribute;
import org.bukkit.attribute.AttributeInstance;
import org.bukkit.attribute.AttributeModifier;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;

import com.elmakers.mine.bukkit.api.magic.MagicPropertyType;
import com.elmakers.mine.bukkit.api.magic.Trigger;
import com.elmakers.mine.bukkit.api.spell.CooldownReducer;
import com.elmakers.mine.bukkit.api.spell.CostReducer;
import com.elmakers.mine.bukkit.api.spell.Spell;
import com.elmakers.mine.bukkit.spell.TriggeredSpell;
import com.elmakers.mine.bukkit.wand.Wand;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap;

public class BaseMageModifier extends ParentedProperties implements CostReducer, CooldownReducer {
    public static final ImmutableSet<String> PROPERTY_KEYS = new ImmutableSet.Builder<String>()
        .addAll(BaseMagicProperties.PROPERTY_KEYS)
        .add("craftable", "useable", "health_scale", "entity_attributes", "triggers").build();

    private List<EntityAttributeModifier> attributeModifiers;
    private boolean checkedAttributes = false;
    protected @Nullable
    Multimap<String, CustomTrigger> triggers;
    protected final Multimap<String, TriggeredSpell> spellTriggers = ArrayListMultimap.create();

    protected final Mage mage;

    public BaseMageModifier(Mage mage, MagicPropertyType type, @Nullable TemplateProperties template) {
        super(type, mage.getController(), template);
        this.mage = mage;
    }

    @Override
    public Mage getMage() {
        return mage;
    }

    @Override
    public boolean isPlayer() {
        return mage.isPlayer();
    }

    @Nullable
    @Override
    public Player getPlayer() {
        return mage.getPlayer();
    }

    @Override
    public void updated() {
        super.updated();
        Mage mage = getMage();
        if (mage == null) return;
        updateMaxMana(mage);
        Wand activeWand = mage.getActiveWand();
        if (activeWand != null) {
            activeWand.updated();
        }
        if (!isLocked()) {
            deactivate();
            activate();
        }
        mage.updatePassiveEffects();
    }

    public void activate() {
        activateAttributes();
        trigger("join");
    }

    protected void activateAttributes() {
        double healthScale = getDouble("health_scale");
        if (healthScale > 0) {
            Player player = mage.getPlayer();
            if (player != null) {
                player.setHealthScale(healthScale);
            }
        }

        Collection<EntityAttributeModifier> modifiers = getAttributeModifiers();
        if (modifiers == null) return;
        LivingEntity entity = mage.getLivingEntity();
        if (entity == null) return;

        for (EntityAttributeModifier modifier : modifiers) {
            AttributeInstance attribute = entity.getAttribute(modifier.attribute);
            if (attribute == null) continue;

            if (modifier.modifier != null) {
                if (!checkedAttributes) {
                    // Only do this once, it's really here to clean up attributes that may have gotten stuck on server crash
                    Collection<AttributeModifier> existingModifiers = attribute.getModifiers();
                    for (AttributeModifier existing : existingModifiers) {
                        if (existing.getName().equalsIgnoreCase(modifier.modifier.getName())) {
                            mage.getController().getLogger().warning("Removed duplicate attribute modifier " + modifier.modifier.getName() + ", was this leftover from a server crash?");
                            attribute.removeModifier(existing);
                            break;
                        }
                    }
                }
                try {
                    attribute.addModifier(modifier.modifier);
                } catch (Exception ex) {
                    controller.getLogger().log(Level.WARNING, "Error adding vanilla attribute modifier: " + modifier.modifier.getName() + " from class/modifier " + getKey(), ex);
                }
            }

            if (modifier.base != null) {
                modifier.previous = attribute.getBaseValue();
                attribute.setBaseValue(modifier.base);
            }
        }

        checkedAttributes = true;
    }

    public void deactivate() {
        deactivateAttributes();
        cancelTrigger("join");
    }

    protected void deactivateAttributes() {
        double healthScale = getDouble("health_scale");
        if (healthScale > 0) {
            Player player = mage.getPlayer();
            if (player != null) {
                player.setHealthScaled(false);
            }
        }

        if (attributeModifiers == null) return;
        LivingEntity entity = mage.getLivingEntity();
        if (entity == null) return;

        // Remove in reverse-order in case a base attribute was changed twice
        ListIterator<EntityAttributeModifier> it = attributeModifiers.listIterator(attributeModifiers.size());
        while (it.hasPrevious()) {
            EntityAttributeModifier modifier = it.previous();
            AttributeInstance attribute = entity.getAttribute(modifier.attribute);
            if (attribute == null) continue;
            if (modifier.modifier != null) {
                attribute.removeModifier(modifier.modifier);
            }
            if (modifier.previous != null) {
                attribute.setBaseValue(modifier.previous);
            }
        }
        attributeModifiers = null;
    }

    @Nullable
    public Collection<EntityAttributeModifier> getAttributeModifiers() {
        if (attributeModifiers != null) {
            return attributeModifiers;
        }

        ConfigurationSection config = getConfigurationSection("entity_attributes");
        if (config == null) return null;
{'fraction_non_alphanumeric': 0.09722332093979906, 'fraction_numerical': 0.00031643066213116053, 'mean_word_length': 2.4325278305729023, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2498714', 'n_tokens_mistral': 3311, 'n_tokens_neox': 3193, 'n_words': 716}