acdream/tests/AcDream.App.Tests/Streaming
Erik d233f81dce feat(session): the in-world logoff — LogOut animation, reverse wormhole, live return to character select
Retires AD-74 (Exit to Character Selection 'behaves as Exit Game') and
files AD-110 (the composed handoff edge) — register rows in this commit.

Retail derivation (named decomp):
- gmGamePlayUI::UseTime @0x004EA3A0: confirmed Yes drains into
  CPlayerSystem::LogOffCharacter(0) when grounded (transient_state &
  CONTACT); the grounded three-way branch now also covers the
  indicator-bar end-session control (it was Options-only).
- CPlayerSystem::LogOffCharacter @0x00563520: SaveToServer FIRST (the
  existing pre-logoff flush hook), then RequestLogOff @0x00562DD0:
  'Logging off...' chat (type 0), 0xF653 via Proto_UI::LogOffCharacter
  @0x00546A20, logOffRequestTime = now + 3.0 (+20.0 when
  IsPlayerKiller @0x0058C910 — PWD bits 0x20|0x2000000), and
  CommandInterpreter::HandleLogOff @0x006B3330 -> Disable.
- The log-off ANIMATION is server-driven: ACE broadcasts
  MotionCommand.LogOut (0x1000011E, Player.cs:596 SendMotionAsCommands)
  and it plays on the local player through the existing inbound
  unpack_movement funnel during the 3 s hold — retail plays nothing
  locally; Disable() is the whole client-side effect.
- gmSmartBoxUI::UseTime @0x004D6E64: hold elapsed ->
  BeginTeleportAnimation(TAS_WORLD_FADE_OUT) @0x004D6E83 (enter cue
  @0x004D638E, unconditional) -> TunnelFadeIn -> Tunnel. The tunnel
  plays the SAME forward 40 fps animation; nothing renders backwards,
  and NO exit cue ever fires on logout (the char-select swap preempts
  the TunnelContinue/FadeOut tail).
- Inbound 0xF653 echo (dispatch case 3 @0x0055C963) ->
  ExecuteLogOff @0x0055D780: world teardown with the LOGON CONNECTION
  KEPT (ExitWorldDisconnect @0x00541E00 removes every connection
  except logonRecID_ — one connection against ACE) and
  Proto_UI::SetEventCounter(0) @0x00541E79; the fresh CharacterList in
  the same batch re-shows character management (gmGamePlayUI::Update
  @0x004E9CD0 -> QueueUIMode(0x1000000a)). ACE mirrors it:
  SendFinalLogOffMessages (Session.cs:249) sends 0xF653 + CharacterList
  + ServerName >=6 s after the request and leaves the session
  AuthConnected — a second EnterWorld needs no re-handshake.

Implementation:
- RuntimeWorldTransitState: the canonical logout lifecycle
  (Requested/PresentationActive/Confirmed, retail 3 s/+20 s holds,
  cancel/reset/ownership convergence).
- WorldSession: RequestCharacterLogOff (non-blocking 0xF653),
  IsCharacterLogOffConfirmed, ReturnToCharacterSelect (InWorld ->
  InCharacterSelect + game-action sequence reset; transport untouched).
- LiveSessionController: BeginCharacterLogOff (flush-first request) and
  CompleteCharacterLogOff — the return-to-selection transaction
  (ReconnectCore minus the transport swap: retire the world
  generation's routes, host reset, state flip, fresh generation
  re-bind, roster re-applied from the pushed CharacterList; failures
  degrade to the full StopCore teardown).
- RuntimeLocalPlayerMovementState.DisableCommandInterpreter +
  DispatcherMovementInputSource gate: retail's Disable() — held keys
  produce no movement while the server LogOut motion plays; cleared by
  the generation reset.
- LocalPlayerTeleportController: the logout pump as the third arm of
  the one wormhole machine (request/hold/wormhole/confirmed handoff;
  teleport starts refused during logout; the handoff runs the session
  transaction whose world reset retires the tunnel as the fresh
  selection state re-shows the character screen).
- UI: both end-session surfaces share the retail three-way grounded
  gate and now run the REAL flow; Options' Exit Game keeps the app
  exit (window close -> the existing graceful-shutdown logoff).

Tests: +5 transit lifecycle, +4 session transaction, +7 logout pump.
Runtime 1756/0 (baseline 1747), App live-DAT 5523/3 (baseline 5512/3
+ 11 this round), Core.Net 1004/0, full solution green (0 failures).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-17 14:02:40 +02:00
..
GpuWorldStateActivatorTests.cs refactor(streaming): compose landblock presentation transaction 2026-07-21 21:45:16 +02:00
GpuWorldStateAnimatedIndexTests.cs fix(rendering): bound portal resource lifetime 2026-07-18 21:35:16 +02:00
GpuWorldStateCollisionResidencyTests.cs refactor(physics): remove parsed collision graphs 2026-07-25 18:21:19 +02:00
GpuWorldStateRenderTraversalTests.cs test(app): put every strict-zero site on the probe (#250) 2026-07-29 03:49:13 +02:00
GpuWorldStateVisibilityTests.cs fix(streaming): stop replaying committed recenter retirements 2026-08-02 20:53:11 +02:00
GraphicalRemotePlacementServiceWindowTests.cs feat(physics): C4 route 4b-1 — remote placement infrastructure (dormant) 2026-08-04 04:08:19 +02:00
LandblockBuildFactoryTests.cs refactor(physics): remove parsed collision graphs 2026-07-25 18:21:19 +02:00
LandblockBuildOriginTests.cs test: FarLoad strip test asserts each build config's designed outcome 2026-08-13 08:52:12 +02:00
LandblockConcretePresentationPipelineTests.cs refactor(runtime): own per-session physics simulation 2026-07-26 13:39:57 +02:00
LandblockPhysicsPublisherTests.cs fix(physics): S2 — static publication emits authored Spheres as Spheres (AP-155 narrowed) 2026-08-07 08:07:02 +02:00
LandblockPresentationPipelineTests.cs fix(streaming): stop replaying committed recenter retirements 2026-08-02 20:53:11 +02:00
LandblockRenderPublisherTests.cs perf(streaming): cursor publication across frame budgets 2026-07-24 19:10:18 +02:00
LandblockRetirementCoordinatorTests.cs fix(streaming): stop replaying committed recenter retirements 2026-08-02 20:53:11 +02:00
LandblockStaticPresentationPublisherTests.cs refactor(runtime): own per-session physics simulation 2026-07-26 13:39:57 +02:00
LocalPlayerTeleportControllerTests.cs feat(session): the in-world logoff — LogOut animation, reverse wormhole, live return to character select 2026-08-17 14:02:40 +02:00
RuntimeTeleportDestinationAdapterTests.cs refactor(runtime): own teleport destination correlation 2026-07-26 17:52:34 +02:00
StreamingCompletionQueueTests.cs fix(streaming): preserve portal destination ownership 2026-07-25 08:35:12 +02:00
StreamingControllerReadinessTests.cs fix(test): cover the atlas-tier seam the D-1 fix depends on; correct AP-150's citation 2026-08-06 07:54:03 +02:00
StreamingFrameControllerTests.cs refactor(physics): delete legacy PhysicsEngine.Resolve/ResolvePlacement/HasCellSurface (C5a, AP-1/AD-1) 2026-08-05 14:11:31 +02:00
StreamingWorkBudgetTests.cs fix(streaming): preserve portal destination ownership 2026-07-25 08:35:12 +02:00
TeleportLandblockTransitionTests.cs fix(world): remove non-retail portal exit fade 2026-07-15 23:20:52 +02:00
WorldGenerationQuiescenceTests.cs refactor(runtime): acknowledge exact world host projections 2026-07-26 18:27:41 +02:00
WorldRevealCoordinatorTests.cs fix(streaming): derive the portal reveal window from the live streaming radii (#280) 2026-08-05 23:54:59 +02:00
WorldRevealDerivedWindowIntegrationTests.cs fix(streaming): make a demoted landblock render-ready like a published one (#280 D-1) 2026-08-06 07:27:28 +02:00
WorldRevealReadinessBarrierTests.cs fix(streaming): make a demoted landblock render-ready like a published one (#280 D-1) 2026-08-06 07:27:28 +02:00