feat(runtime): atomically replace collision generations

This commit is contained in:
Erik 2026-08-01 17:33:34 +02:00
parent 99bf1751bb
commit 9b0f59bd1b
21 changed files with 2435 additions and 408 deletions

View file

@ -66,7 +66,33 @@ public sealed class RuntimeLocalPlayerPhysicsPublicationStateTests
.IsExactPreparedPlacementCurrent(
fixture.Record,
fixture.Placement,
fixture.Command));
fixture.Command));
}
[Fact]
public void DormantOwnershipPreflightFailurePublishesNoCanonicalOwner()
{
using var fixture = new Fixture();
RuntimeLocalPlayerPhysicsPublicationToken publication =
fixture.Prepare();
Assert.True(fixture.Lifetime.Physics.SetPosition.Cancel(
fixture.Record,
publishWithdrawal: false));
var unownedBody = new PhysicsBody();
Assert.Throws<InvalidOperationException>(() => fixture.Lifetime.Physics
.SetPosition.PrepareDormantLocalActivationOwnership(
fixture.Record,
unownedBody,
publication.Placement));
Assert.Null(fixture.Record.PhysicsBody);
Assert.Null(fixture.Movement.Controller);
Assert.False(unownedBody.InWorld);
Assert.False(fixture.Lifetime.Physics.IsSpatialRoot(fixture.Record));
Assert.Equal(1, fixture.Owner.CaptureOwnership().CandidateCount);
Assert.Equal(0, fixture.Owner.CaptureOwnership()
.PendingActivationCount);
}
[Fact]
@ -2467,32 +2493,48 @@ public sealed class RuntimeLocalPlayerPhysicsPublicationStateTests
RuntimeCollisionAdmission admission,
PreparedLandblockCollisionGeneration prepared)
{
while (true)
bool engineCommitted = false;
for (int poll = 0; poll < 10_000; poll++)
{
while (!physics.AdvanceCollisionRetainedOwnerCapture(
admission,
prepared).Completed)
if (!engineCommitted)
{
while (!physics.AdvanceCollisionRetainedOwnerCapture(
admission,
prepared).Completed)
{
}
foreach (uint ownerId in prepared.RetainedOwnerIds)
{
physics.RefreshCollisionRetainedOwner(
admission,
prepared,
ownerId);
}
RuntimeCollisionSealStep seal;
do
{
seal = physics.AdvanceCollisionGenerationSeal(
admission,
prepared);
}
while (!seal.Completed && !seal.Restarted);
if (!seal.Completed)
continue;
}
foreach (uint ownerId in prepared.RetainedOwnerIds)
RuntimeCollisionGenerationCommit result =
physics.CommitCollisionGeneration(admission, prepared);
if (result.Completed)
return result;
while (physics.SetPosition.TryPeekProjection(
out RuntimePlacementProjectionSnapshot projection))
{
physics.RefreshCollisionRetainedOwner(
admission,
prepared,
ownerId);
Assert.True(physics.SetPosition.AcknowledgeProjection(
projection.Token));
}
RuntimeCollisionSealStep seal;
do
{
seal = physics.AdvanceCollisionGenerationSeal(
admission,
prepared);
}
while (!seal.Completed && !seal.Restarted);
if (seal.Completed)
break;
engineCommitted = result.EngineCommitted;
}
return physics.CommitCollisionGeneration(admission, prepared);
throw new InvalidOperationException(
"Collision generation did not complete its Runtime mutation transaction.");
}
private static RuntimeLandblockCollisionAssets CollisionAssets(