Phase 2.1 : D-01 fix — LivingEntityPatch animator field + eager init
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).
This commit is contained in:
@@ -13,6 +13,7 @@ import net.minecraft.world.entity.Entity;
|
|||||||
import net.minecraft.world.entity.LivingEntity;
|
import net.minecraft.world.entity.LivingEntity;
|
||||||
import net.minecraft.world.phys.Vec3;
|
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.Animator;
|
||||||
import com.tiedup.remake.rig.anim.LivingMotion;
|
import com.tiedup.remake.rig.anim.LivingMotion;
|
||||||
import com.tiedup.remake.rig.anim.LivingMotions;
|
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;
|
import com.tiedup.remake.rig.armature.Armature;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stub RIG Phase 0 — patch de capability attaché à un {@link LivingEntity}.
|
* RIG Phase 2 — patch de capability attaché à un {@link LivingEntity}. Porte
|
||||||
* Expose l'animator, l'armature, la motion courante + quelques helpers.
|
* l'{@link Animator} (initialisé eager via {@link TiedUpRigConstants#ANIMATOR_PROVIDER}
|
||||||
* La version finale sera étoffée en Phase 2 (NPCs + player) avec les données
|
* dans {@link #onConstructed(LivingEntity)}) et expose {@link #getArmature()}
|
||||||
* d'entraînement/bondage spécifiques.
|
* (abstract — subclass fournit son biped armature via {@code TiedUpRigRegistry}).
|
||||||
|
*
|
||||||
|
* <p><b>Pattern init EF-style (voir EF LivingEntityPatch:146-156)</b> :
|
||||||
|
* <ol>
|
||||||
|
* <li>{@code onConstructed} fait super.onConstructed puis construit l'animator
|
||||||
|
* via le factory client/server split</li>
|
||||||
|
* <li>{@link #initAnimator(Animator)} permet aux subclasses de registrer leurs
|
||||||
|
* {@code LivingMotion → StaticAnimation} avant que l'animator commence à
|
||||||
|
* tourner</li>
|
||||||
|
* <li>{@link Animator#postInit()} poste l'event {@code InitAnimatorEvent}
|
||||||
|
* pour les extensions tierces</li>
|
||||||
|
* </ol>
|
||||||
|
* </p>
|
||||||
*/
|
*/
|
||||||
public abstract class LivingEntityPatch<T extends LivingEntity> extends EntityPatch<T> {
|
public abstract class LivingEntityPatch<T extends LivingEntity> extends EntityPatch<T> {
|
||||||
public LivingMotion currentLivingMotion = LivingMotions.IDLE;
|
public LivingMotion currentLivingMotion = LivingMotions.IDLE;
|
||||||
public LivingMotion currentCompositeMotion = 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 void updateMotion(boolean considerInaction);
|
||||||
|
|
||||||
public abstract Armature getArmature();
|
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.
|
||||||
|
*
|
||||||
|
* <p>Exemple subclass :</p>
|
||||||
|
* <pre>
|
||||||
|
* protected void initAnimator(Animator a) {
|
||||||
|
* a.addLivingAnimation(LivingMotions.IDLE, TiedUpAnimationRegistry.CONTEXT_STAND_IDLE);
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
protected void initAnimator(Animator animator) {
|
||||||
|
// no-op par défaut
|
||||||
|
}
|
||||||
|
|
||||||
public Animator getAnimator() {
|
public Animator getAnimator() {
|
||||||
return null;
|
return this.animator;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public ClientAnimator getClientAnimator() {
|
public ClientAnimator getClientAnimator() {
|
||||||
return null;
|
return this.animator instanceof ClientAnimator ca ? ca : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LivingMotion getCurrentLivingMotion() {
|
public LivingMotion getCurrentLivingMotion() {
|
||||||
|
|||||||
Reference in New Issue
Block a user