Skip to main content

Overview

Minestom’s event system provides a powerful, hierarchical event graph for handling all server events. The system is based on event nodes that can filter and propagate events to listeners.

Core Components

EventNode

Represents a single node in the event graph. A node can contain children and listeners, filtering events based on conditions before propagating them.
EventNode<T>
interface
Generic event node that accepts events of type T

Creating Event Nodes

// Accept any event type
EventNode<Event> node = EventNode.all("demo");

Node Methods

call
void
Calls an event starting from this node
callCancellable
void
Execute a cancellable event with a success callback
addListener
EventNode<T>
Adds a listener to this nodeReturns this for method chaining
removeListener
EventNode<T>
Removes a listener from this node
addChild
EventNode<T>
Adds a child nodeReturns this for method chaining
removeChild
EventNode<T>
Removes a child node
findChildren
List<EventNode<E>>
Locates all child nodes with the given name and type recursively
setPriority
EventNode<T>
Sets the priority of this node

EventListener

Represents an event listener (handler) that executes actions when events trigger.

Creating Listeners

// Create a basic listener
EventListener<PlayerLoginEvent> listener = EventListener.of(
    PlayerLoginEvent.class,
    event -> {
        System.out.println(event.getPlayer().getUsername() + " logged in");
    }
);

Builder Methods

filter
Builder<T>
Adds a filter condition - listener only executes if condition passes
ignoreCancelled
Builder<T>
Specifies whether to ignore cancelled events (default: true)
expireCount
Builder<T>
Removes listener after specified executions
expireWhen
Builder<T>
Expires listener when condition is met
handler
Builder<T>
Sets the handler function

GlobalEventHandler

Object containing all global event listeners. Accessible from MinecraftServer.getGlobalEventHandler().
GlobalEventHandler globalHandler = MinecraftServer.getGlobalEventHandler();

// Listen to player login globally
globalHandler.addListener(PlayerLoginEvent.class, event -> {
    System.out.println("Player joined: " + event.getPlayer().getUsername());
});

EventFilter

Represents a filter for specific event types based on a “handler” target.

Built-in Filters

EventFilter.ALL
EventFilter<Event, ?>
Accepts all event types
EventFilter.PLAYER
EventFilter<PlayerEvent, Player>
Filters player events, provides Player as handler
EventFilter.ENTITY
EventFilter<EntityEvent, Entity>
Filters entity events, provides Entity as handler
EventFilter.INSTANCE
EventFilter<InstanceEvent, Instance>
Filters instance events, provides Instance as handler
EventFilter.INVENTORY
EventFilter<InventoryEvent, AbstractInventory>
Filters inventory events, provides AbstractInventory as handler
EventFilter.ITEM
EventFilter<ItemEvent, ItemStack>
Filters item events, provides ItemStack as handler
EventFilter.BLOCK
EventFilter<BlockEvent, Block>
Filters block events, provides Block as handler

Custom Filters

EventFilter<MyEvent, MyHandler> customFilter = EventFilter.from(
    MyEvent.class,
    MyHandler.class,
    event -> event.getMyHandler()
);

Usage Examples

Hierarchical Event System

// Create a main event node
EventNode<Event> mainNode = EventNode.all("main");

// Create specialized child nodes
EventNode<PlayerEvent> playerNode = EventNode.type("players", EventFilter.PLAYER);
EventNode<EntityEvent> entityNode = EventNode.type("entities", EventFilter.ENTITY);

// Add children to main node
mainNode.addChild(playerNode);
mainNode.addChild(entityNode);

// Add listeners to child nodes
playerNode.addListener(PlayerMoveEvent.class, event -> {
    // Handle player movement
});

entityNode.addListener(EntityDeathEvent.class, event -> {
    // Handle entity death
});

// Register main node
MinecraftServer.getGlobalEventHandler().addChild(mainNode);

Instance-Specific Events

Instance instance = /* get instance */;

// Get the instance's event node
EventNode<InstanceEvent> instanceNode = instance.eventNode();

// Listen to events only in this instance
instanceNode.addListener(PlayerBlockBreakEvent.class, event -> {
    // Only called for blocks broken in this instance
});

Tag-Based Filtering

Tag<Boolean> PVP_TAG = Tag.Boolean("pvp_enabled");

// Create node that only accepts events from entities with the tag
EventNode<PlayerEvent> pvpNode = EventNode.tag(
    "pvp-zone",
    EventFilter.PLAYER,
    PVP_TAG,
    enabled -> enabled != null && enabled
);

pvpNode.addListener(PlayerDamageEvent.class, event -> {
    // Only called for players with pvp_enabled tag set to true
});
Event nodes are hierarchical - children only receive events that pass through their parent’s filters.

Build docs developers (and LLMs) love