Appearance
Mise a jour automatick d'un item
Félicitations pour être arrivé au terme de ce bloc d'apprentissage ! Dans le cours précédent , nous avons vu comment modifier passivement les statistiques du joueur lorsqu'il tient un item en main. Aujourd'hui, nous allons étudier l'un des mécanismes les plus puissants mais aussi les plus gourmands du modding : la méthode inventoryTick.
Cette méthode permet à un objet d'exécuter du code de manière autonome et continue dès qu'il est présent dans l'inventaire d'une entité, qu'il soit tenu en main, stocké dans la barre d'accès rapide (Hotbar) ou caché au fond des poches du joueur.
- Le concept de Fréquence en Modding : Le Tick (20Hz)
Dans Minecraft, le temps ne se calcule pas en secondes, mais en Ticks. Le moteur de jeu s'actualise exactement 20 fois par seconde (20 Hz).
La méthode inventoryTick est appelée par le serveur à chaque cycle de jeu pour chaque objet présent dans un inventaire. Si un joueur possède votre objet, le code de cette méthode va s'exécuter 20 fois par seconde. C'est l'outil idéal pour créer des objets magiques autonomes, des artefacts maudits ou des générateurs d'effets passifs globaux.
Alerte Performance : Ne surchargez jamais le processeur ! Parce que cette méthode s'exécute 20 fois par seconde, vous devez y écrire un code extrêmement léger. N'y effectuez jamais de boucles de calcul complexes, de recherches massives de blocs ou d'opérations lourdes. Un code mal optimisé dans un
inventoryTickprovoquera immédiatement des chutes massives de FPS (images par seconde) et de TPS (ticks par seconde sur le serveur).
- Analyse des paramètres de la méthode
Voici la signature officielle fournie par Minecraft pour intercepter ce cycle :
java
@Override
public void inventoryTick(ItemStack stack, Level level, Entity entity, int slotId, boolean isSelected) {
[cite_start]// Logique exécutée 20 fois par seconde [cite: 272]
}ItemStack stack: L'exemplaire précis de l'item en cours d'actualisation.Level level: Le monde dans lequel se trouve l'entité (très utile pour notre barrière de sécurité !level.isClientSide).Entity entity: L'entité qui possède l'item (attention, c'est uneEntityglobale, il faudra vérifier s'il s'agit d'unPlayer).int slotId: L'index de la case d'inventaire exacte où repose l'objet.boolean isSelected: Renvoietruesi le joueur tient actuellement l'objet dans sa main principale.
- Structure du Code : Exemple pratique
Créons un exemple concret : un minerai instable baptisé FragmentUraniumItem. Si ce fragment est présent dans l'inventaire (n'importe où), il irradie son porteur en lui infligeant un effet de poison passif. De plus, toutes les 5 secondes (100 ticks), l'objet ronge l'inventaire en infligeant des dégâts de durabilité au fragment lui-même.
java
package com.monmod.items; [cite_start]// [cite: 284]
import net.minecraft.world.effect.MobEffectInstance; [cite_start]// [cite: 285]
import net.minecraft.world.effect.MobEffects; [cite_start]// [cite: 286]
import net.minecraft.world.entity.Entity; [cite_start]// [cite: 287]
import net.minecraft.world.entity.player.Player; [cite_start]// [cite: 288]
import net.minecraft.world.item.Item; [cite_start]// [cite: 289]
import net.minecraft.world.item.ItemStack; [cite_start]// [cite: 290]
import net.minecraft.world.level.Level; [cite_start]// [cite: 291]
[cite_start]public class FragmentUraniumItem extends Item { // [cite: 292]
[cite_start]public FragmentUraniumItem(Properties properties) { // [cite: 293]
super(properties); [cite_start]// [cite: 294]
[cite_start]} // [cite: 295]
[cite_start]@Override // [cite: 296]
[cite_start]public void inventoryTick(ItemStack stack, Level level, Entity entity, int slotId, boolean isSelected) { // [cite: 297]
[cite_start]// 1. Sécurité : Exécuter la logique uniquement côté SERVEUR et sur un JOUEUR [cite: 298]
[cite_start]if (!level.isClientSide && entity instanceof Player joueur) { // [cite: 298]
[cite_start]// 2. Condition : On applique l'effet de Poison en continu [cite: 299]
// Durée de 105 ticks (un peu plus de 5 secondes) pour éviter les micro-coupures
[cite_start]if (!joueur.hasEffect(MobEffects.POISON)) { // [cite: 299]
joueur.addEffect(new MobEffectInstance(MobEffects.POISON, 105, 0, false, false)); [cite_start]// [cite: 301]
}
[cite_start]// 3. Système de Modulo pour temporiser une action (Créer un chronomètre) [cite: 302]
[cite_start]// level.getGameTime() donne le temps total écoulé du monde en ticks. [cite: 302]
[cite_start]// En faisant (Temps % 100 == 0), le code à l'intérieur ne s'exécutera qu'une fois [cite: 303]
[cite_start]if (level.getGameTime() % 100 == 0) { // [cite: 303]
[cite_start]// L'objet s'auto-endommage de 1 point de durabilité toutes les 5 secondes [cite: 304]
stack.hurtAndBreak(1, joueur, (p) -> p.broadcastBreakEvent(joueur.getUsedItemHand())); [cite_start]// [cite: 304]
[cite_start]} // [cite: 305]
[cite_start]} // [cite: 306]
[cite_start]} // [cite: 307]
[cite_start]} // [cite: 308][Note : La signature de l'effet de potion et la lambda de casse ont été corrigées par rapport aux coupures du texte brut].
L'astuce technique : L'opérateur Modulo (%)
Pour éviter qu'une action ne se produise 20 fois par seconde, on utilise le Modulo mathématique sur le temps global du jeu (level.getGameTime()). Le reste de la division par 100 sera égal à zéro précisément toutes les 5 secondes. C'est l'unique méthode propre pour concevoir un retardateur ou un système de rechargement périodique sans bloquer le thread principal du jeu.
Exercice Pratique Final
Pour clore en beauté cette série de cours pratiques, réalisez l'exercice de synthèse suivant :
Objectif : Le Cœur de Phénix Éteint
Créez un item nommé
CoeurPhenixItempossédant une durabilité maximale (ex : 50 utilisations).Implémentez la méthode
inventoryTick.Vérifiez à l'aide de l'argument
isSelectedsi le joueur tient l'objet directement dans sa main principale.Si et seulement si l'item est tenu en main principale :
Côté serveur, appliquez passivement au joueur l'effet de statut Résistance au Feu (
MobEffects.FIRE_RESISTANCE).Utilisez le système de Modulo pour consommer 1 point de durabilité de l'item toutes les 2 secondes (40 ticks) lorsqu'il est brandi.
- Si l'item est simplement stocké au fond de l'inventaire (non sélectionné), il ne doit appliquer aucun effet et ne doit pas perdre de durabilité.