Builds the machinery route 4b-2 and 4b-3 will flip on, and changes no remote behaviour: it has no production caller, so RemotePlacementDrivePendingCount is provably 0 and IsConverged is unchanged. Five pieces: a per-entity remote placement owner (RuntimeRemotePlacementDriveController), a Position-time service-window guard with a Runtime interface plus BOTH host implementations, N3's headless RetryPending pump, parked-count observability in the ownership ledger, and the service-window optimisation that avoids parks we can cheaply predict. Landed alone because it is where the park-withdraws-the-entity failure was decided; that decision is fixed at the source in the preceding commit and must not share a review signal with a behaviour flip. Two parts of route 2's controller are deliberately NOT ported, both verified against retail rather than assumed. There is no ack: SendPositionEvent is called only inside HandleReceivedPosition's local-player FORCE_POSITION gate @0x0045400C-@0x00454091, and the remote arm @0x0045414D has no equivalent. There is no re-issue funnel: retail never re-attempts a position it could not apply — stale timestamps merely bump error_count @0x004542AC — and re-issuing packet N after N+1 has merged would apply a pose the newer packet already superseded, which is correct for a one-shot ForcePosition and wrong for a 5-10 Hz stream. The service-window guard is an OPTIMISATION, not the correctness mechanism. The original contract had it the other way round, justified by a claim that retail cannot represent "arrived but not placeable" — false, and corrected in the review findings: retail's GotoLostCell/reenter_visibility path represents it exactly. A pre-flight guard also cannot be complete, because Core defers on the entity's CURRENT cell, on the swept QueriedCellIds footprint spanning neighbouring landblocks, and on residency evaluated after AdjustToOutside — conditions only Core can see. Review found and this commit fixes: DetachRoute cleared two maps of LIVE Core operations without cancelling them (route 2's AbandonPending is the correct mirror, not the first-entry controller) and its test asserted that blindness as convergence; the headless predicate answered "can ever publish" rather than "is published", and after the first fix still matched only 1 of the 9 landblocks this host publishes; OwnsPlacement admitted remote top-level Creates until gated on the Teleport flag as well as the disposition; Advance re-submitted without re-checking the window; and four comments cited a report that did not exist. Contract item 6 is met by the structural proof, not the earlier test: HasOldPrefixPlacementDebt refuses collision-prefix mutation permission before ParkCollisionResidents is ever entered, so its overlap throw is unreachable. That same mechanism is the unbounded stall filed as #310, which 4b-1 does not bound — it only avoids widening it. #311 files the remaining per-tick allocation in RetryPendingProjections; the early-out for the empty-FIFO case landed via a new HasPendingReceipts accessor so hosts still never touch .Placements. directly. Gates: complete Release solution 10,973 passed / 4 skipped / 0 failed (baseline 10,938). Four review rounds; every fix discrimination-verified by revert. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
84 lines
3.4 KiB
C#
84 lines
3.4 KiB
C#
using AcDream.App.Streaming;
|
|
using AcDream.Core.World;
|
|
using DatReaderWriter.DBObjs;
|
|
|
|
namespace AcDream.App.Tests.Streaming;
|
|
|
|
/// <summary>
|
|
/// C4 route 4b-1: focused tests for the graphical host's
|
|
/// <see cref="GraphicalRemotePlacementServiceWindow"/> — the App-side
|
|
/// implementation of <c>IRuntimeRemotePlacementServiceWindow</c> that did not
|
|
/// exist before this route. Verifies the predicate matches
|
|
/// <see cref="GpuWorldState.IsNearTier"/> exactly (not
|
|
/// <see cref="GpuWorldState.IsNearTierOrPending"/>, which is also true for a
|
|
/// merely-queued landblock — see the class's own doc comment) and
|
|
/// canonicalizes a full ACE cell id to the landblock the tier map keys on.
|
|
/// </summary>
|
|
public sealed class GraphicalRemotePlacementServiceWindowTests
|
|
{
|
|
// GpuWorldState's tier map is keyed by the CANONICAL 0xFFFF-ending form
|
|
// (LoadedLandblock.LandblockId/AddLandblock require callers to already
|
|
// pass it that way — see StreamingControllerReadinessTests' own
|
|
// 0x1236FFFFu convention). The window itself is exercised with a full
|
|
// ACE outdoor-cell id (landblock high word + a real cell low word),
|
|
// matching CreateObject.ServerPosition.LandblockId's actual shape, to
|
|
// prove IsWithinServiceWindow canonicalizes it the same way
|
|
// GpuWorldState's own writers do.
|
|
private const uint LandblockHighWord = 0x0A0B0000u;
|
|
private const uint CanonicalLandblock = LandblockHighWord | 0xFFFFu;
|
|
private const uint OutdoorCell = LandblockHighWord | 0x0001u;
|
|
|
|
[Fact]
|
|
public void True_WhenTheLandblockIsNearTier()
|
|
{
|
|
var state = new GpuWorldState();
|
|
state.AddLandblock(new LoadedLandblock(
|
|
CanonicalLandblock,
|
|
new LandBlock(),
|
|
Array.Empty<AcDream.Core.World.WorldEntity>()));
|
|
var window = new GraphicalRemotePlacementServiceWindow(state);
|
|
|
|
Assert.True(window.IsWithinServiceWindow(OutdoorCell));
|
|
}
|
|
|
|
[Fact]
|
|
public void False_WhenTheLandblockWasNeverPublished()
|
|
{
|
|
var state = new GpuWorldState();
|
|
var window = new GraphicalRemotePlacementServiceWindow(state);
|
|
|
|
Assert.False(window.IsWithinServiceWindow(OutdoorCell));
|
|
}
|
|
|
|
[Fact]
|
|
public void False_WhenTheLandblockIsOnlyPendingNotYetCollisionPublished()
|
|
{
|
|
var state = new GpuWorldState();
|
|
// A live projection arriving before its landblock loads parks as
|
|
// "pending near tier" — GpuWorldState.IsNearTierOrPending reads true
|
|
// for this, but collision has NOT been published yet.
|
|
Assert.False(
|
|
state.AddEntitiesToExistingLandblock(
|
|
LandblockHighWord, Array.Empty<AcDream.Core.World.WorldEntity>()));
|
|
Assert.True(state.IsNearTierOrPending(CanonicalLandblock));
|
|
var window = new GraphicalRemotePlacementServiceWindow(state);
|
|
|
|
Assert.False(window.IsWithinServiceWindow(OutdoorCell));
|
|
}
|
|
|
|
[Fact]
|
|
public void False_AfterTheLandblockRetiresViaDetachNearLayer()
|
|
{
|
|
var state = new GpuWorldState();
|
|
state.AddLandblock(new LoadedLandblock(
|
|
CanonicalLandblock,
|
|
new LandBlock(),
|
|
Array.Empty<AcDream.Core.World.WorldEntity>()));
|
|
var window = new GraphicalRemotePlacementServiceWindow(state);
|
|
Assert.True(window.IsWithinServiceWindow(OutdoorCell));
|
|
|
|
_ = state.DetachNearLayer(LandblockHighWord);
|
|
|
|
Assert.False(window.IsWithinServiceWindow(OutdoorCell));
|
|
}
|
|
}
|