From 4a587b7478b3605c7e89ce409cf697fc4ba4849a Mon Sep 17 00:00:00 2001
From: notevil
Date: Wed, 22 Apr 2026 20:31:00 +0200
Subject: [PATCH] =?UTF-8?q?Phase=202.1=20:=20D-01=20fix=20=E2=80=94=20Livi?=
=?UTF-8?q?ngEntityPatch=20animator=20field=20+=20eager=20init?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Close le trap CRITIQUE tracé dans docs/plans/rig/PHASE0_DEGRADATIONS.md D-01
(getAnimator()=null → NPE garanti sur premier appel à MoveCoordFunctions:202,263).
Pattern EF-style conforme LivingEntityPatch EF:146-156 :
- protected Animator animator field
- Override onConstructed(T) : super + factory apply + initAnimator + postInit
- initAnimator(Animator) hook no-op pour subclasses (bind LivingMotion→Anim)
- getAnimator() retourne le field (non-null après onConstructed)
- getClientAnimator() : cast conditionnel instanceof ClientAnimator
Factory TiedUpRigConstants.ANIMATOR_PROVIDER (déjà en place, pattern lazy
method-ref client/server split) fournit la bonne instance selon Dist.
Compile + tests GREEN maintenus (11 tests bridge).
---
.../remake/rig/patch/LivingEntityPatch.java | 51 ++++++++++++++++---
1 file changed, 45 insertions(+), 6 deletions(-)
diff --git a/src/main/java/com/tiedup/remake/rig/patch/LivingEntityPatch.java b/src/main/java/com/tiedup/remake/rig/patch/LivingEntityPatch.java
index 56b049d..6f7a8f3 100644
--- a/src/main/java/com/tiedup/remake/rig/patch/LivingEntityPatch.java
+++ b/src/main/java/com/tiedup/remake/rig/patch/LivingEntityPatch.java
@@ -13,6 +13,7 @@ import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.phys.Vec3;
+import com.tiedup.remake.rig.TiedUpRigConstants;
import com.tiedup.remake.rig.anim.Animator;
import com.tiedup.remake.rig.anim.LivingMotion;
import com.tiedup.remake.rig.anim.LivingMotions;
@@ -22,26 +23,64 @@ import com.tiedup.remake.rig.anim.types.DynamicAnimation;
import com.tiedup.remake.rig.armature.Armature;
/**
- * Stub RIG Phase 0 — patch de capability attaché à un {@link LivingEntity}.
- * Expose l'animator, l'armature, la motion courante + quelques helpers.
- * La version finale sera étoffée en Phase 2 (NPCs + player) avec les données
- * d'entraînement/bondage spécifiques.
+ * RIG Phase 2 — patch de capability attaché à un {@link LivingEntity}. Porte
+ * l'{@link Animator} (initialisé eager via {@link TiedUpRigConstants#ANIMATOR_PROVIDER}
+ * dans {@link #onConstructed(LivingEntity)}) et expose {@link #getArmature()}
+ * (abstract — subclass fournit son biped armature via {@code TiedUpRigRegistry}).
+ *
+ * Pattern init EF-style (voir EF LivingEntityPatch:146-156) :
+ *
+ * - {@code onConstructed} fait super.onConstructed puis construit l'animator
+ * via le factory client/server split
+ * - {@link #initAnimator(Animator)} permet aux subclasses de registrer leurs
+ * {@code LivingMotion → StaticAnimation} avant que l'animator commence à
+ * tourner
+ * - {@link Animator#postInit()} poste l'event {@code InitAnimatorEvent}
+ * pour les extensions tierces
+ *
+ *
*/
public abstract class LivingEntityPatch extends EntityPatch {
public LivingMotion currentLivingMotion = LivingMotions.IDLE;
public LivingMotion currentCompositeMotion = LivingMotions.IDLE;
+ /** Animator initialisé dans {@link #onConstructed(LivingEntity)}, non-null après. */
+ protected Animator animator;
+
public abstract void updateMotion(boolean considerInaction);
public abstract Armature getArmature();
+ @Override
+ public void onConstructed(T entity) {
+ super.onConstructed(entity);
+ this.animator = TiedUpRigConstants.ANIMATOR_PROVIDER.apply(this);
+ this.initAnimator(this.animator);
+ this.animator.postInit();
+ }
+
+ /**
+ * Hook pour subclasses : bind des {@code LivingMotion → StaticAnimation}
+ * sur l'animator avant qu'il ne commence à tourner. Default no-op.
+ *
+ * Exemple subclass :
+ *
+ * protected void initAnimator(Animator a) {
+ * a.addLivingAnimation(LivingMotions.IDLE, TiedUpAnimationRegistry.CONTEXT_STAND_IDLE);
+ * }
+ *
+ */
+ protected void initAnimator(Animator animator) {
+ // no-op par défaut
+ }
+
public Animator getAnimator() {
- return null;
+ return this.animator;
}
@Nullable
public ClientAnimator getClientAnimator() {
- return null;
+ return this.animator instanceof ClientAnimator ca ? ca : null;
}
public LivingMotion getCurrentLivingMotion() {