5.8 KiB
5.8 KiB
title, type, weight
| title | type | weight |
|---|---|---|
| Event Priorities | docs | 2 |
Event priorities control the order in which event listeners are called. This is important when multiple plugins or handlers need to react to the same event.
Priority Values
Hytale provides five priority levels:
| Priority | Value | Description |
|---|---|---|
FIRST |
-21844 | Runs first, before all others |
EARLY |
-10922 | Runs early, after FIRST |
NORMAL |
0 | Default priority |
LATE |
10922 | Runs late, after NORMAL |
LAST |
21844 | Runs last, after all others |
{{< callout type="info" >}}
Lower values run first. The values are spread across the short range to allow for custom priorities between the standard levels.
{{< /callout >}}
Using EventPriority
With Enum
getEventRegistry().register(
EventPriority.EARLY,
PlayerConnectEvent.class,
event -> {
// This runs before NORMAL handlers
}
);
getEventRegistry().register(
EventPriority.LATE,
PlayerConnectEvent.class,
event -> {
// This runs after NORMAL handlers
}
);
With Custom Value
// Use a custom priority value (between -32768 and 32767)
short customPriority = -5000; // Between EARLY and NORMAL
getEventRegistry().register(
customPriority,
PlayerConnectEvent.class,
event -> {
// Custom priority handler
}
);
Execution Order
When an event is fired, handlers are called in priority order:
FIRST (-21844)
↓
EARLY (-10922)
↓
NORMAL (0) ← Default
↓
LATE (10922)
↓
LAST (21844)
Example
@Override
public void start() {
getEventRegistry().register(EventPriority.LAST, PlayerReadyEvent.class, event -> {
getLogger().at(Level.INFO).log("3. LAST handler");
});
getEventRegistry().register(EventPriority.FIRST, PlayerReadyEvent.class, event -> {
getLogger().at(Level.INFO).log("1. FIRST handler");
});
getEventRegistry().register(PlayerReadyEvent.class, event -> {
getLogger().at(Level.INFO).log("2. NORMAL handler (default)");
});
}
// Output when player is ready:
// 1. FIRST handler
// 2. NORMAL handler (default)
// 3. LAST handler
When to Use Each Priority
FIRST
Use for:
- Setting up event data before other handlers
- Logging/debugging that should see the original event
- Critical validation that must run before anything else
getEventRegistry().register(EventPriority.FIRST, PlayerChatEvent.class, event -> {
// Log original message before any filtering
logChat(event.getSender(), event.getContent());
});
EARLY
Use for:
- Modifications that other plugins should see
- Permission checks before regular handlers
- Data preprocessing
getEventRegistry().register(EventPriority.EARLY, PlayerChatEvent.class, event -> {
// Filter profanity before other plugins process the message
String filtered = filterProfanity(event.getContent());
event.setContent(filtered);
});
NORMAL
Use for:
- Standard event handling
- Most plugin functionality
- Default when priority doesn't matter
getEventRegistry().register(PlayerChatEvent.class, event -> {
// Standard chat processing
processMessage(event.getSender(), event.getContent());
});
LATE
Use for:
- Reactions to modifications made by other handlers
- Analytics/statistics gathering
- Secondary effects
getEventRegistry().register(EventPriority.LATE, PlayerChatEvent.class, event -> {
// Record the final message after all modifications
recordChatHistory(event.getSender(), event.getContent());
});
LAST
Use for:
- Final cleanup or overrides
- Monitoring cancellation status
- Logging final event state
getEventRegistry().register(EventPriority.LAST, PlayerChatEvent.class, event -> {
if (event.isCancelled()) {
getLogger().at(Level.INFO).log("Chat was cancelled by another plugin");
}
});
With Cancellable Events
Priority is especially important with cancellable events:
// FIRST handler might cancel
getEventRegistry().register(EventPriority.FIRST, BreakBlockEvent.class, event -> {
if (isProtectedArea(event.getTargetBlock())) {
event.setCancelled(true);
}
});
// NORMAL handler should check cancellation
getEventRegistry().register(BreakBlockEvent.class, event -> {
if (!event.isCancelled()) {
// Process block break
trackBlockBreak(event.getTargetBlock(), event.getBlockType());
}
});
// LAST handler for monitoring
getEventRegistry().register(EventPriority.LAST, BreakBlockEvent.class, event -> {
if (event.isCancelled()) {
logProtectedBlockAttempt(event.getTargetBlock());
}
});
Async Events and Priority
Async events also support priorities:
getEventRegistry().registerAsync(
EventPriority.EARLY,
PlayerChatEvent.class,
future -> future.thenApply(event -> {
// Early async processing
event.setContent(filterContent(event.getContent()));
return event;
})
);
getEventRegistry().registerAsync(
EventPriority.LATE,
PlayerChatEvent.class,
future -> future.thenApply(event -> {
// Late async processing - sees modified content
logFinalMessage(event.getSender(), event.getContent());
return event;
})
);
Best Practices
{{< callout type="tip" >}} Priority Guidelines:
- Use
FIRSTsparingly - only for logging or critical checks - Protection/permission plugins should use
EARLY - Feature plugins should use
NORMAL(default) - Analytics/logging should use
LATE - Use
LASTonly when you need to see the final event state {{< /callout >}}
{{< callout type="warning" >}} Avoid Priority Conflicts:
- Document your plugin's priority choices
- Check cancellation status at NORMAL and later priorities
- Don't rely on running "after" specific plugins {{< /callout >}}