Setting block type after cancelling block modify event does not work

Hello, I am trying to set the block type of a block after cancelling a ChangeBlockEvent.Break. The code runs and no errors are thrown, but the block has not changed. Here the code I am using(It is just for testing, ignore the unsafe code):

@Listener
public void myEvent(ChangeBlockEvent.Break event) {
    event.setCancelled(true);
    event.getTransactions().get(0).getFinal().getLocation().get().setBlockType(BlockTypes.BEDROCK);
}

Thanks for the help!

Cancelling the event causes the custom/final value of each Transaction be ignored. All of the transactions have their original BlockSnapshot restored.

Thanks! Do you know of any way I can prevent the items from dropping and change the block type without listening to a second event?

I think transaction.setValid(false) will cancel it…or something like that. I’m on my phone so I don’t know for sure

@TrenTech Unfortunately that still causes the same issues.


Here is the solution I went with:

@Listener
public void myEvent(ChangeBlockEvent.Break event) {
  Location<World> loc = event.getTransactions().get(0).getFinal().getLocation().get();
  event.getTransactions()
    .get(0)
    .setCustom(
      BlockSnapshot.builder()
      .from(loc)
      .blockState(
        BlockState.builder().blockType(BlockTypes.BEDROCK).build()
      )
      .build()
    );
}

I set a custom block transaction that overrides the existing transaction, and did not cancel the event.

1 Like

@Aaron1011 I’ve looked back at my initial code, but I am unsure why it doesn’t work. I’m not adding or modifying transactions, just setting the block type on a location. Does that somehow create a new transaction that my event then cancels? If so, why would the event cancel that?

At a guess.

It’s because of how block capturing works.

As the game is still in the same state machine as when it originally captured the blocks, any additional changes direct to the world are captured as if the game caused them in it’s current state.

e.g. a ChangeBlockEvent.break occurs when a player is breaking a block, the game knows this, and saves this context.

When you directly change blocks during that event, the capturing system see’s this as a side effect possibly caused by a mod, captures it, and throws the events again with similar causes to that of the original block break.

It’s possible to add extra stages into the capturing, so changes that happen on the events are considered differently, or get the plugin added to the cause, but considering that it currently isn’t that way I’ve only been assuming that it is intended behaviour.

This is how I imagine it:
You can listen for a DropItemEvent.Destruct, if it’s caused by the correct block, you can just spawn additional entities without adding them to the event. The game notices this, and throws the correct events for you as if that block always had a random chance to drop that. giving other plugins the chance to record that, or drop them later as appropriate.

1 Like