Content Builder

Cree des items, des blocs, des recettes et des entites Minecraft en quelques lignes de code — sans ecrire de sous-classes ni de boilerplate.

fr.eri.eriapi.content Forge 1.12.2 Fluent API

Introduction

Le module Content Builder te permet de creer des items, des blocs et des entites Minecraft sans avoir a ecrire de classes Java complexes. Tout se fait via une Fluent API — tu chaines des methodes comme une phrase pour decrire ce que tu veux.

Normalement, creer un item dans Minecraft Forge demande d'ecrire une sous-classe d'Item, de l'enregistrer dans l'event RegistryEvent, d'enregistrer le modele dans ModelRegistryEvent... C'est beaucoup de code repetitif. EriAPI s'occupe de tout ca pour toi.

Ce que tu peux faire avec ce module

  • Creer des items simples (gemmes, ressources, consommables)
  • Creer des items alimentaires avec effets de potion
  • Creer des outils (epee, pioche, hache...) avec stats personnalisees
  • Creer des armures avec protection et solidite
  • Creer des blocs avec materiau, durete, son, drops
  • Definir des recettes avec forme, sans forme, ou au four
  • Ajouter des comportements personnalises via des callbacks
Enregistrement automatique

Quand tu appelles .register() a la fin de ton builder, EriAPI se charge d'enregistrer l'item ou le bloc dans les events Forge au bon moment. Tu n'as rien d'autre a faire.

Java — Exemple complet en un coup d'oeil
// Un item simple
EriItem.create("monmod", "rubis")
    .maxStackSize(16)
    .rarity(EnumRarity.RARE)
    .tooltip("&7Une gemme precieuse")
    .register();

// Un bloc
EriBlock.create("monmod", "minerai_rubis")
    .material(Material.ROCK)
    .hardness(3.0f)
    .drops(Items.DIAMOND, 1, 3)
    .register();

// Une recette
EriRecipe.shaped("monmod", "bloc_rubis")
    .pattern("RRR", "RRR", "RRR")
    .key('R', monItemRubis)
    .result(monBlocRubis, 1)
    .register();

ContentRegistry

ContentRegistry est le moteur interne qui gere l'enregistrement de tous tes items et blocs aupres de Forge. Tu n'interagis presque jamais directement avec lui — il est utilise automatiquement en coulisse quand tu appelles .register().

ContentRegistry
fr.eri.eriapi.content.ContentRegistry
Interne

Gestionnaire central qui ecoute les events Forge (RegistryEvent.Register<Item>, RegistryEvent.Register<Block>, ModelRegistryEvent) et enregistre automatiquement tout ce qui a ete declare via les builders.

  • void register(Object mod)
    Enregistre le ContentRegistry comme listener d'events Forge pour ton mod. A appeler une seule fois dans la methode annotee @Mod.EventHandler de ta classe principale.
    Statique
Java — Initialiser ContentRegistry dans ta classe @Mod
import fr.eri.eriapi.content.ContentRegistry;

@Mod(modid = "monmod", version = "1.0")
public class MonMod {

    @Mod.EventHandler
    public void preInit(FMLPreInitializationEvent event) {
        // Enregistre ContentRegistry pour qu'il capture les events Forge
        ContentRegistry.register(this);

        // Declare maintenant tes items et blocs
        MonItems.init();
        MonBlocs.init();
    }
}
Ordre d'appel important

Appelle ContentRegistry.register(this) avant de declarer tes items et blocs. Cela garantit que Forge recevra bien les registrations au bon moment du cycle de chargement.

Contextes d'action

Quand tu definis un comportement sur un item ou un bloc (via onRightClick, onBreak, etc.), EriAPI te passe un objet contexte qui contient toutes les informations sur ce qui s'est passe.

ItemActionContext
fr.eri.eriapi.content.ItemActionContext
Contexte item

Passe aux callbacks d'items (onRightClick, onLeftClick).

  • EntityPlayer getPlayer()
    Le joueur qui a clique sur l'item.
    Getter
  • World getWorld()
    Le monde dans lequel l'action s'est produite.
    Getter
  • ItemStack getItemStack()
    L'ItemStack de l'item utilise (avec son NBT, sa durabilite, etc.).
    Getter
  • EnumHand getHand()
    La main utilisee (MAIN_HAND ou OFF_HAND).
    Getter
BlockActionContext
fr.eri.eriapi.content.BlockActionContext
Contexte bloc

Passe aux callbacks de blocs (onBreak, onPlace, onWalk).

  • EntityPlayer getPlayer()
    Le joueur qui a interagi avec le bloc (peut etre null si casse par une machine).
    Getter
  • World getWorld()
    Le monde ou se trouve le bloc.
    Getter
  • BlockPos getPos()
    La position (coordonnees X, Y, Z) du bloc dans le monde.
    Getter
  • IBlockState getBlockState()
    L'etat du bloc au moment de l'action (utile pour les blocs avec variants).
    Getter
Java — Utiliser les contextes dans des callbacks
EriItem.create("monmod", "soin_rapide")
    .onRightClick(ctx -> {
        EntityPlayer joueur = ctx.getPlayer();

        // Soigne le joueur de 4 points de vie (2 coeurs)
        joueur.heal(4f);

        // Envoie un message dans le chat du joueur
        joueur.sendMessage(new TextComponentString("Tu as ete soigne !"));

        // Consomme 1 item dans la main
        ctx.getItemStack().shrink(1);
    })
    .register();

EriBlock.create("monmod", "bloc_piege")
    .onWalk(ctx -> {
        EntityPlayer joueur = ctx.getPlayer();
        if (joueur != null) {
            // Ralentit le joueur qui marche dessus
            joueur.addPotionEffect(new PotionEffect(MobEffects.SLOWNESS, 60, 2));
        }
    })
    .register();

EriItem

EriItem est le point d'entree pour creer n'importe quel item. Tu commences toujours par EriItem.create("modid", "nom"), tu chaines les methodes pour configurer l'item, puis tu termines par .register().

EriItem
fr.eri.eriapi.content.EriItem
Builder

Builder fluent pour creer et enregistrer des items Minecraft sans sous-classe.

  • EriItem create(String modid, String name)
    Cree un nouveau builder d'item. modid est l'identifiant de ton mod, name est le nom de l'item (ex: "rubis"). Ce nom sera utilise comme registry name et pour trouver la texture dans assets/modid/textures/items/name.png.
    Statique
  • EriItem maxStackSize(int size)
    Nombre maximum d'items empilables dans un slot d'inventaire. Par defaut : 64.
    Fluent
  • EriItem maxDamage(int damage)
    Durabilite maximale de l'item. Mettre une valeur > 0 rend l'item damageable (comme un outil). Par defaut : 0 (non damageable).
    Fluent
  • EriItem rarity(EnumRarity rarity)
    Rarete de l'item, qui affecte la couleur de son nom dans les tooltips. Valeurs : COMMON (blanc), UNCOMMON (jaune), RARE (cyan), EPIC (violet).
    Fluent
  • EriItem creativeTab(CreativeTabs tab)
    L'onglet du mode creatif ou apparait l'item. Exemples : CreativeTabs.MATERIALS, CreativeTabs.TOOLS, CreativeTabs.COMBAT.
    Fluent
  • EriItem glowing(boolean glowing)
    Si true, l'item affiche l'effet d'enchantement brillant (comme les items enchantes), meme sans enchantement reel.
    Fluent
  • EriItem tooltip(String line)
    Ajoute une ligne de tooltip (le texte affiché quand le joueur survole l'item). Tu peux appeler cette methode plusieurs fois pour plusieurs lignes. Supporte les codes couleur Minecraft (&7, &c, etc.).
    Fluent
  • EriItem onRightClick(Consumer<ItemActionContext> action)
    Callback execute quand le joueur fait un clic droit avec l'item en main (dans l'air ou sur un bloc). Recoit un ItemActionContext.
    Fluent
  • EriItem onLeftClick(Consumer<ItemActionContext> action)
    Callback execute quand le joueur attaque (clic gauche) avec l'item en main.
    Fluent
  • FoodBuilder food()
    Ouvre le sous-builder alimentaire. Appelle .done() pour revenir a l'EriItem. Voir FoodBuilder.
    Sous-builder
  • ToolBuilder tool()
    Ouvre le sous-builder outil. Appelle .done() pour revenir a l'EriItem. Voir ToolBuilder.
    Sous-builder
  • ArmorBuilder armor()
    Ouvre le sous-builder armure. Appelle .done() pour revenir a l'EriItem. Voir ArmorBuilder.
    Sous-builder
  • EriItem animatedModel(String modelId)
    Configure l'item pour utiliser un modele 3D Blockbench anime en main et en inventaire. Le rendu est delegue a un TileEntityItemStackRenderer interne. modelId est au format "modid:item/nom" (ex: "eriniumfaction:item/faction_sword"). Le fichier JSON Blockbench doit etre dans assets/{modid}/models/item/{nom}.json.
    Fluent
  • Item register()
    Finalise et enregistre l'item aupres de Forge. Retourne l'instance Item cree, que tu peux stocker dans une variable pour l'utiliser dans des recettes.
    Terminal
Java — Exemple complet EriItem
import fr.eri.eriapi.content.EriItem;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.item.EnumRarity;
import net.minecraft.item.Item;

public class MonItems {

    public static Item RUBIS;
    public static Item EPEE_RUBIS;

    public static void init() {

        RUBIS = EriItem.create("monmod", "rubis")
            .maxStackSize(16)
            .rarity(EnumRarity.RARE)
            .glowing(true)
            .tooltip("&7Une gemme precieuse")
            .tooltip("&cTres rare")
            .onRightClick(ctx -> ctx.getPlayer().heal(2f))
            .creativeTab(CreativeTabs.MATERIALS)
            .register();
    }
}

Item simple — modele et texture

Pour un item classique en 2D, tu dois fournir deux fichiers dans src/main/resources/assets/monmod/ : le modele JSON et la texture PNG. EriAPI enregistre la resource location du modele via ModelLoader.setCustomModelResourceLocation(), mais les fichiers JSON (modeles et blockstates) doivent etre fournis par le developpeur dans src/main/resources/. Ces fichiers sont inclus dans le JAR du mod a la compilation.

Java — Declaration minimale
EriItem.create("monmod", "rubis")
    .maxStackSize(64)
    .register();
// -> Texture attendue : assets/monmod/textures/items/rubis.png (16x16 ou 64x64)
// -> Modele JSON attendu : assets/monmod/models/item/rubis.json

Fichier modele a creer manuellement dans src/main/resources/assets/monmod/models/item/rubis.json :

JSON — models/item/rubis.json (a creer manuellement)
{
    "parent": "item/generated",
    "textures": {
        "layer0": "monmod:items/rubis"
    }
}
Item tenu en main (outil, epee...)

Pour un item qui doit etre tenu correctement en main (style outil), utilise "parent": "item/handheld" a la place de "item/generated" dans le JSON du modele.

Item 3D anime — animatedModel() + AnimatedItemController

La methode .animatedModel(String modelId) permet d'afficher l'item avec un modele Blockbench 3D (type Java Block/Item) au lieu d'une simple texture 2D. Le rendu passe par un TileEntityItemStackRenderer interne et les animations se jouent via AnimatedItemController cote client.

Fichiers requis

  • assets/modid/models/item/nom.json — modele Blockbench exporte (format Java Block/Item)
  • assets/modid/animations/item/nom.erianim.json — fichier d'animations (optionnel si l'item n'anime pas)
  • Les textures referencees dans le JSON Blockbench, placees a l'emplacement attendu
Java — Declaration d'un item 3D anime
import fr.eri.eriapi.anim.AnimatedItemController;
import fr.eri.eriapi.content.EriItem;
import net.minecraft.item.EnumRarity;

// Declaration
EriItem.create("monmod", "epee_animee")
    .maxStackSize(1)
    .rarity(EnumRarity.EPIC)
    .animatedModel("monmod:item/epee_animee")   // Modele Blockbench 3D
    .onRightClick(ctx -> {
        if (ctx.world.isRemote) {
            // Joue l'animation "use" du fichier monmod:item/epee_animee.erianim.json
            AnimatedItemController.play("monmod:item/epee_animee", "use");
        }
    })
    .register();
Java — Controle depuis n'importe quel code client-side
// Jouer une animation (animFileId = modelId par defaut)
AnimatedItemController.play("monmod:item/epee_animee", "idle");

// Jouer avec un animFileId explicite (2e parametre)
AnimatedItemController.play("monmod:item/epee_animee", "monmod:item/epee_anims", "swing");

// Arreter l'animation en cours
AnimatedItemController.stop("monmod:item/epee_animee");

// Verifier si une animation est en cours
boolean enCours = AnimatedItemController.isPlaying("monmod:item/epee_animee");
Resolution du animFileId

Le 2e parametre optionnel de play() resout vers assets/modid/animations/path.erianim.json. S'il est omis, EriAPI utilise modelId comme animFileId. L'etat de lecture est partage par modelId : tous les items rendus avec le meme modele jouent la meme animation en meme temps.

FoodBuilder

FoodBuilder est un sous-builder accessible depuis EriItem.food(). Il configure les proprietes alimentaires d'un item — combien il restaure de faim, quel effet de potion il donne, s'il peut etre mange meme quand la faim est pleine, etc. Une fois configure, appelle .done() pour revenir au builder principal EriItem.

FoodBuilder
fr.eri.eriapi.content.FoodBuilder
Sous-builder

Configure les proprietes alimentaires d'un item. Retourne via .done().

  • FoodBuilder hunger(int points)
    Nombre de demi-jambons restaures (1 point = une demi-cuisse de poulet dans la barre de faim). Un steak vanilla restaure 8 points.
    Fluent
  • FoodBuilder saturation(float saturation)
    Modificateur de saturation. Multiplie les points de faim pour calculer la saturation reelle. Une valeur de 1.2f donne une saturation elevee (comme la pomme en or).
    Fluent
  • FoodBuilder alwaysEdible(boolean always)
    Si true, l'item peut etre mange meme quand la barre de faim est pleine (comme la pomme en or).
    Fluent
  • FoodBuilder effect(PotionEffect effect, float probability)
    Ajoute un effet de potion applique en mangeant. probability est la probabilite d'application (entre 0.0f et 1.0f ; 1.0f = toujours). Peut etre appele plusieurs fois.
    Fluent
  • EriItem done()
    Termine la configuration alimentaire et retourne au builder EriItem parent.
    Retour
Java — Exemple FoodBuilder
import fr.eri.eriapi.content.EriItem;
import net.minecraft.init.MobEffects;
import net.minecraft.potion.PotionEffect;

Item POMME_MAGIQUE = EriItem.create("monmod", "pomme_magique")
    .food()
        .hunger(6)
        .saturation(1.2f)
        .alwaysEdible(true)
        .effect(new PotionEffect(MobEffects.REGENERATION, 100, 1), 1.0f)
        .effect(new PotionEffect(MobEffects.ABSORPTION, 200, 0), 0.5f)
        .done()
    .creativeTab(CreativeTabs.FOOD)
    .register();

ToolBuilder

ToolBuilder est un sous-builder accessible depuis EriItem.tool(). Il configure le type d'outil (epee, pioche, hache, pelle, houe), ses degats, sa vitesse d'attaque et sa durabilite. Appelle .done() pour revenir a l'EriItem.

ToolBuilder
fr.eri.eriapi.content.ToolBuilder
Sous-builder

Configure les proprietes d'outil d'un item. Retourne via .done().

  • ToolBuilder type(ToolType type)
    Type d'outil. Valeurs de l'enum ToolType : SWORD, PICKAXE, AXE, SHOVEL, HOE.
    Fluent
  • ToolBuilder damage(float damage)
    Degats de base infliges par l'outil (en demi-coeurs). Une epee en fer fait 6 degats (3 coeurs).
    Fluent
  • ToolBuilder durability(int durability)
    Durabilite de l'outil. Une epee en diamant a 1561 utilisations.
    Fluent
  • ToolBuilder speed(float speed)
    Vitesse d'attaque (attacks per second). La valeur par defaut vanilla pour une epee est 1.6f. Une hache est plus lente (0.9f).
    Fluent
  • EriItem done()
    Termine la configuration de l'outil et retourne au builder EriItem parent.
    Retour
Java — Exemple ToolBuilder
import fr.eri.eriapi.content.EriItem;
import fr.eri.eriapi.content.ToolType;

Item EPEE_RUBIS = EriItem.create("monmod", "epee_rubis")
    .tool()
        .type(ToolType.SWORD)
        .damage(8f)
        .durability(1500)
        .speed(1.6f)
        .done()
    .rarity(EnumRarity.RARE)
    .tooltip("&cEpee en rubis")
    .creativeTab(CreativeTabs.COMBAT)
    .register();

Item PIOCHE_RUBIS = EriItem.create("monmod", "pioche_rubis")
    .tool()
        .type(ToolType.PICKAXE)
        .damage(5f)
        .durability(2000)
        .speed(1.2f)
        .done()
    .creativeTab(CreativeTabs.TOOLS)
    .register();

ArmorBuilder

ArmorBuilder est un sous-builder accessible depuis EriItem.armor(). Il configure le slot d'armure (tete, torse, jambes, pieds), sa protection, sa solidite et le nom du materiau. Appelle .done() pour revenir a l'EriItem.

ArmorBuilder
fr.eri.eriapi.content.ArmorBuilder
Sous-builder

Configure les proprietes d'armure d'un item. Retourne via .done().

  • ArmorBuilder slot(ArmorSlot slot)
    Slot ou l'armure s'equipe. Valeurs de l'enum ArmorSlot : HEAD (casque), CHEST (plastron), LEGS (jambiere), FEET (bottes).
    Fluent
  • ArmorBuilder protection(int points)
    Points de protection de la piece. Un plastron en diamant protege de 8 points. La protection totale d'un set en diamant est de 20.
    Fluent
  • ArmorBuilder toughness(float toughness)
    Solidite de l'armure (reduit les degats des coups puissants). L'armure en diamant vanilla a 2.0f de solidite par piece. La plupart des materiaux ont 0.0f.
    Fluent
  • ArmorBuilder materialName(String name)
    Nom du materiau d'armure. Utilise pour trouver la texture de l'armure sur le joueur (assets/minecraft/textures/models/armor/[name]_layer_1.png).
    Fluent
  • EriItem done()
    Termine la configuration de l'armure et retourne au builder EriItem parent.
    Retour
Java — Exemple ArmorBuilder (set complet)
import fr.eri.eriapi.content.EriItem;
import fr.eri.eriapi.content.ArmorSlot;

public static void initArmure() {

    EriItem.create("monmod", "casque_rubis")
        .armor()
            .slot(ArmorSlot.HEAD)
            .protection(3)
            .toughness(2.0f)
            .materialName("rubis")
            .done()
        .creativeTab(CreativeTabs.COMBAT)
        .register();

    EriItem.create("monmod", "plastron_rubis")
        .armor()
            .slot(ArmorSlot.CHEST)
            .protection(8)
            .toughness(2.0f)
            .materialName("rubis")
            .done()
        .creativeTab(CreativeTabs.COMBAT)
        .register();

    EriItem.create("monmod", "jambiere_rubis")
        .armor()
            .slot(ArmorSlot.LEGS)
            .protection(6)
            .toughness(2.0f)
            .materialName("rubis")
            .done()
        .creativeTab(CreativeTabs.COMBAT)
        .register();

    EriItem.create("monmod", "bottes_rubis")
        .armor()
            .slot(ArmorSlot.FEET)
            .protection(3)
            .toughness(2.0f)
            .materialName("rubis")
            .done()
        .creativeTab(CreativeTabs.COMBAT)
        .register();
}
Texture de l'armure sur le joueur

Place les fichiers de texture a assets/monmod/textures/models/armor/rubis_layer_1.png (corps + bras) et assets/monmod/textures/models/armor/rubis_layer_2.png (jambieres). Ces textures sont au format 64x32 pixels (meme format que l'armure vanilla).

EriBlock

EriBlock est le point d'entree pour creer des blocs. Comme pour les items, tu commences par EriBlock.create("modid", "nom"), tu configures le bloc, et tu termines par .register().

EriBlock
fr.eri.eriapi.content.EriBlock
Builder

Builder fluent pour creer et enregistrer des blocs Minecraft sans sous-classe.

  • EriBlock create(String modid, String name)
    Cree un nouveau builder de bloc. La texture sera cherchee dans assets/modid/textures/blocks/name.png.
    Statique
  • EriBlock material(Material material)
    Materiau du bloc, qui determine comment il se comporte (si les entites le traversent, s'il brule, etc.). Exemples : Material.ROCK, Material.WOOD, Material.IRON, Material.GRASS, Material.GLASS.
    Fluent
  • EriBlock hardness(float hardness)
    Temps de minage du bloc. 0.0f = instantane, -1.0f = indestructible. La pierre vanilla a 1.5f, l'obsidienne a 50.0f.
    Fluent
  • EriBlock resistance(float resistance)
    Resistance aux explosions. La pierre a 10.0f, l'obsidienne a 6000.0f. En general, utilise hardness * 5 pour une valeur coherente.
    Fluent
  • EriBlock harvestTool(String tool, int level)
    Outil requis pour miner le bloc et le niveau minimum. tool : "pickaxe", "axe", "shovel". level : 0=bois, 1=pierre, 2=fer, 3=diamant.
    Fluent
  • EriBlock soundType(SoundType sound)
    Son emis quand le bloc est mine, place ou marche dessus. Exemples : SoundType.STONE, SoundType.WOOD, SoundType.METAL, SoundType.GLASS.
    Fluent
  • EriBlock drops(Item item, int min, int max)
    Ce que le bloc drope quand il est mine. min et max definissent la plage aleatoire de la quantite droppee. Si non specifie, drope le bloc lui-meme.
    Fluent
  • EriBlock creativeTab(CreativeTabs tab)
    L'onglet creatif ou apparait l'item-bloc.
    Fluent
  • EriBlock onBreak(Consumer<BlockActionContext> action)
    Callback execute quand le bloc est mine. Recoit un BlockActionContext.
    Fluent
  • EriBlock onPlace(Consumer<BlockActionContext> action)
    Callback execute quand le bloc est place par un joueur. Le callback est declenche dans onBlockPlacedBy, ce qui garantit que ctx.getPlayer() retourne toujours le joueur qui a place le bloc (jamais null).
    Fluent
  • EriBlock onWalk(Consumer<BlockActionContext> action)
    Callback execute chaque tick qu'une entite marche sur le dessus du bloc.
    Fluent
  • EriBlock hitbox(AxisAlignedBB box)
    Definit une hitbox unique (selection + collision). Remplace la hitbox plein-bloc par defaut. Desactive automatiquement isFullCube et isOpaque. Les coordonnees sont en blocs : 1.0 = 1 bloc = 16 pixels.
    Exemple : new AxisAlignedBB(0, 0, 0, 1, 0.5, 1) = demi-bloc.
    Fluent
  • EriBlock hitboxes(AxisAlignedBB... boxes)
    Definit plusieurs hitboxes independantes. Chaque boite est utilisee separement pour la collision. La selection (outline au survol) affiche l'union englobante de toutes les boites. Desactive automatiquement isFullCube et isOpaque. Recommande : max 6-8 boites pour ne pas impacter les TPS sur serveur charge.
    Fluent
  • EriBlock renderLayer(BlockRenderLayer layer)
    Definit la couche de rendu client du bloc. Utilise pour les blocs translucides, a trous (feuilles, plantes, verre), ou transparents. Valeurs courantes :
    • SOLID (defaut) — bloc opaque plein
    • CUTOUT — alpha binaire (plantes, grilles)
    • CUTOUT_MIPPED — alpha binaire avec mipmaps (feuilles)
    • TRANSLUCENT — transparence alpha continue (verre teinte, glace)
    Fluent
  • EriBlock onEntityWalk(TriConsumer<World, BlockPos, Entity> action)
    Callback execute chaque tick qu'une entite marche sur le bloc (equivalent Forge onEntityWalk). Contrairement a onWalk(Consumer<BlockActionContext>), cette version donne acces direct au monde, a la position et a l'entite, pratique pour appliquer des effets de mouvement ou des degats de zone.
    Fluent
  • EriBlock onEntityCollision(TriConsumer<World, BlockPos, Entity> action)
    Callback execute chaque tick qu'une entite traverse le bloc (entite a l'interieur de la hitbox). Equivalent Forge onEntityCollision. Utile pour les plantes qui infligent des degats au passage, les blocs de ralentissement, ou les pieges a detection.
    Fluent
  • EriBlock logLike()
    Transforme le bloc en tronc d'arbre (BlockRotatedPillar) avec la propriete AXIS (X, Y, Z). Le bloc s'oriente automatiquement selon la face ou il est place (debout, couche nord/sud, couche est/ouest). Le blockstate JSON doit gerer les 3 variants axis=x, axis=y, axis=z.
    Fluent
  • EriBlock leavesLike(Block sapling)
    Transforme le bloc en feuilles d'arbre (BlockLeaves) avec les proprietes CHECK_DECAY et DECAYABLE vanilla. Les feuilles se desintegrent automatiquement quand elles sont coupees d'un tronc. Force la couche de rendu CUTOUT_MIPPED. Le parametre sapling est droppe avec une probabilite de 5% lors de la decomposition naturelle (peut etre null pour desactiver).
    Overload : leavesLike() equivaut a leavesLike(null).
    Fluent
  • EriBlock plantLike()
    Transforme le bloc en plante decorative :
    • Hitbox reduite (0.15, 0, 0.15 a 0.85, 0.9, 0.85)
    • Pas de collision (les entites traversent le bloc)
    • Couche de rendu CUTOUT automatique
    • isOpaque=false, isFullCube=false
    Le blockstate JSON doit utiliser le modele block/cross pour l'affichage en X (comme les fleurs vanilla).
    Fluent
  • Block register()
    Finalise et enregistre le bloc aupres de Forge. Retourne l'instance Block creee.
    Terminal
Java — Exemple EriBlock avec hitboxes
import fr.eri.eriapi.content.EriBlock;
import net.minecraft.block.material.Material;
import net.minecraft.block.SoundType;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.init.Items;
import net.minecraft.util.math.AxisAlignedBB;

public class MonBlocs {

    public static Block MINERAI_RUBIS;
    public static Block BLOC_RUBIS;
    public static Block DEMI_BLOC;
    public static Block MACHINE;

    public static void init() {

        MINERAI_RUBIS = EriBlock.create("monmod", "minerai_rubis")
            .material(Material.ROCK)
            .hardness(3.0f)
            .resistance(15.0f)
            .harvestTool("pickaxe", 2)   // Necessite une pioche en fer minimum
            .soundType(SoundType.STONE)
            .drops(Items.DIAMOND, 1, 3)  // Drope entre 1 et 3 diamants
            .creativeTab(CreativeTabs.BUILDING_BLOCKS)
            .onBreak(ctx -> System.out.println("Minerai de rubis mine !"))
            .register();

        BLOC_RUBIS = EriBlock.create("monmod", "bloc_rubis")
            .material(Material.IRON)
            .hardness(5.0f)
            .resistance(30.0f)
            .harvestTool("pickaxe", 2)
            .soundType(SoundType.METAL)
            .creativeTab(CreativeTabs.BUILDING_BLOCKS)
            .register();

        // Hitbox simple : demi-bloc (8 pixels de haut)
        // 1.0 = 1 bloc = 16 pixels
        DEMI_BLOC = EriBlock.create("monmod", "demi_bloc")
            .material(Material.ROCK)
            .hardness(2.0f)
            .hitbox(new AxisAlignedBB(0, 0, 0, 1, 0.5, 1))
            .register();

        // Plusieurs hitboxes : socle + pilier central
        MACHINE = EriBlock.create("monmod", "machine")
            .material(Material.IRON)
            .hardness(4.0f)
            .hitboxes(
                new AxisAlignedBB(0,    0,    0,    1,    0.25, 1),    // socle plat
                new AxisAlignedBB(0.25, 0.25, 0.25, 0.75, 1,    0.75) // pilier central
            )
            .register();
    }
}
Modele et texture du bloc

Place la texture a src/main/resources/assets/monmod/textures/blocks/minerai_rubis.png (16x16 px). Tu dois aussi fournir manuellement le blockstate et le modele dans src/main/resources/assets/monmod/blockstates/minerai_rubis.json et src/main/resources/assets/monmod/models/block/minerai_rubis.json. EriAPI enregistre uniquement la resource location du modele via ModelLoader — il ne genere aucun fichier JSON. Voir la section Bloc cube — Textures et modele JSON pour le contenu des fichiers.

Bloc cube — Textures et modele JSON

Quand tu enregistres un EriBlock cubique, EriAPI enregistre la resource location du modele aupres de Forge via ModelLoader.setCustomModelResourceLocation(), mais aucun fichier JSON n'est genere automatiquement. Tu dois fournir toi-meme le blockstate, le modele de bloc et le modele d'item dans src/main/resources/assets/<modid>/. Ces fichiers sont inclus dans le JAR du mod a la compilation.

Java — Declaration minimale (commune aux deux cas)
EriBlock.create("monmod", "mon_bloc")
    .material(Material.ROCK)
    .hardness(3.0f)
    .register();

Cas 1 — Une seule texture pour toutes les faces

Place une texture PNG et fournis le blockstate + le modele de bloc + le modele d'item. C'est le cas le plus frequent.

  • src/main/resources/assets/monmod/textures/blocks/mon_bloc.png — la texture (16x16, ou 64x64 recommande)
  • src/main/resources/assets/monmod/blockstates/mon_bloc.jsona creer manuellement
  • src/main/resources/assets/monmod/models/block/mon_bloc.jsona creer manuellement
  • src/main/resources/assets/monmod/models/item/mon_bloc.jsona creer manuellement (pour l'item en inventaire)
JSON — blockstates/mon_bloc.json (a creer manuellement)
{
    "variants": {
        "normal": { "model": "monmod:mon_bloc" }
    }
}
JSON — models/block/mon_bloc.json (a creer manuellement)
{
    "parent": "block/cube_all",
    "textures": {
        "all": "monmod:blocks/mon_bloc"
    }
}
JSON — models/item/mon_bloc.json (a creer manuellement)
{
    "parent": "monmod:block/mon_bloc"
}

Cas 2 — Une texture differente par face

Pour avoir un haut, un bas et des cotes distincts (ex : four, sapin, minerai texture), fournis le fichier models/block/mon_bloc.json avec les six faces.

JSON — models/block/mon_bloc.json (a creer manuellement)
{
    "parent": "block/cube",
    "textures": {
        "up":       "monmod:blocks/mon_bloc_top",
        "down":     "monmod:blocks/mon_bloc_bottom",
        "north":    "monmod:blocks/mon_bloc_side",
        "south":    "monmod:blocks/mon_bloc_side",
        "east":     "monmod:blocks/mon_bloc_side",
        "west":     "monmod:blocks/mon_bloc_side",
        "particle": "monmod:blocks/mon_bloc_side"
    }
}

Fichiers attendus dans ce cas :

  • src/main/resources/assets/monmod/textures/blocks/mon_bloc_top.png
  • src/main/resources/assets/monmod/textures/blocks/mon_bloc_bottom.png
  • src/main/resources/assets/monmod/textures/blocks/mon_bloc_side.png
Regle a retenir

EriAPI ne genere aucun fichier JSON. Il enregistre uniquement la resource location du modele aupres de Forge. Tous les fichiers (blockstates/, models/block/, models/item/, textures/) doivent etre fournis manuellement dans src/main/resources/assets/<modid>/.

Bloc 3D anime (EriAnimBlock)

EriAnimBlock permet de creer un bloc avec un modele Blockbench 3D et des animations. Sous le capot, il utilise un TileEntity + un TESR (Tile Entity Special Renderer) enregistres automatiquement par EriAPI.

Workflow de creation

  1. Modeliser le bloc dans Blockbench (type de projet Java Block/Item).
  2. Exporter le modele en JSON dans assets/modid/models/block/nom.json.
  3. Creer le fichier d'animations assets/modid/animations/block/nom.erianim.json.
  4. Enregistrer le bloc en Java via EriAnimBlock.create().

Fichiers requis

  • assets/modid/models/block/nom.json — modele Blockbench exporte
  • assets/modid/animations/block/nom.erianim.json — fichier d'animations
  • Les textures referencees dans le JSON Blockbench
EriAnimBlock
fr.eri.eriapi.anim.EriAnimBlock
Builder

Builder fluent pour creer un bloc anime avec modele 3D et animations.

  • EriAnimBlock create(String modid, String name)
    Cree un nouveau builder de bloc anime.
    Statique
  • EriAnimBlock material(Material mat)
    Materiau du bloc (Material.IRON, Material.WOOD, etc.).
    Fluent
  • EriAnimBlock hardness(float hardness)
    Temps de minage du bloc.
    Fluent
  • EriAnimBlock resistance(float resistance)
    Resistance aux explosions.
    Fluent
  • EriAnimBlock animation(String animFileId)
    Obligatoire. ID du fichier .erianim.json au format "modid:path/nom" (sans l'extension). Resout vers assets/modid/animations/path/nom.erianim.json.
    Fluent
  • EriAnimBlock tileEntity(Class<?> teClass)
    TileEntity custom (optionnel). Doit etendre AnimatedBlockTileEntity et avoir un constructeur public sans argument. Si non specifie, EriAPI utilise AnimatedBlockTileEntityGeneric (suffisant pour 90% des cas).

    Utilise cette option quand tu as besoin de logique custom : reagir a un event d'animation a une frame precise, enchainer plusieurs animations conditionnellement, sauvegarder un etat NBT propre au bloc, synchroniser des donnees vers le client, etc.
    Fluent
  • EriAnimBlock onRightClick(Consumer<BlockActionContext> handler)
    Callback execute quand le joueur fait un clic droit sur le bloc.
    Fluent
  • Block register()
    Finalise et enregistre le bloc + le TileEntity + le TESR associes. Retourne l'instance Block.
    Terminal
Java — Jouer une animation sur clic droit
import fr.eri.eriapi.anim.AnimatedBlockTileEntity;
import fr.eri.eriapi.anim.EriAnimBlock;
import net.minecraft.block.material.Material;

EriAnimBlock.create("monmod", "coffre_special")
    .material(Material.WOOD)
    .hardness(2.5f)
    .animation("monmod:block/coffre_special")
    .onRightClick(ctx -> {
        AnimatedBlockTileEntity te = (AnimatedBlockTileEntity)
            ctx.world.getTileEntity(ctx.pos);
        if (te != null && !te.isAnimating()) {
            te.playAnimation("open");
        }
    })
    .register();

TileEntity custom : AnimatedBlockTileEntity

Quand tu passes .tileEntity(MonTile.class) au builder, EriAPI utilise ta classe au lieu de AnimatedBlockTileEntityGeneric. Ta classe doit etendre AnimatedBlockTileEntity et avoir un constructeur public sans argument.

AnimatedBlockTileEntity
fr.eri.eriapi.anim.AnimatedBlockTileEntity
Extends

Base class a etendre pour un comportement custom. Les 3 methodes ci-dessous sont conçues pour etre surchargees.

Methodes a surcharger (protected)

  • void onAnimationEvent(AnimationEvent event)
    Appele pour chaque event declenche par l'animation (keyframes de type effect, sound, particle, custom). Utile pour spawner un son/particle a une frame precise.
    Override
  • void onAnimationComplete(String animName)
    Appele quand une animation se termine (atteint la derniere keyframe en mode ONCE / HOLD / HIDE, ou apres une boucle complete pour LOOP_N). Idaal pour chainer plusieurs animations.
    Override
  • void onAnimationCallback(String callbackName)
    Appele specifiquement pour les keyframes de type callback avec le nom du callback (defini dans le JSON animation). Permet de nommer des points precis de l'animation (ex: "chest_opened") et de reagir en Java.
    Override

Utilitaires publics (a appeler)

  • void playAnimation(String animName)
    Joue l'animation nommee avec le EndBehavior defini dans le JSON (par defaut).
    Public
  • void playAnimation(String animName, EndBehavior endBehaviorOverride)
    Joue l'animation en forçant un EndBehavior custom (ONCE, LOOP, HOLD, HIDE, LOOP_N).
    Public
  • void pauseAnimation()
    Met l'animation en pause a la frame courante (synchronise client+serveur).
    Public
  • void resumeAnimation()
    Reprend une animation mise en pause.
    Public
  • void resetAnimation()
    Retourne a la pose initiale (interpolation fluide).
    Public
  • void resetAnimation(boolean instant)
    Retourne a la pose initiale ; instant=true saute l'interpolation (snap immediat).
    Public
  • void stopAnimation()
    Arrete l'animation courante (reste a la frame courante sans revenir a la pose de base).
    Public
  • void setTexture(String target, String value)
    Remplace a la volee une texture du modele. target est la clef de texture du JSON Blockbench, value est le chemin de la nouvelle texture (ex: "monmod:blocks/core_active"). Synchronise vers le client.
    Public
  • void clearTexture(String target)
    Supprime l'override de texture sur target (retour a la texture originale du modele).
    Public
  • void clearAllTextures()
    Supprime tous les overrides de texture d'un coup.
    Public
  • boolean isAnimating()
    Retourne true si une animation est en cours.
    Public
  • String getCurrentAnimation()
    Nom de l'animation courante, ou null si aucune n'est active.
    Public
  • float getAnimationProgress()
    Progression de l'animation courante, de 0.0 a 1.0.
    Public
  • void setBlockYRotation(float rotation)
    Rotation du bloc autour de l'axe Y (degres). Synchronise vers le client.
    Public
Java — TileEntity custom avec callbacks d'animation
import fr.eri.eriapi.anim.AnimatedBlockTileEntity;
import fr.eri.eriapi.anim.AnimationEvent;

public class TileEntityCoffreSpecial extends AnimatedBlockTileEntity {

    public TileEntityCoffreSpecial() {
        super("monmod:block/coffre_special", "monmod:block/coffre_special");
    }

    @Override
    protected void onAnimationEvent(AnimationEvent event) {
        // Ex: jouer un son a une frame precise
        if ("creak".equals(event.getValue())) {
            world.playSound(null, pos, SoundEvents.BLOCK_CHEST_OPEN,
                SoundCategory.BLOCKS, 1.0f, 1.0f);
        }
    }

    @Override
    protected void onAnimationComplete(String animName) {
        // Ex: chainer une autre animation
        if ("open".equals(animName)) {
            playAnimation("idle_open", EndBehavior.LOOP);
        }
    }

    @Override
    protected void onAnimationCallback(String callbackName) {
        // Ex: spawner le loot a un point precis
        if ("spawn_loot".equals(callbackName) && !world.isRemote) {
            spawnLootAt(pos);
        }
    }
}

// Enregistrement :
EriAnimBlock.create("monmod", "coffre_special")
    .material(Material.WOOD)
    .animation("monmod:block/coffre_special")
    .tileEntity(TileEntityCoffreSpecial.class)
    .onRightClick(ctx -> {
        TileEntityCoffreSpecial te = (TileEntityCoffreSpecial)
            ctx.world.getTileEntity(ctx.pos);
        if (te != null && !te.isAnimating()) {
            te.playAnimation("open");
        }
    })
    .register();
Animations avancees

Pour des comportements plus complexes (callbacks sur events d'animation, enchainements conditionnels, logique tick), cree une sous-classe de AnimatedBlockTileEntity et passe-la via .tileEntity(TileCustom.class). Voir la page Animation System pour le detail complet.

EriRecipe

EriRecipe permet de definir des recettes de craft et de fusion de maniere declarative. Il supporte trois types de recettes : avec forme (shaped), sans forme (shapeless) et au four (smelting).

Quand enregistrer les recettes ?

Enregistre tes recettes apres avoir initialise tes items et blocs. Tu peux les placer dans une methode appelee depuis @Mod.EventHandler public void init(FMLInitializationEvent event).

Recette avec forme — EriRecipe.shaped()

Une recette avec forme (shaped recipe) necessite que les ingredients soient places dans un ordre precis dans la grille de craft. C'est le type le plus courant (epees, outils, etc.).

EriRecipe.shaped()
fr.eri.eriapi.content.EriRecipe
Shaped
  • ShapedBuilder shaped(String modid, String name)
    Cree un builder de recette avec forme. name est un identifiant unique pour la recette.
    Statique
  • ShapedBuilder pattern(String... rows)
    Definit le patron de la recette avec des chaines de caracteres representant les lignes de la grille 3x3. Chaque caractere est un ingredient (ou un espace pour une case vide).
    Fluent
  • ShapedBuilder key(char key, Item item)
    Associe un caractere du patron a un item. Peut etre appele plusieurs fois pour plusieurs caracteres.
    Fluent
  • ShapedBuilder key(char key, Block block)
    Variante qui accepte un Block comme ingredient.
    Fluent
  • ShapedBuilder result(Item item, int count)
    L'item produit par la recette et sa quantite.
    Fluent
  • ShapedBuilder result(Block block, int count)
    Variante qui produit un bloc.
    Fluent
  • void register()
    Enregistre la recette dans Forge.
    Terminal
Java — Recette shaped : bloc de rubis (3x3 rubis)
// Patron de craft :
// R R R
// R R R
// R R R
EriRecipe.shaped("monmod", "bloc_rubis")
    .pattern("RRR", "RRR", "RRR")
    .key('R', MonItems.RUBIS)
    .result(MonBlocs.BLOC_RUBIS, 1)
    .register();

// Patron epee :
//   R
//   R
//   B  (baton)
EriRecipe.shaped("monmod", "epee_rubis")
    .pattern(" R ", " R ", " B ")
    .key('R', MonItems.RUBIS)
    .key('B', Items.STICK)
    .result(MonItems.EPEE_RUBIS, 1)
    .register();

Recette sans forme — EriRecipe.shapeless()

Une recette sans forme (shapeless recipe) ne requiert aucun arrangement particulier des ingredients dans la grille — il suffit qu'ils soient tous presents. Utile pour les conversions simples.

EriRecipe.shapeless()
fr.eri.eriapi.content.EriRecipe
Shapeless
  • ShapelessBuilder shapeless(String modid, String name)
    Cree un builder de recette sans forme.
    Statique
  • ShapelessBuilder ingredient(Item item)
    Ajoute un ingredient a la recette. Peut etre appele plusieurs fois.
    Fluent
  • ShapelessBuilder ingredient(Block block)
    Variante qui accepte un Block comme ingredient.
    Fluent
  • ShapelessBuilder result(Item item, int count)
    L'item produit et sa quantite.
    Fluent
  • void register()
    Enregistre la recette dans Forge.
    Terminal
Java — Recette shapeless : defaire un bloc de rubis
// 1 bloc de rubis → 9 rubis (ordre non important)
EriRecipe.shapeless("monmod", "rubis_depuis_bloc")
    .ingredient(MonBlocs.BLOC_RUBIS)
    .result(MonItems.RUBIS, 9)
    .register();

Recette de fusion — EriRecipe.smelting()

Une recette de fusion (smelting recipe) definit ce que produit un item ou bloc quand il est chauffe dans un four. Tu peux aussi specifier les points d'experience gagnes.

EriRecipe.smelting()
fr.eri.eriapi.content.EriRecipe
Smelting
  • SmeltingBuilder smelting(String modid, String name)
    Cree un builder de recette de fusion.
    Statique
  • SmeltingBuilder input(Item item)
    L'item a fondre.
    Fluent
  • SmeltingBuilder input(Block block)
    Variante qui accepte un Block comme input.
    Fluent
  • SmeltingBuilder result(Item item)
    L'item produit par la fusion (toujours 1 exemplaire).
    Fluent
  • SmeltingBuilder xp(float xp)
    Points d'experience gagnes par fusion. Le minerai de fer vanilla donne 0.7f, le diamant 1.0f.
    Fluent
  • void register()
    Enregistre la recette de fusion dans Forge.
    Terminal
Java — Recette smelting : fondre le minerai de rubis
// Minerai de rubis → rubis (avec 1.0 XP)
EriRecipe.smelting("monmod", "rubis_fusion")
    .input(MonBlocs.MINERAI_RUBIS)
    .result(MonItems.RUBIS)
    .xp(1.0f)
    .register();

Exemple complet — Un mod avec un minerai

Voici un exemple complet qui cree un set de contenu coherent : un minerai, un item gemme, un bloc compresse, une epee, et toutes les recettes associees.

Java — MonMod.java (classe principale)
@Mod(modid = "monmod", name = "Mon Mod", version = "1.0")
public class MonMod {

    @Mod.EventHandler
    public void preInit(FMLPreInitializationEvent event) {
        ContentRegistry.register(this);  // 1. Initialise le registre EriAPI

        // 2. Cree les items et blocs
        MonItems.init();
        MonBlocs.init();
    }

    @Mod.EventHandler
    public void init(FMLInitializationEvent event) {
        // 3. Enregistre les recettes (apres les items et blocs)
        MonRecettes.init();
    }
}
Java — MonItems.java
public class MonItems {

    public static Item RUBIS;
    public static Item EPEE_RUBIS;

    public static void init() {
        RUBIS = EriItem.create("monmod", "rubis")
            .maxStackSize(64)
            .rarity(EnumRarity.RARE)
            .tooltip("&7Gemme precieuse extraite du sol")
            .creativeTab(CreativeTabs.MATERIALS)
            .register();

        EPEE_RUBIS = EriItem.create("monmod", "epee_rubis")
            .tool()
                .type(ToolType.SWORD)
                .damage(8f)
                .durability(1500)
                .speed(1.6f)
                .done()
            .rarity(EnumRarity.RARE)
            .tooltip("&cForge dans le feu du rubis")
            .creativeTab(CreativeTabs.COMBAT)
            .register();
    }
}
Java — MonBlocs.java
public class MonBlocs {

    public static Block MINERAI_RUBIS;
    public static Block BLOC_RUBIS;

    public static void init() {
        MINERAI_RUBIS = EriBlock.create("monmod", "minerai_rubis")
            .material(Material.ROCK)
            .hardness(3.0f)
            .resistance(15.0f)
            .harvestTool("pickaxe", 2)
            .soundType(SoundType.STONE)
            .drops(MonItems.RUBIS, 1, 2)
            .creativeTab(CreativeTabs.BUILDING_BLOCKS)
            .register();

        BLOC_RUBIS = EriBlock.create("monmod", "bloc_rubis")
            .material(Material.IRON)
            .hardness(5.0f)
            .resistance(30.0f)
            .harvestTool("pickaxe", 2)
            .soundType(SoundType.METAL)
            .creativeTab(CreativeTabs.BUILDING_BLOCKS)
            .register();
    }
}
Java — MonRecettes.java
public class MonRecettes {

    public static void init() {
        // Bloc de rubis depuis 9 rubis
        EriRecipe.shaped("monmod", "bloc_rubis_craft")
            .pattern("RRR", "RRR", "RRR")
            .key('R', MonItems.RUBIS)
            .result(MonBlocs.BLOC_RUBIS, 1)
            .register();

        // Defaire le bloc → 9 rubis
        EriRecipe.shapeless("monmod", "rubis_depuis_bloc")
            .ingredient(MonBlocs.BLOC_RUBIS)
            .result(MonItems.RUBIS, 9)
            .register();

        // Fondre le minerai → rubis
        EriRecipe.smelting("monmod", "rubis_fusion")
            .input(MonBlocs.MINERAI_RUBIS)
            .result(MonItems.RUBIS)
            .xp(1.0f)
            .register();

        // Craft de l'epee de rubis
        EriRecipe.shaped("monmod", "epee_rubis_craft")
            .pattern(" R ", " R ", " B ")
            .key('R', MonItems.RUBIS)
            .key('B', Items.STICK)
            .result(MonItems.EPEE_RUBIS, 1)
            .register();
    }
}

EriEntity v2.0

EriEntity est le builder fluent pour enregistrer des entites custom avec un modele Blockbench anime. Il fonctionne de pair avec AnimatedEntityRenderer et l'interface IAnimatedEntity pour le rendu anime des entites.

Auto-enregistrement

Depuis v1.4.0, EriEntity.register() enregistre automatiquement l'entite dans Forge via un pool de 32 slots pre-compiles (GeneratedEntitySlot0GeneratedEntitySlot31). Le mod n'a plus besoin de gerer l'EntityEntry ou le renderer manuellement. Un maximum de 32 types d'entites EriEntity peut etre enregistre par mod.

Classes principales

ClassePackageRole
EriEntityfr.eri.eriapi.contentBuilder fluent pour definir une entite
EntityDefinitionfr.eri.eriapi.contentPOJO contenant la configuration de l'entite
EntitySeatfr.eri.eriapi.contentDefinition d'un siege passager
AnimatedEntityRendererfr.eri.eriapi.animRenderer d'entite utilisant des modeles Blockbench
IAnimatedEntityfr.eri.eriapi.animInterface pour les entites avec animation

Methodes du builder EriEntity

  • EriEntity create(String modId, String registryName)
    Cree un nouveau builder d'entite. Methode statique.
    Factory
  • EriEntity model(String modelId)
    Definit le modele Blockbench (ex: "eriniumfaction:entity/monstre").
    Fluent
  • EriEntity texture(String key, String path)
    Associe une cle de texture du modele a un chemin de ResourceLocation.
    Fluent
  • EriEntity animation(String name, String animId)
    Associe un nom d'animation (ex: "idle", "walk") a un identifiant d'animation .erianim.
    Fluent
  • EriEntity hitbox(float width, float height)
    Definit les dimensions de la hitbox (defaut: 0.6 x 1.8).
    Fluent
  • EriEntity seat(float x, float y, float z)
    Ajoute un siege passager simple aux coordonnees Blockbench donnees.
    Fluent
  • EriEntity seat(float x, float y, float z, String attachedGroup)
    Ajoute un siege attache a un groupe du modele (suit les animations du groupe).
    Fluent
  • EriEntity seat(float x, float y, float z, float yawOffset, String attachedGroup, boolean lockCamera)
    Ajoute un siege complet avec rotation yaw, groupe attache et verrouillage camera.
    Fluent
  • EriEntity spawnEgg(int primary, int secondary)
    Active un spawn egg avec les couleurs primaire et secondaire (format 0xRRGGBB).
    Fluent
  • EriEntity creativeTab(String tabName)
    Definit l'onglet creatif pour le spawn egg.
    Fluent
  • EriEntity register()
    Enregistre la definition dans le ContentRegistry ET enregistre automatiquement l'EntityEntry, le renderer, le spawn egg et les regles de spawn dans Forge via le pool de 32 slots (v1.4.0).
    Terminal

Methodes avancees (v1.4.0)

  • EriEntity name(String displayName)
    Nom d'affichage de l'entite.
    Fluent
  • EriEntity health(double health)
    PV max de l'entite (defaut: 20.0).
    Fluent
  • EriEntity armor(double armor)
    Valeur d'armure (defaut: 0).
    Fluent
  • EriEntity armorToughness(double toughness)
    Robustesse de l'armure (defaut: 0).
    Fluent
  • EriEntity attackDamage(double damage)
    Degats au corps a corps (defaut: 2.0).
    Fluent
  • EriEntity movementSpeed(double speed)
    Vitesse de deplacement (defaut: 0.25).
    Fluent
  • EriEntity followRange(double range)
    Portee de detection des cibles (defaut: 16).
    Fluent
  • EriEntity knockbackResistance(double resist)
    Resistance au knockback, 0.0–1.0 (defaut: 0).
    Fluent
  • EriEntity immuneToFire()
    L'entite est immunisee au feu.
    Fluent
  • EriEntity immuneToKnockback()
    L'entite est immunisee au knockback.
    Fluent
  • EriEntity canSwim(boolean swim)
    Definit si l'entite peut nager (defaut: true).
    Fluent
  • EriEntity experienceDrop(int min, int max)
    XP droppee a la mort (valeur aleatoire entre min et max).
    Fluent
  • EriEntity ambientSound(SoundEvent sound)
    Son ambiant.
    Fluent
  • EriEntity hurtSound(SoundEvent sound)
    Son de degats.
    Fluent
  • EriEntity deathSound(SoundEvent sound)
    Son de mort.
    Fluent
  • EriEntity stepSound(SoundEvent sound)
    Son de pas.
    Fluent
  • EriEntity ambientSoundInterval(int ticks)
    Intervalle entre sons ambiants (defaut: 80 ticks).
    Fluent
  • EriEntity aiPreset(AiPreset preset)
    Comportement IA predefini. Valeurs : PASSIVE, HOSTILE_MELEE, HOSTILE_RANGED, NEUTRAL, BOSS.
    Fluent
  • EriEntity ai(Consumer<PathfinderBuilder> config)
    Configuration IA custom via PathfinderBuilder (voir section dediee ci-dessous).
    Fluent
  • EriEntity drop(ItemStack stack, float chance)
    Drop d'item a la mort (chance: 0.0–1.0).
    Fluent
  • EriEntity drop(Item item, int min, int max, float chance)
    Drop aleatoire entre min et max items.
    Fluent
  • EriEntity rareDrop(ItemStack stack, float chance)
    Drop rare (chance divisee par looting level).
    Fluent
  • EriEntity spawn(Consumer<EriSpawner> config)
    Regles de spawn naturel (voir section EriSpawner).
    Fluent
  • EriEntity tracker(int range, int freq, boolean velocity)
    Parametres de tracking reseau (defaut: 64, 3, true).
    Fluent
  • EriEntity onSpawn(Consumer<EntityLivingBase> cb)
    Callback appele au spawn initial.
    Fluent
  • EriEntity onDeath(BiConsumer<EntityLivingBase, DamageSource> cb)
    Callback a la mort.
    Fluent
  • EriEntity onUpdate(Consumer<EntityLivingBase> cb)
    Callback chaque tick (onLivingUpdate).
    Fluent
  • EriEntity onAttack(BiConsumer<EntityLivingBase, Entity> cb)
    Callback quand l'entite attaque.
    Fluent
  • EriEntity onHurt(BiConsumer<EntityLivingBase, DamageSource> cb)
    Callback quand l'entite recoit des degats.
    Fluent
  • EriEntity onInteract(BiConsumer<EntityLivingBase, EntityPlayer> cb)
    Callback quand un joueur clic droit sur l'entite.
    Fluent

AnimatedEntityRenderer

Le renderer d'entite qui affiche un modele Blockbench avec animations. Le pipeline de rendu (groupes, elements, faces, UV) est identique a AnimatedBlockTESR.

  • IRenderFactory<T> factory(String modelId)
    Cree une factory pour RenderingRegistry.registerEntityRenderingHandler().
    Factory
  • IRenderFactory<T> factory(String modelId, float shadowSize)
    Factory avec taille d'ombre personnalisee.
    Factory

IAnimatedEntity

Interface que les entites doivent implementer pour supporter le rendu anime. Le renderer verifie cette interface pour obtenir la pose d'animation.

  • AnimationPose getCurrentPose(float partialTicks)
    Retourne la pose interpolee courante, ou null si aucune animation n'est active.
  • AnimState getAnimState()
    Retourne l'etat d'animation courant de l'entite.

EntitySeat

Chaque entite peut avoir un ou plusieurs sieges pour les passagers. Les coordonnees sont en pixels Blockbench (meme espace de coordonnees que le modele).

ChampTypeDescription
x, y, zfloatPosition du siege en pixels Blockbench (local a l'entite).
yawOffsetfloatRotation yaw du passager en degres (defaut: 0).
attachedGroupStringNom du groupe du modele auquel le siege est attache (peut etre null). Le siege suit les animations du groupe.
lockCamerabooleanSi true, la camera du joueur assis est verrouillee (defaut: false).
Java — Exemple complet EriEntity (v1.4.0)
// Dans preInit() — auto-enregistrement complet
EriEntity.create("monmod", "garde_elite")
    .model("monmod:entity/garde")
    .texture("body", "monmod:textures/entity/garde_body")
    .animation("idle", "monmod:entity/garde_idle")
    .animation("walk", "monmod:entity/garde_walk")
    .animation("attack", "monmod:entity/garde_attack")
    .hitbox(0.7f, 2.0f)
    .name("Garde Elite")
    .health(40).attackDamage(6).armor(4).movementSpeed(0.28)
    .hurtSound(SoundEvents.ENTITY_ZOMBIE_HURT)
    .deathSound(SoundEvents.ENTITY_ZOMBIE_DEATH)
    .aiPreset(AiPreset.HOSTILE_MELEE)
    .ai(ai -> ai.swim().meleeAttack(1.1, false).wander(0.8).watchPlayers(16f).lookIdle().targetPlayers().hurtByTarget(true))
    .drop(new ItemStack(Items.IRON_SWORD), 0.05f)
    .drop(Items.IRON_INGOT, 0, 2, 0.4f)
    .experienceDrop(5, 15)
    .spawn(s -> s.type(EnumCreatureType.MONSTER).weight(8).group(1, 3).lightLevel(0, 7).dimension(0))
    .spawnEgg(0x2C2C2C, 0xFFD700)
    .onDeath((entity, src) -> EriniumFaction.LOGGER.info("Garde tue par {}", src.getDamageType()))
    .register();
// C'est tout ! Pas de EntityEntry manuel, pas de RenderingRegistry manuel.

PathfinderBuilder v2.0

Builder fluent pour configurer les AI tasks d'une entite EriEntity. Utilise dans EriEntity.ai(Consumer<PathfinderBuilder>). Les tasks sont appliquees dans l'ordre d'appel.

Goal tasks

  • PathfinderBuilder swim()
    Permet a l'entite de nager quand elle est dans l'eau.
    Fluent
  • PathfinderBuilder meleeAttack(double speed, boolean longMemory)
    Attaque au corps a corps. longMemory continue de poursuivre la cible meme perdue de vue.
    Fluent
  • PathfinderBuilder wander(double speed)
    Deplacement aleatoire en idle.
    Fluent
  • PathfinderBuilder watchClosest(Class<EntityLivingBase> target, float distance)
    L'entite regarde l'entite cible la plus proche dans la distance donnee.
    Fluent
  • PathfinderBuilder watchPlayers(float distance)
    Raccourci : regarde le joueur le plus proche.
    Fluent
  • PathfinderBuilder lookIdle()
    Regard aleatoire en idle.
    Fluent
  • PathfinderBuilder panicOnHurt(double speed)
    L'entite panique et fuit quand elle est blessee.
    Fluent
  • PathfinderBuilder leapAtTarget(float motionY)
    L'entite saute sur sa cible avec la vitesse verticale donnee.
    Fluent
  • PathfinderBuilder avoidEntity(Class cls, float distance, double walkSpeed, double sprintSpeed)
    Evite les entites de la classe donnee (fuite a walkSpeed, sprint a sprintSpeed).
    Fluent
  • PathfinderBuilder openDoors(boolean closeBehind)
    L'entite peut ouvrir les portes. closeBehind les referme derriere elle.
    Fluent

Target tasks

  • PathfinderBuilder targetPlayers()
    Cible les joueurs a portee.
    Fluent
  • PathfinderBuilder targetClass(Class cls)
    Cible une classe d'entite specifique.
    Fluent
  • PathfinderBuilder hurtByTarget(boolean callForHelp)
    Riposte contre l'attaquant. callForHelp appelle les allies du meme type.
    Fluent

Tasks custom

  • PathfinderBuilder task(EntityAIBase ai)
    Ajoute un goal task custom deja instancie.
    Fluent
  • PathfinderBuilder targetTask(EntityAIBase ai)
    Ajoute un target task custom deja instancie.
    Fluent
  • PathfinderBuilder task(Function<EntityLiving, EntityAIBase> factory)
    Factory qui construit le goal task a partir de l'instance de l'entite.
    Fluent
  • PathfinderBuilder targetTask(Function<EntityLiving, EntityAIBase> factory)
    Factory qui construit le target task a partir de l'instance de l'entite.
    Fluent
Java — Exemple PathfinderBuilder
EriEntity.create("monmod", "garde")
    .health(30).attackDamage(4)
    .aiPreset(AiPreset.HOSTILE_MELEE)
    .ai(ai -> ai
        .swim()
        .meleeAttack(1.0, false)
        .wander(0.8)
        .watchPlayers(12f)
        .lookIdle()
        .targetPlayers()
        .hurtByTarget(true))
    .register();

EriSpawner v2.0

Builder fluent pour configurer les regles de spawn naturel d'une entite. Utilise dans EriEntity.spawn(Consumer<EriSpawner>). Les regles sont enregistrees automatiquement dans Forge via EntityRegistry.addSpawn().

Methodes du builder

  • EriSpawner type(EnumCreatureType type)
    Categorie de creature : MONSTER, CREATURE, AMBIENT, WATER_CREATURE.
    Fluent
  • EriSpawner weight(int weight)
    Poids du spawn (plus eleve = plus frequent).
    Fluent
  • EriSpawner group(int min, int max)
    Taille du groupe au spawn (valeur aleatoire entre min et max).
    Fluent
  • EriSpawner dimension(int... ids)
    Dimensions autorisees (0 = Overworld, -1 = Nether, 1 = End).
    Fluent
  • EriSpawner biome(Biome... biomes)
    Biomes autorises pour le spawn.
    Fluent
  • EriSpawner excludeBiome(Biome... biomes)
    Biomes interdits pour le spawn.
    Fluent
  • EriSpawner lightLevel(int min, int max)
    Plage de niveau de lumiere pour le spawn (0–15).
    Fluent
  • EriSpawner heightRange(int min, int max)
    Plage d'altitude Y pour le spawn.
    Fluent
  • EriSpawner maxPerChunk(int max)
    Nombre maximum d'entites de ce type par chunk.
    Fluent
  • EriSpawner despawnDistance(int blocks)
    Distance (en blocks) au-dela de laquelle l'entite despawn.
    Fluent
Java — Exemple EriSpawner
EriEntity.create("monmod", "zombie_garde")
    .health(20).attackDamage(3)
    .aiPreset(AiPreset.HOSTILE_MELEE)
    .spawn(s -> s
        .type(EnumCreatureType.MONSTER)
        .weight(10)
        .group(2, 4)
        .lightLevel(0, 7)
        .dimension(0)
        .maxPerChunk(8))
    .register();

EriProjectile v2.0

Builder fluent pour enregistrer des projectiles custom avec physique, combat, visuel et callbacks d'impact. Auto-enregistrement Forge via un pool de 32 slots (GeneratedProjectileSlot0GeneratedProjectileSlot31) : pas besoin de sous-classer EntityThrowable ou d'enregistrer manuellement l'EntityEntry.

Factory

  • EriProjectile create(String modId, String registryName)
    Cree un nouveau builder de projectile. Methode statique.
    Factory

Physique

  • EriProjectile velocity(float velocity)
    Vitesse initiale du projectile.
    Fluent
  • EriProjectile gravity(float gravity)
    Gravite appliquee par tick (0 = pas de gravite).
    Fluent
  • EriProjectile inaccuracy(float inaccuracy)
    Imprecision aleatoire du tir.
    Fluent
  • EriProjectile lifetime(int ticks)
    Duree de vie max du projectile en ticks.
    Fluent
  • EriProjectile piercing(int maxEntities)
    Le projectile traverse jusqu'a N entites avant disparition.
    Fluent
  • EriProjectile bouncing(int maxBounces)
    Le projectile rebondit N fois sur les blocs.
    Fluent

Combat

  • EriProjectile damage(float damage)
    Degats infliges a l'impact.
    Fluent
  • EriProjectile damageType(DamageSource type)
    Type de degats custom (defaut: thrown).
    Fluent
  • EriProjectile knockback(float knockback)
    Force de knockback a l'impact.
    Fluent
  • EriProjectile setFire(int seconds)
    Met le feu a l'entite touchee pendant N secondes.
    Fluent

Visuel

  • EriProjectile texture(ResourceLocation texture)
    Texture du projectile.
    Fluent
  • EriProjectile renderAsItem(ItemStack stack)
    Rend le projectile comme un item 3D au lieu d'une texture plate.
    Fluent
  • EriProjectile scale(float scale)
    Echelle de rendu.
    Fluent
  • EriProjectile glowing(boolean glow)
    Le projectile brille (fullbright).
    Fluent
  • EriProjectile trailParticle(EnumParticleTypes particle)
    Particules laissees dans le sillage du projectile.
    Fluent
  • EriProjectile trailColor(int argb)
    Couleur de la trainee (format ARGB).
    Fluent

Callbacks & effets d'impact

  • EriProjectile onHitEntity(BiConsumer<Entity, Entity> cb)
    Callback (projectile, cible) quand le projectile touche une entite.
    Fluent
  • EriProjectile onHitBlock(BiConsumer<Entity, BlockPos> cb)
    Callback (projectile, pos) quand le projectile touche un bloc.
    Fluent
  • EriProjectile onExpire(Consumer<Entity> cb)
    Callback quand le projectile expire (lifetime ecoule).
    Fluent
  • EriProjectile explosionOnImpact(float power, boolean fire)
    Declenche une explosion a l'impact.
    Fluent
  • EriProjectile potionOnImpact(PotionEffect effect, float radius)
    Eclaboussure de potion dans un rayon donne.
    Fluent
  • EriProjectile aoeOnImpact(float radius, float damage)
    Degats de zone dans un rayon (pas d'explosion, pas de destruction).
    Fluent

Spawn egg & tracker

  • EriProjectile spawnEgg(int primary, int secondary)
    Active un spawn egg (format 0xRRGGBB).
    Fluent
  • EriProjectile tracker(int range, int freq, boolean velocity)
    Parametres de tracking reseau (defaut: 64, 10, true).
    Fluent

Enregistrement & tir

  • EriProjectile register()
    Enregistre le projectile dans Forge via le slot pool et retourne le builder (utilisable ensuite pour spawn()).
    Terminal
  • Entity spawn(World world, Entity shooter)
    Instancie et tire le projectile depuis une entite (position et direction du shooter).
    Action
  • Entity spawnAt(World world, double x, double y, double z, float yaw, float pitch)
    Tire le projectile depuis des coordonnees et une direction precises.
    Action
Java — Exemple EriProjectile
EriProjectile fireball = EriProjectile.create("monmod", "fireball")
    .velocity(1.8f)
    .gravity(0.02f)
    .damage(6.0f)
    .setFire(3)
    .knockback(0.5f)
    .texture(new ResourceLocation("monmod", "textures/entity/fireball"))
    .explosionOnImpact(2.0f, true)
    .onHitEntity((proj, target) -> target.setFire(60))
    .register();

// Tirer depuis une entite
fireball.spawn(world, shooterEntity);

// Tirer depuis coordonnees
fireball.spawnAt(world, x, y, z, yaw, pitch);

EntityDataSync / @SyncParam v2.0

Gestion automatique des DataParameter d'une entite via annotations. Declare un champ avec @SyncParam, appelle EntityDataSync.register(this) dans entityInit(), puis utilise get() / set() type-safe sans reflexion en hot path. Persistence NBT automatique pour les champs marques persistent = true.

@SyncParam

  • @interface SyncParam
    Annotation a placer sur un champ d'entite pour l'inclure dans la synchronisation client/serveur.
  • boolean persistent() default true
    Si false, le champ n'est pas sauvegarde en NBT (perdu au restart).
  • String nbtKey() default ""
    Cle NBT custom. Si vide, le nom du champ Java est utilise.

EntityDataSync

  • void register(EntityLiving entity)
    A appeler dans entityInit() apres super.entityInit(). Scanne les champs @SyncParam par reflexion (une seule fois par classe) et cree les DataParameter correspondants.
    Static
  • T get(EntityLiving entity, String fieldName)
    Lit la valeur synchronisee d'un champ. Zero reflexion au runtime.
    Static
  • void set(EntityLiving entity, String fieldName, Object value)
    Ecrit la valeur synchronisee d'un champ (propage automatiquement au client).
    Static
  • void writeNBT(EntityLiving entity, NBTTagCompound tag)
    A appeler dans writeEntityToNBT(). Serialise tous les champs persistent = true.
    Static
  • void readNBT(EntityLiving entity, NBTTagCompound tag)
    A appeler dans readEntityFromNBT(). Deserialise tous les champs persistent = true.
    Static

Types supportes

boolean, int, float, String, ItemStack, BlockPos, ITextComponent.

Java — Exemple complet @SyncParam
public class EntityGarde extends EntityMob {

    @SyncParam private boolean isEnraged = false;
    @SyncParam private int variant = 0;
    @SyncParam(persistent = false) private float animBlend = 0f;
    @SyncParam(nbtKey = "rage_level") private int rageLevel = 0;

    @Override
    protected void entityInit() {
        super.entityInit();
        EntityDataSync.register(this);
    }

    public void setEnraged(boolean v) { EntityDataSync.set(this, "isEnraged", v); }
    public boolean isEnraged()        { return EntityDataSync.get(this, "isEnraged"); }

    @Override
    public void writeEntityToNBT(NBTTagCompound tag) {
        super.writeEntityToNBT(tag);
        EntityDataSync.writeNBT(this, tag);
    }

    @Override
    public void readEntityFromNBT(NBTTagCompound tag) {
        super.readEntityFromNBT(tag);
        EntityDataSync.readNBT(this, tag);
    }
}

EriEntityBase v1.5.0

EriEntityBase est la classe de base a etendre quand tu veux une entite avec une logique Java custom (override de methodes, champs synchronises, NBT specifique) tout en gardant l'auto-configuration EriEntity (stats, AI, sons, drops, callbacks).

Sans cette classe, EriAPI genere l'entite dans un slot pre-compile du pool GeneratedEntitySlots (limite a 32). Avec .entityClass(MonEntite.class), ta classe est enregistree directement dans Forge — tu peux donc surcharger n'importe quelle methode de EntityMob / EntityLivingBase.

EriEntityBase
fr.eri.eriapi.content.EriEntityBase
Extends EntityMob

Classe de base a etendre pour une entite custom. Mirrors la logique de GeneratedEntity mais permet le sous-classement.

Contrat d'extension

  • Extend EriEntityBase
  • Avoir un constructeur public : public MyEntity(World world) { super(world); }
  • Si tu utilises @SyncParam, appelle EntityDataSync.register(this) dans entityInit() apres super.entityInit()
  • Tu peux surcharger n'importe quelle methode ; appelle super pour conserver les comportements EriEntity (sons, drops, callbacks...)

Champs proteges accessibles

  • EntityDefinition eriDef
    La definition qui pilote l'entite. May be null si misconfigure.
    protected
  • String eriDefId
    Id canonique (modId:registryName) utilise pour la restauration NBT.
    protected

Accesseurs publics

  • EntityDefinition getEriDef()
    Retourne la EntityDefinition qui pilote cette entite.
    Public
  • String getEriDefId()
    Retourne l'id canonique (modId:registryName).
    Public
EriEntity.entityClass()
fr.eri.eriapi.content.EriEntity
Builder
  • EriEntity entityClass(Class<? extends EriEntityBase> clazz)
    Specifie une classe Java custom. Quand cette methode est appelee, EriAPI enregistre directement ta classe dans Forge au lieu d'utiliser un slot pre-compile. La classe doit etendre EriEntityBase et avoir un constructeur public MyEntity(World world).
    Fluent
Java — Boss avec champ synchronise @SyncParam
import fr.eri.eriapi.content.*;
import net.minecraft.world.World;

public class EntityBoss extends EriEntityBase {

    @SyncParam public boolean isEnraged = false;
    @SyncParam public int phase = 1;

    public EntityBoss(World world) {
        super(world);
    }

    @Override
    protected void entityInit() {
        super.entityInit();
        EntityDataSync.register(this);
    }

    @Override
    public void onLivingUpdate() {
        super.onLivingUpdate();
        // Passe en phase 2 sous 50% de vie
        if (!world.isRemote && phase == 1 && getHealth() < getMaxHealth() * 0.5f) {
            EntityDataSync.set(this, "phase", 2);
            EntityDataSync.set(this, "isEnraged", true);
        }
    }
}

// Enregistrement :
EriEntity.create("monmod", "boss")
    .health(200).attackDamage(12).armor(10)
    .aiPreset(AiPreset.BOSS)
    .entityClass(EntityBoss.class)   // ← classe custom
    .spawnEgg(0x8B0000, 0xFF4500)
    .register();
Quand utiliser EriEntityBase ?

Utilise EriEntityBase quand tu as besoin de champs synchronises (@SyncParam), de NBT custom, d'override de onLivingUpdate() ou d'autres methodes vanilla. Pour les entites simples (stats + AI + drops), les callbacks du builder (onSpawn, onUpdate, onDeath, etc.) suffisent — pas besoin de creer une classe.

EriProjectileBase v1.5.0

EriProjectileBase est la classe de base a etendre quand tu veux un projectile avec une logique Java custom (trajectoire speciale, effets custom a l'impact, homing) tout en gardant l'auto-configuration EriProjectile (velocite, gravite, piercing, bouncing, explosion, AOE, potion).

EriProjectileBase
fr.eri.eriapi.content.EriProjectileBase
Extends EntityThrowable

Classe de base a etendre pour un projectile custom.

Contrat d'extension

  • Extend EriProjectileBase
  • Constructeur obligatoire : public MyProjectile(World world) { super(world); }
  • Constructeur optionnel : public MyProjectile(World world, EntityLivingBase thrower)
  • Appelle super dans tes overrides pour conserver piercing, bouncing, AOE, etc.

Champs proteges accessibles

  • ProjectileDefinition eriDef
    La definition qui pilote ce projectile.
    protected
  • String eriDefId
    Id canonique (modId:registryName) utilise pour le log NBT.
    protected
  • int pierceCount
    Nombre d'entites que ce projectile a deja percees.
    protected
  • int bounceCount
    Nombre de blocs sur lesquels ce projectile a deja rebondi.
    protected
  • int ticksAlive
    Nombre de ticks depuis le spawn du projectile.
    protected
EriProjectile.projectileClass()
fr.eri.eriapi.content.EriProjectile
Builder
  • EriProjectile projectileClass(Class<? extends EriProjectileBase> clazz)
    Specifie une classe Java custom. Quand cette methode est appelee, EriAPI enregistre directement ta classe dans Forge au lieu d'utiliser un slot pre-compile de GeneratedProjectileSlots.
    Fluent
Java — Missile a tete chercheuse
import fr.eri.eriapi.content.*;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.world.World;

public class ProjectileMissile extends EriProjectileBase {

    public ProjectileMissile(World world) { super(world); }
    public ProjectileMissile(World world, EntityLivingBase thrower) {
        super(world, thrower);
    }

    @Override
    public void onUpdate() {
        super.onUpdate();

        // Tete chercheuse : corrige la trajectoire vers la cible la plus proche
        if (!world.isRemote && ticksExisted % 5 == 0) {
            EntityLivingBase target = findNearestTarget();
            if (target != null) {
                double dx = target.posX - posX;
                double dy = target.posY + target.height * 0.5 - posY;
                double dz = target.posZ - posZ;
                double len = Math.sqrt(dx*dx + dy*dy + dz*dz);
                double speed = 0.4;
                motionX = dx / len * speed;
                motionY = dy / len * speed;
                motionZ = dz / len * speed;
            }
        }
    }

    private EntityLivingBase findNearestTarget() {
        AxisAlignedBB aabb = new AxisAlignedBB(posX-16, posY-16, posZ-16,
                                                posX+16, posY+16, posZ+16);
        EntityLivingBase nearest = null;
        double best = Double.MAX_VALUE;
        for (EntityLivingBase e : world.getEntitiesWithinAABB(EntityLivingBase.class, aabb)) {
            if (e == getThrower()) continue;
            double d = e.getDistanceSq(this);
            if (d < best) { best = d; nearest = e; }
        }
        return nearest;
    }
}

// Enregistrement :
EriProjectile.create("monmod", "missile")
    .damage(8f).velocity(1.2f).gravity(0f).lifetime(200)
    .explosionOnImpact(2.0f, false)
    .projectileClass(ProjectileMissile.class)  // ← classe custom
    .register();

EriItemBase v1.5.0

EriItemBase est la classe de base a etendre quand tu veux un item avec une logique Java custom (NBT persistant, cooldowns complexes, rendu conditionnel, interactions speciales) tout en gardant l'auto-configuration EriItem (tooltip, rarity, glow, stack size, durability).

Pour les outils / armures

Utilise les sous-builders .tool() et .armor() plutot que .itemClass() — EriAPI genere des classes specialisees (GeneratedTool, GeneratedArmor) qui gerent correctement les mechaniques d'outils et d'armure. Utilise .itemClass() pour les items simples qui ont besoin de logique custom.

EriItemBase
fr.eri.eriapi.content.EriItemBase
Extends Item

Classe de base a etendre pour un item custom.

Contrat d'extension

  • Extend EriItemBase
  • Constructeur obligatoire : public MyItem() { super(); } (aucun argument)
  • Tu peux surcharger onItemRightClick, onItemUse, onUpdate, etc.
  • Appelle super dans les overrides pour conserver le callback .onRightClick() du builder

Champs proteges accessibles

  • ItemDefinition eriDef
    La definition qui pilote cet item. Contient tooltip, rarity, glow, etc.
    protected
EriItem.itemClass()
fr.eri.eriapi.content.EriItem
Builder
  • EriItem itemClass(Class<? extends EriItemBase> clazz)
    Specifie une classe Java custom. Quand cette methode est appelee, EriAPI enregistre directement ta classe dans Forge au lieu de GeneratedItem.
    Fluent
Java — Pierre de portail avec NBT custom
import fr.eri.eriapi.content.*;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.*;
import net.minecraft.world.World;

public class ItemPortail extends EriItemBase {

    public ItemPortail() { super(); }

    @Override
    public ActionResult<ItemStack> onItemRightClick(World world, EntityPlayer player, EnumHand hand) {
        ItemStack stack = player.getHeldItem(hand);
        NBTTagCompound nbt = stack.getOrCreateSubCompound("Portail");

        if (!nbt.hasKey("X")) {
            // Premier clic : memorise la position
            nbt.setInteger("X", (int) player.posX);
            nbt.setInteger("Y", (int) player.posY);
            nbt.setInteger("Z", (int) player.posZ);
            if (!world.isRemote) {
                player.sendMessage(new TextComponentString("Position memorisee !"));
            }
        } else {
            // Deuxieme clic : teleporte
            player.setPositionAndUpdate(
                nbt.getInteger("X"),
                nbt.getInteger("Y"),
                nbt.getInteger("Z"));
            stack.removeSubCompound("Portail");
        }
        return new ActionResult<>(EnumActionResult.SUCCESS, stack);
    }
}

// Enregistrement :
EriItem.create("monmod", "portail")
    .maxStackSize(1).glowing(true).rarity(EnumRarity.RARE)
    .tooltip("&7Clic droit : memorise la position")
    .tooltip("&7Deuxieme clic droit : teleporte")
    .itemClass(ItemPortail.class)  // ← classe custom
    .register();