feat(phys): A6.P3 #98 Step 2 — cell-dump probe + roundtrip test
Step 2 of the apparatus plan at C:\Users\erikn\.claude\plans\i-did-some-work-sharded-acorn.md. Adds a one-shot cell-dump probe so the issue #98 replay harness can load real cellar / cottage geometry as JSON fixtures, eliminating live-client iteration from every fix attempt. Probe gate: ACDREAM_DUMP_CELLS=0xA9B40143,0xA9B40146,0xA9B40147 ACDREAM_DUMP_CELLS_DIR=tests/AcDream.Core.Tests/Fixtures/issue98 (default) When set, the first time PhysicsDataCache.CacheCellStruct sees a matching envCellId, it serializes the resulting CellPhysics to <dir>/0x<cellid>.json and prints one [cell-dump] line. Zero cost when unset (gate is a static-readonly IReadOnlySet<uint>.Count check). DTOs (CellDump.cs): - CellDump: top-level record holding cell id, WorldTransform, InverseWorldTransform, resolved polygons, portal polygons, portal infos, visible cell ids. - PolygonDump / PortalDump / Vector3Dto / PlaneDto / Matrix4x4Dto: System.Text.Json-friendly records with explicit From / To converters. What is intentionally NOT dumped: the DAT-native PhysicsBSPTree and CellBSPTree trees. The replay harness drives the leaf-level walkable predicates (WalkableHitsSphere, FindCrossedEdge, PolygonHitsSpherePrecise) directly on the resolved polygon list, which is enough to expose the issue #98 rejection (poly 0x0004 in 0xA9B40143 reports insideEdges=False / overlapsSphere=False at the failing-frame sphere). If a future replay needs BSP traversal we can extend the DTO + Hydrate together without breaking fixtures. Tests (CellDumpRoundTripTests): - Capture → Hydrate preserves WorldTransform / InverseWorldTransform / every polygon's plane + vertices + NumPoints + SidesType. - Capture → Hydrate preserves portal list + visible cell ids. - Write to disk → Read back → Hydrate preserves content. - Hydrate leaves BSP / CellBSP null by design (replay uses leaf-level predicates). Verification: - dotnet build: green, 0 errors. - dotnet test: 1160 passed + 8 pre-existing failed (was 1156 + 8 before this commit; +4 from CellDumpRoundTripTests). Same 8 pre-existing failures, no new regressions. Next: capture the three cells from the live client (Step 2 acceptance), then build the replay harness against the fixtures (Step 3).
This commit is contained in:
parent
35b37dfb5f
commit
f62a873be3
4 changed files with 484 additions and 1 deletions
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
|
||||
namespace AcDream.Core.Physics;
|
||||
|
|
@ -395,6 +396,63 @@ public static class PhysicsDiagnostics
|
|||
public static bool ProbeStepWalkEnabled { get; set; } =
|
||||
Environment.GetEnvironmentVariable("ACDREAM_PROBE_STEP_WALK") == "1";
|
||||
|
||||
/// <summary>
|
||||
/// A6.P3 issue #98 cell-dump probe (2026-05-23). When non-empty, dumps
|
||||
/// the geometry of any cached cell whose EnvCellId matches one of the
|
||||
/// listed ids to a JSON file under
|
||||
/// <see cref="ProbeDumpCellsPath"/>. One-shot per cell (a second cache
|
||||
/// of the same id is a no-op).
|
||||
///
|
||||
/// <para>
|
||||
/// Configured via <c>ACDREAM_DUMP_CELLS</c> as a comma-separated list of
|
||||
/// hex cell ids (with or without <c>0x</c> prefix). The output path
|
||||
/// defaults to
|
||||
/// <c>tests/AcDream.Core.Tests/Fixtures/issue98/<cellid>.json</c>
|
||||
/// (relative to the worktree root). Override with
|
||||
/// <c>ACDREAM_DUMP_CELLS_DIR=<dir></c>.
|
||||
/// </para>
|
||||
///
|
||||
/// <para>
|
||||
/// The dump fuels the deterministic replay harness for issue #98 — the
|
||||
/// goal is to load cells 0xA9B40143 + 0xA9B40146 + 0xA9B40147 as JSON
|
||||
/// fixtures and drive the failing-frame sphere through the walkable
|
||||
/// query in a unit test, eliminating live-client iteration cost from the
|
||||
/// investigation loop.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public static IReadOnlySet<uint> ProbeDumpCellIds { get; set; } =
|
||||
ParseHexIdList(Environment.GetEnvironmentVariable("ACDREAM_DUMP_CELLS"));
|
||||
|
||||
public static string ProbeDumpCellsPath { get; set; } =
|
||||
Environment.GetEnvironmentVariable("ACDREAM_DUMP_CELLS_DIR")
|
||||
?? "tests/AcDream.Core.Tests/Fixtures/issue98";
|
||||
|
||||
public static bool ProbeDumpCellsEnabled => ProbeDumpCellIds.Count > 0;
|
||||
|
||||
private static IReadOnlySet<uint> ParseHexIdList(string? raw)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(raw))
|
||||
return new System.Collections.Generic.HashSet<uint>();
|
||||
|
||||
var ids = new System.Collections.Generic.HashSet<uint>();
|
||||
foreach (var token in raw.Split(',', StringSplitOptions.RemoveEmptyEntries))
|
||||
{
|
||||
var trimmed = token.Trim();
|
||||
if (trimmed.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
|
||||
trimmed = trimmed[2..];
|
||||
|
||||
if (uint.TryParse(
|
||||
trimmed,
|
||||
System.Globalization.NumberStyles.HexNumber,
|
||||
System.Globalization.CultureInfo.InvariantCulture,
|
||||
out var id))
|
||||
{
|
||||
ids.Add(id);
|
||||
}
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Side-channel populated by <c>BSPQuery.SphereIntersectsSolidInternal</c>
|
||||
/// at the leaf where it returns true. Either
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue