Jump to content

Recommended Posts

Posted

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

Posted

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.

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

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

Posted

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.

Posted

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

Posted (edited)

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.

Posted
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

Posted
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?

 

 

Posted

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.

Posted

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.

Posted
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

 

Posted

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

Posted
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

Posted
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

Posted
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?

 

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

Posted
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?

Posted

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.

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.

Announcements



×
×
  • Create New...

Important Information

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