fix(world): restore portal and distant use lifecycles
This commit is contained in:
parent
c730632075
commit
1a14812c44
18 changed files with 401 additions and 196 deletions
|
|
@ -53,7 +53,9 @@ internal sealed class LocalPlayerControllerSlot
|
|||
/// and completes StopCompletely, so its MotionDone relay must reach the
|
||||
/// candidate interpreter before the complete controller is published.
|
||||
/// </summary>
|
||||
public IDisposable BeginMotionPreparation(PlayerMovementController controller)
|
||||
public IDisposable BeginMotionPreparation(
|
||||
PlayerMovementController controller,
|
||||
Action? drainPriorAnimationQueue = null)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(controller);
|
||||
if (_preparingMotionOwner is not null)
|
||||
|
|
@ -62,6 +64,12 @@ internal sealed class LocalPlayerControllerSlot
|
|||
"A local player motion owner is already being prepared.");
|
||||
}
|
||||
|
||||
// The live PartArray exists before the local player controller. Drain
|
||||
// any animation completions produced under that prior ownership while
|
||||
// they still resolve to the prior (or null) interpreter. Publishing
|
||||
// the fresh interpreter first would let those old callbacks pop its
|
||||
// new pending_motions queue and leave an unmatched Ready sentinel.
|
||||
drainPriorAnimationQueue?.Invoke();
|
||||
_preparingMotionOwner = controller;
|
||||
return new MotionPreparation(this, controller);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -368,6 +368,7 @@ internal sealed class PlayerModeController :
|
|||
ApplyStepHeights(controller, playerEntity);
|
||||
uint initialCellId = ResolveInitialCell(playerGuid, playerEntity);
|
||||
|
||||
Action? drainPriorAnimationQueue = null;
|
||||
if (_animations.TryGetValue(playerEntity.Id, out LiveEntityAnimationState? animation)
|
||||
&& animation.Sequencer is { } sequencer)
|
||||
{
|
||||
|
|
@ -384,6 +385,7 @@ internal sealed class PlayerModeController :
|
|||
sequencer.Manager.CheckForCompletedMotions;
|
||||
controller.Motion.DefaultSink =
|
||||
new MotionTableDispatchSink(sequencer);
|
||||
drainPriorAnimationQueue = sequencer.Manager.HandleEnterWorld;
|
||||
}
|
||||
|
||||
// Retail CPhysicsObj owns CMotionInterp and CPartArray throughout
|
||||
|
|
@ -393,7 +395,9 @@ internal sealed class PlayerModeController :
|
|||
// public controller slot remains unpublished until every other
|
||||
// player-mode edge has prepared successfully.
|
||||
using IDisposable motionPreparation =
|
||||
_controllerSlot.BeginMotionPreparation(controller);
|
||||
_controllerSlot.BeginMotionPreparation(
|
||||
controller,
|
||||
drainPriorAnimationQueue);
|
||||
|
||||
ResolveResult initial = _physics.Resolve(
|
||||
playerEntity.Position,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue