Understanding Minestom Events
Concept explanation of Minestom's event-driven architecture for handling server actions
java (17+)
2025-11-03
minestom
events
listeners
concepts
Description
Minestom uses an event-driven architecture where various server actions trigger events that can be listened to and handled by your code. This system allows you to intercept, modify, or cancel default behaviors.
Key Concepts
Event-Driven Architecture
Events are fired when specific actions occur in the server:
- Player actions: Join, quit, chat, move, interact
- Block actions: Place, break, interact
- Entity actions: Spawn, damage, death
- Server actions: Tick, startup, shutdown
- Packet actions: Incoming/outgoing network packets
Event Listeners
Event listeners are functions that respond to events:
- Registration: Register listeners with GlobalEventHandler
- Execution: Listeners are called when events fire
- Priority: Multiple listeners can handle the same event
- Cancellation: Events can be cancelled to prevent default behavior
- Modification: Event data can be modified before processing
Event Lifecycle
- Event creation: Event is created with relevant data
- Listener invocation: All registered listeners are called
- Event processing: Default behavior executes (if not cancelled)
- Event completion: Event is finished
Event Types
- PlayerSpawnEvent: When player joins/spawns
- PlayerDisconnectEvent: When player leaves
- PlayerChatEvent: When player sends message
- PlayerMoveEvent: When player moves
- PlayerBlockBreakEvent: When player breaks block
- PlayerBlockPlaceEvent: When player places block
- EntityDamageEvent: When entity takes damage
- EntityDeathEvent: When entity dies
- ServerTickMonitorEvent: Every server tick
Event Cancellation
Events can be cancelled:
- setCancelled(true): Prevents default behavior
- isCancelled(): Check if event is cancelled
- Cancelled events: Default behavior is skipped
Event Priority
Listeners can have priorities:
- HIGHEST: Executes first
- HIGH: Executes early
- NORMAL: Default priority
- LOW: Executes late
- LOWEST: Executes last
Event Modification
Events contain mutable data:
- Modify event properties: Change event data
- Access event context: Get players, blocks, entities
- Chain events: Trigger other events
Use Cases
- Permission systems: Check permissions before actions
- Chat filtering: Filter or modify chat messages
- Custom mechanics: Implement game-specific rules
- Logging: Log important events
- Integration: Connect with external systems
- Modification: Change default game behavior
Benefits
- Modularity: Separate concerns into listeners
- Flexibility: Easy to add/remove functionality
- Extensibility: Plugins can add their own events
- Control: Fine-grained control over server behavior
Best Practices
- Register listeners at startup
- Unregister listeners when no longer needed
- Use appropriate priorities
- Check event cancellation before processing
- Don’t block the event thread with long operations
- Handle exceptions gracefully
- Document event behavior
- Use event filters to reduce unnecessary processing
Code
// Get global event handlerGlobalEventHandler eventHandler = MinecraftServer.getGlobalEventHandler();// Register player join event listenereventHandler.addListener(PlayerSpawnEvent.class, event -> { // This code runs when a player joins if (event.getEntity() instanceof Player player) { player.sendMessage("Welcome to the server!"); }});// Register chat event with modificationeventHandler.addListener(PlayerChatEvent.class, event -> { // Modify chat format String message = event.getMessage(); Player player = event.getPlayer(); // Cancel if message contains certain words if (message.contains("spam")) { event.setCancelled(true); player.sendMessage("Your message was filtered"); return; } // Modify chat format event.setChatFormat((sender, text) -> Component.text("<" + sender.getUsername() + "> " + text) );});// Register block break event with cancellationeventHandler.addListener(PlayerBlockBreakEvent.class, event -> { Block block = event.getBlock(); // Prevent breaking certain blocks if (block.compare(Block.BEDROCK)) { event.setCancelled(true); event.getPlayer().sendMessage("You cannot break bedrock!"); }});// Register event with priorityeventHandler.addListener(PlayerMoveEvent.class, EventPriority.HIGH, event -> { // This listener runs early (HIGH priority) Player player = event.getPlayer(); // Check boundaries if (event.getNewPosition().y() < 0) { event.setCancelled(true); player.teleport(event.getPlayerPosition()); }});// Multiple listeners for same eventeventHandler.addListener(EntityDamageEvent.class, event -> { // First listener: Log damage System.out.println("Entity damaged: " + event.getDamage());});eventHandler.addListener(EntityDamageEvent.class, event -> { // Second listener: Modify damage if (event.getEntity() instanceof Player) { event.setDamage(event.getDamage() * 0.5f); // Reduce damage by 50% }});// Unregister listener (if you keep reference)EventListener<PlayerSpawnEvent> listener = event -> { // Listener code};eventHandler.addListener(PlayerSpawnEvent.class, listener);// Later...eventHandler.removeListener(PlayerSpawnEvent.class, listener);
Comments
No comments yet. Be the first to comment!
Please login to leave a comment.