Posted July 14, 20223 yr If have written code for an item that should give it more damage when held. However, this only works when swapping off of the item, putting my mouse on the tooltip, or dropping the item on the ground. Here is the code: public Multimap<Attribute, AttributeModifier> getAttributeModifiers(EquipmentSlot slot, ItemStack stack) { Multimap<Attribute, AttributeModifier> multimap = super.getAttributeModifiers(slot, stack); ListMultimap<Attribute, AttributeModifier> mutableMultimap = toMutableMultimap(multimap); if (slot == EquipmentSlot.MAINHAND) { mutableMultimap.put(Attributes.ATTACK_DAMAGE, new AttributeModifier(BASE_ATTACK_DAMAGE_UUID, "ATTACK_DAMAGE_MODIFIER", Integer.MAX_VALUE, AttributeModifier.Operation.ADDITION)); }
July 14, 20223 yr It won't work the way are you are doing it. Your method won't be invoked everytime. ItemStack.getAttributeModifiers() has some caching code that effectively does: if (alreadyCalculatedModifiers != null) { return alreadyCalculatedModifiers; } return callYourCode(); If you want something more dynamic that is called everytime, register for forge's ItemAttributeModifierEvent. Boilerplate: If you don't post your logs/debug.log we can't help you. For curseforge you need to enable the forge debug.log in its minecraft settings. You should also post your crash report if you have one. If there is no error in the log file and you don't have a crash report then post the launcher_log.txt from the minecraft folder. Again for curseforge this will be in your curseforge/minecraft/Install Large files should be posted to a file sharing site like https://gist.github.com You should also read the support forum sticky post.
July 14, 20223 yr Quote ItemStack#getAttributeModifiers directly calls Item#getAttributeModifiers, unless its modifiers are overridden via NBT. My bad, I read that as a cache when it is as you say an override. The original poster should still use the ItemAttributeModifierEvent, otherwise if somebody does define an override their logic won't be invoked. Boilerplate: If you don't post your logs/debug.log we can't help you. For curseforge you need to enable the forge debug.log in its minecraft settings. You should also post your crash report if you have one. If there is no error in the log file and you don't have a crash report then post the launcher_log.txt from the minecraft folder. Again for curseforge this will be in your curseforge/minecraft/Install Large files should be posted to a file sharing site like https://gist.github.com You should also read the support forum sticky post.
July 14, 20223 yr Quote Which is exactly the intended behavior... The item defines the default behavior, if a user goes in and overrides it via NBT you should respect this. My understanding is they want to apply a bonus based on which slot the item is in? There's no way for somebody to replicate this logic if they are using say a loot table function to do the override. Boilerplate: If you don't post your logs/debug.log we can't help you. For curseforge you need to enable the forge debug.log in its minecraft settings. You should also post your crash report if you have one. If there is no error in the log file and you don't have a crash report then post the launcher_log.txt from the minecraft folder. Again for curseforge this will be in your curseforge/minecraft/Install Large files should be posted to a file sharing site like https://gist.github.com You should also read the support forum sticky post.
July 14, 20223 yr We can let the original poster clarify what they really want, then continue this "tangent" if it is still relevant. Boilerplate: If you don't post your logs/debug.log we can't help you. For curseforge you need to enable the forge debug.log in its minecraft settings. You should also post your crash report if you have one. If there is no error in the log file and you don't have a crash report then post the launcher_log.txt from the minecraft folder. Again for curseforge this will be in your curseforge/minecraft/Install Large files should be posted to a file sharing site like https://gist.github.com You should also read the support forum sticky post.
July 14, 20223 yr Author So if I leave the game while holding the item and join back in it won't update unless switched off of. Btw it's a sword item.
July 14, 20223 yr Author The original code has it so when you right click holding the sword it changes a variable that allows the attribute modifer to change. Here is the code : @Override public InteractionResultHolder<ItemStack> use(Level world, Player player, InteractionHand hand) { if (rightClickReady) { rightClickActive = true; rightClickReady = false; buffTimer(10); rightClickCooldown(30); } return super.use(world, player, hand); } @Override public Multimap<Attribute, AttributeModifier> getAttributeModifiers(EquipmentSlot slot, ItemStack stack) { Multimap<Attribute, AttributeModifier> multimap = super.getAttributeModifiers(slot, stack); ListMultimap<Attribute, AttributeModifier> mutableMultimap = toMutableMultimap(multimap); if (slot == EquipmentSlot.MAINHAND && rightClickActive) { mutableMultimap.put(Attributes.ATTACK_DAMAGE, new AttributeModifier(BASE_ATTACK_DAMAGE_UUID, "ATTACK_DAMAGE_MODIFIER", Integer.MAX_VALUE, AttributeModifier.Operation.ADDITION)); } return (toImmutableMultimap(mutableMultimap)); }
July 14, 20223 yr First: That use of Integer.MAX_VALUE is going to cause an overflow. Use 100 or something for testing. Integer.MAX_VALUE + 1 = negative value But I think the correct way to do what you are doing is via a MobEffect, see LivingEntity.addEffect() Your right click would apply the effect and then the effect would add the modifier. It would also mean the effect is saved with the player so it would survive reloads of the game. You certainly can't change data in your Item. There is only ever 1 instance of that. Stored mutable data for an Item should be in the ItemStack nbt. Edited July 14, 20223 yr by warjort Boilerplate: If you don't post your logs/debug.log we can't help you. For curseforge you need to enable the forge debug.log in its minecraft settings. You should also post your crash report if you have one. If there is no error in the log file and you don't have a crash report then post the launcher_log.txt from the minecraft folder. Again for curseforge this will be in your curseforge/minecraft/Install Large files should be posted to a file sharing site like https://gist.github.com You should also read the support forum sticky post.
July 14, 20223 yr 12 minutes ago, ND0322 said: rightClickActive = true; rightClickReady = false; you can not store data like this in your Item class since it's a singleton the Item exists once, you need to use the Tag data of the given ItemStack or for more complex data a Capability and for further post please use the code feature of the Forum or a paste website to upload your code
July 14, 20223 yr Author 1 hour ago, warjort said: First: That use of Integer.MAX_VALUE is going to cause an overflow. Use 100 or something for testing. Integer.MAX_VALUE + 1 = negative value But I think the correct way to do what you are doing is via a MobEffect, see LivingEntity.addEffect() Your right click would apply the effect and then the effect would add the modifier. It would also mean the effect is saved with the player so it would survive reloads of the game. You certainly can't change data in your Item. There is only ever 1 instance of that. Stored mutable data for an Item should be in the ItemStack nbt. So if I were to add an effect to the player I would need to first create that effect with attribute modifers. How would I do this effecttively?
July 14, 20223 yr The following is the basics (it probably contains typos so double check names and values with the Minecraft/Forge source). You create and register the MobEffect like anything else using DeferredRegistry. There is a ForgeRegistries.MOB_EFFECTS. See net.minecraft.world.effect.MobEffects for how it constructs vanilla effects with attribute modifiers. I would guess yours would be very similar to MobEffects.STRENGTH and AttackDamageMobEffect? You will also need a src/main/resources/assets/modid/textures/mob_effect/yourid.png for displaying the status icon to the user and give it a translation in your language file "effect.modid.yourid": "Blah" See the MobEffect class for the callbacks on what behaviour you can override. What you actually add to the entity is a MobEffectInstance, which I suppose most importantly for you defines the duration of the effect. Boilerplate: If you don't post your logs/debug.log we can't help you. For curseforge you need to enable the forge debug.log in its minecraft settings. You should also post your crash report if you have one. If there is no error in the log file and you don't have a crash report then post the launcher_log.txt from the minecraft folder. Again for curseforge this will be in your curseforge/minecraft/Install Large files should be posted to a file sharing site like https://gist.github.com You should also read the support forum sticky post.
July 14, 20223 yr Author I read online that you can add attribute modifiers to a MobEffectInstance here: https://forge.gemwire.uk/wiki/Mob_Effects. How would I "chain addAttributeModifier" when making the mobEffectInstance?
July 14, 20223 yr 1 hour ago, ND0322 said: I read online that you can add attribute modifiers to a MobEffectInstance here: https://forge.gemwire.uk/wiki/Mob_Effects. How would I "chain addAttributeModifier" when making the mobEffectInstance? AttributeModifiers are add to the MobEffect not the MobEffectInstance
July 14, 20223 yr Author When I run it I get a crash that says Caught exception during event RegistryEvent.Register<minecraft:item> dispatch for modid trufflemod java.lang.NullPointerException: Registry Object not present: trufflemod:damage_boost. package com.ND0322.trufflemod.effects; import com.ND0322.trufflemod.truffleMod; import net.minecraft.world.effect.AttackDamageMobEffect; import net.minecraft.world.effect.MobEffect; import net.minecraft.world.effect.MobEffectCategory; import net.minecraft.world.entity.ai.attributes.AttributeModifier; import net.minecraft.world.entity.ai.attributes.Attributes; import net.minecraftforge.eventbus.api.IEventBus; import net.minecraftforge.registries.DeferredRegister; import net.minecraftforge.registries.ForgeRegistries; import net.minecraftforge.registries.RegistryObject; public class ModEffects { public static final DeferredRegister<MobEffect> MOB_EFFECTS = DeferredRegister.create(ForgeRegistries.MOB_EFFECTS,truffleMod.MOD_ID); public static final RegistryObject<MobEffect> DAMAGE_BOOST_EFFECT = MOB_EFFECTS.register("damage_boost", () -> new DamageBoostEffect(MobEffectCategory.BENEFICIAL, 3124687).addAttributeModifier(Attributes.ATTACK_DAMAGE, "648D7064-6A60-4F59-8ABE-C2C23A6DD7A9", 100d, AttributeModifier.Operation.ADDITION)); public static void register(IEventBus eventBus) { MOB_EFFECTS.register(eventBus); } } here is the effect registration.
July 14, 20223 yr Author package com.ND0322.trufflemod.effects; import net.minecraft.world.effect.MobEffect; import net.minecraft.world.effect.MobEffectCategory; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.ai.attributes.AttributeModifier; import net.minecraft.world.entity.ai.attributes.Attributes; public class DamageBoostEffect extends MobEffect { public DamageBoostEffect(MobEffectCategory mobEffectCategory, int color){ super(mobEffectCategory, color); } @Override public boolean isDurationEffectTick(int pDuration, int pAmplifier) { return true; } } here is the effect class
July 14, 20223 yr Author Here is the item class package com.ND0322.trufflemod.items; import java.util.Timer; import java.util.TimerTask; import javax.annotation.Nonnull; import com.ND0322.trufflemod.effects.DamageBoostEffect; import com.ND0322.trufflemod.effects.ModEffects; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ListMultimap; import com.google.common.collect.Multimap; import net.minecraft.world.item.ItemStack; import net.minecraft.client.renderer.EffectInstance; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResultHolder; import net.minecraft.world.effect.MobEffect; import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.ai.attributes.*; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.SwordItem; import net.minecraft.world.item.Tier; import net.minecraft.world.level.Level; public class CopperizedDiamondSword extends SwordItem{ public boolean rightClickReady = true; public boolean rightClickActive = false; MobEffectInstance m = new MobEffectInstance(ModEffects.DAMAGE_BOOST_EFFECT.get(),10,3 ); public CopperizedDiamondSword(Tier pTier, int pAttackDamageModifier, float pAttackSpeedModifier, Properties pProperties) { super(pTier, pAttackDamageModifier, pAttackSpeedModifier, pProperties); } public static<K, V> ListMultimap<K, V> toMutableMultimap(Multimap<K, V> original) { ListMultimap<K, V> copy = ArrayListMultimap.create(); copy.putAll(original); return copy; } public static<K, V> ImmutableMultimap<K, V> toImmutableMultimap(ListMultimap<K, V> original) { return new ImmutableMultimap.Builder<K, V>().putAll(original).build(); } @Override public InteractionResultHolder<ItemStack> use(Level world, Player player, InteractionHand hand) { if (rightClickReady) { player.addEffect(m); } return super.use(world, player, hand); } @Override public Multimap<Attribute, AttributeModifier> getAttributeModifiers(EquipmentSlot slot, ItemStack stack) { Multimap<Attribute, AttributeModifier> multimap = super.getAttributeModifiers(slot, stack); ListMultimap<Attribute, AttributeModifier> mutableMultimap = toMutableMultimap(multimap); if (slot == EquipmentSlot.MAINHAND && rightClickActive) { mutableMultimap.put(Attributes.ATTACK_DAMAGE, new AttributeModifier(BASE_ATTACK_DAMAGE_UUID, "ATTACK_DAMAGE_MODIFIER", Integer.MAX_VALUE, AttributeModifier.Operation.ADDITION)); } return (toImmutableMultimap(mutableMultimap)); } public void rightClickCooldown(int time) { Timer timer = new Timer(); timer.scheduleAtFixedRate(new TimerTask() { int i = time; public void run() { i--; if (i < 0) { System.out.println("cooldown done"); timer.cancel(); rightClickReady = true; System.out.println("cooldown done"); } } },0,1000); } public void buffTimer(int time) { Timer timer = new Timer(); timer.scheduleAtFixedRate(new TimerTask() { int i = time; public void run() { i--; if (i < 0) { System.out.println("timer done"); timer.cancel(); rightClickActive = false; System.out.println(rightClickActive); } } },0,1000); } } The timer stuff is from before I havent removed yet
July 14, 20223 yr 8 minutes ago, ND0322 said: When I run it I get a crash that says Caught exception during event RegistryEvent.Register<minecraft:item> dispatch for modid trufflemod java.lang.NullPointerException: Registry Object not present: trufflemod:damage_boost did you register the DeferredRegisterin the constructor of your main Mod class (see: https://forge.gemwire.uk/wiki/Registration#DeferredRegister)? 4 minutes ago, ND0322 said: public boolean rightClickReady = true; public boolean rightClickActive = false; as i already told you, you can not store data like this in your Item class since it's a singleton the Item exists once, you need to use the Tag data of the given ItemStack or for more complex data a Capability Spoiler public void buffTimer(int time) { Timer timer = new Timer(); timer.scheduleAtFixedRate(new TimerTask() { int i = time; public void run() { i--; if (i < 0) { System.out.println("timer done"); timer.cancel(); rightClickActive = false; System.out.println(rightClickActive); } } },0,1000); } you can not do this, vanilla is in the most areas not thread safe, if you want a delayed task you need to use a TickTask you can take a look at ForgeInternalHandler EntityJoinLevelEvent fro an example
July 14, 20223 yr Author 3 minutes ago, Luis_ST said: did you register the DeferredRegisterin the constructor of your main Mod class (see: https://forge.gemwire.uk/wiki/Registration#DeferredRegister)? as i already told you, you can not store data like this in your Item class since it's a singleton the Item exists once, you need to use the Tag data of the given ItemStack or for more complex data a Capability Hide contents public void buffTimer(int time) { Timer timer = new Timer(); timer.scheduleAtFixedRate(new TimerTask() { int i = time; public void run() { i--; if (i < 0) { System.out.println("timer done"); timer.cancel(); rightClickActive = false; System.out.println(rightClickActive); } } },0,1000); } you can not do this, vanilla is in the most areas not thread safe, if you want a delayed task you need to use a TickTask you can take a look at ForgeInternalHandler EntityJoinLevelEvent fro an example The timer and variables are from before and I am currently not trying to use them. My main problem is the crash issue; however, I do not have a deferred register in the main mod class so that may be the issue. I will try to implement this now
July 14, 20223 yr Author package com.ND0322.trufflemod; import com.ND0322.trufflemod.effects.ModEffects; import com.ND0322.trufflemod.init.ItemInit; import com.ND0322.trufflemod.potions.ModPotions; import net.minecraft.world.item.CreativeModeTab; import net.minecraft.world.item.ItemStack; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.eventbus.api.IEventBus; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; @Mod("trufflemod") public class truffleMod { public static final String MOD_ID = "trufflemod"; public static final CreativeModeTab Truffle_Tab = new CreativeModeTab(MOD_ID) { @Override @OnlyIn(Dist.CLIENT) public ItemStack makeIcon() { return new ItemStack(ItemInit.BRONZE_DOGE_COIN.get()); } }; public truffleMod() { IEventBus bus = FMLJavaModLoadingContext.get().getModEventBus(); ItemInit.ITEMS.register(bus); ModEffects.register(bus); MinecraftForge.EVENT_BUS.register(this); } } This is the main mod class how do I register the deferred register?
July 14, 20223 yr public class CopperizedDiamondSword extends SwordItem{ MobEffectInstance m = new MobEffectInstance(ModEffects.DAMAGE_BOOST_EFFECT.get(),10,3 ); You can't do this. This will try to create the MobEffectInstance when the sword is created. The effect won't be registered yet, they are registered after items. You also want a new MobEffectInstance for every addEffect(). It is this object that keeps track of the time left. You can't share them between players or even different applications of the effect on the same player. Boilerplate: If you don't post your logs/debug.log we can't help you. For curseforge you need to enable the forge debug.log in its minecraft settings. You should also post your crash report if you have one. If there is no error in the log file and you don't have a crash report then post the launcher_log.txt from the minecraft folder. Again for curseforge this will be in your curseforge/minecraft/Install Large files should be posted to a file sharing site like https://gist.github.com You should also read the support forum sticky post.
July 14, 20223 yr Author 6 minutes ago, warjort said: public class CopperizedDiamondSword extends SwordItem{ MobEffectInstance m = new MobEffectInstance(ModEffects.DAMAGE_BOOST_EFFECT.get(),10,3 ); You can't do this. This will try to create the MobEffectInstance when the sword is created. The effect won't be registered yet, they are registered after items. You also want a new MobEffectInstance for every addEffect(). It is this object that keeps track of the time left. You can't share them between players or even different applications of the effect on the same player. Where should I create the MobEffctInstances?
July 14, 20223 yr Like I said, you create one for each player.addEffect() Boilerplate: If you don't post your logs/debug.log we can't help you. For curseforge you need to enable the forge debug.log in its minecraft settings. You should also post your crash report if you have one. If there is no error in the log file and you don't have a crash report then post the launcher_log.txt from the minecraft folder. Again for curseforge this will be in your curseforge/minecraft/Install Large files should be posted to a file sharing site like https://gist.github.com You should also read the support forum sticky post.
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.