[SOLVED] Having Trouble Clearing a Slot


#1

Hi there. I’m trying to clear the contents of a Slot, however, it doesn’t seem to work. I’ll provide code snippets below.

Here I have my listener. I put 1 ItemStack of Stone in this inventory when creating it. The debug message prints out the stone ItemStack correctly. However, the second debug message says that the Slot is actually empty. This would make sense if the event was called after the whole action had been processed, but the fact that we can cancel the event leads me to believe that this event is called before the action is ‘finalized’, meaning that the Slot shouldn’t be empty, correct?

@Listener
public void onClick(ClickInventoryEvent event, @First Player player){
    //This prints and shows that the transaction isn't empty. This prints the ItemStack correctly.
    Formatter.debug("Item: " + event.getCursorTransaction().getFinal().toString());

    //This prints that the Slot is empty, which makes no sense.
    Formatter.debug("Slot: " + event.getTransactions().get(0).getSlot().peek().isPresent());

    InventoryService manager = Sponge.getServiceManager().provide(InventoryService.class).get();
    if(manager.has(event.getTargetInventory())){
        manager.handleClick(event, player);
    }

Now here, this is where the action is processed. I’ve created a system to link an interface to call back on to a Slot. After checking the SlotIndex and validating that it should perform an action (I’ve debugged all of this part and it is finding and operating on the correct Slot as far as I can tell), this bit of code is called to remove the ItemStack from the Slot:

public void removeItem(int index){
    Iterator<Inventory> slots = inventory.slots().iterator();
    while(slots.hasNext()){
        Slot slot = (Slot) slots.next();
        if(slot.getInventoryProperty(SlotIndex.class).get().getValue() == index){
            Formatter.debug("Index");
            slot.clear();
        } else {
            slot.set(ItemStack.builder().itemType(ItemTypes.REDSTONE_BLOCK).build());
        }
    }
    /*inventory.slots().forEach(
            s -> s.getInventoryProperty(SlotIndex.class).filter(i -> i.getValue() == index).ifPresent(si -> s.clear())
    );*/
}

And this above part is the problem. Even though I know the Slot is being found, the slot.clear() isn’t actually clearing the slot. The Stone ItemStack remains there. I’ve also tried slot.set(ItemStack.NONE) and similarly slot.poll(). None of these actually clear the Slot as intended.

Any help would be greatly appreciated! Thank you.


#2

Update:
So apparently, from what I’ve now heard, the ItemStack when clicked is temporarily removed from the Slot, then returned to the Slot after the event if it’s canceled. I don’t quite understand this and it means that I’ll have to create a delayed task every time that event is fired just to clear the Slot that was selected. This seems like the wrong approach, but I can’t quite see any other approach with this Inventory API. Any ideas?


#3

For anyone that needs to clear a Slot when an ItemStack is clicked in it, here’s what I’ve figured out.

event.getCursorTransaction().setCustom(ItemStackSnapshot.NONE);

Doing this without canceling the event allows the ItemStack to be picked up by the cursor then it’s replaced with NONE. Therefore it appears to the Player that the Slot has been cleared.