Jump to content

[1.12] Attaching Capabilities to an Item


TheXFactor117

Recommended Posts

I'm trying to add some extra data to items and I have been using NBT data for that in the past, though I was wondering if I should be using capabilities now since I'm using 1.12. However, I have a few questions about it. The capability stores all of the information within itself, and not on the itemstack's NBT, right? If that's the case, that would seem to mess up how I'm overwriting the ItemStack's Attributes. Right now, I am creating an AttributeModifier's NBT taglist which when I apply it to a weapon for instance, it uses my AttributeModifiers instead of the vanilla default one. Though if I'm storing this tag inside the capability, the ItemStack won't know it's there (if I'm thinking correctly).

 

Other than that, it seems like I can store the other information fairly easily. The other question though is actually adding this information to the capability. I can't add the information within the AttachCapabilityEvent because one of what I've read up on, and two because I need an EntityPlayer to be passed in somehow. That leaves me to use events again and I've already had several issues with those which is why I'm looking into setting this stuff up in a capability.

 

In the end, if anyone could provide some more information on how the item capability works and if it will even be a solution to my problem. Thanks!

Developer of Levels and Lost Eclipse

Link to comment
Share on other sites

5 minutes ago, TheXFactor117 said:

I'm trying to add some extra data to items and I have been using NBT data for that in the past, though I was wondering if I should be using capabilities now since I'm using 1.12. However, I have a few questions about it. The capability stores all of the information within itself, and not on the itemstack's NBT, right? If that's the case, that would seem to mess up how I'm overwriting the ItemStack's Attributes. Right now, I am creating an AttributeModifier's NBT taglist which when I apply it to a weapon for instance, it uses my AttributeModifiers instead of the vanilla default one. Though if I'm storing this tag inside the capability, the ItemStack won't know it's there (if I'm thinking correctly).

 

Other than that, it seems like I can store the other information fairly easily. The other question though is actually adding this information to the capability. I can't add the information within the AttachCapabilityEvent because one of what I've read up on, and two because I need an EntityPlayer to be passed in somehow. That leaves me to use events again and I've already had several issues with those which is why I'm looking into setting this stuff up in a capability.

 

In the end, if anyone could provide some more information on how the item capability works and if it will even be a solution to my problem. Thanks!

If you use the Forge provided ItemStack sensitive version of getAttributeModifiers you get an ItemStack parameter. With an ItemStack parameter you can use ItemStack#getCapability in which you could get the data. And in what way would you need the player? The AttachCapabilityEvent is indeed the way to register it.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

Yes I am using the ItemStack sensitive, so I think that solves that issue.

 

I need the player for some of the information I'm setting. For example, the player has a level and whenever the player creates/gets a new weapon, that weapon should have the same level as the player. I know I need to use AttachCapabilityEvent to register the capability, but could I use that to setup the data for the item?

Edited by TheXFactor117

Developer of Levels and Lost Eclipse

Link to comment
Share on other sites

You could get the player in many ways, you could have it linked to a certain character upon creation (Item#onCreated) which could be reset by placing it back into a crafting table (Custom IRecipe implementation) or on right click (Item#onItemRightClick) you could bind it, or even as soon as it is held in the players hand via Item#onUpdate.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

Yes, but what about for vanilla items? I don't have access to those methods. I'm trying to add information to my own weapons + vanilla's weapons (and other mods weapons should everything be compatible). The problem is I don't know where I would setup all this information - I read something where you couldn't add information to the capability in the AttachCapabilityEvent. If that is the case, where would I do it for vanilla items? Events don't seem to be the place because half of them don't work as intended (e.g. you can't use ItemCraftedEvent to update NBT because that's not what it's designed for).

Developer of Levels and Lost Eclipse

Link to comment
Share on other sites

You can most definitely attach NBT data or Capability Data to ItemStack in the PlayerEvent.ItemCraftedEvent. Then there is the PlayerInteractEvent if you want to do a Right Click bind, ItemCraftedEvent for when it is crafted, or the TickEvent.PlayerTickEvent for when the item is held.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

I don't understand how you can use ItemCraftedEvent to add NBT based on this. Whenever I try the NBT is never saved/added correctly. I was hoping capabilities would be able to solve this but it doesn't look like. Just so I'm understanding things right, you can't add capability data when you attach the capability?

Developer of Levels and Lost Eclipse

Link to comment
Share on other sites

6 minutes ago, TheXFactor117 said:

I don't understand how you can use ItemCraftedEvent to add NBT based on this. Whenever I try the NBT is never saved/added correctly. I was hoping capabilities would be able to solve this but it doesn't look like. Just so I'm understanding things right, you can't add capability data when you attach the capability?

Ahhh, shift clicking the item out of the crafting table doesn't work while editing the result through the event. This is a problem with the Container#mergeItemStack because it uses ItemStack#copy and places that into the new slot or just modifies the current slot with a matching item. This can be 'fixed' by overriding the Items using substitution, using the Right Click/Player Tick, or whenever the vanilla ContainerWorkbench opens replace it with your own version that overrides the mergeItemStack method and applies the data to the stack when it comes out of the result slot or even using a custom Slot for the result instead of the vanilla one which will allow you to modify the Stack any way you want.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

Attaching Capabilities is just like registering an Item pretty much. You are telling the game that the Entity, ItemStack, etc will have it. When this is called the object does't exist. So data cannot be saved to it. The data needs to be added specifically to each ItemStack in this case and is different between all of them. The Capability is not saved to the Item for this reason as they as well as Blocks are singletons.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

Ok - I'll look into implementing it anyways. Though a quick question regarding setting the values: what's the best way to set these values up? I don't want to use the PlayerTickEvent because I don't feel comfortable iterating through every player's inventory every tick to update information. ItemCraftedEvent doesn't really work (though I might not even need to set stuff up by crafting), I think there's an OpenContainer event which would handle things spawned in chests, maybe there are other events that would do this in a better way?

Developer of Levels and Lost Eclipse

Link to comment
Share on other sites

You could use the PlayerTickEvent and only check the held item(s offhand maybe?) and armor slots if necessary, you do not need to iterate through the whole inventory. You could use the PlayerContainerEvent.Open/Close, but that will not do anything unless it opens or closes. You could use the ItemTooltipEvent if you want it to be displayed there and do some packet stuff accompanied with the afformentioned PlayerTickEvent.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

Well PlayerTickEvent + specific slots might not work the best, it would require the player to put the item in the right slot before it was setup. Maybe the best option would be to set everything client side through ItemTooltipEvent and just send a packet to the server and set the values that way?

Developer of Levels and Lost Eclipse

Link to comment
Share on other sites

If you do EntityPlayer#inventory.currentItem you get the currently selected slot. Plus ItemTooltipEvent is only fired when the item is hovered over in an inventory.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

That is why you would do both.

11 minutes ago, Animefan8888 said:

You could use the ItemTooltipEvent if you want it to be displayed there and do some packet stuff accompanied with the afformentioned PlayerTickEvent.

 

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

Ah I see now - there is a downside to just using the TooltipEvent assuming the player doesn't actually look at the weapon...

 

There honestly just needs to be an event for when an item is added into a player inventory. Make my life a hell of a lot easier. Though would looping through the current item on PlayerTick cause any noticeable effects? I'm assuming the entire inventory would cause issues potentially or is the scale of that just not even noticeable nowadays with the computers we have?

Developer of Levels and Lost Eclipse

Link to comment
Share on other sites

I don't think it would be to noticeable in SinglePlayer, but on a server with several people it could cause some problems depending on the server. Considering it is (36 + 4(if armor)) * numPlayers * 20 iterations every second. Then possibly multiple conditional checks. If done right it wouldn't make much of an impact, though doing the above would be significantly better.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

@SubscribeEvent
	public void onPlayerTick(PlayerTickEvent event)
	{
		if (event.phase == Phase.START)
		{
			if (!event.player.getEntityWorld().isRemote)
			{	
				if (event.player.inventory.getCurrentItem().getItem() instanceof ItemSword && !NBTHelper.loadStackNBT(event.player.inventory.getCurrentItem()).hasKey("Level"))
				{
					ItemGenerator.createWeapon(event.player.inventory.getCurrentItem(), event.player);
				}
			}
		}
	}

 

and the createWeapon method...

 

public static void createWeapon(ItemStack stack, EntityPlayer player)
	{
		NBTTagCompound nbt = NBTHelper.loadStackNBT(stack);
		IPlayerInformation playerInfo = player.getCapability(CapabilityPlayerInformation.PLAYER_INFORMATION, null);

		if (playerInfo != null)
		{
			if (Rarity.getRarity(nbt) == Rarity.DEFAULT)
			{
				Rarity.setRarity(nbt, Rarity.getRandomRarity(nbt, player.getEntityWorld().rand)); // sets a random rarity
				
				MineHackSlash.LOGGER.info("Rarity: " + Rarity.getRarity(nbt));
				nbt.setInteger("HideFlags", 6); // hides Attribute Modifier and Unbreakable tags
				nbt.setInteger("Level", 1); // set level to current player level
				setRandomAttributes(stack, nbt, Rarity.getRarity(nbt), player);
				setAttributeModifiers(nbt, stack, player);
				stack.setStackDisplayName(Rarity.getRarity(nbt).getColor() + stack.getDisplayName());
				NBTHelper.saveStackNBT(stack, nbt);
			}
		}
	}

 

My output gets run twice on the server thread. I'm checking for Phase.Start and making sure we're on the server side. However, if I call createWeapon from anything other than PlayerTickEvent, that outputs only one time.

 

Edit: maybe the code I'm trying to run within a tick is taking too long to process? Because if you output world time the time is increasing so it's two separate ticks. It's almost like the event calls my method and calls it again before it can set anything. The Rarity is always set to the first call but later on the method setRandomAttributes uses the rarity to determine how many attributes to apply - this number always uses the second rarity created instead of the first. I'm just confused as to what is happening.

Edited by TheXFactor117

Developer of Levels and Lost Eclipse

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.



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • Your drivers are in a broken state, follow the guide in the FAQ: https://forums.minecraftforge.net/topic/125488-rules-and-frequently-asked-questions-faq/#:~:text=How do I update my drivers%3F
    • A fatal error has been detected by the Java Runtime Environment: # # EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00007ffc3fe22b60, pid=15228, tid=5140 # # JRE version: OpenJDK Runtime Environment Microsoft-8035246 (17.0.8+7) (build 17.0.8+7-LTS) # Java VM: OpenJDK 64-Bit Server VM Microsoft-8035246 (17.0.8+7-LTS, mixed mode, tiered, compressed oops, compressed class ptrs, g1 gc, windows-amd64) # Problematic frame: # C [atio6axx.dll+0x192b60] # # No core dump will be written. Minidumps are not enabled by default on client versions of Windows # # If you would like to submit a bug report, please visit: # https://aka.ms/minecraftjavacrashes # The crash happened outside the Java Virtual Machine in native code. # See problematic frame for where to report the bug i have no idea why please help
    • Quick-Books is great with regards to coordinating your monetary data. You can decide to live talk with a specialist at Quick-Books to get the answer for your questions. You will actually want to get to the talk going to the landing page and call us +1855-210-1428.
    • Update: I managed to make the item not disappear after crafting, but it doesn't remove any durability. import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.enchantment.Enchantments; import net.minecraft.enchantment.UnbreakingEnchantment; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; public class NuggetHammer extends Item { private boolean damage; public NuggetHammer(Properties p_i48487_1_) { super(p_i48487_1_); } @Override public int getMaxDamage(ItemStack stack) { return 54 - 1; } public boolean isBarVisible(ItemStack stack) { return false; } @Override public ItemStack getContainerItem(ItemStack stack) { ItemStack copy = stack.copy(); copy.setCount(1); if (!this.damage) return copy; int unbreaking = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.UNBREAKING, stack); for (int i = 0; i < unbreaking; i++) { if (UnbreakingEnchantment.shouldIgnoreDurabilityDrop(stack, unbreaking, random)) return copy; } copy.setDamageValue(stack.getDamageValue() + 1); if (copy.getDamageValue() > stack.getMaxDamage()) return ItemStack.EMPTY; return copy; } }  
  • Topics

×
×
  • Create New...

Important Information

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