# 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` 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 for MyJoinHandler { fn handle<'a>( &'a self, server: Server, mut event: EventData, ) -> EventData { 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