ClickInventoryEvent get clicked item

Hi.
I want to get the item that the player clicked in the ClickInventoryEvent.
I’ve come up with this code:

public void cancelClick(ClickInventoryEvent event) {
    System.out.println("Transaction = " + event.getCursorTransaction());
    System.out.println("Default = " + event.getCursorTransaction().getDefault());
    System.out.println("Final = " + event.getCursorTransaction().getFinal());
    System.out.println("Original = " + event.getCursorTransaction().getOriginal());
    System.out.println("Has item = " + event.getSlot().get().peek().isPresent());
    ...

This does’t work though.
“Has item” is true only for right click.
“Final” seems to give the correct item for both left and right clicks, but gives air (and not the actual item) for “shift + right click” and “shift + left click”.
So, what am I missing and how can I get the correct item on any click (left/right, with or without shift)?

Most Inventory Events fire AFTER the change happened because what can happen is so complex.

“Has item” is true only for right click.

Its true if the Slot is not empty after your action. Could also happen on a left-click with items on the cursor.
So if you left-click (with empty cursor) or shift-click (with enough space to move the item) the slot you clicked will usually be empty.

“Final” seems to give the correct item for both left and right clicks, but gives air (and not the actual item) for “shift + right click” and “shift + left click”.

The getFinal on the cursor transaction is the item that will be on your cursor after all plugins are done with events. You can modify this with setCustom(...)
getDefault is what vanilla would have done so if no plugin uses setCustom(..) getFinal() returns the same.
With shift click you dont change the item on your cursor so it stays empty.

So, what am I missing

event.getTransactions() gives you all slot transactions in the inventory (comes from the AffectSlotEvent)

So then if you care about the item in the clicked slot you can compare event.getSlot() with the slots in the slot transactions to find out what the item was in that slot before: slotTransaction.getOriginal()

1 Like

Thanks, I really missed event.getTransactions()!

Hey, one more question regarding inventories.
Could you please give me some advice on how to properly clear an inventory in ClickInventoryEvent?
I tried to do it the most straightforward way:

@Listener
public void onClick(ClickInventoryEvent event) {
    event.setCancelled(true);
    event.getTargetInventory().clear();
}

It almost works fine, except that the clicked item does not get cleared.
Is there a good solution to this?

Again Inventory Events are called after the change happened.
setCancelled(true) asks Sponge to revert it all after the event.
Thats why the affected slots are reverted to what they were originally.

So the solution here would be to clear() and set a custom cursortransaction (as the cursor is not part of the inventory and will not be cleared) and not cancel the event.

1 Like