6.5 KiB
6.5 KiB
title, type, weight
| title | type | weight |
|---|---|---|
| Cancellable Events | docs | 3 |
Some events implement the ICancellable interface, allowing you to prevent the default game behavior.
The ICancellable Interface
public interface ICancellable {
boolean isCancelled();
void setCancelled(boolean cancelled);
}
ECS Cancellable Events
ECS events use a similar interface ICancellableEcsEvent:
public interface ICancellableEcsEvent {
boolean isCancelled();
void setCancelled(boolean cancelled);
}
Cancelling Events
getEventRegistry().register(BreakBlockEvent.class, event -> {
Vector3i position = event.getTargetBlock();
if (isProtectedArea(position)) {
event.setCancelled(true);
// Note: BreakBlockEvent doesn't have direct player access
// Use ECS components if you need to message the player
}
});
Checking Cancellation Status
getEventRegistry().register(EventPriority.LATE, BreakBlockEvent.class, event -> {
if (event.isCancelled()) {
// Another handler cancelled this event
return;
}
// Process the event
recordBlockBreak(event.getTargetBlock(), event.getBlockType());
});
Common Cancellable Events
Player Events
| Event | Cancel Effect |
|---|---|
PlayerSetupConnectEvent |
Prevents player from connecting |
PlayerChatEvent |
Prevents message from being sent |
PlayerMouseButtonEvent |
Prevents mouse button action |
PlayerInteractEvent |
Prevents interaction (deprecated) |
ECS Block Events
| Event | Cancel Effect |
|---|---|
BreakBlockEvent |
Prevents block from being broken |
PlaceBlockEvent |
Prevents block from being placed |
DamageBlockEvent |
Prevents damage to block |
UseBlockEvent.Pre |
Prevents block use action |
Other ECS Events
| Event | Cancel Effect |
|---|---|
DropItemEvent |
Prevents item from being dropped |
CraftRecipeEvent |
Prevents crafting |
Best Practices
Check Before Acting
Always check isCancelled() before performing actions:
getEventRegistry().register(BreakBlockEvent.class, event -> {
// Check if already cancelled
if (event.isCancelled()) {
return;
}
// Your logic here
if (shouldPrevent(event.getTargetBlock())) {
event.setCancelled(true);
}
});
Use Appropriate Priority
// Protection plugins should use EARLY
getEventRegistry().register(EventPriority.EARLY, BreakBlockEvent.class, event -> {
if (isProtected(event.getTargetBlock())) {
event.setCancelled(true);
}
});
// Feature plugins should respect cancellation
getEventRegistry().register(EventPriority.NORMAL, BreakBlockEvent.class, event -> {
if (!event.isCancelled()) {
giveBlockReward(event.getTargetBlock());
}
});
// Logging should use LATE
getEventRegistry().register(EventPriority.LATE, BreakBlockEvent.class, event -> {
logBlockBreakAttempt(event.getTargetBlock(), event.isCancelled());
});
Provide Feedback with Chat Events
When cancelling chat events, you can notify the player:
// Note: PlayerChatEvent has String key, use registerAsyncGlobal()
getEventRegistry().registerAsyncGlobal(PlayerChatEvent.class, future -> {
return future.thenApply(event -> {
if (containsBadWord(event.getContent())) {
event.setCancelled(true);
// Send message via PlayerRef (PlayerRef.sendMessage() works)
event.getSender().sendMessage(Message.raw("Please don't use that word!"));
}
return event;
});
});
Uncancelling Events
You can also uncancel an event that was previously cancelled:
getEventRegistry().register(EventPriority.LATE, BreakBlockEvent.class, event -> {
// Override cancellation for certain block types
if (event.isCancelled() && event.getBlockType().getId().equals("temporary_block")) {
event.setCancelled(false);
}
});
{{< callout type="warning" >}} Uncancelling events can cause conflicts with other plugins. Use sparingly and document this behavior. {{< /callout >}}
Example: Connection Whitelist
public class WhitelistPlugin extends JavaPlugin {
private final Set<UUID> whitelist = new HashSet<>();
@Override
public void start() {
// Cancel connection for non-whitelisted players
getEventRegistry().register(PlayerSetupConnectEvent.class, event -> {
if (!whitelist.contains(event.getUuid())) {
event.setCancelled(true);
event.setReason("You are not whitelisted on this server!");
}
});
}
public void addToWhitelist(UUID uuid) {
whitelist.add(uuid);
}
public void removeFromWhitelist(UUID uuid) {
whitelist.remove(uuid);
}
}
Example: Chat Filter
public class ChatFilterPlugin extends JavaPlugin {
private final Set<String> bannedWords = new HashSet<>();
@Override
public void start() {
loadBannedWords();
// Note: PlayerChatEvent has String key, use registerAsyncGlobal()
getEventRegistry().registerAsyncGlobal(PlayerChatEvent.class, future -> {
return future.thenApply(event -> {
String message = event.getContent().toLowerCase();
for (String banned : bannedWords) {
if (message.contains(banned)) {
event.setCancelled(true);
// Send message via PlayerRef
event.getSender().sendMessage(Message.raw("Your message was blocked!"));
break;
}
}
return event;
});
});
}
}
Example: Block Protection
public class ProtectionPlugin extends JavaPlugin {
private final Set<Vector3i> protectedBlocks = new HashSet<>();
@Override
public void start() {
// Register at EARLY to cancel before other plugins process
getEventRegistry().register(EventPriority.EARLY, BreakBlockEvent.class, event -> {
if (protectedBlocks.contains(event.getTargetBlock())) {
event.setCancelled(true);
}
});
getEventRegistry().register(EventPriority.EARLY, PlaceBlockEvent.class, event -> {
if (isProtectedArea(event.getTargetBlock())) {
event.setCancelled(true);
}
});
}
private boolean isProtectedArea(Vector3i pos) {
// Check if position is in a protected region
return false;
}
}