Phase 2's one-line WB patch (Setup-prefix guard at ObjectMeshManager.cs:1230) fixed the symptom but is structurally a band-aid. CLAUDE.md's no-workarounds rule says we should retire it. The proper fix is switching our EnvCell rendering from the general-purpose PrepareMeshDataAsync entry point (which iterates static-object parts + emitters we don't need + triggers the buggy TryGet<Setup> call) to WB's narrower PrepareEnvCellGeomMeshDataAsync API at ObjectMeshManager.cs:386. That function only builds cell room mesh — which is the only thing we use WB for at the cell level. Static objects are already hydrated separately, particle scripts already run via our own EntityScriptActivator. #87 is the issue tracking that refactor. When it lands the WB fork returns to pristine state (no acdream-specific commits on the acdream branch for this file). Handoff doc updated to flag the patch as a known band-aid pending #87. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
7 KiB
Indoor cell rendering — follow-up handoff
Status: Phase 1 (diagnostics) + Phase 2 (fix for missing floors) shipped 2026-05-19. Merged to main. The 9 new bugs surfaced when floors started rendering are filed as docs/ISSUES.md#78 through #86.
This doc is the start-of-session brief for whoever picks up the next indoor-walking phase.
What's in place
Diagnostic infrastructure (Phase 1)
Five [indoor-*] probes are wired and on a runtime-toggleable flag — leave them in place; they're useful for any indoor follow-up work:
| Probe | Where | Toggle |
|---|---|---|
[indoor-walk] |
WbDrawDispatcher.WalkEntitiesInto per cell entity that passes visibility |
ACDREAM_PROBE_INDOOR_WALK=1 or DebugPanel checkbox |
[indoor-cull] |
Same site, when entity is rejected (visibleCellIds-miss or frustum) | ACDREAM_PROBE_INDOOR_CULL=1 |
[indoor-upload] |
WbMeshAdapter.IncrementRefCount + Tick() for EnvCell ids |
ACDREAM_PROBE_INDOOR_UPLOAD=1 |
[indoor-lookup] |
WbDrawDispatcher.Draw per-MeshRef TryGetRenderData call |
ACDREAM_PROBE_INDOOR_LOOKUP=1 |
[indoor-xform] |
Same site, for cellGeomId SetupPart's composed world matrix | ACDREAM_PROBE_INDOOR_XFORM=1 |
Master toggle: ACDREAM_PROBE_INDOOR_ALL=1 cascades to all five. All probes are zero-cost when off.
The WbMeshAdapter also now injects a ConsoleErrorLogger<ObjectMeshManager> (replacing the default NullLogger) so any future exception WB silently catches surfaces as [wb-error] lines automatically. This was the key unlock for Phase 2's diagnosis — see feedback_logger_injection_for_silent_catches memory entry.
Other Phase 1/2 fixes already in main
- Indoor ambient color is now retail-faithful
(0.20, 0.20, 0.20)— was guessed(0.10, 0.09, 0.08). - Indoor lighting triggers off player cell, not camera cell — fixes "darker when camera enters" with third-person chase.
- WB submodule has a one-line band-aid patch (
ObjectMeshManager.cs:1230Setup-prefix guard atTryGet<Setup>) oneriknihlen/WorldBuilder@acdreamat SHA34460c4. Submodule pointer in acdream'smainis advanced. This is a band-aid — seedocs/ISSUES.md#87 for the proper fix (switch to WB's narrowerPrepareEnvCellGeomMeshDataAsyncAPI). Retire the patch when that issue lands.
The 9 follow-up issues
Full descriptions + hypotheses are in docs/ISSUES.md. Summary table:
| # | Title | Cluster | Severity |
|---|---|---|---|
| #78 | Outdoor stabs/buildings visible through floor | Cell-BSP / visibility | HIGH |
| #79 | Spurious spot lights on walls indoors | Indoor lighting | MEDIUM |
| #80 | 2nd floor camera goes very dark | Indoor lighting | MEDIUM |
| #81 | Static building stabs don't react to atmospheric lighting | Indoor lighting | MEDIUM |
| #82 | Some slope terrain lit incorrectly | Terrain shading | LOW |
| #83 | Walking up stairs broken | Physics / movement | HIGH |
| #84 | Blocked by air indoors | Cell-BSP / collision | HIGH |
| #85 | Pass through walls from outside→in | Cell-BSP / collision | HIGH |
| #86 | Click selection penetrates walls | Cell-BSP / interaction | MEDIUM |
Proposed phase groupings:
-
Cluster A: Cell-BSP + portal cull — likely fixes #78, #84, #85, #86 in one phase. Shared root cause hypothesis: the cell BSP physics geometry isn't being correctly used by the movement resolver / WorldPicker / depth-cull. Common pieces:
_physicsDataCache.CacheCellStructatGameWindow.cs:5384caches withcellTransform(including+0.02fZ bump for render anti-z-fight) — physics may be misaligned.- WB's
VisibilityManager.RenderInsideOutstencil pipeline is unused by acdream — explains #78. WorldPickerraycast doesn't test cell BSP — explains #86.- Wall BSP polys likely one-sided — explains #85.
-
Cluster B: Indoor lighting plumbing — #79, #80, #81 each need separate investigation but share the
mesh_modern.frag+SceneLightingUbopipeline. #82 may be terrain-shader-specific. -
Standalone: #83 stairs — needs the existing physics step-up logic to handle EnvCell stair geometry. Could share work with Cluster A if cell BSP is the common path.
Suggested order:
- Cluster A first. Biggest gameplay impact (collision is broken). Probably 1-2 weeks of work.
- #83 stairs as a follow-up once cell BSP collision is solid.
- Cluster B lighting last. Smallest gameplay impact, biggest visual polish.
Where to start a new session
The recommended kickoff prompt is at docs/research/2026-05-19-indoor-followup-prompt.md. Drop it into a fresh Claude Code session in this repo and it should orient itself.
Key files to point Claude at when starting:
- This handoff doc.
docs/ISSUES.mdlines covering #78-#86 (search for "Indoor walking issue cluster").docs/research/2026-05-19-indoor-cell-rendering-cause.md— Phase 2 cause analysis, useful as the "what we already know" anchor for any follow-up.docs/research/2026-05-19-indoor-cell-rendering-verification.md— what's working today.
Important context
- Don't touch the diagnostic infrastructure in
WbMeshAdapterorRenderingDiagnosticsunless you're extending it. Phase 2 left it ready for re-use. - The probes are runtime-toggleable — DebugPanel has checkboxes. No relaunch needed to flip them.
ConsoleErrorLoggeris now the default WB logger. Any future WB-internal exception will surface as[wb-error]automatically without any new diagnostic code.- Don't try to patch WB upstream — the user wants the fix to live only in their fork (
eriknihlen/WorldBuilder). Future WB patches go on theacdreambranch of the fork. - The
+0.02fZ bump on cell origin atGameWindow.cs:5362exists to prevent z-fighting with terrain. It's applied to both render geometry AND physics BSP. May be a confounding factor for #84 (blocked by air).
Verification approach for the next phase
Same pattern that worked for Phase 1+2:
- Diagnostics first. Add probes / log surfaces for the suspected failure paths. The
ConsoleErrorLoggermay already be surfacing relevant errors — checklaunch.logfirst. - Capture cold. Launch the client (the Phase 1 + Phase 2 launch incantation is documented at the top of
CLAUDE.md), walk into Holtburg Inn, take note of the user-observable symptom (e.g., "I'm at position X, I tried to walk through a wall and went through"). - Identify the root cause definitively. Don't apply a fix until the captured data points at one specific code site.
- Apply a surgical fix. Per CLAUDE.md's no-workarounds rule — fix the actual cause, not the symptom.
- Re-capture and verify. Visual confirmation by the user is the acceptance test.
Phase 1+2 took 4 client launches total once the diagnostic infrastructure was in place. The Cluster A phase should be similar — assuming the cell-BSP hypothesis holds, one probe addition + one capture should pin the root cause.