Les événements
-
Sommaire
Introduction
Robin à dit :
Lors du développement de la version 2.0 de buildcraft, SpaceToad a voulu ajouter du pétrole. Le problème, c’est que pour ajouter un fluide il faut modifier la classe du seau de minecraft, ce qui aurait causé une incompatibilité avec les autres mods voulant ajouter un fluide. Pour corriger ce problème, SpaceToad a eu l’idée de créer une api qui modifie les classes de minecraft, et permettrait aux mods utilisant cette api d’ajouter des fluides sans modifier les classes de minecraft. Et c’est ainsi que forge à été créé, en effet la fonctionnalité pour les seaux était la première de forge ( le 4ème commit sur github)
Depuis, avec l’ASM un système d’événement a été mis en place, plus optimisé. Tout ça pour dire que les événements font partie des fonctionnalités les plus importantes de forge, puis qu’ils permettent de faire des choses qui seraient normalement impossible sans modifier les classes de minecraft.En revanche, les événements sont très varier, vous comprendrez qu’il n’est pas possible de tous les présenter. D’ailleurs, les possibilités des événements sont aussi très varier, on peut faire des choses vraiment très différentes avec le même événement. Dans ce tutoriel nous allons donc voir comment utiliser les événements, puis voir quelques exemples d’utilisations. Pour faire ce que vous souhaitez avec les événements, vous allez donc avoir besoin de compétence en java (ce qui est plutôt logique vu que les mods minecraft sont codés en java). Si vous avez besoin d’aide, vous pouvez toujours expliquer votre problème dans la section support pour les moddeurs. Nous verrons plus en détails certains événements dans d’autres tutoriels quand ils sont nécessaires (exemple: nous verrons l’event bone meal dans le tutoriel sur les plantes ou les arbres, l’event bucket dans le tutoriel sur les fluides, etc …).
Pré-requis
Code
La classe contenant les événements
Avant toute chose, nous allons créer la classe qui va contenir nos événements, c’est une classe simple :
public class ClasseEvenements { }
Rien de compliqué. Nous allons à présent ajouter des méthodes qui seront appelées par Forge lorsque l’événement qui y est associé sera déclenché.
Règles pour une méthode d’événement :
- Un seul argument (un event) : c’est une faute récurrente chez les débutants qui ajoutent les arguments dont ils ont besoin.
- N’importe quel nom : vous pouvez appeler la méthode comme bon vous semble, cela n’a pas d’importance. Forge identifie les fonctions d’événement grâce à une annotation et à l’argument.
- Annotée de la classe SubscribeEvent : l’oubli de l’annotation est un oubli assez fréquent chez certaines personnes, il faut bien y penser.
- Aucun retour (void) : la méthode ne doit rien renvoyer, on modifie l’objet passé en argument pour altérer le fonctionnement du jeu.
- Static ou non (au choix) : la méthode peut être static ou non, ce choix change la façon d’enregistrer votre classe sur l’event bus de Forge.
- Public : la méthode doit être public afin que Forge puisse l’appeler.Remarque, l’annotation SubscribeEvent peut prendre des paramètres :
- priority : prend une valeur de l’énumération EventPriority. Les événements avec les priorités les plus élevées seront appelés en premiers. La valeur par défaut est EventPriority.NORMAL.
- receiveCanceled : prend pour valeur une boolean, mettre ce paramètre true permet que la fonction annotée soit quand même appelée lorsque l’événement est annulé.
Voici une classe implémentant différents événements :
public class ClasseEvenements { /* * Une fonction static */ @SubscribeEvent public static void onLivingDeath(LivingDeathEvent event) { } /* * Une fonction non-static */ @SubscribeEvent public void onPlayerInteract(PlayerInteractEvent event) { } /* * Ici j'ai mis un nom alétoire, Forge comprendra quand même qu'il s'agit de l'event KeyInputEvent grâce à l'argument */ @SubscribeEvent public void dkonoOOIjoIBIbIUGIUVioH5498(KeyInputEvent event) { } }
On préférera les noms de la forme : onNomDeLEvent
Voilà nous avons créé nos méthodes, nous verrons dans la suite du tutoriel comment les utiliser.
Enregistrer la classe contenant les événements
Pour enregistrer une classe d’événements il existe plusieurs méthodes.
La première, la plus fréquente, est d’utiliser l’event bus de forge pour enregistrer une instance de notre classe.
MinecraftForge.EVENT_BUS.register(new MaClasse());
Si vous avez une classe qui ne s’occupe que des événements côté client vous pouvez l’enregistrer seulement côté client de la façon suivante :
if(event.getSide().isClient()) { MinecraftForge.EVENT_BUS.register(new MaClasseCliente()); }
Avec la méthode que nous venons de voir, seules les fonctions non-static seront détectées par Forge.
La seconde méthode consiste à mettre en paramètre non pas l’instance de la classe mais la classe elle-même.
MinecraftForge.EVENT_BUS.register(MaClass.class);
Avec cette méthode, seules les fonctions static de votre classe seront détectées par Forge.
La troisième méthode utilise l’annotation EventBusSubscriber, on annote directement la classe que l’on veut enregistrer et Forge s’en chargera pour nous.
L’annotation a besoin de deux paramètres.- Side[] side : un tableau contenant les Side sur lesquels vous voulez enregistrer la classe (enregistrée sur le client et le serveur par défaut)
- String modid : votre modid, celui rentré dans l’annotation Mod
/* * Enregistrement d'une classe d'événements clients sur le client */ @EventBusSubscriber(value = Side.CLIENT, modid = ModTuto.MODID) public class EventHandlerClient { // Exemple d'event qui pourrait se trouver dans cette classe (pour ne pas la laisser vide) public static void onGuiOpen(GuiOpenEvent event) { // ... } }
Avec cette méthode d’enregistrement, Forge ne détecte que les fonctions static.
Attention : ne plus enregistrer vos classes d’événements par FML, bien que cette méthode fonctionne, elle est dépréciée car les events bus FML et Forge ont été rassemblés.
Exemples d’utilisation des événements
Comme dit par Robin dans l’introduction, il existe un grand nombre d’événements (dont voici la liste), il n’est donc pas préférable de faire un exemple pour chacun d’eux.
Cependant certains sont plus utilisés que d’autres, alors je vais donner des exemples pour certains d’entre eux.Chaque événement contient ses propres variables et ses propres fonctions avec lesquelles vous pouvez interagir (ex : modifier les variables, appeler une fonction).
Chaque événement est soit annulable (cancelable), soit a un résultat (hasResult), soit n’a aucun des deux. Pour savoir ce qu’il en est d’un certain événement,
rendez-vous dans sa classe et regardez quelles sont les annotations qu’il possède :- @Cancelable : on peut annuler l’événement grâce à Event#setCanceled
- @HasResult : on peut changer le résultat de l’événement grâce à Event#setResult
On va commencer par l’événement GuiOpenEvent qui ne se déclenche que côté client.
INFO : pour savoir si un événement ne se déclenche que sur le client, il suffit de regarder dans quel package il se trouve. Exemple : net.minecraftforge.client.event.GuiOpenEvent
L’événement GuiOpenEvent est souvent utilisé pour remplacer le menu principal par un menu personnalisé (ce n’est pas sa seule utilisation mais la plus fréquente) :
@EventBusSubscriber(value = Side.CLIENT, modid = ModTuto.MODID) public class EventHandlerClient { /* * Remplace le GUI GuiMainMenu par le GUI MonGui */ @SubscribeEvent public static void onGuiOpen(GuiOpenEvent event) { if(event.getGui() instanceof GuiMainMenu) { event.setGui(new MonGui()); } } }
Grâce à l’événement LivingDropsEvent on peut changer les drops d’une entité, souvent utilisé pour rajouter ses propres objets aux drops d’un monstre.
@EventBusSubscriber(modid = ModTuto.MODID) public class EventHandlerCommon { /* * Ajoute une pomme dans les drops du zombie */ @SubscribeEvent public static void onLivingDrops(LivingDropsEvent event) { if(event.getEntity() instanceof EntityZombie) { Entity entity = event.getEntity(); BlockPos position = entity.getPosition(); event.getDrops().add(new EntityItem(entity.getEntityWorld(), position.getX(), position.getY(), position.getZ(), new ItemStack(Items.APPLE))); } } }
L’événement EntityJoinWorldEvent peut être utilisé pour annuler l’apparition d’une entité.
@EventBusSubscriber(modid = ModTuto.MODID) public class EventHandlerCommon { /* * Annule l'apparition des squelettes */ @SubscribeEvent public static void onLivingJoinWorld(EntityJoinWorldEvent event) { if(event.getEntity() instanceof EntitySkeleton) { event.setCanceled(true); } } }
On peut aussi afficher des messages de bienvenue avec l’événement PlayerLoggedInEvent.
@EventBusSubscriber(modid = ModTuto.MODID) public class EventHandlerCommon { /* * Affiche un message de bienvenue au joueur lorsqu'il rejoint la partie */ @SubscribeEvent public static void onPlayerLoggedIn(PlayerLoggedInEvent event) { event.player.sendMessage(new TextComponentString("Bienvenue " + event.player.getDisplayNameString() + " sur la partie")); } }
A présent vous savez utiliser les événements pour agir sur le jeu, il ne vous reste plus qu’à vous amuser.
Ce tutoriel de BrokenSwing publié sur Minecraft Forge France est mis à disposition selon les termes de la licence Creative Commons Attribution - Pas d’Utilisation Commerciale - Partage dans les Mêmes Conditions 4.0 International -
J’ai corrigé le tutoriel et ai finit de le compléter. Je pense qu’il est complet, à moins que l’on me demande d’autres exemples ou des précisions.
Merci -
Salut,
Peux-tu ajouter le footer avec la licence ? -
Je le ferai oui
C’est bon ?
-
Yep, par contre le formatage du code a sauté, il n’y a plus d’indentation.
Je vais rétablir ça et déplacer la discussion.
-
Bonjour pourrais-tu ajouter un exemple pour ajouter le drop de nos graines lorsque l’on utilise la houe sur un block d’herbe ? J’ai commencé à faire ceci
@SubscribeEvent public static void onUseHoe(UseHoeEvent event) { if(event.getResult() != null)
mais je ne sais pas trop quoi ajouter à la suite
Merci d’avance ! -
-
-
-
-