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

@ -44,6 +44,7 @@ public sealed class RemoteTeleportControllerTests
public Vector3 LastServerPosition { get; set; }
public double LastServerPositionTime { get; set; }
public Vector3 LastShadowSyncPosition { get; set; }
public Quaternion LastShadowSyncOrientation { get; set; }
public void BindCanonicalCell(Func<uint> read, Action<uint> write)
{
_readCell = read;
@ -64,6 +65,7 @@ public sealed class RemoteTeleportControllerTests
public Vector3 LastServerPosition { get; set; }
public double LastServerPositionTime { get; set; }
public Vector3 LastShadowSyncPosition { get; set; }
public Quaternion LastShadowSyncOrientation { get; set; }
public void BindCanonicalCell(Func<uint> read, Action<uint> write) { }
public void HitGround() { }
public void LeaveGround() { }
@ -921,6 +923,165 @@ public sealed class RemoteTeleportControllerTests
Assert.Equal(1, fixture.Engine.ShadowObjects.TotalRegistered);
}
[Fact]
public void ResolverAcceptsNewerPosition_OlderPlacementReturnsSuperseded()
{
const uint guid = 0x70000060u;
const uint sourceCell = 0xA9B40039u;
const uint destinationCell = 0xAAB40001u;
var fixture = CreateLoadedRemoteFixture(guid, sourceCell);
Assert.True(fixture.Live.TryApplyPosition(
PositionUpdate(guid, destinationCell, x: 1f, sequence: 2),
isLocalPlayer: false,
forcePositionRotation: null,
currentLocalVelocity: null,
out _,
out _,
out _));
Assert.True(fixture.Live.RebucketLiveEntity(guid, destinationCell));
Assert.True(fixture.Live.TryGetRecord(guid, out LiveEntityRecord record));
ulong outerPositionAuthority = record.PositionAuthorityVersion;
ulong outerVelocityAuthority = record.VelocityAuthorityVersion;
Vector3 newerWorldPosition = new(195f, 10f, 50f);
RemoteTeleportController? controller = null;
RemoteTeleportController.Result nestedResult = default;
bool nested = false;
controller = new RemoteTeleportController(
fixture.Engine,
fixture.Live,
(_, _) => (0.48f, 1.835f),
CellLocal,
(_, _, _) => { },
(_, _, _) => { },
(_, _) => { },
resolvePlacement: (position, cell, _, _, _, _) =>
{
if (!nested)
{
nested = true;
Assert.True(fixture.Live.TryApplyPosition(
PositionUpdate(guid, destinationCell, x: 3f, sequence: 3),
isLocalPlayer: false,
forcePositionRotation: null,
currentLocalVelocity: null,
out _,
out _,
out _));
Assert.True(fixture.Live.TryGetRecord(guid, out var current));
nestedResult = controller!.TryApply(
current,
current.PositionAuthorityVersion,
current.VelocityAuthorityVersion,
fixture.Remote,
fixture.Entity,
newerWorldPosition,
destinationCell,
new Vector3(3f, 10f, 50f),
Quaternion.Identity,
gameTime: 6.0,
destinationProjectionVisible: true,
generation: 1,
positionSequence: 3);
}
return SuccessfulPlacement(position, cell);
});
RemoteTeleportController.Result outerResult = controller.TryApply(
record,
outerPositionAuthority,
outerVelocityAuthority,
fixture.Remote,
fixture.Entity,
new Vector3(193f, 10f, 50f),
destinationCell,
new Vector3(1f, 10f, 50f),
Quaternion.Identity,
gameTime: 5.0,
destinationProjectionVisible: true,
generation: 1,
positionSequence: 2);
Assert.True(nestedResult.Applied);
Assert.True(nestedResult.ContactResolved);
Assert.True(outerResult.Superseded);
Assert.False(outerResult.Applied);
Assert.Equal(newerWorldPosition, fixture.Remote.Body.Position);
Assert.Equal(newerWorldPosition, fixture.Entity.Position);
controller.Dispose();
}
[Fact]
public void ResolverAcceptsIndependentState_PositionPlacementStillCommits()
{
const uint guid = 0x70000061u;
const uint sourceCell = 0xA9B40039u;
const uint destinationCell = 0xAAB40001u;
var fixture = CreateLoadedRemoteFixture(guid, sourceCell);
Assert.True(fixture.Live.TryApplyPosition(
PositionUpdate(guid, destinationCell, x: 1f, sequence: 2),
isLocalPlayer: false,
forcePositionRotation: null,
currentLocalVelocity: null,
out _,
out _,
out _));
Assert.True(fixture.Live.RebucketLiveEntity(guid, destinationCell));
Assert.True(fixture.Live.TryGetRecord(guid, out LiveEntityRecord record));
ulong positionAuthority = record.PositionAuthorityVersion;
ulong velocityAuthority = record.VelocityAuthorityVersion;
bool stateAccepted = false;
using var controller = new RemoteTeleportController(
fixture.Engine,
fixture.Live,
(_, _) => (0.48f, 1.835f),
CellLocal,
(_, _, _) => { },
(_, _, _) => { },
(_, _) => { },
resolvePlacement: (position, cell, _, _, _, _) =>
{
if (!stateAccepted)
{
stateAccepted = true;
Assert.True(fixture.Live.TryApplyState(
new SetState.Parsed(
guid,
(uint)(PhysicsStateFlags.Hidden
| PhysicsStateFlags.ReportCollisions),
1,
2),
out _));
}
return SuccessfulPlacement(position, cell);
});
Vector3 destination = new(193f, 10f, 50f);
RemoteTeleportController.Result result = controller.TryApply(
record,
positionAuthority,
velocityAuthority,
fixture.Remote,
fixture.Entity,
destination,
destinationCell,
new Vector3(1f, 10f, 50f),
Quaternion.Identity,
gameTime: 5.0,
destinationProjectionVisible: true,
generation: 1,
positionSequence: 2);
Assert.True(stateAccepted);
Assert.True(result.Applied);
Assert.True(result.ContactResolved);
Assert.False(result.Superseded);
Assert.Equal(destination, fixture.Remote.Body.Position);
Assert.Equal(destination, fixture.Entity.Position);
Assert.True(record.FinalPhysicsState.HasFlag(PhysicsStateFlags.Hidden));
Assert.Equal(record.FinalPhysicsState, fixture.Remote.Body.State);
}
[Fact]
public void TeardownCallbackFailure_StillForgetsPendingBeforeGuidReuse()
{
@ -1009,6 +1170,75 @@ public sealed class RemoteTeleportControllerTests
return engine;
}
private static LoadedRemoteFixture CreateLoadedRemoteFixture(
uint guid,
uint sourceCell)
{
var spatial = new GpuWorldState();
spatial.AddLandblock(EmptyLandblock(0xA9B4FFFFu));
spatial.AddLandblock(EmptyLandblock(0xAAB4FFFFu));
var live = new LiveEntityRuntime(spatial, new Resources());
live.RegisterLiveEntity(Spawn(guid, sourceCell));
WorldEntity entity = live.MaterializeLiveEntity(
guid,
sourceCell,
id => new WorldEntity
{
Id = id,
ServerGuid = guid,
SourceGfxObjOrSetupId = 0x02000001u,
Position = new Vector3(191f, 10f, 50f),
Rotation = Quaternion.Identity,
MeshRefs = Array.Empty<MeshRef>(),
})!;
var remote = new GameWindow.RemoteMotion();
remote.Body.SnapToCell(sourceCell, entity.Position, entity.Position);
live.SetRemoteMotionRuntime(guid, remote);
return new LoadedRemoteFixture(
live,
entity,
remote,
BuildEngine(includeDestination: true));
}
private static WorldSession.EntityPositionUpdate PositionUpdate(
uint guid,
uint cell,
float x,
ushort sequence) => new(
guid,
new CreateObject.ServerPosition(
cell,
x,
10f,
50f,
1f,
0f,
0f,
0f),
null,
null,
true,
1,
sequence,
0,
0);
private static ResolveResult SuccessfulPlacement(Vector3 position, uint cell) => new(
position,
cell,
IsOnGround: true,
InContact: true,
OnWalkable: true,
ContactPlane: new Plane(Vector3.UnitZ, 0f),
ContactPlaneCellId: cell);
private readonly record struct LoadedRemoteFixture(
LiveEntityRuntime Live,
WorldEntity Entity,
GameWindow.RemoteMotion Remote,
PhysicsEngine Engine);
private static void AddDestination(PhysicsEngine engine) =>
engine.AddLandblock(
0xAAB4FFFFu,