fix(runtime): preserve hidden setposition collision ownership

This commit is contained in:
Erik 2026-08-01 18:22:45 +02:00
parent 9b0f59bd1b
commit 0fbc7a1fb7
8 changed files with 343 additions and 43 deletions

View file

@ -113,6 +113,42 @@ public sealed class RuntimeSetPositionStateTests
Assert.Equal(1, ownership.PreparedMoverCount);
}
[Theory]
[InlineData(PhysicsStateFlags.Hidden)]
[InlineData(PhysicsStateFlags.Hidden | PhysicsStateFlags.NoDraw)]
public void HiddenObjectCommitsResidenceWhileSuppressingCollisionReports(
PhysicsStateFlags suppressedState)
{
PhysicsEngine engine = FlatEngine(SourceLandblock, 0f);
using var lifetime = new RuntimeEntityObjectLifetime(engine);
RuntimeEntityRecord record = CreateRecord(lifetime, 0x70001022u, 1);
PhysicsStateFlags state = PhysicsStateFlags.Gravity | suppressedState;
PhysicsBody body = AttachBody(lifetime, record, SourceCell, state);
var collisionObserver = new CollisionReportObserver();
using IDisposable collisionSubscription = lifetime.Physics
.CollisionReports.Subscribe(collisionObserver);
RuntimeSetPositionOutcome outcome = lifetime.Physics.SetPosition.Apply(
record,
record.PositionAuthorityVersion,
Command(Request(SourceCell, new Vector3(12f, 18f, 7f))));
Assert.Equal(
RuntimeSetPositionStatus.CommittedHostAcknowledgementPending,
outcome.Status);
Assert.True(body.InWorld);
Assert.Equal(SourceCell, record.FullCellId);
Assert.Equal(new Vector3(12f, 18f, 7f), body.Position);
Assert.True(lifetime.Physics.IsSpatialRoot(record));
Assert.Empty(collisionObserver.Reports);
RuntimeCollisionReportingOwnershipSnapshot reporting = lifetime
.Physics.CollisionReports.CaptureOwnership();
Assert.Equal(0, reporting.OwnerCount);
Assert.Equal(0, reporting.PendingSetPositionDispatchCount);
Assert.True(lifetime.Physics.SetPosition.AcknowledgeProjection(
outcome.Projection));
}
[Fact]
public void PublicPlacementChannelObservesRetriesAndAcknowledgesExactToken()
{
@ -2582,6 +2618,15 @@ public sealed class RuntimeSetPositionStateTests
}
}
private sealed class CollisionReportObserver
: IRuntimeCollisionReportObserver
{
internal List<RuntimeCollisionReport> Reports { get; } = [];
public void OnCollisionReport(in RuntimeCollisionReport report) =>
Reports.Add(report);
}
private sealed class EntityObserver : IRuntimeEntityObjectObserver
{
internal List<RuntimeEntityDelta> Deltas { get; } = [];