Add ItemAttributeModifierEvent (#7484)

This commit is contained in:
KnightMiner 2020-12-28 14:59:09 -05:00 committed by GitHub
parent 33880331d2
commit 1c98b29087
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 222 additions and 4 deletions

View file

@ -214,7 +214,7 @@
return list;
}
@@ -817,7 +841,7 @@
@@ -817,9 +841,10 @@
}
}
} else {
@ -222,8 +222,11 @@
+ multimap = this.func_77973_b().getAttributeModifiers(p_111283_1_, this);
}
+ multimap = net.minecraftforge.common.ForgeHooks.getAttributeModifiers(this, p_111283_1_, multimap);
return multimap;
@@ -954,6 +978,35 @@
}
@@ -954,6 +979,35 @@
return this.func_77973_b().func_219971_r();
}

View file

@ -33,6 +33,7 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.google.common.base.Throwables;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.google.common.collect.Queues;
import com.google.common.collect.Sets;
import com.google.gson.Gson;
@ -48,7 +49,10 @@ import it.unimi.dsi.fastutil.longs.LongSet;
import net.minecraft.advancements.Advancement;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.entity.ai.attributes.Attribute;
import net.minecraft.entity.ai.attributes.AttributeModifier;
import net.minecraft.fluid.*;
import net.minecraft.inventory.EquipmentSlotType;
import net.minecraft.loot.LootContext;
import net.minecraft.loot.LootTable;
import net.minecraft.loot.LootTableManager;
@ -125,6 +129,7 @@ import net.minecraftforge.common.world.MobSpawnInfoBuilder;
import net.minecraftforge.event.AnvilUpdateEvent;
import net.minecraftforge.event.DifficultyChangeEvent;
import net.minecraftforge.event.ForgeEventFactory;
import net.minecraftforge.event.ItemAttributeModifierEvent;
import net.minecraftforge.event.ServerChatEvent;
import net.minecraftforge.event.entity.EntityTravelToDimensionEvent;
import net.minecraftforge.event.entity.item.ItemTossEvent;
@ -1025,6 +1030,16 @@ public class ForgeHooks
MinecraftForge.EVENT_BUS.post(new AdvancementEvent(player, advancement));
}
/**
* Hook to fire {@link ItemAttributeModifierEvent}. Modders should use {@link ItemStack#getAttributeModifiers(EquipmentSlotType)} instead.
*/
public static Multimap<Attribute,AttributeModifier> getAttributeModifiers(ItemStack stack, EquipmentSlotType equipmentSlot, Multimap<Attribute,AttributeModifier> attributes)
{
ItemAttributeModifierEvent event = new ItemAttributeModifierEvent(stack, equipmentSlot, attributes);
MinecraftForge.EVENT_BUS.post(event);
return event.getModifiers();
}
/**
* Used as the default implementation of {@link Item#getCreatorModId}. Call that method instead.
*/

View file

@ -0,0 +1,143 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2020.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.event;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimaps;
import net.minecraftforge.eventbus.api.Event;
import net.minecraft.entity.ai.attributes.Attribute;
import net.minecraft.entity.ai.attributes.AttributeModifier;
import net.minecraft.inventory.EquipmentSlotType;
import net.minecraft.item.ItemStack;
import com.google.common.collect.Multimap;
import javax.annotation.Nullable;
import java.util.Collection;
/**
* This event is fired when the attributes for an ItemStack are being calculated.
* Attributes are calculated on the server when equipping and unequipping an item to add and remove attributes respectively, both must be consistent.
* Attributes are calculated on the client when rendering an item's tooltip to show relevant attributes.
* <br>
* Note that this event is fired regardless of if the stack has NBT overriding attributes or not. If your attribute should be
* ignored when attributes are overridden, you can check for the presence of the {@code AttributeModifiers} tag.
* <br>
* This event is fired on the {@link net.minecraftforge.common.MinecraftForge#EVENT_BUS}.
*/
public class ItemAttributeModifierEvent extends Event
{
private final ItemStack stack;
private final EquipmentSlotType slotType;
private final Multimap<Attribute, AttributeModifier> originalModifiers;
private Multimap<Attribute, AttributeModifier> unmodifiableModifiers;
@Nullable
private Multimap<Attribute, AttributeModifier> modifiableModifiers;
public ItemAttributeModifierEvent(ItemStack stack, EquipmentSlotType slotType, Multimap<Attribute, AttributeModifier> modifiers)
{
this.stack = stack;
this.slotType = slotType;
this.unmodifiableModifiers = this.originalModifiers = modifiers;
}
/**
* Returns an unmodifiable view of the attribute multimap. Use other methods from this event to modify the attributes map.
* Note that adding attributes based on existing attributes may lead to inconsistent results between the tooltip (client)
* and the actual attributes (server) if the listener order is different. Using {@link #getOriginalModifiers()} instead will give more consistent results.
*/
public Multimap<Attribute, AttributeModifier> getModifiers()
{
return this.unmodifiableModifiers;
}
/**
* Returns the attribute map before any changes from other event listeners was made.
*/
public Multimap<Attribute, AttributeModifier> getOriginalModifiers()
{
return this.originalModifiers;
}
/**
* Gets a modifiable map instance, creating it if the current map is currently unmodifiable
*/
private Multimap<Attribute, AttributeModifier> getModifiableMap()
{
if (this.modifiableModifiers == null)
{
this.modifiableModifiers = HashMultimap.create(this.originalModifiers);
this.unmodifiableModifiers = Multimaps.unmodifiableMultimap(this.modifiableModifiers);
}
return this.modifiableModifiers;
}
/**
* Adds a new attribute modifier to the given stack.
* Modifier must have a consistent UUID for consistency between equipping and unequipping items.
* Modifier name should clearly identify the mod that added the modifier.
* @param attribute Attribute
* @param modifier Modifier instance.
* @return True if the attribute was added, false if it was already present
*/
public boolean addModifier(Attribute attribute, AttributeModifier modifier)
{
return getModifiableMap().put(attribute, modifier);
}
/**
* Removes a single modifier for the given attribute
* @param attribute Attribute
* @param modifier Modifier instance
* @return True if an attribute was removed, false if no change
*/
public boolean removeModifier(Attribute attribute, AttributeModifier modifier)
{
return getModifiableMap().remove(attribute, modifier);
}
/**
* Removes all modifiers for the given attribute
* @param attribute Attribute
* @return Collection of removed modifiers
*/
public Collection<AttributeModifier> removeAttribute(Attribute attribute)
{
return getModifiableMap().removeAll(attribute);
}
/**
* Removes all modifiers for all attributes
*/
public void clearModifiers()
{
getModifiableMap().clear();
}
/** Gets the slot containing this stack */
public EquipmentSlotType getSlotType()
{
return this.slotType;
}
/** Gets the item stack instance */
public ItemStack getItemStack()
{
return this.stack;
}
}

View file

@ -0,0 +1,55 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2020.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.debug.item;
import net.minecraft.entity.ai.attributes.AttributeModifier;
import net.minecraft.entity.ai.attributes.AttributeModifier.Operation;
import net.minecraft.entity.ai.attributes.Attributes;
import net.minecraft.inventory.EquipmentSlotType;
import net.minecraft.item.Item;
import net.minecraft.item.Items;
import net.minecraftforge.event.ItemAttributeModifierEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
@Mod(ItemAttributeModifierTest.MOD_ID)
@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.FORGE, modid = ItemAttributeModifierTest.MOD_ID)
public class ItemAttributeModifierTest
{
public static final String MOD_ID = "item_modifier_test";
public static final boolean ENABLED = true;
private static final AttributeModifier MODIFIER = new AttributeModifier(MOD_ID, 10f, Operation.ADDITION);
@SubscribeEvent
public static void onItemAttribute(ItemAttributeModifierEvent event)
{
if (ENABLED && event.getSlotType() == EquipmentSlotType.MAINHAND)
{
final Item item = event.getItemStack().getItem();
if (item == Items.APPLE)
{
event.addModifier(Attributes.ARMOR, MODIFIER);
}
else if (item == Items.GOLDEN_SWORD)
{
event.clearModifiers();
}
}
}
}

View file

@ -96,5 +96,7 @@ license="LGPL v2.1"
modId="forge_codecs_test"
[[mods]]
modId="render_local_player_test"
[[mods]]
modId="item_modifier_test"
[[mods]]
modId="forge_world_type_test"