Patchnote

Historique complet des changements, nouvelles fonctionnalites et corrections de bugs pour chaque version d'EriAPI.

v1.8.5 26 Mai 2026

Fix critique — cosmetic : ModelBakeEvent enregistre trop tard (3e iteration)

Vraie cause racine du bug texture rose/noir des cosmetiques, identifiee grace aux logs client. Les corrections 1.8.3 et 1.8.4 ciblaient des hypotheses plausibles (slot de texture GL incorrect, cache MISSING_TEXTURE sentinel, alpha cull du GUI) mais le bug residuel persistait parce qu'aucun ArmorCosmeticBakedModel n'etait jamais installe dans le model registry.

Cause exacte : ArmorCosmeticManager.bootstrap() — appele depuis ClientProxy.init() (FMLInit) — enregistrait le BakeHandler apres que le ModelBakeEvent initial ait deja ete dispatche. Ce dernier fire pendant le rechargement de resource pack qui se produit entre FMLPreInit et FMLInit. Resultat : notre baked model ne remplacait jamais celui par defaut, et vanilla rendait le modele depuis la sprite atlas items — qui rejetait toute texture non-POT comme MISSING_TEXTURE au stitching.

  • Nouveau point d'entree public : EriCosmetics.preInit() (alias de ArmorCosmeticManager.registerBakeHandler()) — a appeler depuis FMLPreInitializationEvent dans le mod consommateur.
  • Enregistrement automatique en preInit : EriAPI.ClientProxy.preInit() appelle desormais ArmorCosmeticManager.registerBakeHandler(), ce qui enregistre le listener AVANT le premier ModelBakeEvent. Les mods existants n'ont rien a changer.
  • Refactor de bootstrap() : la methode ne s'occupe plus que de l'attachement du ArmorCosmeticLayer aux RenderPlayer. La logique d'enregistrement du ModelBakeEvent a ete extraite dans registerBakeHandler() (publique). Rétro-compatible — bootstrap() appelle defensivement registerBakeHandler() au cas ou le consumer mod n'aurait pas migre.
  • Detecteur de mauvaise registration : si bootstrap() est appele alors qu'au moins un cosmetique est enregistre mais qu'aucun swap n'a ete applique, un WARN explicite est logge avec la solution actionnable.

Aucune cassure d'API. Mise a jour recommandee pour tout mod utilisant le module cosmetic — le fix est applique implicitement, l'appel a EriCosmetics.preInit() reste optionnel et documente.

v1.8.4 26 Mai 2026

Fix — cosmetic : suite du fix texture missing-texture (2e iteration)

La version 1.8.3 a corrige le slot de texture (GL_TEXTURE0 force avant bind) mais le rendu item restait casse en pratique — texture rose/noir persistante en inventaire, hotbar, main, sol et GUI. La 1.8.4 est un follow-up qui ajoute trois mesures complementaires : preload des textures au bake-time, neutralisation du test alpha + activation explicite de GL_TEXTURE_2D dans le TEISR, et un log diagnostique one-shot qui permet d'identifier la cause exacte si le bug persistait encore.

  • Preload des textures au ModelBakeEventArmorCosmeticManager.BakeHandler force desormais TextureManager.loadTexture(rl, new SimpleTexture(rl)) pour chaque texture de chaque cosmetique au moment du resource-pack-load. Cela garantit que la SimpleTexture est uploadee sur un GL ID valide avant tout rendu, et que toute erreur d'I/O (PNG corrompu, ressource manquante) est tracee immediatement avec le chemin attendu sur disque. Une verification additionnelle detecte si la texture chargee est le sentinel TextureUtil.MISSING_TEXTURE et log un WARN explicite.
  • ArmorCosmeticTEISR : ajout de GlStateManager.enableTexture2D() + disableAlpha()/enableAlpha() autour du rendu pour neutraliser les eventuelles desactivations de la pipeline GUI (item glint, alpha cull a 0.1 applique par renderItemModelIntoGUI).
  • BlockbenchRenderer.bindTexture : log diagnostique one-shot par texture par session qui affiche le ResourceLocation, le glTextureId et un flag missing=true/false. Aucun spam per-frame ou per-face.

Aucun changement d'API publique. Les modifications sont purement internes aux classes de rendu et d'enregistrement.

v1.8.3 26 Mai 2026

Fix — cosmetic : texture missing-texture (rose/noir) dans le contexte item

Correction du rendu de texture des cosmetiques d'armure (ArmorCosmeticItem) dans le contexte item — inventaire, hotbar, premiere personne, troisieme personne, sol, item frame, GUI. Le modele 3D Blockbench s'affichait bien (geometrie correcte) mais la texture etait remplacee par le pattern missing-texture rose/noir caracteristique. Le rendu sur le joueur via ArmorCosmeticLayer n'etait pas affecte.

Cause racine — combinaison de deux problemes :

  • Slot de texture incorrect : la pipeline RenderItem.renderItem(stack, IBakedModel) peut laisser GL_TEXTURE1 (utilise pour le lightmap) comme unite de texture active lorsqu'elle delegue au TileEntityItemStackRenderer.renderByItem. TextureManager.bindTexture() bind la texture sur l'unite actuellement active — si c'est le slot 1, le shader fragment continue d'echantillonner le slot 0 (qui contient encore l'item atlas ou n'importe quelle texture residuelle), d'ou le rendu casse.
  • Cache statique potentiellement perime : le champ BlockbenchRenderer.lastBoundTexture court-circuitait le rebind lorsque la meme texture avait deja ete liee, sans tenir compte du fait qu'un autre systeme de rendu (player layer, autre TESR, GUI) avait pu lier une autre texture entre-temps.

Solution — trois mesures cumulatives :

  • ArmorCosmeticTEISR.renderByItem force GlStateManager.setActiveTexture(OpenGlHelper.defaultTexUnit) avant tout dessin, et restaure ce slot a la sortie (defensif).
  • BlockbenchRenderer.bindTexture force setActiveTexture(defaultTexUnit) juste avant chaque TextureManager.bindTexture(), comme safety net peu importe le contexte d'appel.
  • Le reset du cache lastBoundTexture = null au debut de chaque methode publique de BlockbenchRenderer etait deja en place — confirme valide pour eviter les caches perimes entre appels successifs.

Aucun changement d'API publique — aucune migration necessaire cote consommateur. Le fix est purement interne aux classes de rendu.

v1.8.2 25 Mai 2026

Feat — cosmetic : rendu 3D Blockbench dans tous les contextes d'item

Les items ArmorCosmeticItem rendent desormais leur modele Blockbench en 3D dans tous les contextes d'affichage : inventaire, hotbar, premiere personne (main droite / main gauche), troisieme personne (main droite / main gauche), au sol, fixed (item frame), head (porte sur la tete). Avant ce patch, seul le rendu joueur via ArmorCosmeticLayer dessinait le modele 3D — l'inventaire et toutes les autres vues passaient par un sprite 2D extrude (item/generated) qui transitait par l'item atlas. Cela imposait des textures power-of-two carrees et rejetait les PNG non-POT (rendu noir/rose).

Le nouveau pipeline s'appuie sur trois pieces : ArmorCosmeticTEISR (un TileEntityItemStackRenderer qui dessine la geometrie Blockbench avec BlockbenchRenderer), ArmorCosmeticBakedModel (un IBakedModel vide qui flag isBuiltInRenderer() et isGui3d() a true, et expose les transforms par contexte construits depuis le bloc display du JSON), et un handler ModelBakeEvent dans ArmorCosmeticManager qui swap chaque modele cosmetique vanilla par l'ArmorCosmeticBakedModel a chaque reload du resource pack. Les textures sont liees via TextureManager.bindTexture() (passe par SimpleTexture, hors atlas), donc n'importe quelle dimension de PNG fonctionne — POT non requis, multi-texture supporte, UV custom respectes.

Feat — cosmetic : respect du display field du JSON Blockbench

Le bloc display du modele JSON (cles thirdperson_righthand, thirdperson_lefthand, firstperson_righthand, firstperson_lefthand, head, gui, ground, fixed) est converti en ItemCameraTransforms vanilla et applique automatiquement par RenderItem avant l'invocation du TEISR. Les translations en pixels Blockbench (1/16 bloc) sont divisees par 16 pour matcher la convention OpenGL des transforms vanilla. Rotation en degres et scale unit-less sont passes tels quels.

Feat — anim : AnimatedBlockModel.getDisplayTransforms()

AnimatedBlockModel expose desormais publiquement la map des transforms par contexte via getDisplayTransforms() (et hasDisplayTransforms() / getDisplayTransform(String) pour les usages cible). La map est extraite par BlockbenchModelParser depuis le champ display du JSON, avec fallback identite si le bloc est absent — les modeles existants restent retrocompatibles.

v1.8.1 25 Mai 2026

Fix — cosmetic : flip Y dans ArmorCosmeticLayer

Correction du flip Y dans ArmorCosmeticLayer.renderGroupAtBone — les modeles Blockbench s'affichent desormais a l'endroit sur les bones biped. La convention Blockbench (Y+ vers le haut, X+ vers la droite) est maintenant correctement convertie vers l'espace MC entity bone-local (Y- vers le haut, convention ModelBiped.addBox) via un GlStateManager.scale(-1, -1, 1) applique juste apres bone.postRender(0.0625f). Les deux flips de signe preservent l'orientation des normales (winding order) sans necessiter de glFrontFace. Avant ce fix, les modeles cosmetiques etaient rendus tete en bas, suspendus sous le bone.

L'API publique du module cosmetic ne change pas — aucune migration necessaire cote consommateur. Les offsets par defaut (DEFAULT_BONE_OFFSETS) et la table de mapping nom-de-groupe vers bone (GROUP_NAME_TO_BONE) sont deja corrects pour l'espace flippe.

v1.8.0 25 Mai 2026

Nouveau module — cosmetic (cosmetiques d'armure 3D)

Nouveau package fr.eri.eriapi.cosmetic permettant d'attacher un modele Blockbench 3D a n'importe lequel des 4 slots d'armure vanilla (HEAD, CHEST, LEGS, FEET). Les items cosmetiques heritent de zero stats — pas de reduction de degats, pas de durabilite, pas d'enchantabilite — ils servent uniquement de couche visuelle rendue par-dessus le joueur via un LayerRenderer<EntityPlayer> attache a chaque RenderPlayer du skinMap (default + slim).

Item mask = EriCosmetics.armor()
    .modId("votremod")
    .registryName("barry_mask")
    .displayName("Masque de Barry")
    .creativeTab(CreativeTabs.COMBAT)
    .slot(EntityEquipmentSlot.HEAD)
    .model(new ResourceLocation("votremod", "barry_mask"))
    .build();

Le modele suit automatiquement le bone biped vanilla correspondant au slot grace au postRender(0.0625f) : HEAD → bipedHead, CHEST → bipedBody, LEGS / FEET → bipedRightLeg — head tilt, body sneak, swing des bras et marche des jambes sont gerees nativement sans aucun rig custom.

Convention multi-bones — nommage des groupes Blockbench

Un modele peut contenir plusieurs root groups dont le nom determine a quel bone vanilla il s'attache (case-insensitive) : head, body, right_arm, left_arm, right_leg, left_leg (les variantes sans underscore sont aussi acceptees). Tout groupe ne matchant aucun bone est rendu au bone primaire du slot. Permet de creer une armure complete cosmetique qui suit l'integralite du biped vanilla.

Refactor — BlockbenchRenderer extrait du TESR

Le code de geometrie de AnimatedBlockTESR (rendu d'AnimatedBlockModel, gestion des ModelGroup / ModelElement, atlas de textures, application des transformations Blockbench) est desormais expose dans la classe publique fr.eri.eriapi.cosmetic.BlockbenchRenderer. Elle est reutilisee par le module cosmetic et par AnimatedBlockTESR (qui delegue maintenant a renderModelWithOverrides()). Le TESR conserve son optimisation IDLE et son perf tracking — 100% retrocompatible, aucun changement d'API publique pour les utilisateurs existants.

  • renderModel(AnimatedBlockModel) — rendu complet d'un modele au repos.
  • renderModel(model, AnimationPose) — rendu avec pose appliquee.
  • renderGroup(ModelGroup, ...) — rendu d'un seul groupe (utilise par le multi-bone dispatch).
  • renderModelWithOverrides(model, pose, textureOverrides) — signature preservant la semantique du TESR.

Documentation

Nouvelle page cosmetic.html (FR + EN) couvrant l'API complete du builder, le mapping des bones, la convention multi-bones, les offsets par defaut, l'API publique de BlockbenchRenderer et un troubleshooting complet.

v1.7.2 13 Mai 2026

Ajout — LineChart.yLabelDecimals(int)

Le nombre de decimales affichees sur les labels de l'axe Y (et dans le tooltip de survol des points) est desormais configurable. Avant, la methode interne formatValue etait static et hardcodee a 1 decimale, sans setter public — impossible d'afficher des prix au centime ou des valeurs entieres sans virgule parasite.

LineChart chart = new LineChart()
    .yLabelDecimals(2)  // 12.34 au lieu de 12.3
    .addDataset("Prix", points);

Defaut : 1 (retro-compatible). Mettre 0 force un affichage entier. Les valeurs negatives sont clampees a 0.

v1.6.8 07 Mai 2026

Fix critique — EventBuilder.filter() ecrasait les filtres precedents

Chaque appel a .filter(...) sur un EventBuilder remplacait purement et simplement le filtre precedent au lieu de les combiner. Resultat : un listener configure avec plusieurs .filter(...) chaines ne respectait que le dernier, faisant fuir des events qui auraient du etre rejetes par les filtres anterieurs.

Exemple concret rencontre : un handler PlayerTickEvent destine a une dimension specifique, configure ainsi :

EriEvents.on(TickEvent.PlayerTickEvent.class)
    .filter(e -> e.phase == TickEvent.Phase.END)
    .filter(e -> e.player.world.provider.getDimension() == TARGET_DIM)
    .filter(e -> !e.player.world.isRemote)   // ce filtre ECRASAIT les precedents
    .handle(e -> applyEffect(e.player));

Le check de dimension etait perdu, et l'effet s'appliquait sur toutes les dimensions cote serveur.

Resolu : les appels successifs a filter(...) sont desormais combines en AND logique via Predicate.and(). Tous les predicats doivent retourner true pour que le handler soit invoque. Le comportement attendu et naturel est restaure, sans casser les listeners qui n'utilisaient qu'un seul filtre.

v1.6.7 05 Mai 2026

Fix — Modeles 3D animes decales par rapport a la hitbox

Les modeles Blockbench rendus par AnimatedEntityRenderer apparaissaient visuellement decales d'un demi-bloc en X et Z par rapport a la hitbox de l'entite. Cause : Blockbench centre les modeles sur (8, 0, 8) en pixels (= 0.5, 0, 0.5 en unites GL), mais l'origine de l'entite (posX/posY/posZ) correspond au centre du bas de la bounding box. Sans offset, le coin (0,0,0) du modele est rendu au centre de la hitbox.

Resolu dans doRender() : ajout d'un GlStateManager.translate(-0.5f, 0.0f, -0.5f) apres la rotation de yaw pour recentrer le modele. La rotation se fait autour du veritable axe vertical du modele (son centre), pas autour d'un pivot decale. Corrige aussi en cascade les animations de mouvement qui paraissaient buguees — elles etaient simplement appliquees autour du mauvais pivot.

Fix — Mobs hostiles attaquent les joueurs en mode Creative / Spectator

Les presets HOSTILE_MELEE, HOSTILE_RANGED et BOSS de EriEntity appelaient EntityAINearestAttackableTarget sans predicat de filtrage. Resultat : les staff/admins en creatif etaient cibles par les mobs comme n'importe quel joueur survie.

  • EriEntityBase, GeneratedEntity et PathfinderBuilder.targetPlayers() — tous les target tasks ciblant EntityPlayer.class utilisent desormais le constructeur a 6 arguments avec un Predicate<EntityPlayer> qui rejette les joueurs en isCreative() ou isSpectator().
  • Le predicat est stocke comme singleton statique par classe pour eviter une allocation de lambda par entite spawnee — critique a 500-1000 joueurs simultanes.

Perf — AnimatedEntityRenderer : batch des draw calls par texture

L'ancienne implementation appelait buffer.begin() + tessellator.draw() par face. Un modele avec 200 elements et 6 faces par element generait donc 1200 draw calls GPU par entite par frame — chute de FPS catastrophique a partir de quelques entites visibles.

Refactor de renderElement() : les faces d'un meme element sont desormais regroupees par texture dans un seul begin() / draw(). La plupart des elements n'utilisent qu'une ou deux textures — la reduction est typiquement de 6x a 12x selon le modele. Pour un mob complexe a 200 elements mono-texture : 1200 draw calls -> 200.

  • Nouvelles methodes internes : resolveTexture(String) -> ResourceLocation (resolution sans bind) et appendFaceVertices(buffer, ...) (ajoute les 4 vertices d'une face dans un buffer deja ouvert).
  • L'ancienne methode drawFace() est remplacee — aucun changement d'API publique, seul le pipeline interne change.
  • Compatible avec toutes les animations existantes (translation, rotation, scale, cumulativeRotation, texture overrides). Les transforms matricielles restent inchangees, seul le draw-flushing est batche.

100% retrocompatible — aucun changement d'API publique.

v1.6.6 05 Mai 2026

Fix — EriEntityBase : eriDef resolu avant l'initialisation IA / attributs

Le constructeur de EntityLiving appelle applyEntityAttributes() et initEntityAI() via super(world) avant que la sous-classe EriEntityBase ait pu assigner this.eriDef. Consequence : les mobs spawnaient sans IA et avec les stats vanilla par defaut, peu importe ce qui etait declare via EriEntity.create(...).

Restructuration : les overrides de applyEntityAttributes() et initEntityAI() sont desormais des no-ops, et le constructeur appelle applyEriAttributes() + setupEriAI() apres avoir resolu eriDef via DEF_BY_CLASS. Les sous-classes de EriEntityBase (utilisees pour la logique Java custom) recoivent maintenant correctement leurs stats, IA et hitbox.

v1.6.5 02 Mai 2026

Animations Java sur le builder — .javaAnimation()

Les builders EriAnimBlock et EriEntity exposent desormais .javaAnimation(String name, EriAnimJava anim) pour enregistrer une animation Java directement sur le builder fluent — plus besoin de creer une sous-classe TileEntity custom ni d'appeler manuellement addJavaAnimation() dans le constructeur. Les anims sont stockees dans la BlockDefinition / EntityDefinition et recuperables via les helpers correspondants.

  • EriAnimBlock.javaAnimation(name, anim) — ajoute l'anim au map AnimBlockDefinition.javaAnimations. GeneratedBlock.createTileEntity() appelle desormais configure() et boucle pour cabler les anims sur le AnimatedBlockTileEntityGeneric auto-genere.
  • EriEntity.javaAnimation(name, anim) — ajoute l'anim au map EntityDefinition.javaAnimations. Recuperable via ContentRegistry.getEntityDef(modId, name).getJavaAnimation("idle") dans le constructeur de l'entite.
  • Coexiste avec .animation() — les fichiers .erianim et les classes EriAnimJava peuvent etre melanges sur le meme builder.
  • Helper ContentRegistry.getEntityDef(modId, registryName) — nouveau lookup direct par nom (anciennement il fallait iterer getEntityDefs()).

Fix — AnimatedBlockTileEntityGeneric.configure() jamais appele

Bug latent depuis v1.6.4 : le no-arg constructor + pattern configure() du AnimatedBlockTileEntityGeneric n'etait jamais invoque — les blocs animes generes par EriAnimBlock sans .tileEntity(MyTE.class) custom n'avaient ni modelId, ni animFileId, ni defaultAnimation. Resolu dans GeneratedBlock.createTileEntity() : la configuration est appliquee a la creation du TE, en meme temps que les anims Java declarees sur le builder.

100% retrocompatible — les fichiers .erianim existants et les TE customs continuent de fonctionner inchanges.

v1.6.4 02 Mai 2026

Java Animation API — ecrire des animations en pur Java

Nouvelle API pour ecrire des animations directement en Java, sans passer par les fichiers .erianim. Ideal pour les animations procedurales (oscillations sin/cos, reactions a l'etat de l'entite, mouvements parametriques) impossibles ou penibles a exprimer en JSON. Cohabite avec les .erianim via la meme API te.playAnimation("nom").

  • EriAnimJava — classe abstraite a etendre. Deux methodes : defineKeyframes(ctx) (declaratif, cache) et compute(ctx, pose) (procedural, par-frame). duration() obligatoire, endBehavior() optionnel.
  • AnimContext — contexte avec animTick, partial, worldTick, target, helpers asEntity()/asTileEntity(), et DSL at(tick).group(name)....
  • GroupPoseBuilder — API fluide accessible via pose.group("nom"). Methodes add* (additif sur les keyframes) et set* (remplace).
  • Overlayte.playOverlay("nom", anim) joue une seconde anim Java par-dessus l'anim principale (overlay gagne sur les groupes touches). Local au client, ne passe pas par les packets.
  • Registrationte.addJavaAnimation("walk", new WalkAnim()) dans le constructeur du TileEntity. Le registre est partage server+client.

Voir la documentation complete dans Animation System — Java Animation API.

Aucune correction de bug — uniquement des ajouts, 100% retrocompatible. Les fichiers .erianim existants continuent de fonctionner inchanges.

v1.6.1 28 Avril 2026

ListRenderContext — Offset vertical proportionnel (drawTextProp)

Nouvelle methode ListRenderContext.drawTextProp(String, int offsetX, int offsetYPermil, int maxWidth, int color). Contrairement a drawText() ou offsetY est en pixels ecran bruts, drawTextProp exprime l'offset vertical en permil de la hauteur de la ligne (1/1000) — le rendu reste correct a toutes les tailles de fenetre.

Symptome avant : un offset fixe de -14 pixels qui plaçait correctement le nom au-dessus du centre en plein ecran (itemHeight ~96 px) faisait sortir le texte des limites en petite fenetre quand l'item etait redimensionne. drawTextProp(text, x, -150, w, color) place le texte ~15% de la hauteur au-dessus du centre, quelle que soit la taille reelle de la ligne.

Java
// AVANT — offsetY en pixels ecran (casse en petite fenetre)
ctx.drawText(name,   textX,         -14, textMaxW,      0xFFFFFFFF);
ctx.drawText(cost,   textX,         +14, textMaxW,      0xFF4ADE80);
ctx.drawText(status, statusOffsetX, -14, statusW + gap, 0xFFBB55FF);

// APRES — offset en permil de la hauteur (correct a toutes resolutions)
ctx.drawTextProp(name,   textX,         -150, textMaxW,      0xFFFFFFFF);
ctx.drawTextProp(cost,   textX,         +150, textMaxW,      0xFF4ADE80);
ctx.drawTextProp(status, statusOffsetX, -150, statusW + gap, 0xFFBB55FF);

L'ancienne methode drawText est conservee — aucun changement cassant.

v1.6.0 24 Avril 2026

EriBlock — Variantes de blocs et callbacks d'entite

Le builder EriBlock gagne six nouvelles methodes qui couvrent la majorite des patterns vanilla (troncs, feuilles, plantes) et ouvrent les callbacks de marche/collision d'entites. Fini les BlockRotatedPillar et BlockLeaves custom : un simple .logLike() ou .leavesLike(sapling) suffit.

  • .renderLayer(BlockRenderLayer) — fixe la couche de rendu (SOLID, CUTOUT, CUTOUT_MIPPED, TRANSLUCENT). Indispensable pour feuilles, plantes, verre.
  • .onEntityWalk(TriConsumer<World, BlockPos, Entity>) — callback bas-niveau quand une entite marche sur le bloc.
  • .onEntityCollision(TriConsumer<World, BlockPos, Entity>) — callback quand une entite traverse le bloc (pratique pour pieges / plantes toxiques).
  • .logLike() — genere un BlockRotatedPillar (propriete AXIS) pour les troncs orientables.
  • .leavesLike(Block sapling) — genere un BlockLeaves complet (CHECK_DECAY + DECAYABLE, decomposition naturelle, drop de sapling 5%). Force CUTOUT_MIPPED automatiquement.
  • .plantLike() — plante decorative : hitbox reduite, pas de collision, CUTOUT. Le blockstate doit pointer vers block/cross.

TriConsumer — Nouvelle interface fonctionnelle

Java 8 ne fournit pas de TriConsumer<A, B, C> nativement. EriAPI ajoute cette interface dans fr.eri.eriapi.content.TriConsumer pour les callbacks a 3 parametres (utilisee par onEntityWalk / onEntityCollision et disponible pour tes propres builders).

Refactor interne — GeneratedBlockCommons

Pour eviter la duplication entre les 4 variantes de blocs generes (GeneratedBlock, GeneratedLogBlock, GeneratedLeavesBlock, GeneratedPlantBlock), la logique partagee (drops, hitbox, callbacks, TileEntity) a ete extraite dans GeneratedBlockCommons. Aucun changement visible cote API utilisateur.

Exemple complet

Java
// Tronc d'arbre custom (axis X/Y/Z automatique)
Block ERINA_LOG = EriBlock.create("monmod", "erina_log")
    .material(Material.WOOD)
    .hardness(2.0f)
    .harvestTool("axe", 0)
    .soundType(SoundType.WOOD)
    .logLike()
    .register();

// Feuilles qui se decomposent + drop sapling 5%
Block ERINA_LEAVES = EriBlock.create("monmod", "erina_leaves")
    .material(Material.LEAVES)
    .hardness(0.2f)
    .soundType(SoundType.PLANT)
    .leavesLike(ERINA_SAPLING)
    .register();

// Plante toxique qui inflige des degats au contact
Block TOXIC_PLANT = EriBlock.create("monmod", "toxic_plant")
    .material(Material.PLANTS)
    .hardness(0.0f)
    .soundType(SoundType.PLANT)
    .plantLike()
    .onEntityCollision((world, pos, entity) -> {
        if (entity instanceof EntityLivingBase && !world.isRemote) {
            ((EntityLivingBase) entity).addPotionEffect(
                new PotionEffect(MobEffects.POISON, 60, 0)
            );
        }
    })
    .register();

v1.5.2 22 Avril 2026

EriBlock — Hitboxes custom (.hitbox / .hitboxes)

Il est maintenant possible de definir une hitbox non-cubique ou plusieurs hitboxes independantes directement via le builder EriBlock, sans avoir a sous-classer Block manuellement.

  • .hitbox(AxisAlignedBB) — Remplace la hitbox plein-bloc par une boite unique. Desactive automatiquement isFullCube et isOpaque. Unite : 1.0 = 1 bloc = 16 pixels.
  • .hitboxes(AxisAlignedBB...) — Definit plusieurs boites de collision independantes. La selection (outline au survol) affiche l'union englobante. Chaque boite est testee separement lors de la collision des entites via addCollisionBoxToList. Desactive automatiquement isFullCube et isOpaque.
Java — Exemples
// Hitbox simple : demi-bloc (8 pixels de haut)
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 plat + pilier central
EriBlock.create("monmod", "machine")
    .material(Material.IRON)
    .hardness(4.0f)
    .hitboxes(
        new AxisAlignedBB(0,    0,    0,    1,    0.25, 1),
        new AxisAlignedBB(0.25, 0.25, 0.25, 0.75, 1,    0.75)
    )
    .register();

v1.5.1 18 Avril 2026

Animation au niveau de l'element (elementTracks)

Les animations .erianim.json peuvent desormais cibler des elements individuels a l'interieur d'un groupe Blockbench, pas uniquement le groupe entier. Chaque element possede son propre rotationOrigin (pivot) defini dans le modele, et l'animation peut appliquer rotation, translation, echelle, visibilite et spin autour de ce pivot. Entierement retrocompatible : les animations existantes sans elementTracks fonctionnent exactement comme avant.

  • Format JSON — Nouveau champ optionnel "elementTracks" a cote de "tracks" dans chaque AnimationDef. Cles au format "nomGroupe:indexElement" (ex : "body:2"). La structure d'une piste element est identique a celle d'une piste groupe (rotation, rotate, translation, scale, visible, spin).
  • AnimationDef — Nouveau getter getElementTracks(), helper hasElementTracks(), raccourci getElementTrack(String groupName, int elementIndex), et utilitaire statique elementTrackKey(String, int) pour formater la cle canonique.
  • AnimationPose — Nouveau map elementPoses parallele au groupPoses existant, avec getElement(groupName, elementIndex) et getOrCreateElement(...). Les methodes reset(), copyFrom() et lerpToward() incluent desormais les poses d'elements.
  • AnimationController — Le sampler itere elementTracks apres les pistes de groupe et alimente les poses d'element via un helper factorise populatePoseFromTrack(...). Le blending entre animations (START / END) s'applique aussi aux poses d'element.
  • AnimatedBlockTESR / AnimatedEntityRenderer — Les deux renderers lisent la pose d'element et appliquent une matrice OpenGL locale autour du rotationOrigin de chaque element avant de rendre ses faces. La rotation statique JSON est preservee et appliquee en premier, puis la pose animee par-dessus.
JSON — Exemple elementTracks
{
  "formatVersion": 1,
  "modelId": "mymod:block/turret",
  "animations": {
    "idle": {
      "length": 40,
      "loop": true,
      "tracks": {
        "base": { }
      },
      "elementTracks": {
        "body:2": {
          "rotation": [
            { "tick": 0,  "value": [0, 0, 0] },
            { "tick": 20, "value": [0, 180, 0] },
            { "tick": 40, "value": [0, 360, 0] }
          ]
        }
      }
    }
  }
}
Java — Lecture d'une pose d'element
AnimationPose pose = controller.getCurrentPose(partialTicks);
AnimationPose.GroupPose bodyPose = pose.getGroup("body");
AnimationPose.GroupPose elemPose = pose.getElement("body", 2);
if (elemPose != null && !elemPose.visible) return;

Corrections

  • Aucune correction de bug dans cette version — uniquement des ajouts, 100% retrocompatibles.

v1.4.2 17 Avril 2026

EriProjectile — builder de projectiles custom

Nouveau builder fluent pour declarer un projectile personnalise (entite lancee) sans boilerplate Forge. Supporte velocite, degats directs et de zone (AOE), physique (gravite, trainee), effets a l'impact, et callbacks lifecycle. Le projectile est genere dynamiquement via GeneratedProjectile et alloue un slot dans GeneratedProjectileSlots (pool de 32 sous-classes statiques) — compatible CleanRoom, sans ASM.

  • EriProjectile — Builder fluent : model(), texture(), velocity(), gravity(), drag(), damage(), aoe(), effectOnHit(), onHitBlock(), onHitEntity(), onTick(), register().
  • ProjectileDefinition — POJO de configuration contenant tous les parametres du projectile.
  • GeneratedProjectile / GeneratedProjectileSlots — Entites generees dynamiquement a partir de la definition, chacune dans son propre slot pour respecter la contrainte Forge "une Class par EntityEntry".
  • ContentRegistry — Enregistrement automatique des projectiles lors de l'evenement RegistryEvent.Register<EntityEntry>.

Corrections

  • Aucune correction de bug dans cette version — uniquement des ajouts.

v1.4.1 17 Avril 2026

PathfinderBuilder — AI tasks custom pour EriEntity

Builder fluent pour configurer les AI tasks d'une entite EriEntity au-dela des presets (PASSIVE, HOSTILE_MELEE, ...). Permet d'ajouter des comportements precis (nager, attaquer au corps a corps, errer, fuir, ouvrir les portes, sauter vers la cible, etc.) en une chaine fluide. Les tasks sont stockees sous forme de factories (Function<EntityLiving, EntityAIBase>) pour differer l'instanciation jusqu'a ce que l'entite existe.

  • APIEriEntity.ai(ai -> ai.swim().meleeAttack(1.0, false).wander(1.0).watchPlayers(12f).lookIdle().targetPlayers().hurtByTarget(true))
  • Goals disponiblesswim, meleeAttack, wander, watchClosest, watchPlayers, lookIdle, panicOnHurt, leapAtTarget, avoidEntity, openDoors, task(...) (custom).
  • Target goals disponiblestargetPlayers, targetClass, hurtByTarget, targetTask(...) (custom).

Corrections

  • Aucune correction de bug dans cette version — uniquement des ajouts.

v1.4.0 17 Avril 2026

Entity Framework complet — stats, AI presets, drops, spawn rules, callbacks

Extension majeure d'EriEntity (39 methodes fluent) pour declarer une entite complete en une seule chaine : statistiques (health/armor/damage/speed/range), sons, preset d'AI (PASSIVE / HOSTILE_MELEE / HOSTILE_RANGED / NEUTRAL / BOSS), drops, spawn rules (biomes/light/height/dimension) et callbacks lifecycle (onSpawn, onDeath, onUpdate, onAttack, onHurt, onInteract).

  • EntityDefinition — Etendu avec tous les nouveaux champs + inner class EntityDrop.
  • AiPreset / EriSpawner — Nouveaux types pour configurer comportement et spawn.
  • GeneratedEntity — Entite generique (extends EntityMob) qui applique la definition : applyEntityAttributes, initEntityAI (branche sur le preset), dropLoot, getExperiencePoints, sons. onSpawn via flag persistant en NBT pour eviter les re-fires au chunk reload.
  • GeneratedEntitySlots — Pool de 32 sous-classes statiques (Slot0..Slot31) pour respecter la contrainte Forge 1.12.2 "une Class par EntityEntry" sans ASM (compatible CleanRoom).
  • ContentRegistry.onRegisterEntities — Enregistrement automatique (egg, tracker, spawn rules) et cablage de AnimatedEntityRenderer cote client.

Corrections

  • Aucune correction de bug dans cette version — uniquement des ajouts.

v1.3.2 16 Avril 2026

AnimatedItemController : lecture d'animations sur les items animes

Les items crees avec EriItem.animatedModel() peuvent desormais jouer des animations .erianim.json en temps reel. Le nouveau AnimatedItemController expose une API statique simple (play / stop / isPlaying) et partage l'etat de lecture par modelId pour tous les items qui utilisent le meme modele.

  • AnimatedItemController — Nouveau controller client-only dans fr.eri.eriapi.anim. Gere la boucle (EndBehavior LOOP), les one-shots, et la lecture par modelId.
  • AnimatedBlockItemRenderer — Le renderer consulte le controller a chaque frame et transmet la pose au pipeline TESR via une TileEntity proxy. Plus de pose statique.
Java — Exemple
EriItem.create("monmod", "epee")
    .animatedModel("monmod:item/epee")
    .onRightClick(ctx -> {
        if (ctx.world.isRemote) {
            AnimatedItemController.play("monmod:item/epee", "swing");
        }
    })
    .register();

Corrections

  • Documentation animation.html — suppression de l'avertissement « pas de lecture d'animation » et remplacement par la documentation du nouveau controller.

v1.3.1 16 Avril 2026

EriItem : support .animatedModel() pour les items avec rendu Blockbench 3D

Les items crees via EriItem peuvent desormais utiliser un modele 3D Blockbench anime en main et en inventaire, grace a la nouvelle methode .animatedModel(String modelId). Le rendu est delegue au meme AnimatedBlockItemRenderer utilise pour les blocs animes.

  • EriItem.animatedModel(String) — Nouvelle methode fluent qui configure un item pour utiliser un modele Blockbench au format "modid:item/nom".
  • ContentRegistry — Branche automatiquement le TEISR (TileEntityItemStackRenderer) sur les items animes cote client, et enregistre le modele builtin/entity pour que Forge delegue le rendu.
  • ItemDefinition — Nouveau champ animatedModelId pour stocker l'identifiant du modele.
Java — Exemple
EriItem.create("eriniumfaction", "faction_sword")
    .maxStackSize(1)
    .rarity(EnumRarity.EPIC)
    .animatedModel("eriniumfaction:item/faction_sword")
    .register();

Corrections

  • Aucune correction de bug dans cette version — uniquement des ajouts.

v1.3.0 16 Avril 2026

Nouveau : AnimatedEntityRenderer — rendu anime pour les entites

Extension du pipeline de rendu Blockbench aux entites. Le renderer utilise exactement le meme pipeline que AnimatedBlockTESR (groupes, elements, faces, UV, textures animees).

  • AnimatedEntityRenderer<T>RenderLiving qui rend un modele Blockbench avec animations. Methodes factory statiques pour l'enregistrement via RenderingRegistry.
  • IAnimatedEntity — Interface que les entites implementent pour fournir leur pose d'animation au renderer. Methodes getCurrentPose(partialTicks) et getAnimState().

Nouveau : EriEntity builder

Builder fluent pour definir des entites custom avec modele Blockbench, textures, animations, hitbox, sieges passagers et spawn eggs. Les definitions sont stockees dans ContentRegistry pour que le mod les enregistre dans Forge manuellement.

  • EriEntity — Builder fluent : model(), texture(), animation(), hitbox(), seat() (3 surcharges), spawnEgg(), creativeTab(), register().
  • EntityDefinition — POJO de configuration contenant tous les parametres de l'entite.
  • EntitySeat — Definition d'un siege passager avec position Blockbench, yaw offset, groupe attache, et verrouillage camera.
  • ContentRegistry.registerEntity() / getEntityDefs() — Stockage et acces aux definitions d'entites.

Champ category dans AnimationFile

Les fichiers .erianim.json supportent desormais un champ optionnel "category" ("block", "item", ou "entity"). Ce champ est informatif et indique quel type de renderer est prevu pour ce fichier d'animation. Retrocompatible — le defaut est "block".

Corrections

  • Aucune correction de bug dans cette version — uniquement des ajouts.

v1.2.1 26 Mars 2026

Label : nouveaux modes scaleToFit() et wrapped()

  • scaleToFit(boolean) — Au lieu de tronquer le texte avec "...", reduit automatiquement l'echelle du texte pour qu'il rentre dans la largeur du composant. Mutuellement exclusif avec wrapped() (wrapped prend la priorite).
  • wrapped(boolean) — Le texte passe a la ligne aux limites de mots. Si le contenu depasse la hauteur du composant, le scroll vertical a la souris est active (clippe par scissor). Mutuellement exclusif avec scaleToFit() (wrapped gagne).

Tooltip : support du \n litteral depuis les fichiers .lang

Tooltip.render() normalise desormais les \\n litteraux (provenant des fichiers .lang) en vrais retours a la ligne avant le decoupage. Les \n dans les chaines Java et les \\n des fichiers .lang fonctionnent tous les deux.

Dropdown : rendu differe (toujours au-dessus)

  • La liste deroulante est desormais rendue APRES tous les autres composants (rendu differe), garantissant qu'elle apparait toujours par-dessus.
  • Le clic sur la liste fonctionne meme quand le Dropdown est a l'interieur d'un ScrollPanel.
  • Nouvelles methodes statiques : Dropdown.renderDeferredDropdown(), Dropdown.handleDeferredClick(), Dropdown.resetState().
  • EriGuiScreen appelle automatiquement ces methodes — aucune action necessaire pour les ecrans standard.

ItemStackRenderer : showDurability() separe de showCount()

Nouvelle methode showDurability(boolean) independante de showCount(boolean). Permet d'afficher la barre de durabilite sans le texte du compteur, ou inversement. Les deux sont actifs par defaut.

Corrections

  • Aucune correction de bug dans cette version — uniquement des ajouts et ameliorations.

v1.2.0 22 Mars 2026

Editeur d'overlays : systeme d'aimantation automatique (auto-snap)

L'editeur in-game de l'Overlay HUD dispose maintenant d'un systeme d'aimantation automatique. Quand vous deplacez un overlay en mode edition, il se colle automatiquement aux bords et centres des autres overlays ainsi qu'aux reperes de l'ecran, pour un positionnement precis sans avoir a entrer des coordonnees manuellement.

  • Aimantation aux bords d'overlays — Les bords gauche, droit, haut et bas d'un overlay s'aimantent aux bords correspondants des overlays voisins lorsqu'ils se trouvent a moins de 5 pixels de design. 10 types d'accrochage sont geres : alignement bord-a-bord et centre-a-centre dans les deux axes.
  • Aimantation aux bords de l'ecran — L'overlay s'accroche aux quatre bords de l'ecran (x = 0, x = 1920, y = 0, y = 1080) quand il s'en approche a moins de 5 pixels de design.
  • Aimantation au centre de l'ecran — L'overlay peut s'aligner sur le centre absolu de l'ecran (960, 540), aussi bien horizontalement que verticalement.
  • Alignement centre-a-centre — Les centres horizontaux et verticaux de deux overlays peuvent s'aligner entre eux pour une disposition symetrique.
  • Lignes guides cyan — Quand un accrochage est actif, une ligne guide semi-transparente de couleur cyan apparait sur l'axe d'aimantation pour visualiser l'alignement.
  • Indicateur de chevauchement rouge — Si un overlay se superpose a un autre pendant le deplacement, il prend une teinte rouge pour signaler le chevauchement.
  • Maintien de Shift pour desactiver l'aimantation — Maintenez la touche Shift pendant le drag pour desactiver l'aimantation et deplacer l'overlay librement pixel par pixel.

Corrections

  • Aucune correction de bug dans cette version — uniquement des ajouts.

v1.1.0 22 Mars 2026

Nouveau module : Security Framework

Ajout du package fr.eri.eriapi.security — un toolkit complet de prevention anti-duplication et de protection contre les exploits cote serveur. Concu pour les serveurs a forte affluence (500-1000 joueurs).

  • GuiRateLimiter — Limitation d'actions par joueur avec fenetre glissante configurable. Empeche le spam de clics sur les conteneurs.
  • ItemIntegrityValidator — Systeme de snapshot/validation/rollback pour verifier que le nombre total d'items ne change pas apres une operation de conteneur. Detecte automatiquement les tentatives de duplication.
  • ContainerLock — Verrous synchronises par cle pour empecher les acces concurrents aux conteneurs partages (ex: coffre de faction).
  • DupeAlertManager — Alertes en temps reel envoyees a tous les operateurs en ligne via EriChat quand une tentative de duplication est detectee.

Nouvelle documentation : Network GUI

Ajout de la page Network GUI documentant le systeme de communication client-serveur pour les interactions GUI : GuiNetworkHandler, IGuiDataReceiver, format des packets, et exemples complets.

Documentation GUI enrichie

  • Ajout des composants visuels : GradientRectangle, Aurora, Starfield, ParticleSystem, SmokeFog
  • Section reseau deplacee vers la page dediee Network GUI
  • Liens sidebar mis a jour avec Security et Network

Corrections

  • Aucune correction de bug dans cette version — uniquement des ajouts.

v1.0.0 Release initiale

Modules inclus

  • GUI Framework — Toolkit UI complet en 1920x1080 design pixels avec 30+ composants, animations, sons, et scaling automatique.
  • Overlay HUD — Systeme d'overlay draggable avec positionnement en pixels design, ancrage, et editeur in-game.
  • Config System — Configuration annotee avec GUI auto-generee, sync client-serveur, et validation.
  • Command Framework — Builder de commandes avec auto-completion, arguments types, permissions, cooldowns, et sous-commandes.
  • Content Builder — Creation d'items, blocs, recettes et entites via API fluent sans boilerplate Forge.
  • Data & Storage — Stockage persistant par POJOs annotes avec sync client automatique via @Sync.
  • Scheduler — Planification de taches differees, repetitives, chainees, et asynchrones.
  • Chat Builder — Messages chat riches avec couleurs, clics, hover, et pagination.
  • Capability Helpers — Capabilities Forge simplifiees via annotations avec auto-attach et auto-sync.
  • Event Simplifier — Abonnement aux events Forge en une ligne avec filtres, priorite, et expiration.
  • Keybinding Manager — Raccourcis clavier fluent avec combos, double-tap, hold, et contextes.
  • Network GUI — Communication client-serveur pour les interactions GUI.