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

@ -283,6 +283,27 @@ public sealed class AnimationSequencerTests
$"Expected orientation near {rot.Z} but got {transforms[0].Orientation.Z}");
}
[Fact]
public void Constructor_InstallsSetupDefaultAnimationForEveryPartArray()
{
const uint AnimId = 0x0300AA01u;
var setup = Fixtures.MakeSetup(1);
setup.DefaultAnimation = (QualifiedDataId<Animation>)AnimId;
var loader = new FakeLoader();
loader.Register(AnimId, Fixtures.MakeTwoFrameAnim(
1,
Vector3.Zero,
Quaternion.Identity,
new Vector3(2f, 0f, 0f),
Quaternion.Identity));
var sequencer = new AnimationSequencer(setup, new MotionTable(), loader);
Assert.True(sequencer.HasCurrentNode);
Assert.Equal(30f, sequencer.CurrentNodeDiag.Framerate);
Assert.Equal(0, sequencer.CurrentNodeDiag.StartFrame);
Assert.Equal(1, sequencer.CurrentNodeDiag.EndFrame);
}
[Fact]
public void Advance_FrameWrapsAtHighFrame()
{
@ -1883,6 +1904,36 @@ public sealed class AnimationSequencerTests
// ── Helpers ──────────────────────────────────────────────────────────────
[Fact]
public void InitializeSetupDefaultAnimation_PreservesPhysicsAndPlacementState()
{
// CPartArray::InitDefaults (0x00518980) replaces only the animation
// list. It does not call CSequence::clear, so the PartArray's existing
// velocity, omega, and placement frame survive this operation.
const uint animationId = 0x03000531u;
var loader = new FakeLoader();
loader.Register(
animationId,
Fixtures.MakeAnim(2, 1, Vector3.Zero, Quaternion.Identity));
var seq = new AnimationSequencer(
Fixtures.MakeSetup(1),
new MotionTable(),
loader);
var placement = new AnimationFrame(1);
Vector3 velocity = new(1f, 2f, 3f);
Vector3 omega = new(0.1f, 0.2f, 0.3f);
seq.Core.SetVelocity(velocity);
seq.Core.SetOmega(omega);
seq.Core.SetPlacementFrame(placement, 0x1234u);
Assert.True(seq.InitializeSetupDefaultAnimation(animationId));
Assert.Equal(velocity, seq.CurrentVelocity);
Assert.Equal(omega, seq.CurrentOmega);
Assert.Same(placement, seq.Core.PlacementFrame);
Assert.Equal(0x1234u, seq.Core.PlacementFrameId);
}
/// <summary>
/// Expose the core CSequence's FrameNumber via reflection (test-only).
/// R1-P5 rehost (2026-07-02): _framePosition lived directly on