Skip to main content

Overview

The event system in Pumpkin allows plugins to respond to game events. Events are dispatched through the PluginManager and handled by registered EventHandler implementations.

EventHandler Trait

pub trait EventHandler<E: Payload>: Send + Sync {
    fn handle<'a>(&'a self, server: &'a Arc<Server>, event: &'a E) -> BoxFuture<'a, ()> {
        Box::pin(async {})
    }

    fn handle_blocking<'a>(
        &'a self,
        server: &'a Arc<Server>,
        event: &'a mut E,
    ) -> BoxFuture<'a, ()> {
        Box::pin(async {})
    }
}

handle

Handles a non-blocking event (read-only access).
server
&Arc<Server>
required
Reference to the server instance
event
&E
required
Immutable reference to the event

handle_blocking

Handles a blocking event (can modify event data).
server
&Arc<Server>
required
Reference to the server instance
event
&mut E
required
Mutable reference to the event

EventPriority

pub enum EventPriority {
    Highest,
    High,
    Normal,
    Low,
    Lowest,
}
Events are executed in priority order. Lower priority values execute first, allowing higher priority events to override changes.
Highest
EventPriority
Executed last, can see/override all other handler changes
High
EventPriority
Executed after Normal handlers
Normal
EventPriority
Default priority level
Low
EventPriority
Executed before Normal handlers
Lowest
EventPriority
Executed first

Payload Trait

pub trait Payload: Send + Sync {
    fn get_name_static() -> &'static str where Self: Sized;
    fn get_name(&self) -> &'static str;
    fn as_any(&self) -> &dyn Any;
    fn as_any_mut(&mut self) -> &mut dyn Any;
}
All events must implement the Payload trait for type-safe event handling.

Cancellable Trait

pub trait Cancellable: Send + Sync {
    fn cancelled(&self) -> bool;
    fn set_cancelled(&mut self, cancelled: bool);
}
Events that can be cancelled implement this trait.

Event Types

Player Events

All player events are located in pumpkin::plugin::player::

PlayerJoinEvent

pub struct PlayerJoinEvent {
    pub player: Arc<Player>,
    pub join_message: TextComponent,
}
Fired when a player joins the server.
player
Arc<Player>
required
The player who joined
join_message
TextComponent
required
Join message to broadcast (can be modified in blocking handlers)
Example:
impl EventHandler<PlayerJoinEvent> for MyHandler {
    fn handle_blocking<'a>(
        &'a self,
        _server: &'a Arc<Server>,
        event: &'a mut PlayerJoinEvent,
    ) -> BoxFuture<'a, ()> {
        Box::pin(async move {
            event.join_message = TextComponent::text(format!(
                "Welcome {}!",
                event.player.gameprofile.name
            ));
        })
    }
}

PlayerLeaveEvent

pub struct PlayerLeaveEvent {
    pub player: Arc<Player>,
    pub leave_message: TextComponent,
}
Fired when a player leaves the server.

PlayerLoginEvent

pub struct PlayerLoginEvent {
    pub player: Arc<Player>,
    pub kick_message: TextComponent,
}
Fired when a player attempts to login. Can be cancelled to deny login. Example:
impl EventHandler<PlayerLoginEvent> for MyHandler {
    fn handle_blocking<'a>(
        &'a self,
        _server: &'a Arc<Server>,
        event: &'a mut PlayerLoginEvent,
    ) -> BoxFuture<'a, ()> {
        Box::pin(async move {
            if event.player.gameprofile.name == "BadPlayer" {
                event.set_cancelled(true);
                event.kick_message = TextComponent::text("You are banned");
            }
        })
    }
}

PlayerChatEvent

pub struct PlayerChatEvent {
    pub player: Arc<Player>,
    pub message: String,
}
Fired when a player sends a chat message. Can be cancelled.

PlayerMoveEvent

pub struct PlayerMoveEvent {
    pub player: Arc<Player>,
    pub from: Vector3<f64>,
    pub to: Vector3<f64>,
}
Fired when a player moves.

PlayerGamemodeChangeEvent

pub struct PlayerGamemodeChangeEvent {
    pub player: Arc<Player>,
    pub old_gamemode: GameMode,
    pub new_gamemode: GameMode,
}
Fired when a player’s gamemode changes. Can be cancelled.

Block Events

All block events are in pumpkin::plugin::block::

BlockBreakEvent

pub struct BlockBreakEvent {
    pub player: Arc<Player>,
    pub block: &'static Block,
    pub pos: BlockPos,
}
Fired when a player breaks a block. Can be cancelled.
player
Arc<Player>
required
The player breaking the block
block
&'static Block
required
The block being broken
pos
BlockPos
required
Position of the block

BlockPlaceEvent

pub struct BlockPlaceEvent {
    pub player: Arc<Player>,
    pub block: Block,
    pub pos: BlockPos,
}
Fired when a player places a block. Can be cancelled.

World Events

All world events are in pumpkin::plugin::world::

ChunkLoadEvent

pub struct ChunkLoadEvent {
    pub world: Arc<World>,
    pub chunk_pos: Vector2<i32>,
}
Fired when a chunk is loaded.

ChunkSaveEvent

pub struct ChunkSaveEvent {
    pub world: Arc<World>,
    pub chunk_pos: Vector2<i32>,
}
Fired when a chunk is saved.

Server Events

All server events are in pumpkin::plugin::server::

ServerBroadcastEvent

pub struct ServerBroadcastEvent {
    pub message: TextComponent,
    pub sender: TextComponent,
}
Fired when the server broadcasts a message.
message
TextComponent
required
The message being broadcast (can be modified)
sender
TextComponent
required
The sender of the message

Registering Event Handlers

use pumpkin::plugin::*;

struct MyEventHandler;

impl EventHandler<PlayerJoinEvent> for MyEventHandler {
    fn handle<'a>(&'a self, server: &'a Arc<Server>, event: &'a PlayerJoinEvent) -> BoxFuture<'a, ()> {
        Box::pin(async move {
            println!("Player joined: {}", event.player.gameprofile.name);
        })
    }
}

// In plugin's on_load:
context.register_event(
    Arc::new(MyEventHandler),
    EventPriority::Normal,
    false // non-blocking
).await;

Firing Events from Plugins

Plugins can fire custom events:
use pumpkin::plugin::*;

// Define custom event
#[derive(Clone)]
pub struct MyCustomEvent {
    pub data: String,
}

impl Payload for MyCustomEvent {
    fn get_name_static() -> &'static str {
        "MyCustomEvent"
    }
    
    fn get_name(&self) -> &'static str {
        Self::get_name_static()
    }
    
    fn as_any(&self) -> &dyn Any {
        self
    }
    
    fn as_any_mut(&mut self) -> &mut dyn Any {
        self
    }
}

// Fire the event
let event = MyCustomEvent {
    data: "Hello".to_string(),
};
let result = context.plugin_manager.fire(event).await;

Build docs developers (and LLMs) love