[Solved] How could the plugin get the itemstack for placement

Sponge API Version: 5.0.0

I have listened the ChangeBlockEvent.Place event and fetched the player by the event cause, but how could I get the item the player actually used for placement? It is known that the player has both main hand and off hand, so what I thought first is the following codes:

Optional<Player> playerOptional = event.getCause().first(Player.class);
if (playerOptional.isPresent())
{
    Player player = playerOptional.get();
    for (Transaction<BlockSnapshot> t : event.getTransactions())
    {
        ItemStack itemOfBlock = ItemStack.builder().fromBlockState(t.getFinal().getState()).build();
        Optional<ItemStack> stack = player.getItemInHand(HandTypes.MAIN_HAND).filter(itemOfBlock::equalTo);
        if (!stack.isPresent())
        {
            stack = player.getItemInHand(HandTypes.OFF_HAND).filter(itemOfBlock::equalTo);
        }
        if (stack.isPresent())
        {
            // do something
        }
    }
}

The codes are neither simple nor elegant and it could cause an error because the items and the blocks are not matched one-to-one (considering an item representing a sign matches two blocks! wall signs and standing signs), so I wonder if there is a better way to do this.

I have an issue about this on GitHub, though they seem to have closed it without solving it. For now, check InteractBlockEvent.Secondary (careful, it fires for each hand), cache the stack, and use it when the ChangeBlockEvent.Place fires.

1 Like