Fabric API

Fabric API

106M Downloads

[Enhancement] `ItemVariant.matches` could have a special option, or another method, to help match on non-stackable items.

TaitoMagatsu91 opened this issue ยท 3 comments

commented

Method of the interface in question:

/**
* Return true if the item and tag of this variant match those of the passed stack, and false otherwise.
*/
default boolean matches(ItemStack stack) {
return isOf(stack.getItem()) && nbtMatches(stack.getNbt());
}

This interface currently has no way of matching on unstackable items in a more general manner.

Say I want to match on golden swords or bows that are dropped from a mob farm. It's currently not possible to ask the API for a way to filter "all golden swords" or "golden swords with enchantments", "damaged bows", "undamaged bows", etc.

The only thing that's possible is to filter for items that are exactly like the ItemStack that is offered. This is perfect for stackable items. But for unstackables, specially randomly damaged and enchanted gear, I find it still lacks an important piece to be feature-complete :3


As for who is currently using this API (which I understand is still experimental):

I found the need for this enhancement when looking for the source code for the Item Pipes of Modern Industrialization. Here's the method that filters items (either whitelisted or blacklisted) going through a pipe:

https://github.com/AztechMC/Modern-Industrialization/blob/bb0fa25698f0692ad9c1a3a104544be886856b7a/src/main/java/aztech/modern_industrialization/pipes/item/ItemNetworkNode.java#L285-L292

The method uses this same transfer API. I've found it to be perfect, again, for stackable items. But it can't really do much with unstackables at this point in time.


Thank you. I hope I used the right channel for this request.

-- Taito

commented

Hi, your best bet is probably to use .toStack() and then compare the stacks however you want. The performance impact should be quite small. That's what I was planning to do in MI.

(in some cases such as enchantments, the tag obtained with getTag is enough and no allocation is necessary)

Providing more specialized matching functions will increase API surface a lot to only cover a few specific cases, so it's something I'd like to avoid unless there is a big performance or usability difference. For example, AE2 has multiple FuzzyModes to compare damage values, and it would be impossible to encode that in the API.

commented

I have this method for general stack equality checks.

public static final int
    ITEM  = 0b00001,
    COUNT = 0b00010,
    NBT   =  0b00100;

public static boolean check(ItemStack stackA, ItemStack stackB, int criteria)
{
    if ((criteria & ITEM) != 0 && stackA.getItem() != stackB.getItem())
        return false;
    if ((criteria & COUNT) != 0 && stackA.getCount() != stackB.getCount())
        return false;
    if ((criteria & NBT) != 0 && !ItemStack.areNbtEqual(stackA, stackB))
        return false;
    return true;
}

A similar approach might work here to allow API users to select stack matching criteria.

commented

Going to close this as I don't think it has a better solution than just writing your own match function using getItem and getNbt that suits your particular use case.