Cardinal Components API

Cardinal Components API

21M Downloads

Need fast methods to check if item has components and compare CCA item stacks.

grondag opened this issue ยท 6 comments

commented

My request is for some kind of performant utility that tests if an ItemStack contains any non-empty component information.

CCA item components are problematic for Facility/Fluidity because Facility needs to compare potentially many thousands of items within a single storage system when doing any sort of search operation. Facility item stores do not use ItemStack internally because ItemStack is a bad abstraction for uniquely identifying stored items.

A better abstraction would be Item, SpecificItem (item with or without a Tag), and SpecificItemWithQuantity.

The most valuable abstraction would be SpecificItem because finding/comparing Items and tracking quantities are otherwise trivial. But ItemStack obscures the concept of SpecificItem and makes comparison unnecessarily complicated.

ItemStack is at least workable because 1) the class is final and 2) all information other than Item and quantity are stored in a nullable CompoundTag.

The vast majority of items are simple items with no tag. For these, Fluidity can take a shortcut and rely on Item == comparison and avoid expensive NBT traversal operations.

CCA breaks this scheme by 1) adding a component store outside of Tag and 2) making that store - even the existence of it - undiscoverable except by specifically querying individual components per ItemStack instance.

This means a large-scale storage mod must retain ItemStack instances internally for each stored item and also force the use of ItemStack instances as input parameters for all storage operations in order to use the CCA-modified version of ItemStack.areTagsEqual.

The easiest way out of this is to make Facility not store item stacks with embedded CCA components. However, there seems to be no way to determine what these are. So for now I'm adding a black list configuration so server admins can prevent problems like this one.

I'd like to retain simple comparison logic for most items but once this check is available I will probably find a way to make Fluidity/Facility compatible with CCA items for storage and transport. But that will be a non-trivial change and is unlikely to happen soon.

commented

A couple more thoughts on this observed as I'm adding blacklist code:

CCA modifies ItemStack.areTagsEqual() (a static method) but not ItemStack.hasTag() or ItemStack.getTag().

So unless I missed a utility method somewhere this means I have to blacklist CCA items from storage even when they are empty. I have no way to know if they have content unless I want to hard depend on all possible component types of interest on every stack. (Maybe someday, not now.)

More generally, this seems to break the overall contract of ItemStack tag handling - I have no way to know if I should compare tags when tags are empty and the result of the comparison won't make any sense.

commented

CCA breaks this scheme by 1) adding a component store outside of Tag and 2) making that store - even the existence of it - undiscoverable except by specifically querying individual components per ItemStack instance.

While the first issue is inherent to the very concept of item components, the second does have an answer in the API. Calling dev.onyxstudios.cca.api.v3.component.ComponentProvider.fromItemStack(stack).getComponentContainer().keys() (V3 API) or nerdhub.cardinal.components.api.component.ComponentProvider.fromItemStack(stack).getComponentTypes() will give you what you want.

As for the tag issue, not sure how to fix it either without incurring a performance penalty due to redundant serialization operations.

commented

getComponentContainer looks workable. getComponentTypes() is allocating.

Is V3 the newer version and it is the most common in the wild? I have the old one in my dev env somehow.

commented

V3 API is experimental, but it is bundled with every artifact since 2.4.0 - alongside the legacy API. The plan is to get rid of the V2 API and any performance impact that comes with it sometimes during the 1.17 development cycle.

commented

CCA 2.5.0 comes with ComponentContainer#hasComponents, which will be optimized in 3.0.0 to literally return true/false. Should be fast enough for any purpose.

commented

Will give hasComponents a try. Thanks.