using System.Numerics; using AcDream.Content; using AcDream.Content.Pak; using AcDream.Core.Net; using AcDream.Core.Net.Messages; using AcDream.Core.Physics; using AcDream.Runtime.Entities; using AcDream.Runtime.Physics; using AcDream.Runtime.Session; namespace AcDream.Runtime.Tests.Session; /// /// C4 route 4b-1: focused tests for the Runtime-owned, per-entity remote /// placement infrastructure. This route wires NO production caller — every /// test below constructs an already-classified /// directly (the same shape /// /// would hand a real caller) so each scenario is exercised precisely, mirroring /// RuntimeSetPositionStateTests' bare- /// fixture rather than the full GameRuntime/LiveSessionHost /// harness route 2's tests use — this controller has no local-player /// controller, outbound session, or generation dependency to bootstrap. /// /// Each test was verified to actually discriminate its own fix by temporarily /// reverting the corresponding guard/omission in /// and confirming the /// matching test failed, then restoring it. /// public sealed class RuntimeRemotePlacementDriveControllerTests { private const uint SourceLandblock = 0xB1000000u; private const uint SourceCell = SourceLandblock | 0x0001u; private const uint DestinationLandblock = 0xB2000000u; private const uint DestinationCell = DestinationLandblock | 0x0001u; private const float SpawnHeight = 7f; [Fact] public void NotApplicable_WhenDispositionIsNotOwnedByThisRoute() { foreach (RuntimeAuthoritativePositionDisposition disposition in new[] { RuntimeAuthoritativePositionDisposition.Interpolate, RuntimeAuthoritativePositionDisposition.NoPositionOperation, RuntimeAuthoritativePositionDisposition.RejectedAuthority, RuntimeAuthoritativePositionDisposition.RejectedData, RuntimeAuthoritativePositionDisposition.AwaitFreshPosition, }) { using var lifetime = new RuntimeEntityObjectLifetime(FlatEngine()); RuntimeEntityRecord record = CreateRemoteRecord(lifetime, 0x70003001u); AttachBody(lifetime, record, SourceCell); var window = new FakeServiceWindow(); window.Allow(DestinationLandblock); RuntimeRemotePlacementDriveController drive = CreateDrive(lifetime, window); RuntimeAuthoritativePositionRoute route = MakeRoute( record, disposition, DestinationCell); Assert.Equal( RuntimeRemotePlacementExecutionStatus.NotApplicable, drive.TryExecuteAcceptedRemotePosition(record, route)); Assert.Equal(0, drive.PendingCount); AssertConverged(lifetime); } } [Fact] public void NotApplicable_WhenTheEntityHasNoCanonicalBody() { using var lifetime = new RuntimeEntityObjectLifetime(FlatEngine()); RuntimeEntityRecord record = CreateRemoteRecord(lifetime, 0x70003002u); // Deliberately never attach a body. var window = new FakeServiceWindow(); window.Allow(DestinationLandblock); RuntimeRemotePlacementDriveController drive = CreateDrive(lifetime, window); RuntimeAuthoritativePositionRoute route = MakeRoute( record, RuntimeAuthoritativePositionDisposition.SetPosition, DestinationCell); Assert.Equal( RuntimeRemotePlacementExecutionStatus.NotApplicable, drive.TryExecuteAcceptedRemotePosition(record, route)); } /// /// B6 review fix: OwnsPlacement keyed on Disposition alone /// would claim this route too — the classifier emits /// SetPositionSimple for the LOCAL PLAYER's FORCE_POSITION/ /// teleport branches (RuntimeSetPositionOperationKind.LocalAuthoritative), /// not only for remotes. The static predicate itself is exercised /// directly (no entity/body needed) since it takes only the route. /// [Fact] public void OwnsPlacement_FalseWhenOperationKindIsNotRemoteAuthoritative() { // RuntimeSetPositionOperationKind is internal, so a public [Theory] // cannot take it as a parameter (CS0051) — iterate directly instead, // mirroring NotApplicable_WhenDispositionIsNotOwnedByThisRoute's own // foreach-over-internal-enum shape. foreach (RuntimeSetPositionOperationKind operationKind in new[] { RuntimeSetPositionOperationKind.InitialLogin, RuntimeSetPositionOperationKind.LocalAuthoritative, RuntimeSetPositionOperationKind.ProjectileAuthoritative, }) { using var lifetime = new RuntimeEntityObjectLifetime(FlatEngine()); RuntimeEntityRecord record = CreateRemoteRecord(lifetime, 0x7000300Fu); RuntimeAuthoritativePositionRoute route = MakeRoute( record, RuntimeAuthoritativePositionDisposition.SetPositionSimple, DestinationCell, operationKind: operationKind); Assert.False( RuntimeRemotePlacementDriveController.OwnsPlacement(route)); // End to end: this controller must decline the SAME route as // NotApplicable, not merely the static predicate in isolation. var window = new FakeServiceWindow(); window.Allow(DestinationLandblock); RuntimeRemotePlacementDriveController drive = CreateDrive(lifetime, window); Assert.Equal( RuntimeRemotePlacementExecutionStatus.NotApplicable, drive.TryExecuteAcceptedRemotePosition(record, route)); Assert.Equal(0, drive.PendingCount); } } /// /// C2-4 review fix (delta round): the OperationKind is RemoteAuthoritative /// guard alone is STILL not exact — RuntimeAuthoritativePositionRouteClassifier /// .ClassifyCreate emits Disposition = SetPosition AND /// OperationKind = RemoteAuthoritative for a REMOTE top-level /// initial Create too (only the LOCAL PLAYER's Create maps to /// InitialLogin), so both the disposition and operation-kind /// guards pass for a Create-shaped route. Retail's own flag choice is /// what actually distinguishes them: a Create carries /// InitialCreateFlags (Placement|Slide, no /// Teleport); every remote accepted-Position SetPosition/ /// SetPositionSimple route carries AuthoritativeTeleportFlags /// (Teleport|Slide|SendPositionEvent). Route 4b-1 is a /// POSITION-only route — the first-entry conductor owns every Create — /// so a Create-shaped route reaching this controller must be declined. /// [Fact] public void OwnsPlacement_FalseForARemoteTopLevelCreateShapedRoute() { using var lifetime = new RuntimeEntityObjectLifetime(FlatEngine()); RuntimeEntityRecord record = CreateRemoteRecord(lifetime, 0x70003014u); RuntimeAuthoritativePositionRoute createRoute = MakeRoute( record, RuntimeAuthoritativePositionDisposition.SetPosition, DestinationCell, operationKind: RuntimeSetPositionOperationKind.RemoteAuthoritative, setPositionFlags: PhysicsSetPositionFlags.Placement | PhysicsSetPositionFlags.Slide); Assert.False( RuntimeRemotePlacementDriveController.OwnsPlacement(createRoute)); // End to end: this controller must decline the SAME route as // NotApplicable, not merely the static predicate in isolation. var window = new FakeServiceWindow(); window.Allow(DestinationLandblock); RuntimeRemotePlacementDriveController drive = CreateDrive(lifetime, window); Assert.Equal( RuntimeRemotePlacementExecutionStatus.NotApplicable, drive.TryExecuteAcceptedRemotePosition(record, createRoute)); Assert.Equal(0, drive.PendingCount); // The genuine remote accepted-Position shape (SAME disposition, SAME // operation kind, Teleport-flagged) must still be owned — the fix // must not have over-corrected into refusing everything. RuntimeAuthoritativePositionRoute positionRoute = MakeRoute( record, RuntimeAuthoritativePositionDisposition.SetPosition, DestinationCell); Assert.True( RuntimeRemotePlacementDriveController.OwnsPlacement(positionRoute)); } /// /// The central decision's core pin: a destination this host's service /// window does not currently cover must be refused, not parked — no /// operation may open at all, so the body's own InWorld/object /// clock are never touched. /// [Fact] public void Refused_WhenDestinationIsNotWithinServiceWindow_NoOperationOpensAndBodyStaysInWorld() { using var lifetime = new RuntimeEntityObjectLifetime(FlatEngine()); RuntimeEntityRecord record = CreateRemoteRecord(lifetime, 0x70003003u); PhysicsBody body = AttachBody(lifetime, record, SourceCell); // The service window allows nothing — mirrors a destination // landblock this host has never collision-published. var window = new FakeServiceWindow(); RuntimeRemotePlacementDriveController drive = CreateDrive(lifetime, window); RuntimeAuthoritativePositionRoute route = MakeRoute( record, RuntimeAuthoritativePositionDisposition.SetPosition, DestinationCell); RuntimeRemotePlacementExecutionStatus status = drive.TryExecuteAcceptedRemotePosition(record, route); Assert.Equal(RuntimeRemotePlacementExecutionStatus.Refused, status); Assert.True(body.InWorld); Assert.True(record.ObjectClock.IsActive); Assert.Equal( 0, lifetime.Physics.CaptureOwnership().SetPositionOperationCount); AssertConverged(lifetime); } /// /// The exact §"central decision" sequence the contract's acceptance /// section pins: attempt a placement whose destination is refused, then /// deliver the entity's NEXT accepted Position — which, whatever it /// classifies to, ALWAYS runs RuntimeSetPositionState.Forget for /// this entity first /// (, called /// unconditionally regardless of disposition). Because nothing was ever /// parked in the first step, that unconditional Forget has nothing to /// discard, and the entity is STILL in the world afterward — the /// invisible-and-intangible failure this route exists to prevent. /// [Fact] public void CentralDecision_RefusedPlacementThenNextAcceptedPositionForgetsNothing_EntityStaysInWorld() { using var lifetime = new RuntimeEntityObjectLifetime(FlatEngine()); RuntimeEntityRecord record = CreateRemoteRecord(lifetime, 0x70003004u); PhysicsBody body = AttachBody(lifetime, record, SourceCell); var window = new FakeServiceWindow(); RuntimeRemotePlacementDriveController drive = CreateDrive(lifetime, window); RuntimeAuthoritativePositionRoute route = MakeRoute( record, RuntimeAuthoritativePositionDisposition.SetPosition, DestinationCell); // Packet N: destination not placeable now. Assert.Equal( RuntimeRemotePlacementExecutionStatus.Refused, drive.TryExecuteAcceptedRemotePosition(record, route)); Assert.True(body.InWorld); Assert.True(record.ObjectClock.IsActive); // Packet N+1 ~150 ms later: whatever it classifies to (here, // Interpolate — the caller never reaches this controller at all for // that disposition), production's merge unconditionally Forgets any // in-flight operation for this entity FIRST. Simulated directly // (mirrors RuntimeAcceptedPositionDriveControllerTests' // Equal_ClearsPendingWithoutReissuing... fixture, which drives the // same production Forget call without a full second network // round-trip). RuntimePlacementCancellationReceipt cancellation = lifetime.Physics.SetPosition.Forget(record); if (cancellation.IsValid) lifetime.Physics.SetPosition.PublishCancellation(cancellation); Assert.True(body.InWorld); Assert.True(record.ObjectClock.IsActive); Assert.Equal(SourceCell, record.FullCellId); AssertConverged(lifetime); } [Fact] public void Committed_WhenDestinationIsWithinServiceWindowAndCollisionGenerationCommitted() { using var lifetime = new RuntimeEntityObjectLifetime(FlatEngine()); CommitLandblockCollision(lifetime, DestinationLandblock); RuntimeEntityRecord record = CreateRemoteRecord(lifetime, 0x70003005u); PhysicsBody body = AttachBody(lifetime, record, SourceCell); var window = new FakeServiceWindow(); window.Allow(DestinationLandblock); RuntimeRemotePlacementDriveController drive = CreateDrive(lifetime, window); var destination = new Vector3(12f, 14f, SpawnHeight); RuntimeAuthoritativePositionRoute route = MakeRoute( record, RuntimeAuthoritativePositionDisposition.SetPosition, DestinationCell, destination); RuntimeRemotePlacementExecutionStatus status = drive.TryExecuteAcceptedRemotePosition(record, route); Assert.Equal(RuntimeRemotePlacementExecutionStatus.Committed, status); // Runtime's world-frame resolution shifts an authored landblock-local // position into Runtime's continuous world frame // (resolveWorldOffsetFromRuntimeFrame: true) — DestinationLandblock // sits +192m on X from SourceLandblock per CommitLandblockCollision. Assert.Equal(destination + new Vector3(192f, 0f, 0f), body.Position); Assert.Equal(0, drive.PendingCount); // No host subscription is wired in this bare fixture — drain the // Place receipt exactly like production's placement-projection // subscription would, so the operation itself (not this drive's own // ledger) also converges to zero. DrainPlacementFifo(lifetime); Assert.Equal( 0, lifetime.Physics.CaptureOwnership().SetPositionOperationCount); AssertConverged(lifetime); } /// /// B4 review fix: SubmitAndResolve's Committed branch returns and /// retains nothing in _pending, but when nothing synchronously /// consumes-and-acknowledges the Place receipt (this bare fixture has no /// host subscription wired — production's declined-sink retry scenario /// is the identical shape), the operation stays live in Core's /// _operations map until something later calls /// AcknowledgeProjection. Before this fix /// RemotePlacementDrivePendingCount was blind to that live /// operation the instant Committed was returned. This proves it is /// now visible, and that it still converges to zero once the receipt is /// actually acknowledged. /// [Fact] public void Committed_UnacknowledgedOperationStaysVisibleInTheLedgerUntilAcknowledged() { using var lifetime = new RuntimeEntityObjectLifetime(FlatEngine()); CommitLandblockCollision(lifetime, DestinationLandblock); RuntimeEntityRecord record = CreateRemoteRecord(lifetime, 0x70003010u); AttachBody(lifetime, record, SourceCell); var window = new FakeServiceWindow(); window.Allow(DestinationLandblock); RuntimeRemotePlacementDriveController drive = CreateDrive(lifetime, window); var destination = new Vector3(12f, 14f, SpawnHeight); RuntimeAuthoritativePositionRoute route = MakeRoute( record, RuntimeAuthoritativePositionDisposition.SetPosition, DestinationCell, destination); RuntimeRemotePlacementExecutionStatus status = drive.TryExecuteAcceptedRemotePosition(record, route); Assert.Equal(RuntimeRemotePlacementExecutionStatus.Committed, status); // No host subscription is wired in this bare fixture, so the Place // receipt is still genuinely unacknowledged — the ledger must SEE it. Assert.Equal( 1, lifetime.Physics.CaptureOwnership().SetPositionOperationCount); Assert.Equal( 1, lifetime.CaptureOwnership().RemotePlacementDrivePendingCount); DrainPlacementFifo(lifetime); Assert.Equal( 0, lifetime.Physics.CaptureOwnership().SetPositionOperationCount); AssertConverged(lifetime); } [Fact] public void Contention_WhenTheEntityAlreadyOwnsAnActiveOperation() { using var lifetime = new RuntimeEntityObjectLifetime(FlatEngine()); CommitLandblockCollision(lifetime, DestinationLandblock); RuntimeEntityRecord record = CreateRemoteRecord(lifetime, 0x70003006u); PhysicsBody body = AttachBody(lifetime, record, SourceCell); Vector3 positionBefore = body.Position; var window = new FakeServiceWindow(); window.Allow(DestinationLandblock); RuntimeRemotePlacementDriveController drive = CreateDrive(lifetime, window); // An external placement authority (portal/teleport/another route) // already owns this entity's SetPosition operation. RuntimeEntityPlacementToken displaced = lifetime.Physics.SetPosition .TryBeginExclusiveAuthoredPlacement( record, record.PositionAuthorityVersion, RuntimeSetPositionOperationKind.RemoteAuthoritative); Assert.True(displaced.IsValid); RuntimeAuthoritativePositionRoute route = MakeRoute( record, RuntimeAuthoritativePositionDisposition.SetPosition, DestinationCell); Assert.Equal( RuntimeRemotePlacementExecutionStatus.Contention, drive.TryExecuteAcceptedRemotePosition(record, route)); Assert.Equal(positionBefore, body.Position); Assert.Equal(0, drive.PendingCount); RuntimePlacementCancellationReceipt cancellation = lifetime.Physics .SetPosition.ForgetExactPlacement(displaced); if (cancellation.IsValid) lifetime.Physics.SetPosition.PublishCancellation(cancellation); } /// /// Per-entity independence: two remotes interleaved must not share any /// state — one entity's Contention must never block the other's Begin, /// and each converges to zero independently. /// [Fact] public void PerEntityIndependence_TwoRemotesInterleavedDoNotBlockEachOther() { using var lifetime = new RuntimeEntityObjectLifetime(FlatEngine()); CommitLandblockCollision(lifetime, DestinationLandblock); RuntimeEntityRecord first = CreateRemoteRecord(lifetime, 0x70003007u); RuntimeEntityRecord second = CreateRemoteRecord(lifetime, 0x70003008u); PhysicsBody firstBody = AttachBody(lifetime, first, SourceCell); PhysicsBody secondBody = AttachBody(lifetime, second, SourceCell); var window = new FakeServiceWindow(); window.Allow(DestinationLandblock); RuntimeRemotePlacementDriveController drive = CreateDrive(lifetime, window); // First entity's own operation is still outstanding (an external // authority holds it) when the second entity's Position arrives. RuntimeEntityPlacementToken firstDisplaced = lifetime.Physics.SetPosition .TryBeginExclusiveAuthoredPlacement( first, first.PositionAuthorityVersion, RuntimeSetPositionOperationKind.RemoteAuthoritative); Assert.True(firstDisplaced.IsValid); RuntimeAuthoritativePositionRoute firstRoute = MakeRoute( first, RuntimeAuthoritativePositionDisposition.SetPosition, DestinationCell); RuntimeAuthoritativePositionRoute secondRoute = MakeRoute( second, RuntimeAuthoritativePositionDisposition.SetPosition, DestinationCell, new Vector3(20f, 22f, SpawnHeight)); Assert.Equal( RuntimeRemotePlacementExecutionStatus.Contention, drive.TryExecuteAcceptedRemotePosition(first, firstRoute)); Assert.Equal( RuntimeRemotePlacementExecutionStatus.Committed, drive.TryExecuteAcceptedRemotePosition(second, secondRoute)); Assert.Equal( new Vector3(20f, 22f, SpawnHeight) + new Vector3(192f, 0f, 0f), secondBody.Position); Assert.Equal(0, drive.PendingCount); RuntimePlacementCancellationReceipt cancellation = lifetime.Physics .SetPosition.ForgetExactPlacement(firstDisplaced); if (cancellation.IsValid) lifetime.Physics.SetPosition.PublishCancellation(cancellation); DrainPlacementFifo(lifetime); _ = firstBody; } /// /// Per-entity independence, the shape route 2's single _pending /// slot cannot express: TWO entities each hold their OWN outstanding /// preparation retry at the same time. Route 2's /// RetainPending throws if a second live entry would displace the /// first; this per-key map must track both simultaneously and let each /// resolve (or die) independently. /// [Fact] public void PerEntityIndependence_TwoConcurrentPreparationRetriesDoNotCollide() { using var lifetime = new RuntimeEntityObjectLifetime(FlatEngine()); CommitLandblockCollision(lifetime, DestinationLandblock); RuntimeEntityRecord first = CreateRemoteRecord( lifetime, 0x7000300Du, setupTableId: 0x02000001u); RuntimeEntityRecord second = CreateRemoteRecord( lifetime, 0x7000300Eu, setupTableId: 0x02000001u); AttachBody(lifetime, first, SourceCell); AttachBody(lifetime, second, SourceCell); var window = new FakeServiceWindow(); window.Allow(DestinationLandblock); RuntimeRemotePlacementDriveController drive = CreateDrive(lifetime, window); RuntimeAuthoritativePositionRoute firstRoute = MakeRoute( first, RuntimeAuthoritativePositionDisposition.SetPosition, DestinationCell); RuntimeAuthoritativePositionRoute secondRoute = MakeRoute( second, RuntimeAuthoritativePositionDisposition.SetPosition, DestinationCell); // Both entities' Setup assets are unresolved (Missing) — both retry. Assert.Equal( RuntimeRemotePlacementExecutionStatus.Contention, drive.TryExecuteAcceptedRemotePosition(first, firstRoute)); Assert.Equal( RuntimeRemotePlacementExecutionStatus.Contention, drive.TryExecuteAcceptedRemotePosition(second, secondRoute)); Assert.Equal(2, drive.PendingCount); // The FIRST entity's retry dies (an unrelated accepted Position for // IT ALONE forgets it); the second must remain completely // unaffected — a shared/overwriting single slot could not represent // this. RuntimePlacementCancellationReceipt cancellation = lifetime.Physics.SetPosition.Forget(first); if (cancellation.IsValid) lifetime.Physics.SetPosition.PublishCancellation(cancellation); drive.Advance(); Assert.Equal(1, drive.PendingCount); // The second entity's own operation is still tracked — the first's // cancellation removed exactly one operation, not both. Assert.Equal( 1, lifetime.Physics.CaptureOwnership().SetPositionOperationCount); // Cleanup: retire the second entity's still-live retry too. RuntimePlacementCancellationReceipt secondCancellation = lifetime.Physics.SetPosition.Forget(second); if (secondCancellation.IsValid) { lifetime.Physics.SetPosition .PublishCancellation(secondCancellation); } drive.Advance(); Assert.Equal(0, drive.PendingCount); } /// /// B3 review fix: a retained preparation retry must re-check the SAME /// service-window guard the entry point uses before Advance() /// resubmits it — a destination that retired its collision publication in /// the frames since the retry was retained must be dropped, not /// resubmitted. Discriminates from the OLD unconditional resubmit: /// resubmitting against the SAME always-Missing collision source /// returns the SAME retryable status, so without the re-check the entry /// would simply be re-retained (PendingCount stays 1) even though /// the window already forbids the destination — never converging. /// [Fact] public void Advance_DropsRetainedRetryWhenTheServiceWindowNoLongerCoversItsDestination() { using var lifetime = new RuntimeEntityObjectLifetime(FlatEngine()); RuntimeEntityRecord record = CreateRemoteRecord( lifetime, 0x70003011u, setupTableId: 0x02000001u); AttachBody(lifetime, record, SourceCell); CommitLandblockCollision(lifetime, DestinationLandblock); var window = new FakeServiceWindow(); window.Allow(DestinationLandblock); RuntimeRemotePlacementDriveController drive = CreateDrive(lifetime, window); RuntimeAuthoritativePositionRoute route = MakeRoute( record, RuntimeAuthoritativePositionDisposition.SetPosition, DestinationCell); // The Setup asset is unresolved (Missing) — the first attempt // retries rather than commits, retaining the entry. Assert.Equal( RuntimeRemotePlacementExecutionStatus.Contention, drive.TryExecuteAcceptedRemotePosition(record, route)); Assert.Equal(1, drive.PendingCount); Assert.Equal( 1, lifetime.Physics.CaptureOwnership().SetPositionOperationCount); // The remote wandered back out of range between this retry being // retained and the next host cadence pump. window.Forbid(DestinationLandblock); drive.Advance(); Assert.Equal(0, drive.PendingCount); Assert.Equal( 0, lifetime.Physics.CaptureOwnership().SetPositionOperationCount); AssertConverged(lifetime); } /// /// Currency: a preparation-retry entry left tracking a token some OTHER /// caller already Forgot must not leak once this entity's NEXT packet /// takes a path that itself never touches _pending (here, a /// service-window refusal) — proving the self-heal is doing real work, /// not merely being masked by the retry branch's own dictionary /// overwrite (which would hide the leak if this test only ever re-hit /// the SAME retryable status). /// [Fact] public void StalePreparationRetry_SelfHealsRatherThanLeakingWhenTheNextPacketNeverTouchesPending() { using var lifetime = new RuntimeEntityObjectLifetime(FlatEngine()); RuntimeEntityRecord record = CreateRemoteRecord( lifetime, 0x70003009u, setupTableId: 0x02000001u); AttachBody(lifetime, record, SourceCell); CommitLandblockCollision(lifetime, DestinationLandblock); // A Setup asset that never resolves (Missing) — the first attempt // through this collision source retries rather than commits. var window = new FakeServiceWindow(); window.Allow(DestinationLandblock); RuntimeRemotePlacementDriveController drive = CreateDrive(lifetime, window); RuntimeAuthoritativePositionRoute route = MakeRoute( record, RuntimeAuthoritativePositionDisposition.SetPosition, DestinationCell); Assert.Equal( RuntimeRemotePlacementExecutionStatus.Contention, drive.TryExecuteAcceptedRemotePosition(record, route)); Assert.Equal(1, drive.PendingCount); // An unrelated accepted Position for this SAME entity Forgets the // retained retry before it ever resolves — the mundane 5-10 Hz case. RuntimePlacementCancellationReceipt cancellation = lifetime.Physics.SetPosition.Forget(record); if (cancellation.IsValid) lifetime.Physics.SetPosition.PublishCancellation(cancellation); // The destination is no longer serviceable by the NEXT packet (the // remote wandered back out of range) — the Refused branch never // assigns or clears _pending itself, so only the entry-point // self-heal can retire the dead entry left behind above. window.Forbid(DestinationLandblock); RuntimeAuthoritativePositionRoute refusedRoute = MakeRoute( record, RuntimeAuthoritativePositionDisposition.SetPosition, DestinationCell); RuntimeRemotePlacementExecutionStatus status = drive.TryExecuteAcceptedRemotePosition(record, refusedRoute); Assert.Equal(RuntimeRemotePlacementExecutionStatus.Refused, status); Assert.Equal(0, drive.PendingCount); AssertConverged(lifetime); } /// /// C2-1 review fix (delta round): the retained _pending entry /// holds a LIVE Core operation (already begun via /// TryBeginExclusiveAuthoredPlacement, sitting at /// AwaitingPreparation) — clearing this controller's own map on /// detach is not enough; the operation itself must be cancelled or it /// pins its landblock prefix forever (docs/ISSUES.md #310). Asserting /// SetPositionOperationCount == 0 in addition to the ledger going /// to zero is what actually proves the Core operation died, not just /// that this controller stopped watching it — sibling tests in this file /// (Committed_..., ParkCollisionResidents_...) already /// check this dimension; this one previously did not, and would have /// passed even with the old clear-only DetachRoute. /// [Fact] public void LedgerConverges_AfterDetachRouteClearsTrackedEntries() { using var lifetime = new RuntimeEntityObjectLifetime(FlatEngine()); RuntimeEntityRecord record = CreateRemoteRecord( lifetime, 0x7000300Au, setupTableId: 0x02000001u); AttachBody(lifetime, record, SourceCell); CommitLandblockCollision(lifetime, DestinationLandblock); var window = new FakeServiceWindow(); window.Allow(DestinationLandblock); RuntimeRemotePlacementDriveController drive = CreateDrive(lifetime, window); var route = new object(); drive.AttachRoute(route); RuntimeAuthoritativePositionRoute positionRoute = MakeRoute( record, RuntimeAuthoritativePositionDisposition.SetPosition, DestinationCell); Assert.Equal( RuntimeRemotePlacementExecutionStatus.Contention, drive.TryExecuteAcceptedRemotePosition(record, positionRoute)); Assert.Equal(1, drive.PendingCount); Assert.Equal( 1, lifetime.Physics.CaptureOwnership().SetPositionOperationCount); drive.DetachRoute(route); Assert.Equal(0, drive.PendingCount); Assert.Equal(0, lifetime.CaptureOwnership().RemotePlacementDrivePendingCount); Assert.Equal( 0, lifetime.Physics.CaptureOwnership().SetPositionOperationCount); } /// /// C2-1 review fix (delta round): the OTHER map — _awaitingAcknowledgement /// — holds an equally live Core operation (a published, unacknowledged /// Place sitting at AwaitingCommitAcknowledgement), and the /// prior DetachRoute left it live the same way. Mirrors the /// _pending case above for the SECOND map DetachRoute must cancel. /// [Fact] public void LedgerConverges_AfterDetachRouteCancelsAnUnacknowledgedCommit() { using var lifetime = new RuntimeEntityObjectLifetime(FlatEngine()); CommitLandblockCollision(lifetime, DestinationLandblock); RuntimeEntityRecord record = CreateRemoteRecord(lifetime, 0x70003012u); AttachBody(lifetime, record, SourceCell); var window = new FakeServiceWindow(); window.Allow(DestinationLandblock); RuntimeRemotePlacementDriveController drive = CreateDrive(lifetime, window); var route = new object(); drive.AttachRoute(route); RuntimeAuthoritativePositionRoute positionRoute = MakeRoute( record, RuntimeAuthoritativePositionDisposition.SetPosition, DestinationCell, new Vector3(12f, 14f, SpawnHeight)); Assert.Equal( RuntimeRemotePlacementExecutionStatus.Committed, drive.TryExecuteAcceptedRemotePosition(record, positionRoute)); // No host subscription is wired in this bare fixture, so the Place // receipt is still genuinely unacknowledged — the SAME shape the // production declined-sink FIFO retry class leaves behind. Assert.Equal( 1, lifetime.Physics.CaptureOwnership().SetPositionOperationCount); Assert.Equal( 1, lifetime.CaptureOwnership().RemotePlacementDrivePendingCount); drive.DetachRoute(route); Assert.Equal( 0, lifetime.CaptureOwnership().RemotePlacementDrivePendingCount); Assert.Equal( 0, lifetime.Physics.CaptureOwnership().SetPositionOperationCount); } /// /// C2-1 review fix (delta round), disposal safety: /// CountLiveAwaitingAcknowledgement calls /// RuntimeSetPositionState.IsPlacementCurrent, whose first /// statement is EnsureNotDisposed — it THROWS once disposed. A /// post-Dispose() CaptureOwnership() read is the designed /// contract (GameWindowLifetime.DisposeGameRuntime: /// runtime.Dispose(); runtime.CaptureOwnership();), so this /// dimension must survive it too. Deliberately leaves the entry /// UNDRAINED at dispose time — a genuine leak, exactly what this ledger /// exists to report — to prove the disposed branch reports it rather /// than hiding it behind a thrown exception. /// [Fact] public void CountLiveAwaitingAcknowledgement_SurvivesReadAfterDisposeWithoutThrowing() { var lifetime = new RuntimeEntityObjectLifetime(FlatEngine()); CommitLandblockCollision(lifetime, DestinationLandblock); RuntimeEntityRecord record = CreateRemoteRecord(lifetime, 0x70003013u); AttachBody(lifetime, record, SourceCell); var window = new FakeServiceWindow(); window.Allow(DestinationLandblock); RuntimeRemotePlacementDriveController drive = CreateDrive(lifetime, window); RuntimeAuthoritativePositionRoute positionRoute = MakeRoute( record, RuntimeAuthoritativePositionDisposition.SetPosition, DestinationCell, new Vector3(12f, 14f, SpawnHeight)); Assert.Equal( RuntimeRemotePlacementExecutionStatus.Committed, drive.TryExecuteAcceptedRemotePosition(record, positionRoute)); lifetime.Dispose(); int pendingAfterDispose = -1; Exception? thrown = Record.Exception(() => pendingAfterDispose = lifetime.CaptureOwnership().RemotePlacementDrivePendingCount); Assert.Null(thrown); Assert.Equal(1, pendingAfterDispose); } [Fact] public void AttachRoute_ThrowsForADifferentRouteWhileTheFirstIsStillLive() { using var lifetime = new RuntimeEntityObjectLifetime(FlatEngine()); var window = new FakeServiceWindow(); RuntimeRemotePlacementDriveController drive = CreateDrive(lifetime, window); var firstRoute = new object(); var secondRoute = new object(); drive.AttachRoute(firstRoute); Assert.Throws( () => drive.AttachRoute(secondRoute)); drive.DetachRoute(firstRoute); drive.AttachRoute(secondRoute); } /// /// Gate item: ParkCollisionResidents throws on overlap for every /// spatial root in a retiring prefix that holds an active operation /// (RuntimeSetPositionState.cs:3387-3395). This is the concrete /// proof it stays unreachable under this route's design — both after a /// refusal (no operation ever opened) and after a normal commit /// (operation retired to zero), the SAME prefix can be "retired" without /// throwing. /// [Fact] public void ParkCollisionResidents_StaysUnreachable_AfterRefusalAndAfterCommit() { using var lifetime = new RuntimeEntityObjectLifetime(FlatEngine()); CommitLandblockCollision(lifetime, DestinationLandblock); RuntimeEntityRecord refusedEntity = CreateRemoteRecord(lifetime, 0x7000300Bu); AttachBody(lifetime, refusedEntity, DestinationCell); RuntimeEntityRecord committedEntity = CreateRemoteRecord(lifetime, 0x7000300Cu); AttachBody(lifetime, committedEntity, SourceCell); var refusingWindow = new FakeServiceWindow(); RuntimeRemotePlacementDriveController refusingDrive = CreateDrive(lifetime, refusingWindow); RuntimeAuthoritativePositionRoute refusedRoute = MakeRoute( refusedEntity, RuntimeAuthoritativePositionDisposition.SetPosition, DestinationCell); Assert.Equal( RuntimeRemotePlacementExecutionStatus.Refused, refusingDrive.TryExecuteAcceptedRemotePosition(refusedEntity, refusedRoute)); var allowingWindow = new FakeServiceWindow(); allowingWindow.Allow(DestinationLandblock); RuntimeRemotePlacementDriveController committingDrive = CreateDrive(lifetime, allowingWindow); RuntimeAuthoritativePositionRoute committedRoute = MakeRoute( committedEntity, RuntimeAuthoritativePositionDisposition.SetPosition, DestinationCell, new Vector3(30f, 30f, SpawnHeight)); Assert.Equal( RuntimeRemotePlacementExecutionStatus.Committed, committingDrive.TryExecuteAcceptedRemotePosition( committedEntity, committedRoute)); // No host subscription is wired in this bare fixture — drain the // Place receipt exactly like production's placement-projection // subscription would, converging the operation to zero the same way // a live host's synchronous consumption does. DrainPlacementFifo(lifetime); // Both entities now sit resident in the destination prefix with NO // active operation. Retiring that prefix must not throw. Exception? thrown = Record.Exception(() => lifetime.Physics.SetPosition.ParkCollisionResidents( DestinationLandblock, includeOutdoorCells: true)); Assert.Null(thrown); } // ── Fixture ────────────────────────────────────────────────────────── /// /// Stands in for the production placement-projection subscription this /// bare fixture never wires — a committed placement's Place /// receipt would otherwise sit unacknowledged forever, exactly like /// RuntimeAcceptedPositionDriveControllerTests.DrainPlacementFifo. /// private static void DrainPlacementFifo(RuntimeEntityObjectLifetime lifetime) { while (lifetime.Physics.SetPosition.TryPeekProjection( out RuntimePlacementProjectionSnapshot head)) { if (!lifetime.Physics.SetPosition.AcknowledgeProjection(head.Token)) break; } } private static void AssertConverged(RuntimeEntityObjectLifetime lifetime) { Assert.Equal( 0, lifetime.CaptureOwnership().RemotePlacementDrivePendingCount); } private static RuntimeRemotePlacementDriveController CreateDrive( RuntimeEntityObjectLifetime lifetime, IRuntimeRemotePlacementServiceWindow window) => new( lifetime, new GameRuntimeClock(), new UnusedCollisionSource(), window); private static RuntimeAuthoritativePositionRoute MakeRoute( RuntimeEntityRecord record, RuntimeAuthoritativePositionDisposition disposition, uint destinationCellId, Vector3? destinationPosition = null, RuntimeSetPositionOperationKind operationKind = RuntimeSetPositionOperationKind.RemoteAuthoritative, PhysicsSetPositionFlags? setPositionFlags = null) { // Publishes the destination into the record's accepted Snapshot — // exactly what the upstream merge // (RuntimeEntityObjectLifetime.TryApplyPosition) already did before a // real caller would ever reach this controller — so the controller's // own service-window read (record.Snapshot.Position.LandblockId) // observes the SAME destination the route was classified against. Vector3 position = destinationPosition ?? new Vector3(10f, 10f, SpawnHeight); record.Snapshot = record.Snapshot with { Position = new CreateObject.ServerPosition( destinationCellId, position.X, position.Y, position.Z, 1f, 0f, 0f, 0f), }; var authority = new RuntimeAuthoritativePositionAuthority( new RuntimeGenerationToken(1), record.Key!.Value, record.PositionAuthorityVersion, AcceptedPositionSequence: 2, PreviousTeleportSequence: 0, AcceptedTeleportSequence: 0, PositionTimestampDisposition.Apply); bool performsSetPosition = disposition is RuntimeAuthoritativePositionDisposition.SetPosition or RuntimeAuthoritativePositionDisposition.SetPositionSimple; return new RuntimeAuthoritativePositionRoute( authority, disposition, operationKind, setPositionFlags ?? (performsSetPosition ? PhysicsSetPositionFlags.Teleport | PhysicsSetPositionFlags.Slide : PhysicsSetPositionFlags.None), PlacementFrame: 0u, UnparentBeforeRouting: true, ApplyPlacementFrameBeforeRouting: false, LeaveWorld: false, TeleportHookPhase: RuntimeTeleportHookPhase.None, StopInterpolating: false, ConstrainPhase: RuntimePositionConstrainPhase.AfterPositionOperation, PreserveHeading: false, ZeroVelocity: false, SendPositionImmediately: false, CollisionBatchEligible: true); } private static RuntimeEntityRecord CreateRemoteRecord( RuntimeEntityObjectLifetime lifetime, uint guid, uint? setupTableId = null) { RuntimeEntityRecord record = lifetime.RegisterEntity( Spawn(guid, setupTableId)).Canonical!; lifetime.Entities.SetFinalPhysicsState(record, PhysicsStateFlags.Gravity); return record; } private static PhysicsBody AttachBody( RuntimeEntityObjectLifetime lifetime, RuntimeEntityRecord record, uint cellId) { lifetime.Entities.SetFullCell( record, cellId, (cellId & 0xFFFF0000u) | 0xFFFFu); var body = new PhysicsBody { Position = new Vector3(10f, 10f, SpawnHeight), Orientation = Quaternion.Identity, LastUpdateTime = 1d, State = PhysicsStateFlags.Gravity, TransientState = TransientStateFlags.Active, }; body.SnapToCell(cellId, body.Position, body.Position); lifetime.Entities.SetPhysicsBody(record, body); record.ObjectClock.Activate(); lifetime.Physics.AcknowledgeSpatialProjection(record, spatial: true); return body; } private static WorldSession.EntitySpawn Spawn(uint guid, uint? setupTableId) => new( guid, new CreateObject.ServerPosition( SourceCell, 10f, 10f, SpawnHeight, 1f, 0f, 0f, 0f), setupTableId, AnimPartChanges: Array.Empty(), TextureChanges: Array.Empty(), SubPalettes: Array.Empty(), BasePaletteId: null, ObjScale: null, Name: "remote", ItemType: null, MotionState: null, MotionTableId: 0x09000001u); private static PhysicsEngine FlatEngine() { var engine = new PhysicsEngine { DataCache = new PhysicsDataCache(), }; engine.AddLandblock( SourceLandblock, new TerrainSurface(new byte[81], new float[256]), Array.Empty(), Array.Empty(), worldOffsetX: 0f, worldOffsetY: 0f); return engine; } /// /// Mirrors RuntimeAcceptedPositionDriveControllerTests.CommitLandblockCollision /// exactly, against a bare /// instead of a full GameRuntime. Also observes the SOURCE /// landblock's world frame once — Runtime's world-frame resolution is /// arithmetic thereafter, so a destination landblock never needs its own /// call (route 2's own fixture comment). /// private static void CommitLandblockCollision( RuntimeEntityObjectLifetime lifetime, uint landblockId) { var heights = new byte[81]; Array.Fill(heights, (byte)SpawnHeight); var heightTable = new float[256]; for (int index = 0; index < heightTable.Length; index++) heightTable[index] = index; lifetime.Physics.ObserveLocalWorldFrame( SourceCell, teleportAdvanced: false); lifetime.Physics.SetPosition.BeginCollisionGeneration(landblockId, 1UL); lifetime.Physics.Engine.AddLandblock( landblockId, new TerrainSurface(heights, heightTable), Array.Empty(), Array.Empty(), worldOffsetX: 192f, worldOffsetY: 0f); lifetime.Physics.SetPosition.CommitCollisionGeneration( landblockId, 1UL, ready: true); } private sealed class FakeServiceWindow : IRuntimeRemotePlacementServiceWindow { private readonly HashSet _within = []; internal void Allow(uint landblockId) => _within.Add(Canonical(landblockId)); internal void Forbid(uint landblockId) => _within.Remove(Canonical(landblockId)); public bool IsWithinServiceWindow(uint landblockId) => _within.Contains(Canonical(landblockId)); private static uint Canonical(uint landblockId) => (landblockId & 0xFFFF0000u) | 0xFFFFu; } private sealed class UnusedCollisionSource : IPreparedCollisionSource { public PreparedAssetPresence ProbeCollision( PakAssetType type, uint sourceFileId) => PreparedAssetPresence.Available; public PreparedCollisionReadResult ReadSetupCollision( uint sourceFileId, CancellationToken cancellationToken = default) => PreparedCollisionReadResult.Missing; public PreparedCollisionReadResult ReadGfxObjCollision( uint sourceFileId, CancellationToken cancellationToken = default) => throw new NotSupportedException(); public PreparedCollisionReadResult ReadCellStructureCollision( uint sourceFileId, CancellationToken cancellationToken = default) => throw new NotSupportedException(); public PreparedCollisionReadResult ReadEnvCellTopology( uint sourceFileId, CancellationToken cancellationToken = default) => throw new NotSupportedException(); public PreparedCollisionSourceStats CollisionStats => default; public void Dispose() { } } }