fix(streaming): #145 — teleport re-use via server-authoritative placement
Portals only worked once per session: teleporting OUT of a dungeon
mis-rooted the player into the SOURCE dungeon's coordinate frame, so every
move was sent dungeon-framed and ACE rejected it ("failed transition") —
the player couldn't move, never reached a portal, and the world wouldn't
re-render (only skybox).
Root cause: acdream's streaming-relative frame recenters on teleport, but
resident physics landblocks keep their load-time world-offset. After
recentering onto the outdoor destination, the collapsed source dungeon
(offset 0,0 as the prior center) and the destination (offset 0,0 as the
new center) overlap, and the Z-agnostic outdoor cell-snap returns the
dungeon for both the arrival placement and every per-frame resolve.
Fix (server-authoritative teleport placement):
- Drop the stale source center landblock from physics at the teleport
recenter (GameWindow.OnLivePositionUpdated) so the resolve falls through
to the server position (Resolve NO-LANDBLOCK verbatim) until the
destination streams in.
- Place outdoor teleports immediately (TeleportArrivalRules) — holding is
futile because streaming does not progress during a PortalSpace hold.
- Clear a dangling CellGraph.CurrCell when its landblock is removed
(PhysicsEngine.RemoveLandblock) — otherwise the dungeon-streaming gate
keeps streaming collapsed onto the gone dungeon (only skybox renders).
Keeps DungeonStreamingGate (gate suppression during the hold). Indoor
(dungeon-entry) placement is unchanged (cell-keyed, IsSpawnCellReady).
User-verified: in->out->re-enter works repeatedly, no ACE errors, world
renders. Remaining facets (server objects + own avatar not rendering after
a teleport-out) are entity render/lifecycle — split to #138.
Registers AP-36 + AD-2 updated. New: DungeonStreamingGate (+4 tests),
TeleportArrivalRules (+4 tests). Build + 2727 tests green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
f6a576af8e
commit
a15bd3b56d
9 changed files with 290 additions and 32 deletions
|
|
@ -103,3 +103,42 @@ public sealed class TeleportArrivalController
|
|||
_place(_destPos, _destCell, forced);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pure readiness decision for a teleport arrival, factored out of
|
||||
/// <c>GameWindow.TeleportArrivalReadiness</c> for testing.
|
||||
/// </summary>
|
||||
public static class TeleportArrivalRules
|
||||
{
|
||||
/// <summary>
|
||||
/// Decide whether a held teleport arrival can place now.
|
||||
/// </summary>
|
||||
/// <param name="claimUnhydratable">The destination cell can never hydrate.</param>
|
||||
/// <param name="indoor">Destination is an indoor cell (cell index ≥ 0x0100).</param>
|
||||
/// <param name="indoorCellReady">For an indoor destination, the EnvCell floor has hydrated.</param>
|
||||
public static ArrivalReadiness Decide(
|
||||
bool claimUnhydratable,
|
||||
bool indoor,
|
||||
bool indoorCellReady)
|
||||
{
|
||||
if (claimUnhydratable)
|
||||
return ArrivalReadiness.Impossible;
|
||||
|
||||
// Indoor (sealed dungeon / building interior): gate on the EnvCell floor hydrating,
|
||||
// exactly as #135. The dungeon-IN path pre-collapses + waits for the cell struct, and
|
||||
// its placement validates the specific claimed cell (the indoor resolve is cell-keyed,
|
||||
// not the grid-snap), so it is unaffected by the overlap that broke teleport-OUT.
|
||||
if (indoor)
|
||||
return indoorCellReady ? ArrivalReadiness.Ready : ArrivalReadiness.NotReady;
|
||||
|
||||
// Outdoor: place IMMEDIATELY on the server-authoritative position. #145/#138 — holding
|
||||
// for the destination to stream in is futile: streaming does NOT progress while the
|
||||
// player is held in PortalSpace (the destination only loads once placement flips the
|
||||
// state to InWorld). The stale source center landblock is dropped at recenter (see
|
||||
// GameWindow.OnLivePositionUpdated), so the arrival resolve falls through to the
|
||||
// server-authoritative cell/position (Resolve NO-LANDBLOCK verbatim) and the player is
|
||||
// placed grounded there; streaming then loads the destination and the per-frame resolve
|
||||
// grounds onto it. This trusts the server's teleport position — retail-faithful.
|
||||
return ArrivalReadiness.Ready;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue