Cancel BlockPlace event (doesn't work)

Hey,
I want to prevent players from placing blocks, if they don’t have the permissions for this action.
My code:

@Listener
    public void onBreakBlockEvent(PlaceBlockEvent event) {
            if(!player.hasPermission("break")) {
                event.setCancelled(true);
            }
    }

When I try to send messages to the player with player.sendMessage(), everything is okey, so my event works and there is nothing wrong when it comes to my player object :smile:

Greets

Make sure the method has the @Listener annotation. If your IDE can’t find it, grab the latest SpongeAPI and implementation.

I thought @Subscribe ?!

That’s all changed with the Event refactoring. You can take a look at the docs PR to see what the updated documentation should be.

Sorry, i forgot to add that to my snipped, but as I said, my Event works, so I didn’t forget to add @Listener

Okay, so you’re meaning that if you cancel the BlockPlaceEvent, it doesn’t revert the change.

Yes i read about it but was there an update on the API already ? Because the latest API is still 2.1.

Ok, how can I undo the change? So I want to prevent users without permissions from placing a block…

You could try removing the drops and replacing the broken block location with the broken block

Assuming cancelling is implemented properly, this should be handled for you.

Wait… now that I think about it, are you sure the event is being fired? It might not be implemented yet.

EDIT: It’s not implemented. A search on both the Sponge coremod and SpongeCommon doesn’t give any results for PlaceBlockEvent. That’s the problem. I’ve posted an issue on GitHub for it: https://github.com/SpongePowered/Sponge/issues/340

EDIT 2: Never mind. It is implemented.

Wait… You mean, that the PlaceBlockEvent is not implemented ? PlaceBlockEvent works for me. I just can not cancel the Event, but the event fires. Proof: I send a message to the player on every block place -> works!
So what do you mean?
Greets

You aren’t even using the player object from the event… Grab the Player from getCause().first(Player.class)

PlaceBlockEvent works fine for me in Sponge so the issue is on your end.

2 Likes

Hm, I’m afraid to do this, do you think this can cause some lags (because i have to get the player object everytime new, when the player places a block…)

Edit: Can you explain, why I do it wrong? I pass the player object to the class including the Listeners on playerjoin…

That’s the recommended way, and it’s a pretty cheap operation
https://github.com/SpongePowered/SpongeAPI/blob/master/src/main/java/org/spongepowered/api/event/cause/Cause.java#L197

That doesn’t make sense though. Remember, event handlers are fired every time that event occurs, sponge won’t call your method only for that player. It may be worth reading the Event docs https://docs.spongepowered.org/en/plugin/events.html

I know, that sponge does that for every player placing a block, but I don’t think, that it’s wrong to pass the object, when a player joins, because then I don’t have to get the object new when the event gets fired.

Or is my theory wrong?

You still have to check what caused the event, if it is indeed a player or not.
You could add a check in the beginning of the event handler to see whether the player matches the player you have in your class field.
something like:

@Listener
public void onPlaceBlockEvent(PlaceBlockEvent event) {
    Optional<Player> optPlayer = event.getCause().getFirst(Player.class);
    if (optPlayer.isPresent() && optPlayer.get().equals(this.player)) {
        // The event was caused by the player we're interested in
    } else {
        return; // Don't care, this event is not in our interest
    }
}

Okey, I understand you, but why does my method work (when I send a message to the player, which fired the event, the message goes to the right player)?

Because it’s the only player? I’m pretty sure (if I understand what you were doing) that the message would be sent to every player connected. If I’m wrong then I need to see more code to better understand what the situation is.

Thats the point. I tested this with 2 online players…
Wait a minute, I will test it again.

//Edit:
Okey, you are right (the logical way wins :slight_smile: )
I think, I tried this when I was using the event like you recommended it to me …

Would be great if you can help out with this question:
Is there a method to undo a block change (as we know it from multiple bukkit plugins, which can protect areas)? Or do I have to write my own method?

Thanks :smiley:

You would have to track all changes a player has made to be able revert them.

Dismissing/cancelling a block change when a player has insufficient rights is far easier.