Jump to content

[1.12.2] Syncing an ItemStackHandler capability within an ItemStack


ObliviousSpartan

Recommended Posts

I am making a quiver for my weapons mod, which stores 4 different stacks of Arrows using capabilities. In a single player world, this works as intended, without issues.

However, when running on a server, none of the visual changes show up. So I need to synchronise the ItemStackHandler capability on it from the Server to the Client.

The reason for this syncing is that the quiver has a tooltip which shows what the Quiver contains. In addition, there is a HUD overlay which shows how many arrows are left. On top of all that, the Quiver texture changes depending on how full it is.

lIohsyd.pngh16UIzs.png

The above pics show what they should look like when properly synced (however the HUD element is a WIP and will change)

 

I have seen the following topic on this: 

However, I am not sure how to acquire the Capability NBT Tag to add to the share tag for the ItemStack, since the capability tag is private and inaccessible.

And with the second way with using packets and an IContainerListener, I am unsure how it works with storing ItemStacks and what data to send with the packet.

 

What would be the best way to approach doing the syncing of those visual elements? Any help would be greatly appreciated.

 

Edited by ObliviousSpartan
Much less confusing title
Link to comment
Share on other sites

I think it works like this. For your capability since on server you need NBT to save / load, you should have the Capability.IStorage methods for readNBT() and writeNBT() implemented which can be accessed through convenience methods Capability#readNBT() and Capability#writeNBT(). And on server you can get the Capability with the ItemStack#getCapability() method. Lastly, the Item class has the getShareTag() and getNBTShareTag() methods to allow you to add NBT data to the packets that are used to sync to client.

 

Putting it together, I think you want to do the following:

  1. Make sure your custom Capability IStorage properly implements a readNBT() and writeNBT() method.
  2. In your custom Item class make sure that the getShareTag() returns true and that the getNBTShareTag() method adds the cability NBT (which you can get from Capability#writeNBT()). IMPORTANT: You will want to specify some sort of key that you can use on client side to extract the data.
  3. In your client rendering or wherever, you use look in the ItemStack NBT for the key that you specified in Step 2 above. You should not need to actually get that NBT info into the client Capability, I think you can just use it directly from the NBT.

Note that to make it simpler you don't have to transmit the whole Capability NBT, if you just want a simple piece of data you could just transmit that instead. In any case, the key is the getNBTShareTag() and you just have to look up the data from the capability and come up with (there is some flexibility here) a NBT element to add that you can inspect on the client side.

 

One other thing, it isn't clear to me whether changes in Capability will trigger an ItemStack update packet or not. There have been various PRs over the years discussing this. My point is you may want to force the update by sending the vanilla packet when your Capability changes.

 

Lastly, I find that working with NBT is technically simple but easy to get confused in the details because the compounds can get complex due to the fact they can be nested -- you can have a list of compound, a compound with lists, and so forth. So I highly recommend using console print statements throughout your code to print out the tag information at critical points so you can trace what is going on. 

  • Like 1
  • Thanks 1

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Link to comment
Share on other sites

Thanks for the suggestions.

I am using the capability for ItemStorageHandler (provided by Minecraft Forge) for this purpose, which already has NBT read/write functionality. Because of this, making a custom capability isn't necessary.

I figured out how to access the capability NBT data to put in the getNBTShareTag() method for use for the client. I have placed it in the Share Tag using the key "ClientInventory", and accessed it using the same key though the addInformation() method for tooltips and my Hud overlay.

 

Here's the getNBTShareTag() method below:

@Override
public NBTTagCompound getNBTShareTag(ItemStack stack)
{
	IItemHandler handler = stack.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null);
  	// The capability tag is simply a NBTTagList of all the items in the ItemStack
	NBTBase capTag = CapabilityItemHandler.ITEM_HANDLER_CAPABILITY.getStorage().writeNBT(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, handler, null);
	NBTTagCompound tag = super.getNBTShareTag(stack);
		
	tag.setTag("ClientInventory", capTag);
	return tag;
}

 

And now the quiver seems to sync properly! :D

iEwpDaD.png

Tooltips work fine!

 

x9LptMf.png

And the HUD element shows the correct amount of ammo stored in the quiver. Note in the above image I had just shot an arrow from the quiver, so forcing an update packet isn't necessary.

 

Thank you so much for the help!

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.