Event System & Cancellation

The PotatoMC event system implements a type-safe publisher/observer pattern mirroring Bukkit/Paper API conventions.

1. Registering Event Handlers

Register event listeners in on_enable() via context.register_event(...):

use potato_api::event::{PlayerJoinEvent, BlockBreakEvent, Cancellable};
use potato_api::text::Component;

// 1. Listen to player joins
context.register_event(|event: &mut PlayerJoinEvent| {
    let name = event.player.name();
    let comp = Component::from_mini_message(&format!("<yellow>Welcome, <gold>{}</gold>!</yellow>", name));
    event.player.send_component(&comp);
});

// 2. Prevent breaking bedrock
context.register_event(|event: &mut BlockBreakEvent| {
    if event.block.block_type == "minecraft:bedrock" {
        event.set_cancelled(true);
        if let Some(ref player) = event.player {
            player.send_message("§cBedrock is indestructible!");
        }
    }
});

2. Event Priorities

Event listeners execute in strict priority order. The earlier an event handler executes, the sooner it can inspect or cancel an event:

  • 1. EventPriority::Lowest

    First to observe, useful for low-level modifications.

  • 2. EventPriority::Low
  • 3. EventPriority::Normal

    The default priority level.

  • 4. EventPriority::High
  • 5. EventPriority::Highest

    Runs right before action confirmation.

  • 6. EventPriority::Monitor

    Read-only observation; actions MUST NOT be altered here.

3. The Cancellable Trait

Events that can be prevented implement the Cancellable trait:

pub trait Cancellable {
    fn is_cancelled(&self) -> bool;
    fn set_cancelled(&mut self, cancelled: bool);
}

Calling event.set_cancelled(true) instructs PotatoMC to abort the underlying action (e.g. block breaking, teleportation, player chat, inventory interaction).

4. Complete 26-Event Catalog

IDEvent StructCancellableDescription & Fields
1ServerStartedEventNoServer is ready and accepting connections.
2ServerStoppingEventNoServer is initiating shutdown sequence.
3PlayerJoinEventNoPlayer spawned in world: player: Player.
4PlayerQuitEventNoPlayer disconnected: player: Player.
5PlayerChatEventYesPlayer sent message: player: Player, message: String.
6PlayerMoveEventYesPlayer movement: player: Player, from: Location, to: Location.
7PlayerInteractEventYesPlayer click: player: Player, clicked_block: Option<Block>, action: String.
8PlayerTeleportEventYesTeleportation: player: Player, from: Location, to: Location.
9PlayerToggleFlightEventYesFlight state toggled: player: Player, is_flying: bool.
10PlayerToggleSneakEventYesSneak state toggled: player: Player, is_sneaking: bool.
11PlayerToggleSprintEventYesSprint state toggled: player: Player, is_sprinting: bool.
12PlayerRespawnEventNoPlayer clicked respawn: player: Player, respawn_location: Location.
13BlockBreakEventYesBlock broken: player: Option<Player>, block: Block.
14BlockPlaceEventYesBlock placed: player: Player, block: Block, placed_against: Option<Block>.
15EntityDamageEventYesEntity damaged: entity: Entity, damage: f32, cause: String.
16EntityDeathEventNoEntity killed: entity: Entity, dropped_items: Vec<ItemStack>.
17EntitySpawnEventYesEntity spawning: entity: Entity, location: Location.
18ItemDropEventYesItem dropped by player: player: Player, item: ItemStack.
19ItemPickupEventYesItem collected: player: Player, item: ItemStack.
20InventoryOpenEventYesPlayer opened inventory: player: Player, title: String.
21InventoryCloseEventNoPlayer closed inventory: player: Player.
22InventoryClickEventYesPlayer clicked slot: player: Player, slot: usize, click_type: String.
23ChunkLoadEventNoChunk loaded into memory: x: i32, z: i32, world: String.
24ChunkUnloadEventYesChunk unloading: x: i32, z: i32, world: String.
25WorldSaveEventNoWorld chunk data flushed to disk: world: String.
26ServerTickEventNoMain server tick cycle (every 50ms): tick_number: u64.