14 KiB
title, type, weight
| title | type | weight |
|---|---|---|
| Événements Serveur | docs | 6 |
Événements liés au cycle de vie du serveur, aux plugins et aux opérations système.
Événements du Cycle de Vie du Serveur
BootEvent
Déclenché quand le serveur finit de démarrer. C'est un événement marqueur sans champs.
Package : com.hypixel.hytale.server.core.event.events
{{< tabs items="Champs,Exemple" >}} {{< tab >}} Cet événement n'a pas de champs. C'est une simple notification que le démarrage est terminé. {{< /tab >}} {{< tab >}}
getEventRegistry().register(BootEvent.class, event -> {
getLogger().at(Level.INFO).log("Démarrage du serveur terminé !");
// Initialiser les fonctionnalités post-démarrage
initializeMetrics();
startBackgroundTasks();
openConnectionsToExternalServices();
});
{{< /tab >}} {{< /tabs >}}
ShutdownEvent
Déclenché quand le serveur s'arrête. C'est un événement marqueur avec des constantes de priorité.
Package : com.hypixel.hytale.server.core.event.events
{{< tabs items="Constantes,Exemple" >}} {{< tab >}}
| Constante | Valeur | Description |
|---|---|---|
DISCONNECT_PLAYERS |
-48 | Priorité pour déconnecter les joueurs |
UNBIND_LISTENERS |
-40 | Priorité pour délier les listeners réseau |
SHUTDOWN_WORLDS |
-32 | Priorité pour arrêter les mondes |
Utilisez ces constantes avec EventPriority pour ordonner les handlers d'arrêt.
{{< /tab >}}
{{< tab >}}
getEventRegistry().register(ShutdownEvent.class, event -> {
getLogger().at(Level.INFO).log("Arrêt du serveur !");
// Effectuer le nettoyage
saveAllPlayerData();
closeExternalConnections();
flushMetrics();
});
// Utiliser les constantes de priorité pour l'ordre
getEventRegistry().register(
ShutdownEvent.DISCONNECT_PLAYERS,
ShutdownEvent.class,
event -> {
// Notifier les joueurs avant la déconnexion
Universe.get().getPlayers().forEach(player ->
player.sendMessage(Message.raw("Le serveur s'arrête !"))
);
}
);
{{< /tab >}} {{< /tabs >}}
{{< callout type="warning" >}} Important : Gardez les handlers d'arrêt rapides et synchrones. Le serveur peut forcer l'arrêt si les handlers prennent trop de temps. {{< /callout >}}
Événements de Plugin
PluginSetupEvent
Déclenché quand un plugin est en cours de configuration (avant le démarrage).
Package : com.hypixel.hytale.server.core.event.events.plugin
{{< tabs items="Champs,Méthodes,Exemple" >}} {{< tab >}}
| Champ | Type | Description |
|---|---|---|
| plugin | JavaPlugin |
Le plugin en configuration |
| pluginInfo | PluginInfo |
Métadonnées du plugin |
| {{< /tab >}} | ||
| {{< tab >}} |
getPlugin()- Retourne l'instance du plugingetPluginInfo()- Retourne les métadonnées du plugin {{< /tab >}} {{< tab >}}
getEventRegistry().register(PluginSetupEvent.class, event -> {
PluginInfo info = event.getPluginInfo();
getLogger().at(Level.INFO).log("Configuration du plugin : " + info.getName() +
" v" + info.getVersion());
// Vérifier les dépendances du plugin
if (isDependencyPlugin(info.getName())) {
registerDependencyHooks(event.getPlugin());
}
});
{{< /tab >}} {{< /tabs >}}
PluginEnableEvent
Déclenché quand un plugin est activé.
Package : com.hypixel.hytale.server.core.event.events.plugin
{{< tabs items="Champs,Méthodes,Exemple" >}} {{< tab >}}
| Champ | Type | Description |
|---|---|---|
| plugin | JavaPlugin |
Le plugin activé |
| {{< /tab >}} | ||
| {{< tab >}} |
getPlugin()- Retourne l'instance du plugin {{< /tab >}} {{< tab >}}
getEventRegistry().register(PluginEnableEvent.class, event -> {
JavaPlugin plugin = event.getPlugin();
getLogger().at(Level.INFO).log("Plugin activé : " + plugin.getName());
// Se connecter à d'autres plugins
if (plugin.getName().equals("Economy")) {
hookEconomyPlugin(plugin);
}
});
{{< /tab >}} {{< /tabs >}}
PluginDisableEvent
Déclenché quand un plugin est désactivé.
Package : com.hypixel.hytale.server.core.event.events.plugin
{{< tabs items="Champs,Méthodes,Exemple" >}} {{< tab >}}
| Champ | Type | Description |
|---|---|---|
| plugin | JavaPlugin |
Le plugin désactivé |
| {{< /tab >}} | ||
| {{< tab >}} |
getPlugin()- Retourne l'instance du plugin {{< /tab >}} {{< tab >}}
getEventRegistry().register(PluginDisableEvent.class, event -> {
JavaPlugin plugin = event.getPlugin();
getLogger().at(Level.INFO).log("Plugin désactivé : " + plugin.getName());
// Se déconnecter des autres plugins
if (plugin.getName().equals("Economy")) {
unhookEconomyPlugin();
}
});
{{< /tab >}} {{< /tabs >}}
Événements de Tick
ServerTickEvent
Déclenché à chaque tick serveur (typiquement 20 fois par seconde).
Package : com.hypixel.hytale.server.core.event.events.server
{{< tabs items="Champs,Méthodes,Exemple" >}} {{< tab >}}
| Champ | Type | Description |
|---|---|---|
| tickNumber | long |
Numéro du tick actuel |
| deltaTime | float |
Temps depuis le dernier tick (secondes) |
| {{< /tab >}} | ||
| {{< tab >}} |
getTickNumber()- Retourne le compte de ticks actuelgetDeltaTime()- Retourne le delta time en secondes {{< /tab >}} {{< tab >}}
getEventRegistry().register(ServerTickEvent.class, event -> {
long tick = event.getTickNumber();
// Exécuter toutes les secondes (20 ticks)
if (tick % 20 == 0) {
updateScoreboards();
}
// Exécuter toutes les minutes (1200 ticks)
if (tick % 1200 == 0) {
saveAutoSave();
cleanupExpiredData();
}
});
{{< /tab >}} {{< /tabs >}}
{{< callout type="warning" >}} Performance Critique : Cet événement se déclenche 20 fois par seconde. Gardez les handlers extrêmement légers. Utilisez le comptage de ticks pour les tâches périodiques au lieu de s'exécuter à chaque tick. {{< /callout >}}
Événements de Commande
CommandExecuteEvent
{{< badge "Annulable" >}}
Déclenché quand une commande est exécutée.
Package : com.hypixel.hytale.server.core.event.events.command
{{< tabs items="Champs,Méthodes,Exemple" >}} {{< tab >}}
| Champ | Type | Description |
|---|---|---|
| sender | CommandSender |
Qui a exécuté la commande |
| command | String |
Nom de la commande |
| args | String[] |
Arguments de la commande |
| {{< /tab >}} | ||
| {{< tab >}} |
getSender()- Retourne l'expéditeur de la commandegetCommand()- Retourne le nom de la commandegetArgs()- Retourne le tableau d'argumentsisCancelled()- Vérifie si annulésetCancelled(boolean)- Annule la commande {{< /tab >}} {{< tab >}}
getEventRegistry().register(CommandExecuteEvent.class, event -> {
CommandSender sender = event.getSender();
String command = event.getCommand();
// Logger toutes les commandes
getLogger().at(Level.INFO).log(sender.getName() + " a exécuté : /" + command +
" " + String.join(" ", event.getArgs()));
// Bloquer certaines commandes pour les non-ops
if (command.equals("stop") && !sender.isOp()) {
event.setCancelled(true);
sender.sendMessage("Vous n'avez pas la permission !");
}
});
{{< /tab >}} {{< /tabs >}}
Exemples Pratiques
Plugin de Métriques Serveur
public class MetricsPlugin extends JavaPlugin {
private long startTime;
private long tickCount = 0;
private long lastTickTime;
@Override
public void start() {
// Suivre le démarrage du serveur
getEventRegistry().register(BootEvent.class, event -> {
startTime = System.currentTimeMillis();
lastTickTime = startTime;
getLogger().at(Level.INFO).log("Démarrage terminé, suivi des métriques...");
});
// Calculer les TPS
getEventRegistry().register(ServerTickEvent.class, event -> {
tickCount++;
// Calculer les TPS toutes les secondes
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("TPS faibles : " + String.format("%.2f", tps));
}
}
});
// Sauvegarder les métriques à l'arrêt
getEventRegistry().register(ShutdownEvent.class, event -> {
long uptime = System.currentTimeMillis() - startTime;
saveMetrics(uptime, tickCount);
});
}
}
Gestionnaire de Dépendances de Plugins
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() {
// Suivre le chargement des plugins
getEventRegistry().register(PluginEnableEvent.class, event -> {
JavaPlugin plugin = event.getPlugin();
if (requiredPlugins.contains(plugin.getName())) {
loadedDependencies.put(plugin.getName(), plugin);
getLogger().at(Level.INFO).log("Dépendance chargée : " + plugin.getName());
// Vérifier si toutes les dépendances sont chargées
if (loadedDependencies.keySet().containsAll(requiredPlugins)) {
initializeDependentFeatures();
}
}
});
// Gérer le déchargement de dépendance
getEventRegistry().register(PluginDisableEvent.class, event -> {
JavaPlugin plugin = event.getPlugin();
if (loadedDependencies.remove(plugin.getName()) != null) {
getLogger().warning("Dépendance déchargée : " + plugin.getName());
disableDependentFeatures();
}
});
}
}
Journalisation & Limitation de Débit des Commandes
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();
// Ne limiter que les joueurs
if (!(sender instanceof Player)) return;
Player player = (Player) sender;
UUID uuid = player.getUuid();
// Obtenir l'historique des commandes
List<Long> history = commandHistory.computeIfAbsent(
uuid, k -> new ArrayList<>()
);
long now = System.currentTimeMillis();
// Supprimer les anciennes entrées (plus d'1 seconde)
history.removeIf(time -> now - time > 1000);
// Vérifier la limite de débit
if (history.size() >= MAX_COMMANDS_PER_SECOND) {
event.setCancelled(true);
player.sendMessage("Trop de commandes ! Veuillez ralentir.");
getLogger().warning("Limité : " + player.getDisplayName());
return;
}
// Enregistrer cette commande
history.add(now);
// Logger dans un fichier
logCommand(player, event.getCommand(), event.getArgs());
});
// Nettoyer à la déconnexion
getEventRegistry().register(PlayerDisconnectEvent.class, event -> {
commandHistory.remove(event.getPlayer().getUuid());
});
}
}
Gestionnaire de Tâches Planifiées
public class SchedulerPlugin extends JavaPlugin {
private final List<ScheduledTask> tasks = new ArrayList<>();
@Override
public void start() {
// Planifier diverses tâches
scheduleTask("autosave", 6000, this::autoSave); // Toutes les 5 minutes
scheduleTask("cleanup", 72000, this::cleanup); // Toutes les heures
scheduleTask("broadcast", 12000, this::broadcast); // Toutes les 10 minutes
// Exécuter les tâches selon le 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("Tâche échouée : " + 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) {}
}
Bonnes Pratiques
{{< callout type="info" >}} Directives pour les Événements Serveur :
- Gardez les handlers de
ShutdownEventrapides et fiables - Utilisez le comptage de ticks dans
ServerTickEventpour les tâches périodiques - Nettoyez les ressources dans
PluginDisableEvent - Initialisez les fonctionnalités inter-plugins dans
PluginEnableEvent - Loggez les exécutions de commandes importantes pour l'audit {{< /callout >}}
{{< callout type="error" >}}
Critique : Ne jamais effectuer d'opérations bloquantes (I/O, réseau, base de données) directement dans ServerTickEvent. Utilisez des tâches asynchrones à la place.
{{< /callout >}}