Disable items from crating inventory

Plugin Source::

public void onItemCraft(ClickInventoryEvent event, @Root Player player, @Getter("getTargetInventory") Inventory inventory) {
    if (inventory.getArchetype() == InventoryArchetypes.PLAYER || inventory.getArchetype() == InventoryArchetypes.WORKBENCH) {
        Inventory craftingInputs = inventory.query(QueryOperationTypes.INVENTORY_TYPE.of(InputSlot.class));

        craftingInputs.slots().forEach(slot -> slot.peek().ifPresent(itemStack -> {
            String itemId = itemStack.getType().getId();
            logger.info(itemId);
        }));
    }
}

Hello all. Hopefully I can get some advice here because I’m stuck.

What I’m trying to do is block certain items from being placed in a crafting inventory. The above code worked in 5.2, but when upgrading to 7.1 it no longer was working. I modified to the new api code, but still nothing. Any help/point in the right direction is appreciated.

What happens if you change those ==s to .equals()s?

Is this using the ‘book’ to help with recipes?

Ok so changing it to .equals() did nothing. Still not registering anything.

And no, this is basically just to keep people from trying to craft with custom items.

First (pun intended), your use of @Root is causing issues. There aren’t any guarantees about what the root cause of an event should be, so it’s best to use @First instead. I’d also recommend avoiding @Getter; it’s simple enough to call event.getTargetInventory() (or player.getInventory(), if you prefer) and saves some reflection calls.

Checking the archetype is handy, but has the potential to be incorrect if mods modify the player’s inventory. Instead, you should focus on using queries. I’ve written two pretty detailed posts on how querying with inventories work and the important of context which you can find here and here.

Based on my tests (SF 2840), querying for InputSlot is what’s returning an empty inventory. This is likely because this section of the API hasn’t been built yet, and I don’t see any CraftingInput subinterface as I do for CraftingOutput in relation to OutputSlot. However, there is another way you should be doing this anyways: CraftingInventory. This is going to contain both your CraftingGridInventory and CraftingOutput (or, if you don’t need the output, you can query for CraftingGridInventory directly). This can be done with the following query that would replace the one you currently have for InputSlot:

CraftingInventory craftingInv = inv.query(QueryOperationTypes.INVENTORY_TYPE.of(CraftingInventory.class).first();
// If you're confused as to why there is a .first() at the end, see the posts I linked above

Now, one final piece: Unless you’re working with combinations of items that are being crafted, it makes much more sense to use event.getTransactions() and see if an unwanted item is being added - if so, cancel it.

Ok got it to work with the following:

Inventory craftingInv = inventory.query(QueryOperationTypes.INVENTORY_TYPE.of(CraftingInventory.class));

Thank you all for the help!

@m1zark Under most circumstances there will only be one CraftingInventory, but please note the following: Inventory API query return Type · Issue #1741 · SpongePowered/SpongeAPI · GitHub.