Jump to content

Held item not working unless switched off of


ND0322

Recommended Posts

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));
            
            
                
            
        }

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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));
    }
    

Link to comment
Share on other sites

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 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.

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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?

 

 

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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

 

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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?

 

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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?

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.