Wires the dormant TeleportAnimSequencer as the transit driver: on PlayerTeleport the player holds in PortalSpace behind a full-screen fade (FadeOverlay) until the destination terrain is resident (TeleportWorldReady, gated on the priority-applied landblock), then materializes (Place), and after the world fades back in regains control + acks the server (FireLoginComplete). No movement resolves against the empty world, so the outbound cell frame can't corrupt. Outdoor changes from place-immediately back to hold-until-resident (now fast, not a band-aid). - FadeOverlay: fullscreen NDC black quad, alpha = ShowTunnel ? 1 : FadeAlpha. - Retires TeleportArrivalController + its 2 tests (TAS subsumes the driver role). - Divergence register: AD-2 updated to the new mechanism; AD-31 (fade vs swirl). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
51 lines
3.1 KiB
C#
51 lines
3.1 KiB
C#
namespace AcDream.App.Streaming;
|
||
|
||
/// <summary>Result of the per-frame dungeon streaming-gate decision.</summary>
|
||
/// <param name="InsideDungeon">Passed to <see cref="StreamingController.Tick"/> — collapse
|
||
/// streaming to the single dungeon landblock.</param>
|
||
/// <param name="ObserverLandblockKey">When non-null, override the streaming observer to this
|
||
/// landblock key (the cell id's high 16 bits, 0xXXYY). Null leaves the caller's observer as-is.</param>
|
||
public readonly record struct DungeonGateResult(bool InsideDungeon, uint? ObserverLandblockKey);
|
||
|
||
/// <summary>
|
||
/// AP-36: the dungeon streaming gate (#133 FPS). When the player stands in a SEALED
|
||
/// EnvCell (an indoor cell that doesn't see outside), streaming collapses to the single
|
||
/// dungeon landblock — AC dungeons have no adjacent landblocks, so the normal 25×25
|
||
/// window would pull in ~129 unrelated ocean-grid dungeons. The trigger is the player's
|
||
/// CURRENT cell (<c>CellGraph.CurrCell</c>, set the moment the player is placed), and the
|
||
/// observer is pinned to that cell's OWN landblock (the cell id high 16 bits) because a
|
||
/// dungeon's EnvCells sit at arbitrary ocean-grid world coords with negative local offsets.
|
||
///
|
||
/// <para>Extracted from <c>GameWindow.OnUpdate</c> as a pure function so the
|
||
/// teleport-hold rule (below) is unit-testable without the GL/dat/network stack.</para>
|
||
/// </summary>
|
||
public static class DungeonStreamingGate
|
||
{
|
||
/// <summary>
|
||
/// Decide the streaming gate from the player's current cell.
|
||
/// </summary>
|
||
/// <param name="isTeleportHold">True while a teleport arrival is held (the controller is in
|
||
/// PortalSpace): the player is NOT yet placed, so <paramref name="currCellId"/> is the frozen
|
||
/// SOURCE cell, not where the player is going.</param>
|
||
/// <param name="currCellIsSealedDungeon"><c>CurrCell is EnvCell && !SeenOutside</c>.</param>
|
||
/// <param name="currCellId">The current cell id (0xXXYYNNNN).</param>
|
||
public static DungeonGateResult Compute(
|
||
bool isTeleportHold, bool currCellIsSealedDungeon, uint currCellId)
|
||
{
|
||
// #145/#138: during a teleport hold the player is NOT yet placed, so CurrCell is
|
||
// the frozen SOURCE cell — where the player IS, not where they're going. Streaming
|
||
// must follow the DESTINATION, which the PortalSpace observer pin already does, so
|
||
// the source-cell gate is suppressed. Otherwise a teleport OUT of a dungeon keeps
|
||
// streaming collapsed on the source dungeon (CurrCell still sealed) → the outdoor
|
||
// destination never hydrates → the TAS transit holds 600 frames → force-snap to
|
||
// ocean. A teleport INTO a dungeon is handled explicitly upstream by
|
||
// StreamingController.PreCollapseToDungeon (and the controller's _collapsed latch
|
||
// holds it through the hold), so suppressing the gate here doesn't regress it.
|
||
if (isTeleportHold)
|
||
return new DungeonGateResult(false, null);
|
||
|
||
if (currCellIsSealedDungeon)
|
||
return new DungeonGateResult(true, currCellId >> 16);
|
||
return new DungeonGateResult(false, null);
|
||
}
|
||
}
|