acdream/tests/AcDream.Core.Tests/Physics/CellTransitAddAllOutsideCellsTests.cs
Erik 28cd97be62 fix(phys): A6.P4 door bug — AddAllOutsideCells coord convention + replay apparatus
CellTransit.AddAllOutsideCells assumed sphere coords were absolute world
coords (subtracting lbXf = 0xA9 * 192 = 32448 from the sphere position).
Production has used landblock-local coords since Phase A.1
(streaming-center landblock at world origin), so the subtraction
produced localX = -32316, gridX = -1346 → out-of-range → early return
→ ZERO outdoor cells added.

For outdoor primary cells the bug was masked by GetNearbyObjects's
radial sweep. For indoor primary cells (where #98 gates the outdoor
sweep), the door's outdoor cell 0xA9B40029 never reached
portalReachableCells, the door's BSP was never queried, and the player
walked through Holtburg cottage doors unimpeded.

Fix: AddAllOutsideCells treats worldSphereCenter as landblock-local
directly. Matches retail CLandCell::add_all_outside_cells which uses
the per-cell 6-byte landblock-relative position struct.

Existing CellTransitAddAllOutsideCellsTests + CellTransitFindCellSetTests
updated to use landblock-local sphere coords (they were the only callers
using the world-coord convention; production never did).

Apparatus shipped:
- DoorBugTrajectoryReplayTests — live-capture-driven replay harness
  that pinpointed the bug per-field at unit-test speed (<500ms iteration)
- AddAllOutsideCells_LandblockLocalSphere_AddsDoorOutdoorCell — direct
  unit test that demonstrates the fix
- FindTransitCellsSphere_IndoorExitPortal_AddsOutsideForCapturedSpherePos
  — verifies cell-portal traversal at the captured sphere position
- DoorSetupGfxObjInspectionTests.HoltburgCottage_CellPortals_DatInspection
  — dat-direct EnvCell + Environment.Cells + portal-poly inspector
- Fixture: tests/AcDream.Core.Tests/Fixtures/door-bug/live-capture.jsonl
  (tick 13558 walkthrough + tick 22760 outdoor block)

Visual verification (user-driven at Holtburg cottage door, ~50cm off-center):
- outside→inside RUN: now BLOCKS (was: walks through)
- outside→inside WALK: presumed blocks (not retested)
- inside→outside RUN: PARTIAL — body intersects door, sphere slides through
- inside→outside WALK: same partial behavior

The remaining inside→outside asymmetry is a SEPARATE bug in BSP
collision response for two-sided polygons. The [bsp-test] probe now
fires 245 times for the door entity from indoor (was 0 pre-fix) —
door IS being queried; the BSP polygon-level collision response is
the new bug. Handoff at
docs/research/2026-05-25-door-bug-partial-fix-shipped.md.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 07:53:34 +02:00

47 lines
1.6 KiB
C#

using System.Collections.Generic;
using System.Numerics;
using AcDream.Core.Physics;
using Xunit;
namespace AcDream.Core.Tests.Physics;
public class CellTransitAddAllOutsideCellsTests
{
[Fact]
public void SphereWellInsideCell_AddsOneCell()
{
// A6.P4 (2026-05-24): coords are LANDBLOCK-LOCAL (X/Y in [0, 192]).
// Player at landblock-local (12, 12, 0) → cell (0,0) in landblock 0xA9B40000.
// Pre-fix this test passed world coords (32460, 34572) and the function
// subtracted lbXf=32448 to get local 12. Post-fix the function expects
// landblock-local directly.
var candidates = new HashSet<uint>();
CellTransit.AddAllOutsideCells(
worldSphereCenter: new Vector3(12f, 12f, 0f),
sphereRadius: 0.5f,
currentCellId: 0xA9B40001u,
candidates);
Assert.Single(candidates);
Assert.Contains(0xA9B40001u, candidates);
}
[Fact]
public void SphereAtCellEastBoundary_AddsTwoCells()
{
// A6.P4 (2026-05-24): landblock-local coords. Player at (23.6, 12, 0)
// — near +X edge of cell (0,0). Sphere reaches to local X = 23.6 + 0.5
// = 24.1 → cell (1,0) added.
var candidates = new HashSet<uint>();
CellTransit.AddAllOutsideCells(
worldSphereCenter: new Vector3(23.6f, 12f, 0f),
sphereRadius: 0.5f,
currentCellId: 0xA9B40001u,
candidates);
Assert.Equal(2, candidates.Count);
Assert.Contains(0xA9B40001u, candidates);
// Cell (1,0): low-16 id = 1 * 8 + 0 + 1 = 9 → 0x0009.
Assert.Contains(0xA9B40009u, candidates);
}
}