Event Simplifier

Ecoute les events Forge avec des lambdas en une seule ligne — filtres, priorite, one-shot et expiration automatique.

fr.eri.eriapi.event Forge 1.12.2 Java 8

Introduction

Le module Event Simplifier est une surcouche au systeme d'events de Forge. Normalement, pour ecouter un event dans Forge, il faut creer une classe annotee @Mod.EventBusSubscriber, ecrire une methode annotee @SubscribeEvent, et enregistrer la classe dans le bus. C'est verbeux et difficile a maintenir quand on a beaucoup d'events differents.

Avec EriEvents, la meme chose s'ecrit en une ligne :

Java — Avant (Forge brut)
// Avant : beaucoup de code pour juste ecouter un event
@Mod.EventBusSubscriber
public class MesEvents {
    @SubscribeEvent
    public static void onDeath(LivingDeathEvent e) {
        System.out.println(e.getEntity().getName() + " est mort !");
    }
}
Java — Apres (EriEvents)
// Apres : une seule ligne, n'importe ou dans ton code
EriEvents.on(LivingDeathEvent.class, e -> {
    System.out.println(e.getEntity().getName() + " est mort !");
});
Package

Toutes les classes de ce module se trouvent dans le package fr.eri.eriapi.event.

EriEvents — API statique

EriEvents est le point d'entree principal du module. Elle expose deux formes d'utilisation : le one-liner (un seul appel, handler direct) et le builder (configuration en plusieurs etapes avant d'attacher le handler).

One-liner — enregistrement immediat

Passe la classe de l'event et un lambda directement. L'event sera ecoute immediatement et indefiniment.

Java — EriEvents.on() one-liner
// Ecoute tous les deces d'entites
EriEvents.on(LivingDeathEvent.class, e -> {
    System.out.println(e.getEntity().getName() + " est mort !");
});

Builder — configuration avancee

Appelle EriEvents.on(ClassEvent.class) sans handler pour obtenir un EventBuilder. Tu peux ensuite chainer les options avant d'appeler .handle() pour activer l'ecoute.

Java — EriEvents.on() avec builder
// Ecoute la connexion d'un joueur, mais seulement si c'est "Steve"
EriEvents.on(PlayerLoggedInEvent.class)
    .filter(e -> e.player.getName().equals("Steve"))
    .once()
    .handle(e -> e.player.sendMessage(new TextComponentString("Bienvenue Steve !")));

Methodes statiques de EriEvents

Methode Description
on(Class<E> type, Consumer<E> handler) Enregistre un handler immediat (one-liner). Retourne un EventHandle.
on(Class<E> type) Cree un EventBuilder pour configurer l'ecoute avant de l'activer.

EventBuilder — Options de configuration

EventBuilder est l'objet retourne par EriEvents.on(Class). Il expose une Fluent API pour configurer toutes les options avant d'activer l'ecoute. Appelle toujours .handle() en dernier pour enregistrer le listener.

Java — EventBuilder complet
EriEvents.on(LivingDeathEvent.class)
    .filter(e -> e.getEntity() instanceof EntityPlayer)  // Seulement les joueurs
    .priority(EventPriority.HIGH)                        // Priorite haute
    .once()                                              // Se declenche une seule fois
    .expireAfter(6000)                                   // Expire apres 5 minutes (6000 ticks)
    .modId("mymod")                                      // Associe a "mymod" pour cleanup groupee
    .handle(e -> handleDeath(e));                        // Lance l'ecoute

Methodes du builder

Methode Type du parametre Description
filter(Predicate<E>) Predicate<E> Condition a verifier avant d'appeler le handler. Si le predicate retourne false, l'event est ignore pour cet handler. Les appels successifs a filter(...) sont combines en AND logique : tous les predicats doivent retourner true pour que le handler s'execute. Cela permet de chainer plusieurs conditions sans en perdre.
priority(EventPriority) net.minecraftforge.fml.common.eventhandler.EventPriority Priorite d'execution du listener parmi les autres listeners du meme event. Valeurs : HIGHEST, HIGH, NORMAL, LOW, LOWEST. Par defaut : NORMAL.
once() Le handler se declenche une seule fois puis se desenregistre automatiquement. Pratique pour attendre qu'une chose se produise une seule fois.
expireAfter(int ticks) int Le handler se desenregistre automatiquement apres le nombre de ticks indique (20 ticks = 1 seconde). Pratique pour les effets temporaires.
modId(String) String Associe ce listener a un identifiant de mod. Permet de desenregistrer tous les listeners d'un mod en un seul appel via EventRegistry.
handle(Consumer<E>) Consumer<E> Definit le handler et active l'ecoute. Retourne un EventHandle pour controler le listener apres coup. A appeler en dernier.
Combine once() et expireAfter()

Tu peux utiliser .once() et .expireAfter() ensemble. Le handler se desenregistre des que l'une des deux conditions est atteinte en premier.

Exemples par cas d'usage

Java — Filtrer par type d'entite
// Seulement quand un joueur meurt
EriEvents.on(LivingDeathEvent.class)
    .filter(e -> e.getEntity() instanceof EntityPlayer)
    .handle(e -> System.out.println("Un joueur est mort !"));
Java — Listener temporaire (30 secondes)
// Ecoute les mouvements pendant 30 secondes puis s'arrete
EriEvents.on(PlayerTickEvent.class)
    .filter(e -> e.phase == PlayerTickEvent.Phase.END)
    .expireAfter(600) // 30 secondes = 600 ticks
    .handle(e -> trackPlayerPosition(e.player));
Java — Attendre la premiere connexion
// S'execute une seule fois au premier login puis s'arrete
EriEvents.on(PlayerLoggedInEvent.class)
    .once()
    .handle(e -> System.out.println("Premier login : " + e.player.getName()));

EventHandle — Controle apres enregistrement

Chaque appel a .handle() (ou au one-liner) retourne un EventHandle. Cet objet te permet de controler le listener apres son enregistrement : le deactiver manuellement, verifier s'il est encore actif, ou savoir s'il a deja ete execute.

Java — Utilisation de EventHandle
// Enregistre et garde une reference au handle
EventHandle handle = EriEvents.on(TickEvent.class).handle(e -> doStuff());

// Plus tard, quand tu n'en as plus besoin :
handle.unregister();    // Desenregistre le listener

// Verifications
handle.isActive();      // true si le listener est encore enregistre
handle.wasExecuted();   // true si le handler a ete appele au moins une fois

Methodes de EventHandle

Methode Retour Description
unregister() void Desenregistre immediatement le listener du bus d'events Forge. Sans effet s'il est deja inactif.
isActive() boolean Retourne true si le listener est encore enregistre et actif. Retourne false apres un appel a unregister(), apres once() declenche, ou apres expiration.
wasExecuted() boolean Retourne true si le handler a ete appele au moins une fois.
Garde toujours une reference si tu en as besoin

Si tu enregistres un listener one-liner sans stocker le handle, tu ne pourras plus le deactiver manuellement. Utilise EventRegistry.unregisterAll("mymod") dans ce cas pour faire le menage.

EventRegistry — Cleanup groupee

EventRegistry est le registre interne qui suit tous les listeners actifs. Il permet de desenregistrer des groupes entiers de listeners en un seul appel, ce qui est tres utile lors du dechargement d'un mod ou d'un monde.

Java — EventRegistry
// Desenregistre tous les listeners associes a "mymod"
EventRegistry.getInstance().unregisterAll("mymod");

// Desenregistre absolument tous les listeners EriEvents actifs
EventRegistry.getInstance().unregisterAll();

// Nombre de listeners actuellement actifs
int count = EventRegistry.getInstance().activeCount();

Methodes de EventRegistry

Methode Retour Description
getInstance() EventRegistry Retourne l'instance singleton du registre.
unregisterAll(String modId) void Desenregistre tous les listeners enregistres avec .modId(modId). A appeler lors du dechargement de ton mod.
unregisterAll() void Desenregistre tous les listeners EriEvents actifs, quel que soit leur modId.
activeCount() int Retourne le nombre de listeners actuellement actifs dans le registre.
Bonne pratique : toujours taguer avec modId

Utilise .modId("tonmod") sur tous tes listeners. Appelle ensuite EventRegistry.getInstance().unregisterAll("tonmod") dans l'event FMLServerStoppingEvent ou FMLClientStoppingEvent pour ne laisser aucun listener orphelin en memoire.

Exemple complet

Voici un exemple concret qui illustre plusieurs fonctionnalites du module en meme temps. L'objectif : annoncer dans le chat global quand un joueur tue l'Ender Dragon, avec un message enrichi grace au module Chat Builder d'EriAPI.

Java — Annonce de mort du Dragon
// Dans ta classe principale ou un gestionnaire d'init
EriEvents.on(LivingDeathEvent.class)
    .filter(e -> e.getEntity().getName().equals("Ender Dragon"))
    .modId("mymod")
    .handle(e -> {
        Entity source = e.getSource().getTrueSource();
        if (source instanceof EntityPlayer) {
            EriChat.create()
                .text(source.getName()).color(TextFormatting.GOLD).bold()
                .text(" a tue le ").color(TextFormatting.WHITE)
                .text("Dragon !").color(TextFormatting.RED).bold()
                .broadcast();
        }
    });

Exemple multi-listeners avec cleanup

Cet exemple montre comment enregistrer plusieurs listeners et faire le menage proprement.

Java — Gestionnaire d'events avec cleanup
public class MonModEvents {

    public static void registerAll() {
        // Salutation a la connexion (une seule fois par session, expire apres 5 min)
        EriEvents.on(PlayerLoggedInEvent.class)
            .once()
            .expireAfter(6000)
            .modId("mymod")
            .handle(e -> e.player.sendMessage(
                new TextComponentString("Bienvenue sur le serveur !")));

        // Detection des kills de boss (priorite haute, indefini)
        EriEvents.on(LivingDeathEvent.class)
            .filter(e -> e.getEntity().isNonBoss() == false)
            .priority(EventPriority.HIGH)
            .modId("mymod")
            .handle(e -> onBossKilled(e));

        // Stats en arriere-plan (toutes les 20 ticks = 1 seconde)
        EriEvents.on(ServerTickEvent.class)
            .filter(e -> e.phase == ServerTickEvent.Phase.END)
            .modId("mymod")
            .handle(e -> updateStats());
    }

    public static void cleanup() {
        // Desenregistre tous les listeners de ce mod en un appel
        EventRegistry.getInstance().unregisterAll("mymod");
    }

    private static void onBossKilled(LivingDeathEvent e) {
        System.out.println("Boss elimine : " + e.getEntity().getName());
    }

    private static void updateStats() {
        // Mise a jour des statistiques serveur
    }
}

// Dans ta classe @Mod :
@Mod.EventHandler
public void serverStarting(FMLServerStartingEvent event) {
    MonModEvents.registerAll();
}

@Mod.EventHandler
public void serverStopping(FMLServerStoppingEvent event) {
    MonModEvents.cleanup();
}
Compatibilite avec Forge

EriEvents utilise le bus d'events standard de Forge (MinecraftForge.EVENT_BUS) en interne. Tous les events Forge (LivingDeathEvent, PlayerTickEvent, BlockEvent, etc.) sont supportes sans configuration supplementaire.