refactor(runtime): extract local teleport and player mode
Move local teleport, player-mode, animation, shadow, and sealed-dungeon lifetimes out of GameWindow. Make player-mode entry transactional and isolate approach completions by controller lifetime and approach generation so stale callbacks cannot affect replacements. Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
parent
c557038353
commit
eeb0f6b45c
29 changed files with 3311 additions and 1073 deletions
|
|
@ -1092,7 +1092,10 @@ public sealed class PlayerMovementController
|
|||
// route through here. When PhysicsDiagnostics.ProbeCellEnabled is
|
||||
// off this collapses to a single bool-compare + assignment — zero
|
||||
// logging cost.
|
||||
private void UpdateCellId(uint newCellId, string reason)
|
||||
private void UpdateCellId(
|
||||
uint newCellId,
|
||||
string reason,
|
||||
bool publishRenderRoot = true)
|
||||
{
|
||||
if (newCellId != CellId && PhysicsDiagnostics.ProbeCellEnabled)
|
||||
{
|
||||
|
|
@ -1109,7 +1112,8 @@ public sealed class PlayerMovementController
|
|||
// jump-looping near the cottage doorway clobbered the render root every tick → the render
|
||||
// rooted at the NPC's tiny connector cell → only its ~8-tri shell drew, rest = GL clear
|
||||
// color = the cottage doorway "blue-hole" flap (diagnosed 2026-06-03 via [flap-cam]/[shell]).
|
||||
_physics.UpdatePlayerCurrCell(newCellId);
|
||||
if (publishRenderRoot)
|
||||
_physics.UpdatePlayerCurrCell(newCellId);
|
||||
}
|
||||
|
||||
public void SetPosition(Vector3 pos, uint cellId)
|
||||
|
|
@ -1127,11 +1131,47 @@ public sealed class PlayerMovementController
|
|||
/// directly via <c>SnapToCell</c> rather than delta-syncing through the setter.
|
||||
/// </summary>
|
||||
public void SetPosition(Vector3 pos, uint cellId, Vector3 cellLocal)
|
||||
=> SetPositionCore(
|
||||
pos,
|
||||
cellId,
|
||||
cellLocal,
|
||||
publishSharedState: true);
|
||||
|
||||
/// <summary>
|
||||
/// Builds a new local controller's canonical body pose without publishing
|
||||
/// the renderer's global current cell or mutating the incarnation-stable
|
||||
/// PositionManager. Player-mode entry commits those shared edges only
|
||||
/// after camera, shadow, and host preparation succeeds.
|
||||
/// </summary>
|
||||
internal void PreparePositionForCommit(
|
||||
Vector3 pos,
|
||||
uint cellId,
|
||||
Vector3 cellLocal) =>
|
||||
SetPositionCore(
|
||||
pos,
|
||||
cellId,
|
||||
cellLocal,
|
||||
publishSharedState: false);
|
||||
|
||||
internal void CommitPreparedPosition()
|
||||
{
|
||||
_physics.UpdatePlayerCurrCell(CellId);
|
||||
PositionManager?.UnStick();
|
||||
}
|
||||
|
||||
private void SetPositionCore(
|
||||
Vector3 pos,
|
||||
uint cellId,
|
||||
Vector3 cellLocal,
|
||||
bool publishSharedState)
|
||||
{
|
||||
_body.SnapToCell(cellId, pos, cellLocal);
|
||||
_prevPhysicsPos = pos;
|
||||
_currPhysicsPos = pos;
|
||||
UpdateCellId(_body.CellPosition.ObjCellId, "teleport");
|
||||
UpdateCellId(
|
||||
_body.CellPosition.ObjCellId,
|
||||
"teleport",
|
||||
publishSharedState);
|
||||
|
||||
// Treat as grounded after a server-side position snap.
|
||||
_body.TransientState = TransientStateFlags.Contact
|
||||
|
|
@ -1164,7 +1204,8 @@ public sealed class PlayerMovementController
|
|||
// tears down any active stick. (StopInterpolating/UnConstrain have no
|
||||
// armed acdream counterparts — no local-player InterpolationManager,
|
||||
// constraint leash unarmed per #167.)
|
||||
PositionManager?.UnStick();
|
||||
if (publishSharedState)
|
||||
PositionManager?.UnStick();
|
||||
// Reset the edge tracker: the stop wiped the motion state, so keys
|
||||
// still physically held must re-fire as press edges on the next
|
||||
// Update (matches the pre-W6 level-triggered behavior of walking
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue