--- title: Événements Serveur type: docs weight: 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 >}} ```java 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 >}} ```java 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 plugin - `getPluginInfo()` - Retourne les métadonnées du plugin {{< /tab >}} {{< tab >}} ```java 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 >}} ```java 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 >}} ```java 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 actuel - `getDeltaTime()` - Retourne le delta time en secondes {{< /tab >}} {{< tab >}} ```java 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 commande - `getCommand()` - Retourne le nom de la commande - `getArgs()` - Retourne le tableau d'arguments - `isCancelled()` - Vérifie si annulé - `setCancelled(boolean)` - Annule la commande {{< /tab >}} {{< tab >}} ```java 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 ```java 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 ```java public class DependencyPlugin extends JavaPlugin { private final Map loadedDependencies = new HashMap<>(); private final Set 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 ```java public class CommandSecurityPlugin extends JavaPlugin { private final Map> 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 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 ```java public class SchedulerPlugin extends JavaPlugin { private final List 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 `ShutdownEvent` rapides et fiables - Utilisez le comptage de ticks dans `ServerTickEvent` pour 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 >}}