# Phase N.3 handoff — texture decoding via WorldBuilder **Use this whole document as the prompt** when handing off to a fresh agent. Everything they need to pick up cold is below. --- ## Background you'll need You're working in `acdream`, a from-scratch C# .NET 10 reimplementation of Asheron's Call's retail client. The project's house rule (in `CLAUDE.md`) is **the code is modern, the behavior is retail**. acdream just shipped **Phase N.1** (commits `26cf2b8` through `ad8b931`), the first sub-phase of a strategic migration to fork WorldBuilder (`github.com/Chorizite/WorldBuilder`, MIT) and depend on its tested rendering + dat-handling code instead of porting algorithms from retail decomp ourselves. **Read first:** - `docs/architecture/worldbuilder-inventory.md` — the full taxonomy of what WB has and what we keep porting ourselves - `docs/superpowers/specs/2026-05-08-phase-n-worldbuilder-migration-design.md` — the parent design doc for Phase N - `CLAUDE.md` — especially the "Reference repos" section (now points at WB as the rendering BASE) and the workflow rules **Phase N.1 commit history (just shipped):** read `git log --oneline c8782c9..ad8b931` to see how N.0 + N.1 were structured. The pattern repeats for N.3. ## What N.3 is Replace acdream's texture decoding pipeline with WorldBuilder's `Chorizite.OpenGLSDLBackend.Lib.TextureHelpers`. WB handles INDEX16, P8, BGRA, DXT, and alpha-channel decoding. Our existing implementations of these are scattered across `src/AcDream.App/Rendering/TextureCache.cs` and possibly `src/AcDream.Core/Meshing/` — find them with `grep -rln "INDEX16\|P8 decode\|DXT\|BGRA" src/`. ## Acceptance criteria - Build green (`dotnet build`) - All existing tests green (the 8 pre-existing `DispatcherToMovementIntegrationTests` failures don't count — they exist on main) - New conformance tests added per format that's substituted (one xUnit Theory per: INDEX16, P8, BGRA, DXT). Each compares a fixed input byte array decoded by our path vs WB's path; assertions on output pixel array. - Visual verification at Holtburg (or wherever) shows no texture regressions: terrain texturing, mesh texturing, particle textures all look the same. - ISSUES.md updated with any known cosmetic deltas (the N.1 pattern — if WB and retail disagree on something subtle, file it, don't try to fix it inline). ## Tasks (suggested decomposition) Follow the N.1 plan structure (`docs/superpowers/plans/2026-05-08-phase-n1-scenery-via-wb-helpers.md`) as the template. Concretely: 1. **Audit our texture decode paths.** Grep, list every file/method that decodes a texture. Map each to the WB equivalent in `references/WorldBuilder/Chorizite.OpenGLSDLBackend/Lib/TextureHelpers.cs` (read it end to end first). 2. **Per-format conformance test.** TDD style: write the test, run it to fail, then plumb the substitution. Conformance test fixture inputs should include real-dat byte sequences (read a known-good texture from a dat, encode the bytes as a hex blob in the test). 3. **Substitution.** Replace each decode site with the WB call. Keep our GL upload pathways — those are NOT WB's responsibility. 4. **Visual verification.** Launch the client at Holtburg, walk around, look at a tree (mesh texture), the ground (atlas texture), particles (the recent C.1 rain/clouds/aurora work), and a building (composite texture). Compare against retail or against a screenshot before the change. 5. **Delete legacy decoders** once visual verification passes. 6. **Update roadmap + ISSUES** as the final commit. ## Watchouts (lessons from N.1) - **ACME has a downstream fork with extra filters** (`references/WorldBuilder-ACME-Edition/`). WB's `TextureHelpers` may have ACME-specific patches not yet in upstream. Compare both before assuming WB's version is canonical. We forked upstream WB; ACME is reference-only. - **Conformance tests are non-negotiable.** Phase N.1's rotation bug was caught by the conformance test. Don't skip them. If a test fails, it's a real divergence — investigate before "fixing" the test. - **Whackamole stops the migration.** If 3+ visual regressions appear on default-on, stop, file as ISSUES, ship. The migration goal is "use WB's tested code"; pixel-perfect equivalence with our broken hand-ports is not the goal. - **`Setup.SortingSphere` ≠ `Setup.CylSphere`.** The N.1 attempt at `obj_within_block` over-suppressed because we used the wrong radius source (sorting sphere too large). For texture decoding this likely doesn't matter, but the general lesson is: read WB's full source carefully before adapting; don't assume parallel methods do parallel things. - **Per-vertex road check — STOP signal.** If you find yourself reading ACME for "what's missing" and considering a per-vertex filter, STOP. N.1 tried this (commit `e279c46`), regressed visually, reverted in `677a726`. ACME's filter set works as a coherent unit; pick-and-choose fails. If the N.3 work uncovers a similar ACME-only filter, file it in ISSUES and move on, don't port it inline. ## Where to start 1. `git pull` on main to get the latest (Phase N.1 just merged). 2. Create a new worktree for the work: `git worktree add .claude/worktrees/ -b claude/`. 3. Read the three "read first" docs above. 4. Run `dotnet build && dotnet test` to confirm clean baseline. 5. Read `references/WorldBuilder/Chorizite.OpenGLSDLBackend/Lib/TextureHelpers.cs` end to end. Take notes on the public API surface. 6. Run the audit task (#1 in Tasks above). Output should be a markdown table of "our function / file:line / WB equivalent / format covered." 7. Use `superpowers:writing-plans` to convert the audit into a concrete per-format plan. Then use `superpowers:subagent-driven-development` to execute it with fresh subagents per format. ## Useful greps - `grep -rln "INDEX16\|IndexedSurface\|P8\|DXT\|BGRA\|TextureFormat" src/` — find decode paths - `grep -rln "TextureCache" src/` — find our cache layer - `grep -n "public static.*Decode\|public static.*Convert" references/WorldBuilder/Chorizite.OpenGLSDLBackend/Lib/TextureHelpers.cs` — WB's public API ## Open question to resolve early Does `Chorizite.OpenGLSDLBackend.Lib.TextureHelpers` cover ALL the formats we use, or does it have gaps? Audit our texture types against WB's API in step 1. If WB is missing a format we need, the migration for that format gets deferred (file in ISSUES; keep our decoder for it; note in the roadmap).