docs(#79/#93): dat-truth check refutes the mesh-gate theory for missing fountain/candle particles

Same-session follow-up: user confirmed the light-carrier hydration fix
worked, then reported missing candle flames + fountain water particles.
Tested whether it's the same root cause (a mesh-empty Setup dropped by
EntityHydrationRules before its Setup.DefaultScript — the ambient
particle script GpuWorldState.cs:221 fires — is ever read). Refuted: the
fountain (0x02000AA3) has a surviving mesh part and a real DefaultScript
(0x33000B21), never dropped by the gate. The guessed "candle" objects
(0x02001967, ring of 16 around the fountain) have real mesh and no
DefaultScript at all — not candles. Separate root cause; filed as its
own issue rather than chased further this session.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-07-09 11:44:03 +02:00
parent 9ebb206086
commit f6b054b7d7

View file

@ -134,4 +134,53 @@ public class Issue93TownNetworkFountainRoomLightInspectionTests
_out.WriteLine($" meshRefs survivor count = {survivors} (markerSkipped={markerSkipped} gfxNull={gfxNull}) " +
$"=> GameWindow.cs:7324 would {(survivors == 0 ? "DROP" : "KEEP")} this entity");
}
/// <summary>
/// Follow-up (same session, 2026-07-09): user confirmed lighting improved but
/// reported missing candle flames + fountain water particles. Hypothesis tested:
/// same mesh-empty hydration-gate class as the light fix, just for
/// Setup.DefaultScript instead of Setup.Lights (GpuWorldState.cs:221 fires
/// ambient particle scripts from DefaultScript.DataId per hydrated entity — the
/// SAME lb.Entities list EntityHydrationRules.ShouldKeepEntity gates).
/// <b>REFUTED — do not re-chase this specific mechanism for #79/#93's particle
/// residual.</b> The fountain (0x02000AA3) has a SURVIVING mesh part (1/1) AND a
/// real DefaultScript (0x33000B21, almost certainly the water spray) — never
/// dropped by the gate, mesh or no. The "16 ring objects" guess (0x02001967) was
/// WRONG: real mesh, DefaultScript==0 — not candles, no script at all. Filed as
/// its own issue (missing ambient particles) — the remaining suspects are
/// downstream of hydration entirely: does EntityScriptActivator/
/// PhysicsScriptRunner actually fire DefaultScript=0x33000B21 for dat-hydrated
/// (ServerGuid==0) entities at runtime, does that script resolve to a real
/// PhysicsScriptTable entry, and does the resulting emitter reach the particle
/// renderer. NOT investigated further this session — separate root cause,
/// separate fix.
/// </summary>
[Theory]
[InlineData(0x02000AA3u)] // the fountain itself (cell 0x00070144 center)
[InlineData(0x02001967u)] // the 16 ring objects around the fountain (candles?)
[InlineData(0x020018C5u)] // the other cell-center static
public void FountainAndCandleSetup_DefaultScriptAndMeshSurvivorCount_Dump(uint setupId)
{
var datDir = ResolveDatDir();
if (datDir is null) { _out.WriteLine("SKIP: no dat dir"); return; }
using var dats = new DatCollection(datDir, DatAccessType.Read);
var setup = dats.Get<Setup>(setupId);
Assert.NotNull(setup);
_out.WriteLine($"=== Setup 0x{setupId:X8}: Parts={setup!.Parts.Count} DefaultScript.DataId=0x{setup.DefaultScript.DataId:X8} Lights={setup.Lights.Count} ===");
var flat = AcDream.Core.Meshing.SetupMesh.Flatten(setup);
int survivors = 0;
foreach (var mr in flat)
{
if (AcDream.Core.Meshing.GfxObjDegradeResolver.IsRuntimeHiddenMarker(dats, mr.GfxObjId)) continue;
if (dats.Get<GfxObj>(mr.GfxObjId) is null) continue;
survivors++;
}
bool wouldBeKeptByCurrentFix = AcDream.Core.Meshing.EntityHydrationRules.ShouldKeepEntity(survivors, setup.Lights.Count);
_out.WriteLine($" flattened={flat.Count} meshSurvivors={survivors} " +
$"hasDefaultScript={setup.DefaultScript.DataId != 0} " +
$"=> current ShouldKeepEntity(mesh,lights) = {wouldBeKeptByCurrentFix}");
}
}