Cancel ChangeBlockEvent.Place without cancel ItemStack modification

Hi,
The title says all. I’m trying to just cancel the block change and not the ItemStack change. I tried to invalidate block transations but it also cancel the holded item modification. If anyone know or think about a workaround, post it here :wink:

Its been a long time since i have needed to cancel that event with the itemstack in tacked. The problem is that event is fired after the itemstack is modified (it maybe in the cause - really can not remember).

But if i remember, I fixed the issue by “cancelling” a event before hand. I believe it was InteractBlockEvent.Secondary and checked that the item in the hand was a block. I believe sponge have added some methods to that event for checking if its a block as the item.

I can do some testing but it may take a while as im pretty busy.

What you could do is capture the snapshot before hand, then create a scheduled task for a few ticks later to reduce the itemstack total by 1 (With appropriate filters to check that the item stack was indeed canceled)

Yes, I thook about that but it seems to be a bit tricky. Is it really the best solution ?

Sorry I misread the “without”, it used to be that the event fired and if you cancelled it the itemstack would have still been modified. Anyway here is how I would do it (btw its tested)

@Listener
public void onBlockPlace(ChangeBlockEvent.Place event, @Root Player player){
    Optional<ItemStackSnapshot> opItem = event.getCause().getContext().get(EventContextKeys.USED_ITEM);
    if(opItem.isPresent()){
        if(player.get(Keys.GAME_MODE).get().equals(GameModes.CREATIVE)){
            return;
        }
        ItemStackSnapshot snapshot = null;
        if(opItem.get().getQuantity() == 1){
            snapshot = ItemStackSnapshot.NONE;
        }else{
            snapshot = ItemStack.builder().fromSnapshot(opItem.get()).quantity(opItem.get().getQuantity() - 1).build().createSnapshot();
        }
        for (Inventory sInv : player.getInventory().slots()){
            if(!sInv.peek().isPresent()){
                continue;
            }
            int compare = ItemStackComparators.ALL.compare(sInv.peek().get(), opItem.get().createStack());
            if(compare != 0){
                continue;
            }
            final ItemStackSnapshot snapshot1 = snapshot;
            Sponge.getScheduler().createTaskBuilder().execute(() -> sInv.set(snapshot1.createStack())).delayTicks(1).submit(Main.this);
            break;
        }
        event.setCancelled(true);
    }
}
1 Like