Pumpkin-Docs/docs/en/plugin-dev/rust/events.md
2026-04-14 19:13:36 +02:00

110 lines
3.0 KiB
Markdown

# Writing a Event Handler
Event handlers are one of the main functions of plugins. They allow a plugin to tap into the
internal workings of the server and alter its behavior to perform some other action. For a
simple example, we will implement a handler for the `PlayerJoinEvent` and the `PlayerLeaveEvent`.
## Implementing an Event
Individual event handlers are just structs which implement the `EventHandler<E>` trait (where `E` is a specific event data).
### What are blocking events?
The Pumpkin plugin event system differentiates between two types of events: blocking and non-blocking. Each have their benefits:
#### Blocking events
```diff
Pros:
+ Can modify the event (like editing the join message)
+ Can cancel the event
+ Have a priority system
Cons:
- Are executed in sequence
- Can slow down the server if not implemented well
```
#### Non-blocking events
```diff
Pros:
+ Are executed concurrently
+ Are executed after all blocking events finish
+ Can still do some modifications (anything that is behind a Mutex or RwLock)
Cons:
- Cannot cancel the event
- Have no priority system
- Allow for less control over the event
```
### Writing a handler
Since our main aim here is to change the welcome message that the player sees when they join a server, we will be choosing the blocking event type with a normal priority.
:::code-group
```rs [lib.rs]
// [!code ++:20]
use pumpkin_plugin_api::{
Context, Plugin, PluginMetadata, Server,
events::{EventData, EventHandler, EventPriority, PlayerJoinEvent},
text::TextComponent,
};
use tracing::*;
struct MyJoinHandler;
impl EventHandler<PlayerJoinEvent> for MyJoinHandler {
fn handle<'a>(
&'a self,
server: Server,
mut event: EventData<PlayerJoinEvent>,
) -> EventData<PlayerJoinEvent> {
event.join_message = TextComponent::text("Hello, world!");
event
}
}
```
:::
**Explanation**:
- `struct MyJoinHandler;`: The struct for our event handler
- If the event is non-blocking, we still use the handle function, and return the event data. The event data will still be ignored.
### Registering the handler
Now that we have written the event handler, we need to tell the plugin to use it. We can do that by adding a single line into the `on_load` method:
:::code-group
```rs [lib.rs]
struct HelloPlugin;
impl Plugin for HelloPlugin {
fn new() -> Self {
HelloPlugin
}
fn metadata(&self) -> PluginMetadata {
// ...
}
fn on_load(&mut self, context: Context) -> pumpkin_plugin_api::Result<()> {
info!("Hello from the example plugin!");
context.register_event_handler(MyJoinHandler, EventPriority::Normal, true)?;
Ok(())
}
fn on_unload(&mut self, _context: Context) -> pumpkin_plugin_api::Result<()> {
info!("Example plugin unloaded. Goodbye!");
Ok(())
}
}
```
:::
Now if we build the plugin and join the server, we should see a "Hello, World!" message!
## Adding a leave event
As an exercise for the reader, try adding a PlayerLeaveEvent