feat(physics): port retail complete object frame pipeline

Restore the named-retail object update order across local, remote, static, projectile, animation, shadow, teleport, and effect lifetimes. Separate authoritative root commits from spatial rebucketing, preserve per-owner hook/FIFO ordering, and remove update-path allocations with exact lifecycle and residency gates.

Add deterministic conformance, adversarial lifetime, GUID-reuse, pending-cell, quaternion, timestamp, and allocation coverage. Release build is warning-free and all 6,446 tests pass with five intentional skips; retail, architecture, and adversarial reviews are clean.

Co-authored-by: OpenAI Codex <codex@openai.com>
This commit is contained in:
Erik 2026-07-20 09:10:31 +02:00
parent 31a0889f08
commit f961d70023
77 changed files with 12513 additions and 1871 deletions

View file

@ -20,52 +20,25 @@ namespace AcDream.Core.Physics.Motion;
/// <c>combine_motion</c>/<c>re_modify</c> — the composition the retired
/// AP-73 row approximated with one cycle.
/// </para>
///
/// <para>
/// The <see cref="TurnApplied"/>/<see cref="TurnStopped"/> callbacks are the
/// interim ObservedOmega seam: the App seeds the remote body's angular
/// velocity from the wire turn so rotation starts the same tick (retail
/// rotates the body from the sequence omega inside the per-tick
/// <c>apply_physics</c> chain — R6 scope; register row). They fire BEFORE
/// the dispatch so a consumer sees the seed even if the dat lacks the
/// modifier entry.
/// </para>
/// </summary>
public sealed class MotionTableDispatchSink : IInterpretedMotionSink
{
private readonly AnimationSequencer _sequencer;
/// <summary>Turn-class dispatch observed: (motion, signedSpeed) —
/// TurnLeft arrives either as the explicit 0x0E command or as
/// TurnRight + negative speed (adjust_motion wire convention).</summary>
public Action<uint, float>? TurnApplied { get; set; }
/// <summary>Turn-class stop observed.</summary>
public Action? TurnStopped { get; set; }
public MotionTableDispatchSink(AnimationSequencer sequencer)
{
ArgumentNullException.ThrowIfNull(sequencer);
_sequencer = sequencer;
}
private static bool IsTurn(uint motion)
=> (motion & 0xFF000000u) == 0x65000000u && (motion & 0xFFu) is 0x0D or 0x0E;
public bool ApplyMotion(uint motion, float speed)
{
if (IsTurn(motion))
TurnApplied?.Invoke(motion, speed);
uint result = _sequencer.PerformMovement(MotionTableMovement.Interpreted(motion, speed));
return result == MotionTableManagerError.Success;
}
public bool StopMotion(uint motion)
{
if (IsTurn(motion))
TurnStopped?.Invoke();
uint result = _sequencer.PerformMovement(MotionTableMovement.StopInterpreted(motion, 1f));
return result == MotionTableManagerError.Success;
}
@ -75,14 +48,10 @@ public sealed class MotionTableDispatchSink : IInterpretedMotionSink
/// (0x00518890): <c>MotionTableManager::PerformMovement(type 5)</c>.
/// The manager stops everything and queues its Ready-sentinel
/// pending_animations entry UNCONDITIONALLY — the completable partner
/// of the interp's A9 pending_motions node. A full stop ends any turn
/// cycle, so the ObservedOmega seam is notified like
/// <see cref="StopMotion"/>'s turn-class branch.
/// of the interp's A9 pending_motions node.
/// </summary>
public bool StopCompletely()
{
TurnStopped?.Invoke();
uint result = _sequencer.PerformMovement(MotionTableMovement.StopCompletely());
return result == MotionTableManagerError.Success;
}