fix(world): restore portal and distant use lifecycles

This commit is contained in:
Erik 2026-07-25 09:59:25 +02:00
parent c730632075
commit 1a14812c44
18 changed files with 401 additions and 196 deletions

View file

@ -44,7 +44,12 @@ internal sealed class LiveEntityAnimationPresenter
ArgumentNullException.ThrowIfNull(record);
ArgumentNullException.ThrowIfNull(animation);
LiveEntityRuntime runtime = _liveEntities;
if (!runtime.IsCurrentSpatialAnimation(record, animation)
// The PartArray completion relay is a logical CPhysicsObj component,
// not a render-workset component. Projection hydration can bind it
// while world rendering is intentionally quiesced during login or
// teleport; waiting for spatial visibility would orphan the initial
// StopCompletely pending-motion node before the first visible frame.
if (!runtime.IsCurrentAnimationOwner(record, animation)
|| !ReferenceEquals(record.WorldEntity, animation.Entity)
|| animation.Sequencer is not { MotionDoneTarget: null } sequencer)
{
@ -55,7 +60,12 @@ internal sealed class LiveEntityAnimationPresenter
sequencer.MotionDoneTarget = (motion, success) =>
{
LiveEntityRuntime current = _liveEntities;
if (!current.IsCurrentSpatialAnimation(record, animation)
// CPhysicsObj owns its PartArray and CMotionInterp across
// leave/enter-world projection edges. The callback may therefore
// complete while rendering is intentionally withheld (login or
// teleport reveal), but it must never cross an entity incarnation
// or an animation-component replacement.
if (!current.IsCurrentAnimationOwner(record, animation)
|| !ReferenceEquals(record.WorldEntity, capturedEntity)
|| !ReferenceEquals(animation.Entity, capturedEntity))
{