This commit is contained in:
2026-01-20 20:33:59 +01:00
commit b16a40e431
583 changed files with 87339 additions and 0 deletions

View File

@@ -0,0 +1,246 @@
---
title: Event Priorities
type: docs
weight: 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
```java
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
```java
// 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
```java
@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
```java
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
```java
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
```java
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
```java
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
```java
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:
```java
// 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:
```java
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 `FIRST` sparingly - only for logging or critical checks
- Protection/permission plugins should use `EARLY`
- Feature plugins should use `NORMAL` (default)
- Analytics/logging should use `LATE`
- Use `LAST` only 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 >}}