fix(headless): complete connected movement gate
This commit is contained in:
parent
fd9559a063
commit
3f3401257c
11 changed files with 756 additions and 48 deletions
|
|
@ -55,6 +55,12 @@ public sealed class PhysicsEngine
|
|||
/// <summary>Number of registered landblocks (diagnostic).</summary>
|
||||
public int LandblockCount => _landblocks.Count;
|
||||
|
||||
/// <summary>
|
||||
/// Optional high-volume collision trace sink. Production leaves this
|
||||
/// unset; focused diagnostic gates may opt in explicitly.
|
||||
/// </summary>
|
||||
public Action<string>? DiagnosticLog { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// True once the landblock covering <paramref name="cellOrLandblockId"/> has had its
|
||||
/// terrain + cells registered via <see cref="AddLandblock"/>. Accepts a canonical
|
||||
|
|
@ -797,8 +803,8 @@ public sealed class PhysicsEngine
|
|||
|
||||
if (physics is null)
|
||||
{
|
||||
if (snapDiag)
|
||||
Console.WriteLine(System.FormattableString.Invariant(
|
||||
if (snapDiag && DiagnosticLog is { } noLandblockLog)
|
||||
noLandblockLog(System.FormattableString.Invariant(
|
||||
$"[snap] claim=0x{cellId:X8} pos=({currentPos.X:F3},{currentPos.Y:F3},{currentPos.Z:F3}) branch=NO-LANDBLOCK (lbs={_landblocks.Count}) -> verbatim"));
|
||||
return new ResolveResult(candidatePos, cellId, IsOnGround: false);
|
||||
}
|
||||
|
|
@ -831,8 +837,11 @@ public sealed class PhysicsEngine
|
|||
float? claimFloorZ = WalkableFloorZNearest(cellId, candidatePos, currentPos.Z);
|
||||
if (claimFloorZ is not null)
|
||||
{
|
||||
Console.WriteLine(System.FormattableString.Invariant(
|
||||
$"[snap] claim=0x{cellId:X8} pos=({currentPos.X:F3},{currentPos.Y:F3},{currentPos.Z:F3}) VALIDATED -> grounded to its walkable floor z={claimFloorZ.Value:F3}"));
|
||||
if (DiagnosticLog is { } validatedLog)
|
||||
{
|
||||
validatedLog(System.FormattableString.Invariant(
|
||||
$"[snap] claim=0x{cellId:X8} pos=({currentPos.X:F3},{currentPos.Y:F3},{currentPos.Z:F3}) VALIDATED -> grounded to its walkable floor z={claimFloorZ.Value:F3}"));
|
||||
}
|
||||
// #133 (2026-06-13): return the VALIDATED claim's OWN full cell id,
|
||||
// NOT lbPrefix | (cellId & 0xFFFF). lbPrefix is found by scanning
|
||||
// resident landblocks for one whose [0,192) local bounds contain
|
||||
|
|
@ -1017,10 +1026,14 @@ public sealed class PhysicsEngine
|
|||
// max(terrain, z) stays as the under-terrain sanity bound —
|
||||
// our recoverable stand-in for retail's lost-cell machinery
|
||||
// (documented divergence, same as the #107 demote).
|
||||
if (snapDiag && currentPos.Z > terrainZ)
|
||||
if (snapDiag
|
||||
&& currentPos.Z > terrainZ)
|
||||
{
|
||||
Console.WriteLine(System.FormattableString.Invariant(
|
||||
if (DiagnosticLog is { } outdoorLog)
|
||||
{
|
||||
outdoorLog(System.FormattableString.Invariant(
|
||||
$"[snap] OUTDOOR claim 0x{cellId:X8} z={currentPos.Z:F3} above terrain {terrainZ:F3} — committing the server Z (retail SetPositionInternal shape; physics settles on tick 1)"));
|
||||
}
|
||||
targetZ = currentPos.Z;
|
||||
}
|
||||
}
|
||||
|
|
@ -1028,8 +1041,8 @@ public sealed class PhysicsEngine
|
|||
|
||||
// Step-height enforcement: block upward movement that exceeds the limit.
|
||||
float zDelta = targetZ - currentPos.Z;
|
||||
if (snapDiag)
|
||||
Console.WriteLine(System.FormattableString.Invariant(
|
||||
if (snapDiag && DiagnosticLog is { } resultLog)
|
||||
resultLog(System.FormattableString.Invariant(
|
||||
$"[snap] claim=0x{cellId:X8} pos=({currentPos.X:F3},{currentPos.Y:F3},{currentPos.Z:F3}) cells={physics.Cells.Count} bestCell=0x{(bestCell?.CellId ?? 0u):X8} bestZ={(bestCellZ?.ToString("F3") ?? "none")} terrainZ={terrainZ:F3} indoor={currentlyIndoor} -> targetZ={targetZ:F3} targetCell=0x{(lbPrefix | (targetCellId & 0xFFFFu)):X8} stepReject={zDelta > stepUpHeight}"));
|
||||
if (zDelta > stepUpHeight)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue