Event API Reference/fr

## 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 {
}

```

 **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

```

 **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

```

 **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);

```

 **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é ;)
}

```