acdream/tests/AcDream.App.Tests/World/UpdateFrameOrchestratorTests.cs
Erik 6dc7ba51ee feat(physics): C4 route 4b-3 — remote teleport + cell-less through the canonical placement
Flips the last remote classification (SetPosition: teleport-advanced and
cell-less) onto 4b-1's RuntimeRemotePlacementDriveController, runs retail's
teleport_hook before the placement, and deletes the legacy remote-teleport
machinery. Contract: docs/research/2026-08-04-c4-route-4b-3-contract.md.

Retail: MoveOrTeleport @0x00516330's branch @0x00516386 -> teleport_hook
@0x005163EF -> SetFlags(0x1012) @0x00516414 -> SetPosition @0x00516420 ->
return 1 @0x00516438. The hook @0x00514ED0 runs BEFORE the placement and
regardless of its outcome. Retail places this branch unconditionally, at any
distance and any contact state (arg4 is read only @0x0051638E, after the
branch) — which is what retires AP-137's cell-less enqueue-vs-place delta.

D1 — the classifier's cell-less input is now the PRE-merge committed cell.
Retail's predicate is `this_1->cell == 0`, the BODY's own cell at
MoveOrTeleport entry (this_1 is assigned from this @0x00516334). acdream fed
the POST-merge canonical.FullCellId, which RefreshSnapshot ->
RefreshDerivedState -> SetFullCell has already stamped with the accepted wire
cell; a zero wire cell fails validation into RejectedData first. The shipped
remote cell-less predicate was therefore dead code, not merely different from
remotePlacementRequired. Threaded via a builder overload; route 1's overload
is untouched. The graphical !IsSpatiallyVisible arm of
projectionRequiresTeleportHook is deleted — a presentation predicate with no
retail analogue that fired the teleport machinery on a routine hot path.

Deleted: RemoteTeleportController (605), RemoteTeleportPlacement (85),
RemoteShadowPlacementSynchronizer (49), their 1,709 lines of tests, the
remotePlacementRequired predicate, the TeleportHookRequired plumbing, the
legacy pre-operation ConstrainTo fallback, and the player arm's legacy
!IsGrounded fallback. Net -2,030 lines.

Structural fix (two independent Opus reviews, round 1 FAIL/FAIL): three of the
four MAJORs were one defect — OnPosition carried two parallel inline copies of
the routing tail (player-guid, NPC-guid) that had drifted. Extracted
RunRemoteArmTail (3 call sites) and ApplyWireAirborneLeftoverBookkeeping (2),
both branches now share one implementation.

  A1  ToConstraintArm mapped AirborneSnap -> AirborneNoOperation, so the NPC
      arm armed ConstrainTo ZERO times for an out-of-contact wire-grounded
      creature — a regression this slice introduced while closing a
      structurally identical hole. Now maps to NearInterpolate; switch made
      total with a throwing default proven unreachable.
  R1  D2's write-nothing shape existed on the player arm only; NPC packets
      fell through and wrote the body. Retail makes no player/NPC distinction.
  R2  report_collision_end(this,1) @0x00514F31 was bound to
      ShadowObjects.Suspend, a port of a DIFFERENT retail function
      (remove_shadows_from_cells) that teleport_hook never calls. Now routes
      to RuntimeCollisionReportingState.LeaveWorld, which wraps the private
      ForceEnd in an admission-blocking transaction so a DoCollisionEnd
      callback cannot recreate the contact table.
  R3/A2 A teleported NPC synthesized ServerVelocity from the teleport distance
      (~1,000+ m/s) and planned a run cycle from it. Both the install and
      RemoteServerControlledVelocityCycle.Apply now gate on !isTeleportRoute.

BISECT HAZARD — A1's fix is correct only BECAUSE R1 landed. AirborneSnap is
reachable wire-airborne on the NPC arm only while D2's shape is missing there.
Reverting R1 alone silently inverts A1 into the opposite divergence: arming
where retail returns 0. Revert both or neither.

Also in the velocity hunk: the NPC block's two !IsPlayerGuid(update.Guid)
guards were dropped when it was wrapped in `if (!isTeleportRoute)`. Safe — all
five exit paths of the enclosing IsPlayerGuid block return, so the predicate is
unconditionally false below it — but it was unremarked by both reviews.

Register: AP-137 REWRITTEN (not deleted) to the surviving acdream-only
divergences — null classification during the login window and Rejected*
through UnroutedCatchUp keep a row. AD-42's RemoteTeleportController citation
retired; AP-136/AP-138 writer lists corrected to the two surviving non-Position
rebucket writers; AP-138 gains the teleport arm as a second producer of the
visible-without-collision residual (retirement path remains #309). AP-135 is
untouched and its two airborne bookkeeping writes are preserved on both arms.
AP-131 does not retire; #276 does not close.

Proof obligation 1: ParkCollisionResidents' overlap throw stays unreachable —
the teleport arm adds packets to the same TryBeginExclusiveAuthoredPlacement
one-operation-per-key machinery the far arm uses, opens no new operation shape,
and every DeferredCell outcome cancels synchronously with
restoreCancelledPark: true. The guarded property remains
HasOldPrefixPlacementDebt's stall, not a throw (4b-1's B2 caveat stands).

Correction to an earlier claim: LiveEntityPresentationController's
_activePlacementOwners was NOT write-never at HEAD —
remotePlacementRequired -> BeginPlacement -> Begin -> BeginAuthoritativePlacement
was a live writer chain. It becomes write-never BECAUSE this slice deletes that
chain, which is why deleting the dead half is behaviour-preserving.

Probe: ACDREAM_PROBE_REMOTE_TELEPORT=1 emits one [remote-teleport] line per
routed arm (guid, cause, hook-ran, placement status). TEMPORARY, strip with the
probe family.

Carried, disclosed not fixed: no dedicated bidirectional collision-partner test
for R2 (the wiring, not LeaveWorld itself, is what lacks coverage); the
stress test's teleport step drives hand-written field assignments rather than
the canonical arm; the per-packet runTeleportHook closure allocation (network
path, not the resolve path Slice I's 0 B discipline governs — file before
route 5 adds a fourth call site). B2: IRuntimeCollisionReportObserver has zero
production implementations, so retail's bidirectional DoCollisionEnd half still
reaches no gameplay consumer — this fix closes the wrong-function binding, not
that nobody listens.

Complete Release suite MEASURED at 11,013 passed / 4 skipped / 0 failed
(baseline 11,027/4/0; net -14 = ~33 deleted test cases against ~19 added).
Neither known flake fired (#302 PortalProjectionTests GC-allocation, #308
NakEmissionTests wall-clock).

STILL OWED: the two-client connected gate, which MUST use an NPC/creature
teleport target. Both round-1 MAJORs lived on the NPC arm and the velocity
cycle early-returns for 0x50xxxxxx guids, so a player target structurally
cannot observe A1, A2, or R3.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-04 16:00:10 +02:00

1181 lines
44 KiB
C#

using System.Reflection;
using AcDream.App.Rendering;
using AcDream.App.Net;
using AcDream.App.Streaming;
using AcDream.App.Update;
using AcDream.App.World;
using AcDream.Runtime;
using AcDream.Runtime.Session;
using AcDream.Runtime.World;
namespace AcDream.App.Tests.World;
public sealed class UpdateFrameOrchestratorTests
{
[Fact]
public void Tick_PreservesTheCompleteAcceptedPhaseGraph()
{
var calls = new List<string>();
UpdateFrameOrchestrator frame = Create(calls);
frame.Tick(new UpdateFrameInput(1.0 / 60.0));
Assert.Equal(
[
"teardown",
"clock",
"streaming",
"input",
"objects",
"network",
"commands",
"ordinary-reconcile",
"liveness",
"teleport",
"auto-entry",
"camera",
"commit",
],
calls);
}
[Fact]
public void ConditionalReconciles_RemainAtTheirOwningEdges()
{
// The outer ownership oracle is complemented by the production
// teleport and camera tests that pin both conditional reconcile edges.
var calls = new List<string>();
UpdateFrameOrchestrator frame = Create(
calls,
teleportPlace: true,
inboundCreatedPlayer: true);
frame.Tick(new UpdateFrameInput(1.0 / 60.0));
Assert.Equal(
[
"teardown",
"clock",
"streaming",
"input",
"objects",
"network",
"commands",
"ordinary-reconcile",
"liveness",
"teleport-place",
"teleport-reconcile",
"teleport-reveal",
"auto-entry",
"inbound-player-projection",
"inbound-player-reconcile",
"camera",
"commit",
],
calls);
}
[Theory]
[InlineData(double.NaN)]
[InlineData(double.NegativeInfinity)]
[InlineData(double.PositiveInfinity)]
[InlineData(-1.0)]
[InlineData(0.0)]
[InlineData(double.MaxValue)]
public void InvalidSimulationDelta_BecomesZeroWithoutSuppressingOuterPhases(
double hostDelta)
{
var calls = new List<string>();
var observed = new FrameObservations();
UpdateFrameOrchestrator frame = Create(calls, observed: observed);
frame.Tick(new UpdateFrameInput(hostDelta));
Assert.Equal(
[
"teardown", "clock", "streaming", "input", "objects",
"network", "commands", "ordinary-reconcile", "liveness",
"teleport", "auto-entry", "camera", "commit",
],
calls);
Assert.Equal([0.0], observed.PublishedTimes);
Assert.Equal([0.0], observed.Input.Select(value => value.SimulationDeltaSeconds));
Assert.Equal([0f], observed.LiveDeltas);
Assert.Equal([0f], observed.TeleportDeltas);
Assert.Equal([0.0], observed.Camera.Select(value => value.SimulationDeltaSeconds));
Assert.All(
observed.Input.Concat(observed.Camera),
timing => Assert.Equal(0.0, timing.ScriptTime));
}
[Fact]
public void Clock_AdvancesOnceAndPublishesTheSameTimeToEveryConsumer()
{
var calls = new List<string>();
var observed = new FrameObservations();
UpdateFrameOrchestrator frame = Create(calls, observed: observed);
frame.Tick(new UpdateFrameInput(0.25));
frame.Tick(new UpdateFrameInput(double.NaN));
frame.Tick(new UpdateFrameInput(0.5));
Assert.Equal([0.25, 0.25, 0.75], observed.PublishedTimes);
Assert.Equal(
[0.25, 0.25, 0.75],
observed.Input.Select(value => value.ScriptTime));
Assert.Equal(
[0.25, 0.25, 0.75],
observed.Camera.Select(value => value.ScriptTime));
Assert.Equal([0.25f, 0f, 0.5f], observed.LiveDeltas);
Assert.Equal([0.25f, 0f, 0.5f], observed.TeleportDeltas);
Assert.Equal(
[0.25, 0.0, 0.5],
observed.Input.Select(value => value.SimulationDeltaSeconds));
Assert.Equal(
[0.25, 0.0, 0.5],
observed.Camera.Select(value => value.SimulationDeltaSeconds));
}
[Fact]
public void QuiescedWorld_FreezesScriptClockAndLivenessWhilePortalPhasesContinue()
{
var calls = new List<string>();
var observed = new FrameObservations();
var transit = new RuntimeWorldTransitState();
var availability = new WorldGenerationAvailabilityState(transit);
long generation =
RuntimeWorldTransitTestDriver.BeginPortal(
transit,
0x11340021u);
UpdateFrameOrchestrator frame = Create(
calls,
observed: observed,
availability: availability);
frame.Tick(new UpdateFrameInput(0.25));
frame.Tick(new UpdateFrameInput(0.25));
Assert.True(transit.AcknowledgeDestinationReadiness(
new RuntimeDestinationReadiness(
generation,
0x11340021u,
IsIndoor: false,
IsUnhydratable: false,
RequiredRenderRadius: 1,
IsRenderNeighborhoodReady: true,
AreCompositeTexturesReady: true,
IsCollisionReady: true)));
Assert.True(RuntimeWorldTransitTestDriver.MaterializePortal(
transit,
generation,
0x11340021u));
transit.Complete(generation);
frame.Tick(new UpdateFrameInput(0.25));
Assert.Equal([0.0, 0.0, 0.25], observed.PublishedTimes);
Assert.Equal(1, calls.Count(call => call == "liveness"));
Assert.Equal(3, calls.Count(call => call == "streaming"));
Assert.Equal(3, calls.Count(call => call == "network"));
Assert.Equal(3, calls.Count(call => call == "teleport"));
Assert.Equal(3, calls.Count(call => call == "camera"));
Assert.Equal(3, calls.Count(call => call == "commit"));
Assert.Equal([0.25f, 0.25f, 0.25f], observed.LiveDeltas);
Assert.Equal([0.25f, 0.25f, 0.25f], observed.TeleportDeltas);
}
[Fact]
public void Clock_RejectsFiniteDeltaAboveTheSinglePrecisionConsumerRange()
{
double tooLarge = (double)float.MaxValue * 2.0;
Assert.True(double.IsFinite(tooLarge));
Assert.Equal(0.0, UpdateFrameClock.NormalizeDeltaSeconds(tooLarge));
}
[Fact]
public void AggregateTeardownFailure_IsReportedAndRetriedNextFrame()
{
var calls = new List<string>();
var teardown = new RecordingTeardown(calls)
{
Failure = new AggregateException(new InvalidOperationException("transient")),
};
var failures = new RecordingFailureSink();
UpdateFrameOrchestrator frame = Create(
calls,
teardown: teardown,
failureSink: failures);
frame.Tick(new UpdateFrameInput(0.1));
teardown.Failure = null;
frame.Tick(new UpdateFrameInput(0.1));
Assert.Equal(2, teardown.Attempts);
Assert.Single(failures.Errors);
string[] oneFrame =
[
"teardown", "clock", "streaming", "input", "objects", "network",
"commands", "ordinary-reconcile", "liveness", "teleport",
"auto-entry", "camera", "commit",
];
Assert.Equal(oneFrame.Concat(oneFrame), calls);
}
[Fact]
public void NonAggregateTeardownFailure_PropagatesBeforeTimeOrLaterPhases()
{
var calls = new List<string>();
var teardown = new RecordingTeardown(calls)
{
Failure = new InvalidOperationException("fatal"),
};
UpdateFrameOrchestrator frame = Create(calls, teardown: teardown);
InvalidOperationException error = Assert.Throws<InvalidOperationException>(
() => frame.Tick(new UpdateFrameInput(0.1)));
Assert.Equal("fatal", error.Message);
Assert.Equal(["teardown"], calls);
}
[Fact]
public void OrchestrationTypes_UseOnlyTheExplicitTypedOwnerGraph()
{
Type[] expectedFieldTypes =
[
typeof(IUpdateFrameTeardownPhase),
typeof(IUpdateFrameFailureSink),
typeof(UpdateFrameClock),
typeof(IUpdateFrameScriptClockPublisher),
typeof(IStreamingFramePhase),
typeof(IGameplayInputFramePhase),
typeof(IRetailLiveFramePhase),
typeof(ILiveEntityLivenessFramePhase),
typeof(ILocalPlayerTeleportFramePhase),
typeof(IPlayerModeAutoEntryFramePhase),
typeof(ICameraFramePhase),
typeof(IUpdateFrameCommitPhase),
typeof(IWorldGenerationAvailability),
];
FieldInfo[] fields = typeof(UpdateFrameOrchestrator).GetFields(
BindingFlags.Instance | BindingFlags.NonPublic);
Assert.Equal(
expectedFieldTypes.OrderBy(type => type.FullName),
fields.Select(field => field.FieldType).OrderBy(type => type.FullName));
Assert.All(fields, field =>
{
Assert.NotEqual(typeof(GameWindow), field.FieldType);
Assert.False(typeof(Delegate).IsAssignableFrom(field.FieldType));
});
Type[] phaseInterfaces = expectedFieldTypes.Where(type => type.IsInterface).ToArray();
Assert.DoesNotContain(
phaseInterfaces,
phaseInterface => phaseInterface.IsAssignableFrom(typeof(GameWindow)));
Type[] productionPhaseOwners = typeof(GameWindow).Assembly.GetTypes()
.Where(type => !type.IsAbstract && !type.IsInterface)
.Where(type => phaseInterfaces.Any(contract => contract.IsAssignableFrom(type)))
.ToArray();
foreach (Type owner in productionPhaseOwners)
{
FieldInfo[] ownerFields = owner.GetFields(
BindingFlags.Instance | BindingFlags.NonPublic);
Assert.DoesNotContain(ownerFields, field => field.FieldType == typeof(GameWindow));
Assert.DoesNotContain(
ownerFields,
field => typeof(Delegate).IsAssignableFrom(field.FieldType));
}
Assert.DoesNotContain(
typeof(GameWindow).GetFields(BindingFlags.Instance | BindingFlags.NonPublic),
field => field.Name == "_physicsScriptGameTime");
}
[Fact]
public void PhysicsScriptClockConsumers_RetainTheTypedSourceNotGameWindowClosures()
{
Type[] consumers =
[
typeof(DatLiveEntityProjectionMaterializer),
typeof(AcDream.App.Physics.LiveEntityNetworkUpdateController),
];
foreach (Type consumer in consumers)
{
FieldInfo clock = Assert.Single(
consumer.GetFields(BindingFlags.Instance | BindingFlags.NonPublic),
field => field.Name == "_gameTime");
Assert.Equal(typeof(IPhysicsScriptTimeSource), clock.FieldType);
Assert.DoesNotContain(
consumer.GetFields(BindingFlags.Instance | BindingFlags.NonPublic),
field => field.FieldType == typeof(GameWindow));
}
Assert.False(typeof(IPhysicsScriptTimeSource).IsAssignableFrom(typeof(GameWindow)));
}
[Fact]
public void ProductionFrame_PublishesPhysicsScriptTimeExactlyOnce()
{
string root = FindRepoRoot();
string source = File.ReadAllText(Path.Combine(
root,
"src",
"AcDream.App",
"Rendering",
"GameWindow.cs"));
string adapters = File.ReadAllText(Path.Combine(
root,
"src",
"AcDream.App",
"Update",
"UpdateFrameRuntimeAdapters.cs"));
string frameRoot = File.ReadAllText(Path.Combine(
root,
"src",
"AcDream.App",
"Composition",
"FrameRootComposition.cs"));
Assert.Equal(0, CountOccurrences(source, "PublishTime("));
Assert.Equal(1, CountOccurrences(adapters, "_runner.PublishTime("));
Assert.Contains("new PhysicsScriptClockPublisher(", frameRoot,
StringComparison.Ordinal);
}
[Fact]
public void ExtractedLiveObjectSource_PinsRetailAndRegisteredAdaptationOrder()
{
string source = File.ReadAllText(Path.Combine(
FindRepoRoot(),
"src",
"AcDream.App",
"Update",
"LiveObjectFrameController.cs"));
AssertAppearsInOrder(
source,
"_localPlayerFrame.AdvanceBeforeNetwork",
"_selectionInteractions?.DrainOutbound",
"_animations.Tick",
"_staticAnimations.Tick",
"_animationPresenter.Present",
"_equippedChildren.Tick",
"_staticAnimations.ProcessHooks",
"_effects.Tick");
AssertAppearsInOrder(
source,
"_translucencyFades.AdvanceAll",
"_animationHooks.Drain",
"_entityEffects.RefreshLiveOwnerPoses",
"_particleSink.RefreshAttachedEmitters",
"_lights.Refresh",
"_particleVisibility.Apply",
"_particles.Tick",
"_scripts.Tick");
AssertAppearsInOrder(
source,
"public void Reconcile()",
"_entityEffects.RefreshLiveOwnerPoses",
"_equippedChildren.ReconcileSpatialMutations",
"_particleSink.RefreshAttachedEmitters",
"_lights.Refresh");
Assert.Equal(1, CountOccurrences(source, "_staticAnimations.Tick("));
Assert.Equal(1, CountOccurrences(source, "_staticAnimations.ProcessHooks("));
Assert.Equal(1, CountOccurrences(source, "_effects.Tick("));
Assert.Equal(1, CountOccurrences(source, "_particles.Tick("));
Assert.Equal(1, CountOccurrences(source, "_scripts.Tick("));
}
[Fact]
public void PlacementRetryRunsAfterStreamingAndInboundBeforeCommandReconcile()
{
string root = FindRepoRoot();
string outer = File.ReadAllText(Path.Combine(
root,
"src",
"AcDream.App",
"Update",
"UpdateFrameOrchestrator.cs"));
string live = File.ReadAllText(Path.Combine(
root,
"src",
"AcDream.App",
"World",
"RetailLiveFrameCoordinator.cs"));
AssertAppearsInOrder(
outer,
"_streaming.Tick();",
"_liveFrame.Tick(");
AssertAppearsInOrder(
live,
"_session.Tick();",
"_placementProjectionRetry?.RetryPending();",
"_localPlayer.RunPostNetworkCommandPhase();",
"_spatialReconciler.Reconcile();");
}
[Theory]
[InlineData(true)]
[InlineData(false)]
public void LiveFrameRetriesPlacementAfterInboundEvenWhenWorldIsQuiesced(
bool worldAvailable)
{
var calls = new List<string>();
var phases = new RecordingLivePhases(calls)
{
IsWorldAvailable = worldAvailable,
};
var frame = new RetailLiveFrameCoordinator(
phases,
new GpuWorldState(),
phases,
phases,
phases,
phases,
phases,
phases);
frame.Tick(1f / 60f);
Assert.Equal(
worldAvailable
? ["objects", "network", "placement-retry", "commands", "reconcile"]
: ["network", "placement-retry", "commands", "render-sync"],
calls);
}
[Fact]
public void GameWindow_ComposesTheLiveFrameOwnersWithoutOwningTheirBodies()
{
string source = File.ReadAllText(Path.Combine(
FindRepoRoot(),
"src",
"AcDream.App",
"Rendering",
"GameWindow.cs"));
string livePresentation = File.ReadAllText(Path.Combine(
FindRepoRoot(),
"src",
"AcDream.App",
"Composition",
"LivePresentationComposition.cs"));
string sessionPlayer = File.ReadAllText(Path.Combine(
FindRepoRoot(),
"src",
"AcDream.App",
"Composition",
"SessionPlayerComposition.cs"));
string frameRoot = File.ReadAllText(Path.Combine(
FindRepoRoot(),
"src",
"AcDream.App",
"Composition",
"FrameRootComposition.cs"));
Assert.Contains("new LiveObjectFrameController(", sessionPlayer);
Assert.Contains("new LiveSpatialPresentationReconciler(", sessionPlayer);
Assert.Contains("new RetailLiveFrameCoordinator(", frameRoot);
Assert.DoesNotContain("AdvanceLiveObjectRuntime", source, StringComparison.Ordinal);
Assert.DoesNotContain("ReconcileLiveObjectSpatialPresentation", source,
StringComparison.Ordinal);
Assert.DoesNotContain("ILiveAnimationPresentationContext", source,
StringComparison.Ordinal);
}
[Fact]
public void GameWindow_DelegatesTheCompleteStreamingFrameBody()
{
string source = File.ReadAllText(Path.Combine(
FindRepoRoot(),
"src",
"AcDream.App",
"Rendering",
"GameWindow.cs"));
string sessionPlayer = File.ReadAllText(Path.Combine(
FindRepoRoot(),
"src",
"AcDream.App",
"Composition",
"SessionPlayerComposition.cs"));
Assert.Contains("new StreamingFrameController(", sessionPlayer);
Assert.DoesNotContain("_streamingFrame", source, StringComparison.Ordinal);
Assert.Equal(1, CountOccurrences(
source,
"_frameGraphs.Tick("));
Assert.DoesNotContain("_streamingController.Tick(observerCx", source,
StringComparison.Ordinal);
Assert.DoesNotContain("DungeonStreamingGate.Compute", source,
StringComparison.Ordinal);
Assert.DoesNotContain("DrainRescued()", source, StringComparison.Ordinal);
}
[Fact]
public void GameWindow_DelegatesTheCompleteGameplayInputFrameBody()
{
string source = File.ReadAllText(Path.Combine(
FindRepoRoot(),
"src",
"AcDream.App",
"Rendering",
"GameWindow.cs"));
string sessionPlayer = File.ReadAllText(Path.Combine(
FindRepoRoot(),
"src",
"AcDream.App",
"Composition",
"SessionPlayerComposition.cs"));
Assert.Contains("new GameplayInputFrameController(", sessionPlayer);
Assert.DoesNotContain("_gameplayInputFrame!.Tick", source,
StringComparison.Ordinal);
Assert.DoesNotContain("_inputDispatcher?.Tick()", source,
StringComparison.Ordinal);
Assert.DoesNotContain("TryTakeRawSample", source,
StringComparison.Ordinal);
Assert.DoesNotContain("_combatAttackController?.Tick()", source,
StringComparison.Ordinal);
Assert.DoesNotContain("CaptureMovementInput", source,
StringComparison.Ordinal);
Assert.DoesNotContain("EndMouseLookAndRestoreCursor", source,
StringComparison.Ordinal);
Assert.DoesNotContain("HideCursorForMouseLook", source,
StringComparison.Ordinal);
Assert.DoesNotContain("RestoreCursorAfterMouseLook", source,
StringComparison.Ordinal);
Assert.DoesNotContain("CanStartLiveCombatAttack", source,
StringComparison.Ordinal);
Assert.DoesNotContain("SendLiveCombatAttack", source,
StringComparison.Ordinal);
Assert.DoesNotContain("PreparePlayerForAttackRequest", source,
StringComparison.Ordinal);
Assert.DoesNotContain("DumpMovementTruthOutbound", source,
StringComparison.Ordinal);
Assert.DoesNotContain("DumpMovementTruthServerEcho", source,
StringComparison.Ordinal);
Assert.DoesNotContain("wantCaptureMouse: ()", source,
StringComparison.Ordinal);
Assert.DoesNotContain(
"_gameplayInputFrame?.EndMouseLook",
source,
StringComparison.Ordinal);
string pointerSource = File.ReadAllText(Path.Combine(
FindRepoRoot(),
"src",
"AcDream.App",
"Input",
"CameraPointerInputController.cs"));
Assert.Contains("_gameplayFrame?.EndMouseLook();", pointerSource,
StringComparison.Ordinal);
string teleportSource = File.ReadAllText(Path.Combine(
FindRepoRoot(),
"src",
"AcDream.App",
"Streaming",
"LocalPlayerTeleportController.cs"));
AssertAppearsInOrder(
teleportSource,
"_transit.CanQueueTeleportStart(teleportSequence)",
"_input.EndMouseLook();",
"_transit.TryQueueTeleportStart(teleportSequence)");
string playerModeSource = File.ReadAllText(Path.Combine(
FindRepoRoot(),
"src",
"AcDream.App",
"Input",
"PlayerModeController.cs"));
Assert.Contains("_input.EndMouseLook();", playerModeSource,
StringComparison.Ordinal);
AssertAppearsInOrder(
source,
"private void OnFocusChanged(bool focused)",
"_cameraPointerInput?.HandleFocusChanged(focused);");
}
[Fact]
public void GameWindow_DelegatesTheCompleteLocalTeleportLifetime()
{
string root = FindRepoRoot();
string source = File.ReadAllText(Path.Combine(
root,
"src",
"AcDream.App",
"Rendering",
"GameWindow.cs"));
string networkSource = File.ReadAllText(Path.Combine(
root,
"src",
"AcDream.App",
"Physics",
"LiveEntityNetworkUpdateController.cs"));
string sessionPlayer = File.ReadAllText(Path.Combine(
root,
"src",
"AcDream.App",
"Composition",
"SessionPlayerComposition.cs"));
string frameRoot = File.ReadAllText(Path.Combine(
root,
"src",
"AcDream.App",
"Composition",
"FrameRootComposition.cs"));
Assert.Contains(
"new LocalPlayerTeleportController(",
sessionPlayer,
StringComparison.Ordinal);
Assert.DoesNotContain("_localPlayerTeleport!.Tick", source,
StringComparison.Ordinal);
Assert.DoesNotContain("_teleportTransit", source, StringComparison.Ordinal);
Assert.DoesNotContain("_teleportAnim", source, StringComparison.Ordinal);
Assert.DoesNotContain("_teleportViewPlane", source, StringComparison.Ordinal);
Assert.DoesNotContain("_pendingTeleport", source, StringComparison.Ordinal);
Assert.DoesNotContain("AimTeleportDestination", source, StringComparison.Ordinal);
Assert.DoesNotContain("ResetTeleportTransitState", source, StringComparison.Ordinal);
Assert.DoesNotContain("PlaceTeleportArrival", source, StringComparison.Ordinal);
Assert.DoesNotContain("TryActivatePendingTeleportPresentation", source,
StringComparison.Ordinal);
Assert.DoesNotContain("Action<WorldSession.EntityPositionUpdate>", networkSource,
StringComparison.Ordinal);
Assert.Contains("ILocalPlayerTeleportNetworkSink", networkSource,
StringComparison.Ordinal);
AssertAppearsInOrder(
frameRoot,
"new LiveEntityLivenessFramePhase(",
"session.LocalTeleport,",
"new PlayerModeAutoEntryFramePhase(",
"cameraFrame,",
"live.WorldAvailability);");
}
[Fact]
public void GameplayInputOwnersUseTypedSeamsWithoutGameWindowBackReferences()
{
Type[] owners =
[
typeof(AcDream.App.Input.GameplayInputFrameController),
typeof(AcDream.App.Input.DispatcherMovementInputSource),
typeof(AcDream.App.Input.MouseLookController),
];
foreach (Type owner in owners)
{
FieldInfo[] fields = owner.GetFields(
BindingFlags.Instance | BindingFlags.NonPublic);
Assert.DoesNotContain(fields, field => field.FieldType == typeof(GameWindow));
Assert.DoesNotContain(
fields,
field => typeof(Delegate).IsAssignableFrom(field.FieldType));
}
Assert.DoesNotContain(
typeof(AcDream.App.Input.MouseLookController).GetFields(
BindingFlags.Instance | BindingFlags.NonPublic),
field => field.FieldType == typeof(Silk.NET.Input.IMouse));
FieldInfo combatOperations = Assert.Single(
typeof(AcDream.Runtime.Gameplay.RuntimeCombatAttackState).GetFields(
BindingFlags.Instance | BindingFlags.NonPublic),
field => field.Name == "_operations");
Assert.Equal(
typeof(AcDream.Runtime.Gameplay.IRuntimeCombatAttackOperations),
combatOperations.FieldType);
Assert.DoesNotContain(
typeof(AcDream.App.Combat.LiveCombatAttackOperations).GetFields(
BindingFlags.Instance | BindingFlags.NonPublic),
field => typeof(Delegate).IsAssignableFrom(field.FieldType));
FieldInfo combatTargets = Assert.Single(
typeof(AcDream.App.Combat.LiveCombatAttackOperations).GetFields(
BindingFlags.Instance | BindingFlags.NonPublic),
field => field.Name == "_targets");
Assert.Equal(
typeof(AcDream.App.Combat.ICombatAttackTargetSource),
combatTargets.FieldType);
Assert.DoesNotContain(
typeof(AcDream.App.Combat.CombatAttackTargetSource).GetFields(
BindingFlags.Instance | BindingFlags.NonPublic),
field => typeof(Delegate).IsAssignableFrom(field.FieldType));
Assert.DoesNotContain(
typeof(AcDream.App.Combat.CombatAttackTargetSource).GetFields(
BindingFlags.Instance | BindingFlags.NonPublic),
field => field.FieldType
== typeof(AcDream.App.Interaction.SelectionInteractionController));
FieldInfo outboundDiagnostics = Assert.Single(
typeof(LocalPlayerOutboundController).GetFields(
BindingFlags.Instance | BindingFlags.NonPublic),
field => field.Name == "_diagnostic");
Assert.Equal(
typeof(IMovementTruthDiagnosticSink),
outboundDiagnostics.FieldType);
Assert.DoesNotContain(
typeof(AcDream.App.Input.MovementTruthDiagnosticController).GetFields(
BindingFlags.Instance | BindingFlags.NonPublic),
field => typeof(Delegate).IsAssignableFrom(field.FieldType));
FieldInfo approachCompletions = Assert.Single(
typeof(AcDream.App.Input.PlayerModeController).GetFields(
BindingFlags.Instance | BindingFlags.NonPublic),
field => field.Name == "_approachCompletions");
Assert.Equal(
typeof(AcDream.App.Interaction.IPlayerApproachCompletionLifetimeOwner),
approachCompletions.FieldType);
Assert.DoesNotContain(
typeof(AcDream.App.Input.PlayerModeController).GetFields(
BindingFlags.Instance | BindingFlags.NonPublic),
field => field.FieldType
== typeof(AcDream.App.Interaction.SelectionInteractionController));
Assert.DoesNotContain(
typeof(AcDream.App.Interaction.PlayerApproachCompletionState).GetFields(
BindingFlags.Instance | BindingFlags.NonPublic),
field => typeof(Delegate).IsAssignableFrom(field.FieldType));
string playerModeSource = File.ReadAllText(Path.Combine(
FindRepoRoot(),
"src",
"AcDream.App",
"Input",
"PlayerModeController.cs"));
// C3c (clause 4 — sealed-setter lifecycle routing): the movement
// controller, physics body, host, and committed placement are
// Runtime-owned, published by the first-entry conductor's
// publication transaction. Player-mode entry attaches presentation
// only: it gates on the Runtime-published controller, then wires
// camera -> shadow -> host slot -> mode flag. The old pinned
// markers (PreparePositionForCommit / InstallOrRebind /
// CommitPreparedPosition / `_controllerSlot.Controller =`) were
// exactly the App-side controller construction+commit this flip
// deleted.
AssertAppearsInOrder(
playerModeSource,
"controller.IsRuntimePublished",
"_camera.EnterChaseMode(legacyCamera, retailCamera);",
"_shadow.SyncPose(",
"_hostSlot.Host = playerHost;",
"_mode.IsPlayerMode = true;");
Assert.Contains("_shadow.Restore(playerEntity, priorShadow);", playerModeSource,
StringComparison.Ordinal);
Assert.Contains("_camera.RestoreState(priorCamera);", playerModeSource,
StringComparison.Ordinal);
string mouseLookSource = File.ReadAllText(Path.Combine(
FindRepoRoot(),
"src",
"AcDream.App",
"Input",
"MouseLookController.cs"));
AssertAppearsInOrder(
mouseLookSource,
"controller?.StopMouseDrift",
"retail.FilterMouseDelta",
"_state.ApplyDelta");
string localPlayerSource = File.ReadAllText(Path.Combine(
FindRepoRoot(),
"src",
"AcDream.App",
"Input",
"RetailLocalPlayerFrameController.cs"));
Assert.DoesNotContain("Func<MovementInput>", localPlayerSource,
StringComparison.Ordinal);
Assert.Contains("IMovementInputSource", localPlayerSource,
StringComparison.Ordinal);
}
[Fact]
public void CameraAndLocalPlayerFrameOwnersUseTypedSeamsWithoutWindowCallbacks()
{
Type[] owners =
[
typeof(AcDream.App.Rendering.CameraFrameController),
typeof(AcDream.App.Input.RetailLocalPlayerFrameController),
typeof(AcDream.App.Input.LocalPlayerProjectionController),
typeof(AcDream.App.Input.LiveLocalPlayerFrameRuntime),
typeof(AcDream.App.Input.LiveLocalPlayerProjectionRuntime),
typeof(AcDream.App.Combat.CombatCameraTargetSource),
];
foreach (Type owner in owners)
{
FieldInfo[] fields = owner.GetFields(
BindingFlags.Instance | BindingFlags.NonPublic);
Assert.DoesNotContain(fields, field => field.FieldType == typeof(GameWindow));
Assert.DoesNotContain(
fields,
field => typeof(Delegate).IsAssignableFrom(field.FieldType));
}
string root = FindRepoRoot();
string source = File.ReadAllText(Path.Combine(
root,
"src",
"AcDream.App",
"Rendering",
"GameWindow.cs"));
Assert.Equal(1, CountOccurrences(
source,
"_frameGraphs.Tick("));
Assert.DoesNotContain("CanAdvanceLocalPlayer", source, StringComparison.Ordinal);
Assert.DoesNotContain("GetCombatCameraTargetPoint()", source,
StringComparison.Ordinal);
Assert.DoesNotContain("_cameraController.Fly.Update(", source,
StringComparison.Ordinal);
Assert.DoesNotContain("_localPlayerFrame.TryGetPresentationAfterNetwork", source,
StringComparison.Ordinal);
Assert.DoesNotContain("_cameraFrame", source, StringComparison.Ordinal);
string cameraSource = File.ReadAllText(Path.Combine(
root,
"src",
"AcDream.App",
"Rendering",
"CameraFrameController.cs"));
AssertAppearsInOrder(
cameraSource,
"_localFrame.TryGetPresentationAfterNetwork",
"_spatialReconciler.Reconcile();",
"legacy.Update(",
"retail?.Update(");
}
[Fact]
public void GameWindow_OnUpdateOwnsOnlyProfilingAndOneOrchestratorTick()
{
string source = File.ReadAllText(Path.Combine(
FindRepoRoot(),
"src",
"AcDream.App",
"Rendering",
"GameWindow.cs"));
Assert.Equal(1, CountOccurrences(
source,
"_frameGraphs.Tick("));
Assert.DoesNotContain("_updateFrameClock.Advance(", source,
StringComparison.Ordinal);
Assert.DoesNotContain("_liveFrameCoordinator", source,
StringComparison.Ordinal);
Assert.DoesNotContain("_liveEntityLiveness?.Tick", source,
StringComparison.Ordinal);
Assert.DoesNotContain("_playerModeAutoEntry?.TryEnter", source,
StringComparison.Ordinal);
AssertAppearsInOrder(
source,
"private void OnUpdate(double dt)",
"_frameProfiler.BeginStage(",
"_frameGraphs.Tick(",
"private void OnRender(double deltaSeconds)");
}
[Fact]
public void ProductionFrameAdaptersRetainTypedOwnersWithoutWindowCallbacks()
{
Type[] adapters =
[
typeof(LiveEntityTeardownFramePhase),
typeof(ConsoleUpdateFrameFailureSink),
typeof(PhysicsScriptClockPublisher),
typeof(LiveEntityLivenessFramePhase),
typeof(PlayerModeAutoEntryFramePhase),
];
foreach (Type adapter in adapters)
{
FieldInfo[] fields = adapter.GetFields(
BindingFlags.Instance | BindingFlags.NonPublic);
Assert.DoesNotContain(fields, field => field.FieldType == typeof(GameWindow));
Assert.DoesNotContain(
fields,
field => typeof(Delegate).IsAssignableFrom(field.FieldType));
}
FieldInfo clock = Assert.Single(
typeof(LiveEntityLivenessFramePhase).GetFields(
BindingFlags.Instance | BindingFlags.NonPublic),
field => field.Name == "_clock");
Assert.Equal(typeof(IClientMonotonicTimeSource), clock.FieldType);
FieldInfo teardownRuntime = Assert.Single(
typeof(LiveEntityTeardownFramePhase).GetFields(
BindingFlags.Instance | BindingFlags.NonPublic));
Assert.Equal(typeof(LiveEntityRuntime), teardownRuntime.FieldType);
Type[] typedProductionOwners =
[
typeof(LiveEntityLivenessController),
typeof(AcDream.App.Input.LivePlayerModeAutoEntryContext),
typeof(LiveSessionLocalPhysicsTimestampPublisher),
typeof(AcDream.App.Physics.LiveEntityNetworkUpdateController),
typeof(AcDream.App.Rendering.LiveEntityPartArrayLifecycle),
typeof(AcDream.App.Net.LiveEntitySessionController),
];
foreach (Type owner in typedProductionOwners)
{
FieldInfo[] fields = owner.GetFields(
BindingFlags.Instance | BindingFlags.NonPublic);
Assert.DoesNotContain(fields, field => field.FieldType == typeof(GameWindow));
Assert.DoesNotContain(
fields,
field => typeof(Delegate).IsAssignableFrom(field.FieldType));
}
FieldInfo originIdentity = Assert.Single(
typeof(LiveEntityWorldOriginCoordinator).GetFields(
BindingFlags.Instance | BindingFlags.NonPublic),
field => field.Name == "_identity");
Assert.Equal(
typeof(AcDream.App.Input.ILocalPlayerIdentitySource),
originIdentity.FieldType);
string source = File.ReadAllText(Path.Combine(
FindRepoRoot(),
"src",
"AcDream.App",
"Rendering",
"GameWindow.cs"));
string livePresentation = File.ReadAllText(Path.Combine(
FindRepoRoot(),
"src",
"AcDream.App",
"Composition",
"LivePresentationComposition.cs"));
string sessionRuntime = File.ReadAllText(Path.Combine(
FindRepoRoot(),
"src",
"AcDream.App",
"Net",
"LiveSessionRuntimeFactory.cs"));
Assert.DoesNotContain("PublishLocalPhysicsTimestamps", source,
StringComparison.Ordinal);
Assert.DoesNotContain("LoginWorldReady", source,
StringComparison.Ordinal);
Assert.DoesNotContain("candidate => _liveEntityHydration.OnPrune", source,
StringComparison.Ordinal);
Assert.DoesNotContain("CreateLiveEntitySessionSink", source,
StringComparison.Ordinal);
Assert.DoesNotContain("private System.Numerics.Vector3 CellLocalForSeed", source,
StringComparison.Ordinal);
Assert.DoesNotContain("OnPlayScriptReceived", source,
StringComparison.Ordinal);
Assert.Contains("d.WorldOrigin.GetCenter", livePresentation,
StringComparison.Ordinal);
// C4 route 4b-3 deleted the sole consumer of
// d.WorldOrigin.CellLocalForSeed in this file — the standalone
// RemoteTeleportController construction. LiveWorldOriginState.
// CellLocalForSeed itself is not deleted (LocalPlayerTeleportController
// still uses it).
Assert.DoesNotContain("CreateLiveSessionEventRouter", source,
StringComparison.Ordinal);
Assert.Contains("_world.EntitySession.CreateSink()", sessionRuntime,
StringComparison.Ordinal);
Assert.DoesNotContain("GameWindow", sessionRuntime,
StringComparison.Ordinal);
}
private static UpdateFrameOrchestrator Create(
List<string> calls,
RecordingTeardown? teardown = null,
RecordingFailureSink? failureSink = null,
FrameObservations? observed = null,
bool teleportPlace = false,
bool inboundCreatedPlayer = false,
IWorldGenerationAvailability? availability = null)
{
teardown ??= new RecordingTeardown(calls);
failureSink ??= new RecordingFailureSink();
return new UpdateFrameOrchestrator(
teardown,
failureSink,
new UpdateFrameClock(),
new RecordingClockPublisher(calls, observed),
new RecordingStreaming(calls),
new RecordingInput(calls, observed),
new RecordingLiveFrame(calls, observed),
new RecordingLiveness(calls),
new RecordingTeleport(calls, observed, teleportPlace),
new RecordingAutoEntry(calls),
new RecordingCamera(calls, observed, inboundCreatedPlayer),
new RecordingCommit(calls),
availability);
}
private sealed class RecordingTeardown(List<string> calls)
: IUpdateFrameTeardownPhase
{
public Exception? Failure { get; set; }
public int Attempts { get; private set; }
public void RetryPendingTeardowns()
{
calls.Add("teardown");
Attempts++;
if (Failure is not null)
throw Failure;
}
}
private sealed class RecordingFailureSink : IUpdateFrameFailureSink
{
public List<AggregateException> Errors { get; } = [];
public void ReportTeardownFailure(AggregateException error) => Errors.Add(error);
}
private sealed class RecordingClockPublisher(
List<string> calls,
FrameObservations? observed) : IUpdateFrameScriptClockPublisher
{
public void PublishTime(double scriptTime)
{
calls.Add("clock");
observed?.PublishedTimes.Add(scriptTime);
}
}
private sealed class RecordingStreaming(List<string> calls) : IStreamingFramePhase
{
public void Tick() => calls.Add("streaming");
}
private sealed class RecordingInput(
List<string> calls,
FrameObservations? observed) : IGameplayInputFramePhase
{
public void Tick(UpdateFrameTiming timing)
{
calls.Add("input");
observed?.Input.Add(timing);
}
}
private sealed class RecordingLiveFrame(
List<string> calls,
FrameObservations? observed) : IRetailLiveFramePhase
{
public void Tick(float deltaSeconds)
{
observed?.LiveDeltas.Add(deltaSeconds);
calls.Add("objects");
calls.Add("network");
calls.Add("commands");
calls.Add("ordinary-reconcile");
}
}
private sealed class RecordingLiveness(List<string> calls)
: ILiveEntityLivenessFramePhase
{
public void Tick() => calls.Add("liveness");
}
private sealed class RecordingTeleport(
List<string> calls,
FrameObservations? observed,
bool place)
: ILocalPlayerTeleportFramePhase
{
public void Tick(float deltaSeconds)
{
observed?.TeleportDeltas.Add(deltaSeconds);
if (!place)
{
calls.Add("teleport");
return;
}
calls.Add("teleport-place");
calls.Add("teleport-reconcile");
calls.Add("teleport-reveal");
}
}
private sealed class RecordingAutoEntry(List<string> calls)
: IPlayerModeAutoEntryFramePhase
{
public void TryEnter() => calls.Add("auto-entry");
}
private sealed class RecordingCamera(
List<string> calls,
FrameObservations? observed,
bool inboundCreatedPlayer) : ICameraFramePhase
{
public void Tick(UpdateFrameTiming timing)
{
if (inboundCreatedPlayer)
{
calls.Add("inbound-player-projection");
calls.Add("inbound-player-reconcile");
}
calls.Add("camera");
observed?.Camera.Add(timing);
}
}
private sealed class RecordingLivePhases(List<string> calls) :
ILiveObjectFramePhase,
IRuntimeLiveSessionFramePhase,
IPostNetworkCommandFramePhase,
ILiveSpatialReconcilePhase,
IRenderProjectionSyncPhase,
IWorldGenerationAvailability,
IRuntimePlacementProjectionRetryPhase
{
public bool IsWorldAvailable { get; set; }
public long QuiescedGeneration => IsWorldAvailable ? 0L : 1L;
public void Tick(float deltaSeconds) => calls.Add("objects");
public void Tick() => calls.Add("network");
public void RunPostNetworkCommandPhase() => calls.Add("commands");
public void Reconcile() => calls.Add("reconcile");
public void SynchronizeActiveSources() => calls.Add("render-sync");
public void RetryPending() => calls.Add("placement-retry");
}
private sealed class RecordingCommit(List<string> calls)
: IUpdateFrameCommitPhase
{
public void Commit() => calls.Add("commit");
}
private sealed class FrameObservations
{
public List<double> PublishedTimes { get; } = [];
public List<UpdateFrameTiming> Input { get; } = [];
public List<float> LiveDeltas { get; } = [];
public List<float> TeleportDeltas { get; } = [];
public List<UpdateFrameTiming> Camera { get; } = [];
}
private static string FindRepoRoot()
{
DirectoryInfo? directory = new(AppContext.BaseDirectory);
while (directory is not null)
{
if (File.Exists(Path.Combine(directory.FullName, "AcDream.slnx")))
return directory.FullName;
directory = directory.Parent;
}
throw new DirectoryNotFoundException("Could not find AcDream.slnx.");
}
private static void AssertAppearsInOrder(string source, params string[] markers)
{
int previous = -1;
foreach (string marker in markers)
{
int current = source.IndexOf(marker, previous + 1, StringComparison.Ordinal);
Assert.True(current >= 0, $"Missing source marker: {marker}");
Assert.True(current > previous, $"Out-of-order source marker: {marker}");
previous = current;
}
}
private static int CountOccurrences(string source, string marker) =>
source.Split(marker, StringSplitOptions.None).Length - 1;
}