131 probe: print matched emitter owner ids + the setup-dump diagnostic (portal identification capture)
unattached=0 in the last capture refuted the unattached hypothesis (the fix-1 pass is vacuous); the swirl outdoors rides a MATCHED attached emitter, so its owner is an OutdoorStatic keyed by a synthetic id. The matched-ids dump on an inside-vs-outside capture pair names the owner: the id that flips. Issue131SetupProbeTests dumps the outstage candidate setups from the dat. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
87afbc0a42
commit
a07279dfd1
2 changed files with 81 additions and 2 deletions
|
|
@ -5097,6 +5097,7 @@ public sealed class GameWindow : IDisposable
|
||||||
// #131 [outstage-pt] probe state (throwaway — strip when #131 closes).
|
// #131 [outstage-pt] probe state (throwaway — strip when #131 closes).
|
||||||
private string? _lastOutStagePtSig;
|
private string? _lastOutStagePtSig;
|
||||||
private readonly HashSet<uint> _outStageUnmatchedScratch = new();
|
private readonly HashSet<uint> _outStageUnmatchedScratch = new();
|
||||||
|
private readonly HashSet<uint> _outStageMatchedScratch = new();
|
||||||
|
|
||||||
private static System.Numerics.Vector3 SkyPesAnchor(
|
private static System.Numerics.Vector3 SkyPesAnchor(
|
||||||
AcDream.Core.World.SkyObjectData obj,
|
AcDream.Core.World.SkyObjectData obj,
|
||||||
|
|
@ -9742,19 +9743,28 @@ public sealed class GameWindow : IDisposable
|
||||||
{
|
{
|
||||||
int matched = 0, attached = 0, unattached = 0;
|
int matched = 0, attached = 0, unattached = 0;
|
||||||
_outStageUnmatchedScratch.Clear();
|
_outStageUnmatchedScratch.Clear();
|
||||||
|
_outStageMatchedScratch.Clear();
|
||||||
foreach (var (emitter, _) in _particleSystem.EnumerateLive())
|
foreach (var (emitter, _) in _particleSystem.EnumerateLive())
|
||||||
{
|
{
|
||||||
if (emitter.AttachedObjectId == 0) { unattached++; continue; }
|
if (emitter.AttachedObjectId == 0) { unattached++; continue; }
|
||||||
attached++;
|
attached++;
|
||||||
if (_outdoorSceneParticleEntityIds.Contains(emitter.AttachedObjectId)) matched++;
|
if (_outdoorSceneParticleEntityIds.Contains(emitter.AttachedObjectId))
|
||||||
|
{
|
||||||
|
matched++;
|
||||||
|
if (_outStageMatchedScratch.Count < 48)
|
||||||
|
_outStageMatchedScratch.Add(emitter.AttachedObjectId);
|
||||||
|
}
|
||||||
else if (_outStageUnmatchedScratch.Count < 12)
|
else if (_outStageUnmatchedScratch.Count < 12)
|
||||||
_outStageUnmatchedScratch.Add(emitter.AttachedObjectId);
|
_outStageUnmatchedScratch.Add(emitter.AttachedObjectId);
|
||||||
}
|
}
|
||||||
var unm = new System.Text.StringBuilder(96);
|
var unm = new System.Text.StringBuilder(96);
|
||||||
foreach (uint id in _outStageUnmatchedScratch)
|
foreach (uint id in _outStageUnmatchedScratch)
|
||||||
unm.Append(System.FormattableString.Invariant($" 0x{id:X8}"));
|
unm.Append(System.FormattableString.Invariant($" 0x{id:X8}"));
|
||||||
|
var mat = new System.Text.StringBuilder(192);
|
||||||
|
foreach (uint id in _outStageMatchedScratch)
|
||||||
|
mat.Append(System.FormattableString.Invariant($" 0x{id:X8}"));
|
||||||
string ptSig = System.FormattableString.Invariant(
|
string ptSig = System.FormattableString.Invariant(
|
||||||
$"ids={_outdoorSceneParticleEntityIds.Count} attachedEmitters={attached} matched={matched} unattached={unattached} unmatchedIds=[{unm}]");
|
$"ids={_outdoorSceneParticleEntityIds.Count} attachedEmitters={attached} matched={matched} unattached={unattached} matchedIds=[{mat}] unmatchedIds=[{unm}]");
|
||||||
if (ptSig != _lastOutStagePtSig)
|
if (ptSig != _lastOutStagePtSig)
|
||||||
{
|
{
|
||||||
_lastOutStagePtSig = ptSig;
|
_lastOutStagePtSig = ptSig;
|
||||||
|
|
|
||||||
69
tests/AcDream.App.Tests/Rendering/Issue131SetupProbeTests.cs
Normal file
69
tests/AcDream.App.Tests/Rendering/Issue131SetupProbeTests.cs
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
using System;
|
||||||
|
using DatReaderWriter;
|
||||||
|
using DatReaderWriter.Options;
|
||||||
|
using Xunit;
|
||||||
|
using Xunit.Abstractions;
|
||||||
|
using DatSetup = DatReaderWriter.DBObjs.Setup;
|
||||||
|
using DatGfxObj = DatReaderWriter.DBObjs.GfxObj;
|
||||||
|
|
||||||
|
namespace AcDream.App.Tests.Rendering;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// #131 diagnostic (throwaway): identify the Holtburg portal among the
|
||||||
|
/// outside-stage setup ids captured by the [outstage] probe, by dumping each
|
||||||
|
/// candidate setup's parts + bounds from the dat. The portal's setup is the
|
||||||
|
/// translucent swirl; lamp posts / creatures / signs identify by part shape.
|
||||||
|
/// </summary>
|
||||||
|
public class Issue131SetupProbeTests
|
||||||
|
{
|
||||||
|
private readonly ITestOutputHelper _out;
|
||||||
|
public Issue131SetupProbeTests(ITestOutputHelper output) => _out = output;
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Diagnostic_DumpOutstageCandidateSetups()
|
||||||
|
{
|
||||||
|
var datDir = CornerFloodReplayTests.ResolveDatDir();
|
||||||
|
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); return; }
|
||||||
|
using var dats = new DatCollection(datDir, DatAccessType.Read);
|
||||||
|
|
||||||
|
uint[] candidates =
|
||||||
|
{
|
||||||
|
0x020010AC, // 0x7A9B4050 PASS r=11.9 — portal candidate A
|
||||||
|
0x02000B8E, // 0x7A9B403B PASS r=11.6 — portal candidate B
|
||||||
|
0x020019FF, // many instances (lamp posts?)
|
||||||
|
0x02000290,
|
||||||
|
0x02000001, // baseline (human?)
|
||||||
|
0x02000E08,
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (uint setupId in candidates)
|
||||||
|
{
|
||||||
|
var setup = dats.Get<DatSetup>(setupId);
|
||||||
|
if (setup is null)
|
||||||
|
{
|
||||||
|
_out.WriteLine(FormattableString.Invariant($"setup 0x{setupId:X8}: NOT FOUND"));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
_out.WriteLine(FormattableString.Invariant(
|
||||||
|
$"setup 0x{setupId:X8}: parts={setup.Parts.Count}"));
|
||||||
|
int shown = 0;
|
||||||
|
foreach (uint partId in setup.Parts)
|
||||||
|
{
|
||||||
|
if (shown++ >= 4) { _out.WriteLine(" ..."); break; }
|
||||||
|
var gfx = dats.Get<DatGfxObj>(partId);
|
||||||
|
if (gfx is null) { _out.WriteLine(FormattableString.Invariant($" part 0x{partId:X8}: not found")); continue; }
|
||||||
|
var sb = new System.Text.StringBuilder();
|
||||||
|
sb.Append(FormattableString.Invariant(
|
||||||
|
$" part 0x{partId:X8}: polys={gfx.Polygons.Count} verts={gfx.VertexArray.Vertices.Count} surfaces=["));
|
||||||
|
int sShown = 0;
|
||||||
|
foreach (uint surfId in gfx.Surfaces)
|
||||||
|
{
|
||||||
|
if (sShown++ >= 6) { sb.Append(" ..."); break; }
|
||||||
|
sb.Append(FormattableString.Invariant($" 0x{surfId:X8}"));
|
||||||
|
}
|
||||||
|
sb.Append(" ]");
|
||||||
|
_out.WriteLine(sb.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue