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 deArmorCosmeticManager.registerBakeHandler()) — a appeler depuisFMLPreInitializationEventdans le mod consommateur. -
Enregistrement automatique en preInit :
EriAPI.ClientProxy.preInit()appelle desormaisArmorCosmeticManager.registerBakeHandler(), ce qui enregistre le listener AVANT le premierModelBakeEvent. Les mods existants n'ont rien a changer. -
Refactor de
bootstrap(): la methode ne s'occupe plus que de l'attachement duArmorCosmeticLayerauxRenderPlayer. La logique d'enregistrement duModelBakeEventa ete extraite dansregisterBakeHandler()(publique). Rétro-compatible —bootstrap()appelle defensivementregisterBakeHandler()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'aucunswapn'a ete applique, unWARNexplicite 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
ModelBakeEvent—ArmorCosmeticManager.BakeHandlerforce desormaisTextureManager.loadTexture(rl, new SimpleTexture(rl))pour chaque texture de chaque cosmetique au moment du resource-pack-load. Cela garantit que laSimpleTextureest 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 sentinelTextureUtil.MISSING_TEXTUREet log unWARNexplicite. -
ArmorCosmeticTEISR: ajout deGlStateManager.enableTexture2D()+disableAlpha()/enableAlpha()autour du rendu pour neutraliser les eventuelles desactivations de la pipeline GUI (item glint, alpha cull a 0.1 applique parrenderItemModelIntoGUI). -
BlockbenchRenderer.bindTexture: log diagnostique one-shot par texture par session qui affiche leResourceLocation, leglTextureIdet un flagmissing=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 laisserGL_TEXTURE1(utilise pour le lightmap) comme unite de texture active lorsqu'elle delegue auTileEntityItemStackRenderer.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.lastBoundTexturecourt-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.renderByItemforceGlStateManager.setActiveTexture(OpenGlHelper.defaultTexUnit)avant tout dessin, et restaure ce slot a la sortie (defensif). -
BlockbenchRenderer.bindTextureforcesetActiveTexture(defaultTexUnit)juste avant chaqueTextureManager.bindTexture(), comme safety net peu importe le contexte d'appel. -
Le reset du cache
lastBoundTexture = nullau debut de chaque methode publique deBlockbenchRendereretait 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,GeneratedEntityetPathfinderBuilder.targetPlayers()— tous les target tasks ciblantEntityPlayer.classutilisent desormais le constructeur a 6 arguments avec unPredicate<EntityPlayer>qui rejette les joueurs enisCreative()ouisSpectator().- 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) etappendFaceVertices(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 mapAnimBlockDefinition.javaAnimations.GeneratedBlock.createTileEntity()appelle desormaisconfigure()et boucle pour cabler les anims sur leAnimatedBlockTileEntityGenericauto-genere.EriEntity.javaAnimation(name, anim)— ajoute l'anim au mapEntityDefinition.javaAnimations. Recuperable viaContentRegistry.getEntityDef(modId, name).getJavaAnimation("idle")dans le constructeur de l'entite.- Coexiste avec
.animation()— les fichiers.erianimet les classesEriAnimJavapeuvent etre melanges sur le meme builder. - Helper
ContentRegistry.getEntityDef(modId, registryName)— nouveau lookup direct par nom (anciennement il fallait iterergetEntityDefs()).
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) etcompute(ctx, pose)(procedural, par-frame).duration()obligatoire,endBehavior()optionnel.AnimContext— contexte avecanimTick,partial,worldTick,target, helpersasEntity()/asTileEntity(), et DSLat(tick).group(name)....GroupPoseBuilder— API fluide accessible viapose.group("nom"). Methodesadd*(additif sur les keyframes) etset*(remplace).- Overlay —
te.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. - Registration —
te.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.
// 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 unBlockRotatedPillar(propriete AXIS) pour les troncs orientables..leavesLike(Block sapling)— genere unBlockLeavescomplet (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 versblock/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
// 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 automatiquementisFullCubeetisOpaque. 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 viaaddCollisionBoxToList. Desactive automatiquementisFullCubeetisOpaque.
// 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 chaqueAnimationDef. 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(), helperhasElementTracks(), raccourcigetElementTrack(String groupName, int elementIndex), et utilitaire statiqueelementTrackKey(String, int)pour formater la cle canonique. - AnimationPose — Nouveau map
elementPosesparallele augroupPosesexistant, avecgetElement(groupName, elementIndex)etgetOrCreateElement(...). Les methodesreset(),copyFrom()etlerpToward()incluent desormais les poses d'elements. - AnimationController — Le sampler itere
elementTracksapres les pistes de groupe et alimente les poses d'element via un helper factorisepopulatePoseFromTrack(...). 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
rotationOriginde chaque element avant de rendre ses faces. La rotation statique JSON est preservee et appliquee en premier, puis la pose animee par-dessus.
{
"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] }
]
}
}
}
}
}
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.
- API —
EriEntity.ai(ai -> ai.swim().meleeAttack(1.0, false).wander(1.0).watchPlayers(12f).lookIdle().targetPlayers().hurtByTarget(true)) - Goals disponibles —
swim,meleeAttack,wander,watchClosest,watchPlayers,lookIdle,panicOnHurt,leapAtTarget,avoidEntity,openDoors,task(...)(custom). - Target goals disponibles —
targetPlayers,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.onSpawnvia 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
AnimatedEntityRenderercote 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 parmodelId. - AnimatedBlockItemRenderer — Le renderer consulte le controller a chaque frame et transmet la pose au pipeline TESR via une TileEntity proxy. Plus de pose statique.
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/entitypour que Forge delegue le rendu. - ItemDefinition — Nouveau champ
animatedModelIdpour stocker l'identifiant du modele.
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> —
RenderLivingqui rend un modele Blockbench avec animations. Methodes factory statiques pour l'enregistrement viaRenderingRegistry. - IAnimatedEntity — Interface que les entites implementent pour fournir leur pose d'animation au renderer. Methodes
getCurrentPose(partialTicks)etgetAnimState().
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(). EriGuiScreenappelle 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.