Jump to content

[1.16.5] Has @SubscribeEvent annotation, but takes an argument that is not a subtype of the base type interface


Triphion

Recommended Posts

I was trying to add the ItemAttributeModifierEvent so that I could change values depending on different circumstances. But I ran into a weird error which i've never seen before and I can't really make out what it means. Any help would be appreciated.

This is my event handler and main class for reference.

	public MainClass() 
	{
		instance = this;

		final IEventBus modBus = FMLJavaModLoadingContext.get().getModEventBus();

		modBus.addListener(this::commonSetup);
		modBus.addListener(this::clientSetup);
		modBus.addListener(this::onLoadComplete);
		
		EtauricBlocks.BLOCKS.register(modBus);
		EtauricItems.ITEMS.register(modBus);
		
		EtauricEntities.ENTITIES.register(modBus);
		
		//EtauricBiomes.BIOMES.register(modBus);
		
		MinecraftForge.EVENT_BUS.register(this);
	}
	@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD)
	private static class EventHandler
	{
		@SubscribeEvent
		public static void registerItems(final RegistryEvent.Register<Item> event) 
		{
			final IForgeRegistry<Item> registry = event.getRegistry();
			
			EtauricBlocks.BLOCKS.getEntries().stream().map(RegistryObject::get).forEach(block -> {
				final Item.Properties properties = new Item.Properties().tab(EtauricBlocks.getBlockGroup(block));
				final BlockItem blockItem = new BlockItem(block, properties);
				blockItem.setRegistryName(block.getRegistryName());
				
				if (!EtauricBlocks.ignoreBlocks().contains(block)) 
				{
					registry.register(blockItem);
				}
			});
			
			Utils.getLogger().info("All BlockItems successfully registered! ");
		}
		
		@SubscribeEvent
		public static void registerBiomes(final RegistryEvent.Register<Biome> event) 
		{
			//EtauricBiomes.registerBiomes();
			
			Utils.getLogger().info("Register Biomes. ");
		}

		@SubscribeEvent
		public static void registerEntityAttributes(final EntityAttributeCreationEvent event)
		{
			event.put(EtauricEntities.CHUPNUT.get(), ChupnutEntity.createAttributes().build());
			event.put(EtauricEntities.DEATH_BITER.get(), DeathBiterEntity.createAttributes().build());
			event.put(EtauricEntities.OGRE.get(), OgreEntity.createAttibutes().build());
			event.put(EtauricEntities.LUNAR_LUNATIC.get(), LunarLunaticEntity.createAttributes().build());
			event.put(EtauricEntities.TARANTULA.get(), TarantulaEntity.createAttributes().build());
			event.put(EtauricEntities.WRATHFUL_OGRE.get(), WrathfulOgreEntity.createAttributes().build());

			event.put(EtauricEntities.BEAST_KING.get(), BeastKingEntity.createAttributes().build());
			event.put(EtauricEntities.MOON_CRAWLER.get(), MoonCrawlerEntity.createAttributes().build());
		}

		@SubscribeEvent
		public static void updateItemAttributes(ItemAttributeModifierEvent event)
		{
			Utils.getLogger().info("ItemStackModifierEvent called!");

			ItemStack itemStack = event.getItemStack();
			Item item = itemStack.getItem();

			if (item == EtauricItems.SCORCHER_BLADE.get())
			{
				if (((ScorcherBlade) item).getBurning(event.getItemStack()) == true)
				{
					event.addModifier(Attributes.ATTACK_DAMAGE, new AttributeModifier("damage", 4.0D, AttributeModifier.Operation.MULTIPLY_BASE));
					event.addModifier(Attributes.ATTACK_SPEED, new AttributeModifier("speed", 4.0D, AttributeModifier.Operation.MULTIPLY_BASE));
				}
				else
				{
					event.addModifier(Attributes.ATTACK_DAMAGE, new AttributeModifier("damage", 1.0D, AttributeModifier.Operation.MULTIPLY_BASE));
					event.addModifier(Attributes.ATTACK_SPEED, new AttributeModifier("speed", 1.0D, AttributeModifier.Operation.MULTIPLY_BASE));
				}
			}
		}

My event handler is an internal class of the MainClass. I have another event handler for Client as well as another EventHandler that is not a static one. 

Note: These are two different code snippets, but they for some reason became just one.

Edited by Triphion
Link to comment
Share on other sites

18 minutes ago, diesieben07 said:

ItemAttributeModifierEvent is not a mod bus event.

Alright, thanks! I moved it into my general EventHandler and it seems to work fine now. As a sidenote, I seem to have a hard time understanding the new way of changing attributes. I had a way of changing attributes based on different modes on items. I have an event that fires every time a player presses a certain keybinding, and that works fine. But to add the attributes through the event after the maps got changed to immutable has been quite hard.

	@SubscribeEvent
	public static void updateItemAttributes(ItemAttributeModifierEvent event)
	{
		Utils.getLogger().info("ItemStackModifierEvent called!");

		ItemStack itemStack = event.getItemStack();
		Item item = itemStack.getItem();

		if (item == EtauricItems.SCORCHER_BLADE.get())
		{
			if (((ScorcherBlade) item).getBurning(event.getItemStack()) == true)
			{
				event.addModifier(Attributes.ATTACK_DAMAGE, new AttributeModifier("damage", 4.0D, AttributeModifier.Operation.MULTIPLY_BASE));
				event.addModifier(Attributes.ATTACK_SPEED, new AttributeModifier("speed", 4.0D, AttributeModifier.Operation.MULTIPLY_BASE));
			}
			else
			{
				event.addModifier(Attributes.ATTACK_DAMAGE, new AttributeModifier("damage", 1.0D, AttributeModifier.Operation.MULTIPLY_BASE));
				event.addModifier(Attributes.ATTACK_SPEED, new AttributeModifier("speed", 1.0D, AttributeModifier.Operation.MULTIPLY_BASE));
			}
		}
	}

But this only continues to add attribute in every single way possible. From what i've read, the addModifier adds values if the modifier doesn't exist, and so I thought this would work. Something that also puzzled me is the two different attributeMultimaps methods, getOriginalModifiers() and getModifiers(). How do I make this work?

Edited by Triphion
Link to comment
Share on other sites

11 minutes ago, diesieben07 said:

The event is for changing the attributes of other items. If the Item is yours, simply override getAttributeModifiers in your Item class.

 

getOriginalModifiers gives you the modifiers that are actually present on the stack (and that are produced by its Item). getModifiers are the modifiers after they have been modified by anyone using the event (using removeAttribute, removeModifier or addModifier).

Oh, okay! But i'm still having a hard time understanding how i'm gonna modify the values. I had an old way of doing this, but this doesn't work anymore due to it being an immutable list now. 

	@Override
	public Multimap<Attribute, AttributeModifier> getAttributeModifiers(EquipmentSlotType slot, ItemStack stack)
	{
		final Multimap<Attribute, AttributeModifier> modifiers = super.getAttributeModifiers(slot, stack);

		if (slot == EquipmentSlotType.MAINHAND && getBurning(stack) == true)
		{
			replaceModifier(modifiers, Attributes.ATTACK_DAMAGE, BASE_ATTACK_DAMAGE_UUID, 1.75D);
			replaceModifier(modifiers, Attributes.ATTACK_SPEED, BASE_ATTACK_SPEED_UUID, 1.332D);
		}
		else if (slot == EquipmentSlotType.MAINHAND && getBurning(stack) == false)
		{
			replaceModifier(modifiers, Attributes.ATTACK_DAMAGE, BASE_ATTACK_DAMAGE_UUID, 1D);
			replaceModifier(modifiers, Attributes.ATTACK_SPEED, BASE_ATTACK_SPEED_UUID, 1D);
		}

		return modifiers;
	}

	private void replaceModifier(Multimap<Attribute, AttributeModifier> modifierMultimap, Attribute attribute, UUID id, double multiplier)
	{
		// Get the modifiers for the specified attribute
		final Collection<AttributeModifier> modifiers = modifierMultimap.get((attribute));

		// Find the modifier with the specified ID, if any
		final Optional<AttributeModifier> modifierOptional = modifiers.stream().filter(attributeModifier -> attributeModifier.getId().equals(id)).findFirst();

		if (modifierOptional.isPresent()) { // If it exists,
			final AttributeModifier modifier = modifierOptional.get();
			modifiers.remove(modifier); // Remove it
			modifiers.add(new AttributeModifier(modifier.getId(), modifier.getName(), modifier.getAmount() * multiplier, modifier.getOperation())); // Add the new modifier
		}
	}

What would be the correct way to do this now? 

Note: This may be due to my limited experience with Java, although I use C# very often and these languages are pretty similiar, this is still pretty hard lol.

Link to comment
Share on other sites

23 hours ago, diesieben07 said:

Make a new Multimap from the existing one and mutate it.

Alright, I've researched this since yesterday and I simply cannot figure this out. What do you mean by "mutate" it? What I was thinking was to create a copy of the old multimap, change a few values in there, and then replace the old one. But this doesn't work since i'm getting an unsupportedOperationException: null. Which is confusing since if I cannot remove and add values from the copy I made and replace the old ones, how am I supposed to change the values? 

Link to comment
Share on other sites

1 hour ago, diesieben07 said:

modifiableMap = LinkedHashMultimap.create(originalMap);
// do your modifications on modifiableMap

return modifiableMap;

 

Thank you so much! With all my researching I didn't come across LinkedHash anywhere. I feel like Java is harder to find solutions and documentations on. C# has complete docs with references, examples and very detailed explanations and scenarios.

Sidenote: Do you know if there are any good docs where I can read up a bit more on Java in general?

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.

Announcements



×
×
  • Create New...

Important Information

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