BukkitWiki

Welcome to the BukkitWiki!

This Wiki is home to Bukkit's documentation and regulations surrounding the Bukkit Project and it's services. Want to help out? We would love to have you! Signup to get started!

READ MORE

BukkitWiki
Advertisement

Les bases[]

L'api bukkit dispose d'un système d'évènements permettant aux plugins d'écouter et de réagir à ce qui se passe sur le serveur. Cette référence à pour but d'aller plus loin que le tutoriel général, en expliquant chaque détail et chaque fonctionnalité de ce système d'évènements.

Listener[]

L'écoute des évènements passe par l'interface Listener. Il vous faut donc une classe qui implémente cette interface. Comme pour les commandes, si vous écoutez peu d'évènements et que vous faites des choses simples, vous pouvez tout à fait utiliser votre classe principale, comme ceci:

public class Plugin extends JavaPlugin implements Listener {
}


Mais si vous avez plus d'évènements et si ils sont assez longs, il est préférable de créer une classe à part, comme cela:

public class PluginListener implements Listener {
}
Lightbulb Note: N'oubliez pas d'importer org.bukkit.event.Listener si votre IDE ne le fait pas tout seul

La méthode onXXX(Event)[]

L'interface Listener ne propose pas de méthodes toutes prêtes pour écouter les évènements du serveur. C'est à vous de créer une méthode dans votre Listener pour chaque évènement que vous voulez écouter.
Ces méthodes doivent être de la forme suivante, et doivent comporter l'annotation @EventHandler:

@EventHandler
public void onXXX(Event e) {
    //Action à effectuer quand l'évènement e survient
}
  • onXXX: le nom de la méthode devrait être "on" suivi du nom de l'évènement, par exemple "onPlayerJoin"
  • Event: la classe de l'évènement à écouter. Tous les évènement sont listés ici

L'enregistrement[]

Enregistrement du Listener[]

Ce n'est pas tout ! Pour que le serveur appelle votre méthode à chaque fois que l'évènement correspondant survient, il faut le lui dire lors du lancement de votre plugin. Pour cela on passe par le PluginManager et on utilise registerEvents(Listener, JavaPlugin):

@Override
public void onEnable() {
   Listener l = new PluginListener();
   PluginManager pm = getServer().getPluginManager();
   pm.registerEvents(l, this);
}


Si vous utilisez votre classe principale en tant que Listener, faites simplement:

@Override
public void onEnable() {
   PluginManager pm = getServer().getPluginManager();
   pm.registerEvents(this, this);
}


Enregistrement dans le Listener[]

Vous avez vu comment enregistrer votre Listener dans le onEnable() de votre plugin, mais sachez que vous pouvez aussi enregistrer le Listener directement dans son constructeur !

public class PluginListener implements Listener {
   public PluginListener(Plugin p) {//Constructeur du Listener, avec comme paramètre la classe principale du plugin
      PluginManager pm = p.getServer().getPluginManager();
      pm.registerEvents(this, p);
   }
}

Vous n'avez alors plus qu'a créer une nouvelle instance du Listener au lancement de votre plugin:

@Override
public void onEnable() {
   Listener l = new PluginListener(this);
}


Exemple[]

Classe qui implémente Listener:

import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;

public class PluginListener implements Listener {
   @EvantHandler
   public void onPlayerJoin(PlayerJoinEvent e) {//PlayerJoinEvent est l'évènement de connexion d'un joueur sur le serveur
      Player p = e.getPlayer();//On récupère le joueur qui vient de se connecter à partir de l'évènement
      p.sendMessage("Bienvenue sur le serveur !");//On lui envoie un message
   }
}


Classe principale du plugin:

import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.plugin.PluginManager;
import org.bukkit.event.Listener;

public class Plugin extends JavaPlugin {
   @Override
   public void onEnable() {
      Listener l = new PluginListener();//On crée une instance de notre classe qui implémente Listener
      PluginManager pm = getServer().getPluginManager();//On récupère le PluginManager du serveur
      pm.registerEvents(l, this);//On enregistre notre instance de Listener et notre plugin auprès du PluginManager
   }
}


Événements annulables[]

Certain évènements bukkit implémentent l'interface Cancellable et peuvent être annulés. Si un évènement est annulé rien ne se passera sur le serveur.

Annuler un évènement[]

Vous pouvez annuler un évènement avec sa méthode setCancelled(boolean):

@EventHandler
public void onEvent(Event e) {
    e.setCancelled(true);//On annule cet évènement
}


Ne pas écouter les évènements annulés[]

Par défaut, votre méthode d'écoute sera appelée même si l'évènement est annulé avant. Pour n'être notifié que des évènement qui n'ont pas été annulés, ajoutez le paramètre ignoreCancelled à l'annotation @EventHandler:

@EventHandler(ignoreCancelled = true)


Priorité d'écoute[]

Il y'a 6 priorité pour le système d'évènements:

  • EventPriority.LOWEST
  • EventPriority.LOW
  • EventPriority.NORMAL
  • EventPriority.HIGH
  • EventPriority.HIGHEST
  • EventPriority.MONITOR

Lorsqu'un évènement survient, Craftbukkit appelle les méthodes d'écoute qui ont une faible priorité en premier, et celle qui ont une forte priorité en dernier, afin que ces dernières aient le dernier mot sur le sort de l'évènement (notamment s'il est annulé ou pas). Par défaut la priorité est NORMAL.

Pour définir cette priorité, ajoutez le paramètre priority à l'annotation @EventHandler:

@EventHandler(priority = EventPriority.HIGH)//Mettez la priorité que vous voulez
Lightbulb Note: La priorité MONITOR ne devrait être utilisé QUE si on ne modifie PAS l'évènement (pas d'annulation, pas de modification). Elle existe pour permettre à des plugins de voir ce qu'il se passe vraiment, pas pour avoir le dernier mot.


Arrêter l'écoute[]

Il est facilement possible d'arrêter d'écouter un/des évènement(s) grâce à la classe HandlerList.

D'un évènement particulier[]

Pour arrêter d'écouter un évènement particulier, récupérez le HandlerList de sa classe et appelez la méthode unregister avec comme paramètre l'instance de votre plugin.

Event.getHandlerList().unregister(plugin);// Remplacez Event par la classe de l'évènement que vous voulez arrêter d'écouter
Lightbulb Note: Vous pouvez aussi passer un Listener comme paramètre, au lieu du plugin, pour arrêter l'écoute uniquement avec ce Listener.

Du plugin[]

Pour arrêter d'écouter tous les événements, appelez la méthode statique unregisterAll de HandlerList:

HandlerList.unregisterAll(plugin);
Lightbulb Note: Là aussi vous pouvez passer un Listener comme paramètre, au lieu du plugin, pour arrêter l'écoute uniquement avec ce Listener.


Évènements personnalisés[]

Vous pouvez créer vos propres évènements, et les utiliser exactement comme les évènements "officiels".

Création[]

Il faut respecter le standard des évènements bukkit: une classe qui hérite de Event et un HandlerList statique et accessible.

import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;

public class MonEvent extends Event {
    private static final HandlerList handlers = new HandlerList();
 
    @Override //La classe Event nous oblige à surcharger la méthode getHandler()
    public HandlerList getHandlers() {
        return handlers;
    }
 
    public static HandlerList getHandlerList() {
        return handlers;
    }
}


Le rendre annulable[]

Pour l'instant, votre évènement n'est pas annulable: il ne peut pas être annulé. Pour le rendre annulable, il faut qu'il implémente l'interface Cancellable:

public class MonEvent extends Event implements Cancellable {
    private static final HandlerList handlers = new HandlerList();
    private boolean cancelled = false;//Si l'évènement est annulé ou non. Par défaut non
 
    @Override
    public HandlerList getHandlers() {
        return handlers;
    }
 
    public static HandlerList getHandlerList() {
        return handlers;
    }

    public boolean isCancelled() {
       return cancelled;//Renvoie si l'évènement est annulé ou non.
    }
 
   public void setCancelled(boolean cancel) {
      this.cancelled = cancel;//Modifie l'état "annulé" de l'évènement
   }
}


Appel[]

Pour écouter un évènement, il faut déjà qu'il survienne ! En tant normal, c'est le serveur qui se charge de créer des évènements et de les appeler en fonction de ce qui se passe, mais là vous devez le faire vous-même. Rassurez-vous, ce n'est pas bien sorcier: on utilise la méthode callEvent(Event) du PluginManager:

MonEvent e = new MonEvent();//On crée un nouvel évènement personnalisé
PluginManager pm = Bukkit.getServer().getPluginManager();//Ceci permet de récupérer le PluginManager sans être dans la classe principale du plugin
pm.callEvent(e);//On appelle l'évènement


Ecoute[]

L'écoute d'un évènement personnalisé se fait exactement de la même façon qu'un évènement "officiel" !
Avec un Listener, une méthode d'écoute:

public class PluginListener implements Listener {
   @EventHandler
   public void onMonEvent(MonEvent e) {
      //Action à effectuer quand l'évènement survient
   }
}

etc...

Écouter un évènement particulier d'un Listener[]

Écouter tous les évènements d'un Listener est plutôt facile, mais n'en écouter qu'un seul parmi tous ceux d'un Listner est une autre paire de manches ! En effet la méthode qui permet d'enregistrer un seul évènement auprès du PluginManager est: registerEvent(Class<? extends Event> event, Listener listener, EventPriority priority, EventExecutor executor, Plugin plugin). Comme vous le voyez, elle prend plein d'autres paramètres, qu'il n'est pas question de remplacer par null ou vous aurez une belle erreur.

EventExecutor[]

La classe de l'évènement, vous l'avez, pas de problème de ce côté-là. Le Listener aussi, la priorité c'est facile, le plugin c'est bon... mais l'exécuteur, qu'est-ce que c'est ? Eh bien, l'exécuteur, c'est l'objet qui "retient" la méthode d'écoute, et qui va l'appeler quand on le lui demandera. Il est donc crucial. Malheureusement il n'est pas possible d'instancier un nouvel EventExecutor: c'est une classe abstraite, et l'api bukkit ne propose pas d'implémentation. Vous devez donc créer vous-même une classe qui hérite de EventExecutor:

import java.lang.reflect.Method;

import org.bukkit.event.Event;
import org.bukkit.event.EventException;
import org.bukkit.event.Listener;
import org.bukkit.plugin.EventExecutor;

public class PluginEventExecutor implements EventExecutor {

   private Method method;//On stocke la méthode d'écoute dans une variable

   PluginEventExecutor(final Method m) {
      method = m;//On récupère la méthode d'écoute avec le constructeur
   }

   public void execute(final Listener listener, final Event event) throws EventException {//Cette méthode est appelée lors d'un "callEvent(Event)"
      if (!method.getParameterTypes()[0].isAssignableFrom(event.getClass()))
	    return;// Si l'évènement n'est pas du type attendu par la méthode d'écoute, on ne va pas plus loin.

      try {
         method.invoke(listener, event);// On appelle la méthode d'écoute du Listener, avec en paramètre l'évènement survenu
      } catch (Exception e) {
         throw new EventException(e.getCause(), "Error while trying to invoke method " + method.getName() + "()");
         // Si une erreur survient, il faut créer une nouvelle EventException.
         // Ici on affiche "Error while trying to invoke method " + le nom de la méthode
      }

   }

}


Enregistrer l'évènement[]

Maintenant qu'on a notre EventExecutor, il nous reste juste à récupérer la méthode d'écoute, puis à enregistrer l'évènement auprès du PluginManager. Voici ce que ça donne au lancement du plugin:

@Override
public void onEnable() {
   PluginListener listener = new PluginListener();// On crée une instance de notre listener
   Method m = PluginListener.getMethod("onEvent", Event.class);// On récupère la méthode d'écoute avec son nom et son paramètre
   PluginEventExecutor executor = new PluginEventExecutor(m);// On crée une instance de notre EventExecutor
   PluginManager pm = getServer().getPluginManager();// On récupère le PluginManager
   pm.registerEvent(Event.class, listener, EventPriority.NORMAL, executor, this);// On enregistre l'évènement. 
   // Vous pouvez bien sûr changer la priorité ;)
}



Language   EnglishбеларускаяDeutschespañolsuomifrançaisitaliano한국어Nederlandsnorskpolskiportuguêsрусскийlietuviųčeština
Advertisement