Scheduler

Planifie des taches differees, repetitives, asynchrones ou enchainees — sans bloquer le jeu.

fr.eri.eriapi.scheduler Minecraft 1.12.2 Java 8

Introduction

Le Scheduler d'EriAPI permet de planifier des taches de plusieurs facons :

  • Execution differee — lance une action apres N ticks (20 ticks = 1 seconde)
  • Repetition — execute une action toutes les N ticks, un nombre fini ou infini de fois
  • Async — execute du code lourd hors du main thread, puis revient sur le main thread pour toucher aux objets Minecraft
  • Chaine sequentielle — enchaîne plusieurs actions avec des delais precis entre elles
Package

Toutes les classes du Scheduler sont dans le package fr.eri.eriapi.scheduler.

Attention aux ticks

Minecraft tourne a 20 ticks par seconde. Un delai de 20 ticks = 1 seconde, 100 ticks = 5 secondes, 1200 ticks = 1 minute.

EriScheduler — API statique

EriScheduler est le point d'entree principal du module. Toutes ses methodes sont statiques : pas besoin d'instancier quoi que ce soit.

Execution differee — delay()

Execute une action une seule fois, apres un delai en ticks.

Java — EriScheduler.delay()
// Delai de 20 ticks = 1 seconde
ScheduledTask task = EriScheduler.delay(20, () -> {
    player.sendMessage(new TextComponentString("1 seconde plus tard !"));
});

Repetition limitee — repeat(ticks, maxCount, Runnable)

Execute une action toutes les N ticks, au maximum maxCount fois.

Java — EriScheduler.repeat() avec limite
// Toutes les 20 ticks, 5 fois au maximum
ScheduledTask task = EriScheduler.repeat(20, 5, () -> {
    System.out.println("Tick!");
});

Repetition infinie — repeat(ticks, Runnable)

Execute une action toutes les N ticks indefiniment, jusqu'a ce que tu l'annules manuellement.

Java — EriScheduler.repeat() infini
// Toutes les 100 ticks = toutes les 5 secondes, sans limite
ScheduledTask task = EriScheduler.repeat(100, () -> {
    System.out.println("Toutes les 5 secondes");
});

Tache asynchrone — async()

Lance un Callable hors du main thread. Voir la section AsyncExecutor pour les details.

Java — EriScheduler.async()
EriScheduler.async(() -> fetchDataFromWeb())
    .thenSync(result -> player.sendMessage(new TextComponentString("Data: " + result)));

Chaine sequentielle — chain()

Cree une TaskChain pour enchaîner des actions avec des delais. Voir la section TaskChain.

Gestion globale

Java — Methodes utilitaires
// Annuler toutes les taches actives
EriScheduler.cancelAll();

// Obtenir le nombre de taches actives
int count = EriScheduler.activeCount();

Reference des methodes

Methode Parametres Description
delay() int ticks, Runnable Execute une action une fois apres N ticks
repeat() int ticks, int maxCount, Runnable Repete une action N fois toutes les X ticks
repeat() int ticks, Runnable Repete indefiniment toutes les X ticks
async() Callable<T> Lance une tache hors du main thread, retourne un AsyncExecutor
chain() Cree une nouvelle TaskChain vide
cancelAll() Annule toutes les taches en cours
activeCount() Retourne le nombre de taches actives

ScheduledTask — Reference de tache

Chaque appel a EriScheduler.delay() ou EriScheduler.repeat() retourne un objet ScheduledTask. Garde cette reference pour controler la tache apres sa creation.

Java — Controle d'une ScheduledTask
ScheduledTask task = EriScheduler.repeat(20, () -> doStuff());

task.pause();           // Gele le compteur de ticks (la tache ne s'execute plus)
task.resume();          // Reprend le decompte la ou il s'etait arrete
task.cancel();          // Arrete definitivement la tache

boolean running   = task.isRunning();    // true si active et non pausee
boolean cancelled = task.isCancelled();  // true si annulee
boolean paused    = task.isPaused();     // true si gelee

int executions = task.getExecutionCount(); // Nombre de fois que la tache s'est executee

Reference des methodes

Methode Retour Description
pause() void Gele le compteur, la tache ne s'execute plus
resume() void Reprend le decompte apres un pause()
cancel() void Annule definitivement la tache
isRunning() boolean true si la tache est active et non pausee
isCancelled() boolean true si la tache a ete annulee
isPaused() boolean true si la tache est gelee
getExecutionCount() int Nombre total d'executions effectuees
Bonne pratique

Stocke toujours la reference de ta tache dans un champ de ta classe si tu as besoin de l'annuler plus tard (par exemple dans la methode onGuiClosed() de ton ecran).

TaskChain — Chaine sequentielle

Une TaskChain permet d'enchaîner plusieurs actions avec des delais precis entre chacune. C'est ideal pour des sequences d'evenements en jeu : animations de texte, tutoriels, cinematiques, etc.

Java — TaskChain : enchaîner des actions
EriScheduler.chain()
    .then(0,  () -> System.out.println("Maintenant"))
    .then(20, () -> System.out.println("1s plus tard"))
    .then(40, () -> System.out.println("2s plus tard"))
    .run();
Comment fonctionne le delai dans une chaine ?

Le parametre de then(ticks, action) est le delai depuis le debut de la chaine, pas depuis l'etape precedente. Un delai de 0 execute l'action immediatement au lancement de run(). Pense-y comme des "timestamps" dans une timeline.

Reference des methodes

Methode Parametres Description
then() int ticks, Runnable Ajoute une etape a la chaine avec un delai en ticks
run() Lance la chaine. Toutes les etapes sont planifiees immediatement.

AsyncExecutor — Taches asynchrones

L'AsyncExecutor permet d'executer du code lourd (appels reseau, lecture de fichiers, calculs intensifs) dans un thread separe, sans bloquer le jeu. Quand le resultat est pret, tu peux revenir sur le main thread pour interagir avec les objets Minecraft.

Ne touche jamais aux objets Minecraft hors du main thread

Dans le callback de async(), tu ne dois pas appeler de methodes Minecraft (player, world, etc.). Utilise thenSync() pour revenir sur le main thread avant de manipuler des objets du jeu.

Java — AsyncExecutor : hors thread puis retour main thread
EriScheduler.async(() -> {
    // Hors du main thread — ideal pour les operations lentes
    return fetchDataFromWeb();
})
.onError(e -> {
    // Appelee si une exception est lancee dans le bloc async
    System.err.println("Erreur: " + e.getMessage());
})
.thenSync(result -> {
    // Retour sur le main thread — safe pour toucher aux objets Minecraft
    player.sendMessage(new TextComponentString("Data: " + result));
});

Reference des methodes

Methode Parametres Description
onError() Consumer<Exception> Callback appele si une exception est lancee dans le bloc async
thenSync() Consumer<T> Callback execute sur le main thread avec le resultat de la tache async

Exemple complet — Countdown

Voici un exemple concret qui combine repeat() et ScheduledTask pour faire un compte a rebours affiché dans le chat du joueur.

Java — Countdown 5...4...3...2...1...Go!
// Compte a rebours : 5...4...3...2...1...Go!
// La tache se repete 6 fois (5 chiffres + le message "Go!")
final int[] count = {5};

ScheduledTask countdown = EriScheduler.repeat(20, 6, () -> {
    if (count[0] > 0) {
        player.sendMessage(new TextComponentString(count[0] + "..."));
        count[0]--;
    } else {
        player.sendMessage(new TextComponentString("Go!"));
    }
});
Pourquoi final int[] ?

En Java 8, les lambdas ne peuvent capturer que des variables effectives finales. Un tableau d'un seul element est une astuce courante pour avoir un compteur mutable dans un lambda : la reference au tableau est finale, mais son contenu (count[0]) peut changer.

Exemple avec TaskChain — Sequence de messages

Pour une sequence de messages avec des timings precis, la TaskChain est plus lisible :

Java — Sequence de messages avec TaskChain
EriScheduler.chain()
    .then(0,   () -> player.sendMessage(new TextComponentString("Bienvenue sur le serveur !")))
    .then(40,  () -> player.sendMessage(new TextComponentString("Rejoins le Discord : discord.gg/...")))
    .then(80,  () -> player.sendMessage(new TextComponentString("Tape /help pour la liste des commandes.")))
    .then(120, () -> player.sendMessage(new TextComponentString("Bonne partie !")))
    .run();

Exemple avec AsyncExecutor — Chargement de donnees

Un cas d'usage typique : charger des donnees depuis une API externe sans freezer le jeu.

Java — Chargement async avec retour sur main thread
player.sendMessage(new TextComponentString("Chargement en cours..."));

EriScheduler.async(() -> {
    // Simule un appel reseau lent (hors main thread)
    URL url = new URL("https://api.example.com/player/" + player.getName());
    BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()));
    return reader.readLine();
})
.onError(e -> {
    player.sendMessage(new TextComponentString("Impossible de charger les donnees."));
})
.thenSync(data -> {
    // On est de retour sur le main thread, safe pour Minecraft
    player.sendMessage(new TextComponentString("Ton score : " + data));
});
Nettoyage des taches

Si tu crées des taches repetitives dans une GUI ou un ecran, pense a les annuler quand l'ecran se ferme. Surcharge la methode onGuiClosed() de EriGuiScreen et appelle task.cancel() ou EriScheduler.cancelAll().