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:
parent
31a0889f08
commit
f961d70023
77 changed files with 12513 additions and 1871 deletions
|
|
@ -0,0 +1,150 @@
|
|||
using System.Numerics;
|
||||
using AcDream.Core.Physics;
|
||||
|
||||
namespace AcDream.Core.Tests.Physics;
|
||||
|
||||
public sealed class RetailObjectActivityGateTests
|
||||
{
|
||||
[Fact]
|
||||
public void FarPartArrayObject_ConsumesInactiveClockAndRebasesWhenNearAgain()
|
||||
{
|
||||
var clock = new RetailObjectQuantumClock();
|
||||
var body = new PhysicsBody
|
||||
{
|
||||
TransientState = TransientStateFlags.Active,
|
||||
};
|
||||
Assert.Equal(0, clock.Advance(0.02).Count);
|
||||
|
||||
Assert.Equal(
|
||||
RetailObjectActivityResult.Inactive,
|
||||
RetailObjectActivityGate.Evaluate(
|
||||
clock,
|
||||
body,
|
||||
lifecycleEligible: true,
|
||||
hasPartArray: true,
|
||||
isStatic: false,
|
||||
objectPosition: new Vector3(96.01f, 0f, 0f),
|
||||
playerPosition: Vector3.Zero,
|
||||
elapsedSeconds: 0.02));
|
||||
Assert.False(clock.IsActive);
|
||||
Assert.Equal(0.0, clock.PendingSeconds, 8);
|
||||
Assert.False(body.TransientState.HasFlag(TransientStateFlags.Active));
|
||||
|
||||
Assert.Equal(
|
||||
RetailObjectActivityResult.Reactivated,
|
||||
RetailObjectActivityGate.Evaluate(
|
||||
clock,
|
||||
body,
|
||||
lifecycleEligible: true,
|
||||
hasPartArray: true,
|
||||
isStatic: false,
|
||||
objectPosition: new Vector3(95.99f, 0f, 0f),
|
||||
playerPosition: Vector3.Zero,
|
||||
elapsedSeconds: 0.02));
|
||||
Assert.True(clock.IsActive);
|
||||
Assert.Equal(0.0, clock.PendingSeconds, 8);
|
||||
Assert.True(body.TransientState.HasFlag(TransientStateFlags.Active));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FrozenInterval_IsDiscardedByInactiveToActiveRebase()
|
||||
{
|
||||
var clock = new RetailObjectQuantumClock();
|
||||
Assert.Equal(0, clock.Advance(0.02).Count);
|
||||
|
||||
Assert.Equal(
|
||||
RetailObjectActivityResult.Suspended,
|
||||
RetailObjectActivityGate.Evaluate(
|
||||
clock,
|
||||
body: null,
|
||||
lifecycleEligible: false,
|
||||
hasPartArray: true,
|
||||
isStatic: false,
|
||||
objectPosition: Vector3.Zero,
|
||||
playerPosition: Vector3.Zero,
|
||||
elapsedSeconds: 0.5));
|
||||
Assert.Equal(
|
||||
RetailObjectActivityResult.Reactivated,
|
||||
RetailObjectActivityGate.Evaluate(
|
||||
clock,
|
||||
body: null,
|
||||
lifecycleEligible: true,
|
||||
hasPartArray: true,
|
||||
isStatic: false,
|
||||
objectPosition: Vector3.Zero,
|
||||
playerPosition: Vector3.Zero,
|
||||
elapsedSeconds: 0.01));
|
||||
|
||||
Assert.Equal(0.0, clock.PendingSeconds, 8);
|
||||
Assert.Equal(0, clock.Advance(0.02).Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PartArrayLessObject_RemainsActiveBeyondDistanceGate()
|
||||
{
|
||||
var clock = new RetailObjectQuantumClock();
|
||||
|
||||
Assert.Equal(
|
||||
RetailObjectActivityResult.Active,
|
||||
RetailObjectActivityGate.Evaluate(
|
||||
clock,
|
||||
body: null,
|
||||
lifecycleEligible: true,
|
||||
hasPartArray: false,
|
||||
isStatic: false,
|
||||
objectPosition: new Vector3(500f, 0f, 0f),
|
||||
playerPosition: Vector3.Zero,
|
||||
elapsedSeconds: 0.02));
|
||||
Assert.True(clock.IsActive);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MissingPlayer_PreservesPriorInactiveStateWithoutReactivation()
|
||||
{
|
||||
var clock = new RetailObjectQuantumClock();
|
||||
clock.Deactivate();
|
||||
|
||||
Assert.Equal(
|
||||
RetailObjectActivityResult.Inactive,
|
||||
RetailObjectActivityGate.Evaluate(
|
||||
clock,
|
||||
body: null,
|
||||
lifecycleEligible: true,
|
||||
hasPartArray: true,
|
||||
isStatic: false,
|
||||
objectPosition: Vector3.Zero,
|
||||
playerPosition: null,
|
||||
elapsedSeconds: 0.04));
|
||||
|
||||
Assert.False(clock.IsActive);
|
||||
Assert.Equal(0.0, clock.PendingSeconds, 8);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NearStaticObject_DoesNotReactivateOrdinaryObjectPath()
|
||||
{
|
||||
var clock = new RetailObjectQuantumClock();
|
||||
clock.Deactivate();
|
||||
var body = new PhysicsBody
|
||||
{
|
||||
State = PhysicsStateFlags.Static,
|
||||
TransientState = TransientStateFlags.None,
|
||||
};
|
||||
|
||||
Assert.Equal(
|
||||
RetailObjectActivityResult.Inactive,
|
||||
RetailObjectActivityGate.Evaluate(
|
||||
clock,
|
||||
body,
|
||||
lifecycleEligible: true,
|
||||
hasPartArray: true,
|
||||
isStatic: true,
|
||||
objectPosition: Vector3.Zero,
|
||||
playerPosition: Vector3.Zero,
|
||||
elapsedSeconds: 0.04));
|
||||
|
||||
Assert.False(clock.IsActive);
|
||||
Assert.Equal(0.0, clock.PendingSeconds, 8);
|
||||
Assert.False(body.TransientState.HasFlag(TransientStateFlags.Active));
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue