13 KiB
title, type, weight
| title | type | weight |
|---|---|---|
| Server Events | docs | 6 |
Events related to server lifecycle, plugins, and system operations.
Server Lifecycle Events
BootEvent
Fired when the server finishes booting up. This is a marker event with no fields.
Package: com.hypixel.hytale.server.core.event.events
{{< tabs items="Fields,Example" >}} {{< tab >}} This event has no fields. It is a simple notification that boot has completed. {{< /tab >}} {{< tab >}}
getEventRegistry().register(BootEvent.class, event -> {
getLogger().at(Level.INFO).log("Server boot complete!");
// Initialize post-boot features
initializeMetrics();
startBackgroundTasks();
openConnectionsToExternalServices();
});
{{< /tab >}} {{< /tabs >}}
ShutdownEvent
Fired when the server is shutting down. This is a marker event with priority constants.
Package: com.hypixel.hytale.server.core.event.events
{{< tabs items="Constants,Example" >}} {{< tab >}}
| Constant | Value | Description |
|---|---|---|
DISCONNECT_PLAYERS |
-48 | Priority for disconnecting players |
UNBIND_LISTENERS |
-40 | Priority for unbinding network listeners |
SHUTDOWN_WORLDS |
-32 | Priority for shutting down worlds |
Use these constants with EventPriority to order shutdown handlers.
{{< /tab >}}
{{< tab >}}
getEventRegistry().register(ShutdownEvent.class, event -> {
getLogger().at(Level.INFO).log("Server shutting down!");
// Perform cleanup
saveAllPlayerData();
closeExternalConnections();
flushMetrics();
});
// Use priority constants for ordering
getEventRegistry().register(
ShutdownEvent.DISCONNECT_PLAYERS,
ShutdownEvent.class,
event -> {
// Notify players before disconnect
Universe.get().getPlayers().forEach(player ->
player.sendMessage(Message.raw("Server shutting down!"))
);
}
);
{{< /tab >}} {{< /tabs >}}
{{< callout type="warning" >}} Important: Keep shutdown handlers fast and synchronous. The server may force-terminate if handlers take too long. {{< /callout >}}
Plugin Events
PluginSetupEvent
Fired when a plugin is being set up (before start).
Package: com.hypixel.hytale.server.core.event.events.plugin
{{< tabs items="Fields,Methods,Example" >}} {{< tab >}}
| Field | Type | Description |
|---|---|---|
| plugin | JavaPlugin |
The plugin being set up |
| pluginInfo | PluginInfo |
Plugin metadata |
| {{< /tab >}} | ||
| {{< tab >}} |
getPlugin()- Returns the plugin instancegetPluginInfo()- Returns plugin metadata {{< /tab >}} {{< tab >}}
getEventRegistry().register(PluginSetupEvent.class, event -> {
PluginInfo info = event.getPluginInfo();
getLogger().at(Level.INFO).log("Plugin setting up: " + info.getName() +
" v" + info.getVersion());
// Check for plugin dependencies
if (isDependencyPlugin(info.getName())) {
registerDependencyHooks(event.getPlugin());
}
});
{{< /tab >}} {{< /tabs >}}
PluginEnableEvent
Fired when a plugin is enabled.
Package: com.hypixel.hytale.server.core.event.events.plugin
{{< tabs items="Fields,Methods,Example" >}} {{< tab >}}
| Field | Type | Description |
|---|---|---|
| plugin | JavaPlugin |
The enabled plugin |
| {{< /tab >}} | ||
| {{< tab >}} |
getPlugin()- Returns the plugin instance {{< /tab >}} {{< tab >}}
getEventRegistry().register(PluginEnableEvent.class, event -> {
JavaPlugin plugin = event.getPlugin();
getLogger().at(Level.INFO).log("Plugin enabled: " + plugin.getName());
// Hook into other plugins
if (plugin.getName().equals("Economy")) {
hookEconomyPlugin(plugin);
}
});
{{< /tab >}} {{< /tabs >}}
PluginDisableEvent
Fired when a plugin is disabled.
Package: com.hypixel.hytale.server.core.event.events.plugin
{{< tabs items="Fields,Methods,Example" >}} {{< tab >}}
| Field | Type | Description |
|---|---|---|
| plugin | JavaPlugin |
The disabled plugin |
| {{< /tab >}} | ||
| {{< tab >}} |
getPlugin()- Returns the plugin instance {{< /tab >}} {{< tab >}}
getEventRegistry().register(PluginDisableEvent.class, event -> {
JavaPlugin plugin = event.getPlugin();
getLogger().at(Level.INFO).log("Plugin disabled: " + plugin.getName());
// Unhook from other plugins
if (plugin.getName().equals("Economy")) {
unhookEconomyPlugin();
}
});
{{< /tab >}} {{< /tabs >}}
Tick Events
ServerTickEvent
Fired every server tick (typically 20 times per second).
Package: com.hypixel.hytale.server.core.event.events.server
{{< tabs items="Fields,Methods,Example" >}} {{< tab >}}
| Field | Type | Description |
|---|---|---|
| tickNumber | long |
Current tick number |
| deltaTime | float |
Time since last tick (seconds) |
| {{< /tab >}} | ||
| {{< tab >}} |
getTickNumber()- Returns current tick countgetDeltaTime()- Returns delta time in seconds {{< /tab >}} {{< tab >}}
getEventRegistry().register(ServerTickEvent.class, event -> {
long tick = event.getTickNumber();
// Run every second (20 ticks)
if (tick % 20 == 0) {
updateScoreboards();
}
// Run every minute (1200 ticks)
if (tick % 1200 == 0) {
saveAutoSave();
cleanupExpiredData();
}
});
{{< /tab >}} {{< /tabs >}}
{{< callout type="warning" >}} Performance Critical: This event fires 20 times per second. Keep handlers extremely lightweight. Use tick counting for periodic tasks instead of running on every tick. {{< /callout >}}
Command Events
CommandExecuteEvent
{{< badge "Cancellable" >}}
Fired when a command is executed.
Package: com.hypixel.hytale.server.core.event.events.command
{{< tabs items="Fields,Methods,Example" >}} {{< tab >}}
| Field | Type | Description |
|---|---|---|
| sender | CommandSender |
Who executed the command |
| command | String |
Command name |
| args | String[] |
Command arguments |
| {{< /tab >}} | ||
| {{< tab >}} |
getSender()- Returns the command sendergetCommand()- Returns command namegetArgs()- Returns arguments arrayisCancelled()- Check if cancelledsetCancelled(boolean)- Cancel command {{< /tab >}} {{< tab >}}
getEventRegistry().register(CommandExecuteEvent.class, event -> {
CommandSender sender = event.getSender();
String command = event.getCommand();
// Log all commands
getLogger().at(Level.INFO).log(sender.getName() + " executed: /" + command +
" " + String.join(" ", event.getArgs()));
// Block certain commands for non-ops
if (command.equals("stop") && !sender.isOp()) {
event.setCancelled(true);
sender.sendMessage("You don't have permission!");
}
});
{{< /tab >}} {{< /tabs >}}
Practical Examples
Server Metrics Plugin
public class MetricsPlugin extends JavaPlugin {
private long startTime;
private long tickCount = 0;
private long lastTickTime;
@Override
public void start() {
// Track server boot
getEventRegistry().register(BootEvent.class, event -> {
startTime = System.currentTimeMillis();
lastTickTime = startTime;
getLogger().at(Level.INFO).log("Server boot complete, tracking metrics...");
});
// Calculate TPS
getEventRegistry().register(ServerTickEvent.class, event -> {
tickCount++;
// Calculate TPS every second
if (tickCount % 20 == 0) {
long now = System.currentTimeMillis();
long elapsed = now - lastTickTime;
double tps = 20000.0 / elapsed;
lastTickTime = now;
if (tps < 18.0) {
getLogger().warning("Low TPS: " + String.format("%.2f", tps));
}
}
});
// Save metrics on shutdown
getEventRegistry().register(ShutdownEvent.class, event -> {
long uptime = System.currentTimeMillis() - startTime;
saveMetrics(uptime, tickCount);
});
}
}
Plugin Dependency Manager
public class DependencyPlugin extends JavaPlugin {
private final Map<String, JavaPlugin> loadedDependencies = new HashMap<>();
private final Set<String> requiredPlugins = Set.of("Economy", "Permissions");
@Override
public void start() {
// Track plugin loading
getEventRegistry().register(PluginEnableEvent.class, event -> {
JavaPlugin plugin = event.getPlugin();
if (requiredPlugins.contains(plugin.getName())) {
loadedDependencies.put(plugin.getName(), plugin);
getLogger().at(Level.INFO).log("Dependency loaded: " + plugin.getName());
// Check if all dependencies are loaded
if (loadedDependencies.keySet().containsAll(requiredPlugins)) {
initializeDependentFeatures();
}
}
});
// Handle dependency unload
getEventRegistry().register(PluginDisableEvent.class, event -> {
JavaPlugin plugin = event.getPlugin();
if (loadedDependencies.remove(plugin.getName()) != null) {
getLogger().warning("Dependency unloaded: " + plugin.getName());
disableDependentFeatures();
}
});
}
}
Command Logging & Rate Limiting
public class CommandSecurityPlugin extends JavaPlugin {
private final Map<UUID, List<Long>> commandHistory = new HashMap<>();
private static final int MAX_COMMANDS_PER_SECOND = 5;
@Override
public void start() {
getEventRegistry().register(CommandExecuteEvent.class, event -> {
CommandSender sender = event.getSender();
// Only rate limit players
if (!(sender instanceof Player)) return;
Player player = (Player) sender;
UUID uuid = player.getUuid();
// Get command history
List<Long> history = commandHistory.computeIfAbsent(
uuid, k -> new ArrayList<>()
);
long now = System.currentTimeMillis();
// Remove old entries (older than 1 second)
history.removeIf(time -> now - time > 1000);
// Check rate limit
if (history.size() >= MAX_COMMANDS_PER_SECOND) {
event.setCancelled(true);
player.sendMessage("Too many commands! Please slow down.");
getLogger().warning("Rate limited: " + player.getDisplayName());
return;
}
// Record this command
history.add(now);
// Log to file
logCommand(player, event.getCommand(), event.getArgs());
});
// Cleanup on disconnect
getEventRegistry().register(PlayerDisconnectEvent.class, event -> {
commandHistory.remove(event.getPlayer().getUuid());
});
}
}
Scheduled Tasks Manager
public class SchedulerPlugin extends JavaPlugin {
private final List<ScheduledTask> tasks = new ArrayList<>();
@Override
public void start() {
// Schedule various tasks
scheduleTask("autosave", 6000, this::autoSave); // Every 5 minutes
scheduleTask("cleanup", 72000, this::cleanup); // Every hour
scheduleTask("broadcast", 12000, this::broadcast); // Every 10 minutes
// Execute tasks based on tick
getEventRegistry().register(ServerTickEvent.class, event -> {
long tick = event.getTickNumber();
for (ScheduledTask task : tasks) {
if (tick % task.interval() == 0) {
try {
task.runnable().run();
} catch (Exception e) {
getLogger().error("Task failed: " + task.name(), e);
}
}
}
});
}
private void scheduleTask(String name, int intervalTicks, Runnable runnable) {
tasks.add(new ScheduledTask(name, intervalTicks, runnable));
}
record ScheduledTask(String name, int interval, Runnable runnable) {}
}
Best Practices
{{< callout type="info" >}} Server Event Guidelines:
- Keep
ShutdownEventhandlers fast and reliable - Use tick counting in
ServerTickEventfor periodic tasks - Clean up resources in
PluginDisableEvent - Initialize cross-plugin features in
PluginEnableEvent - Log important command executions for auditing {{< /callout >}}
{{< callout type="error" >}}
Critical: Never perform blocking operations (I/O, network, database) directly in ServerTickEvent. Use async tasks instead.
{{< /callout >}}