docs: roadmap N.0 shipped + realistic N.2-N.9 estimates + N.3 handoff
Roadmap updates after Phase N.1 ship:
- Marks N.0 (submodule + project refs setup) as ✓ SHIPPED with the
c8782c9 commit reference
- Updates N.2-N.9 effort estimates with realistic post-N.1 numbers
(originals were 1-2 days / 1 week / 2 weeks; realistic numbers
factor in conformance-test discovery, ACME-vs-Chorizite delta
hunts, and the visual-verification-then-revert cycle that ate
most of N.1's calendar time)
- Adds a "Lessons from N.1" subsection so future N phases benefit
from the rotation-bug-conformance-test pattern, the ACME divergence
insight, and the "whackamole = stop" rule
- Updates total calendar estimate to 3-4 months / 10-12 engineering
weeks for N.2-N.9 (was 2-3 months / 6-8 weeks)
New handoff doc at docs/research/2026-05-08-phase-n3-handoff.md
captures everything a fresh agent picking up N.3 (texture decoding)
needs: phase context, what to read first, suggested task decomposition,
watchouts (especially the ACME-divergence and conformance-test
lessons), and where to start.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
ad8b931be7
commit
6010827b21
2 changed files with 192 additions and 11 deletions
|
|
@ -530,9 +530,39 @@ submodule replacing `references/WorldBuilder/` snapshot, project
|
||||||
references in our solution. Long-lived `acdream` branch in the fork
|
references in our solution. Long-lived `acdream` branch in the fork
|
||||||
for our deletions/additions; merge upstream `master` periodically.
|
for our deletions/additions; merge upstream `master` periodically.
|
||||||
|
|
||||||
|
**Lessons from N.1 (apply to N.2-N.10):**
|
||||||
|
|
||||||
|
1. **Per-helper conformance tests work.** The N.1 conformance test caught a
|
||||||
|
~180° rotation bug in our retail port that had been silently wrong
|
||||||
|
forever. Write the conformance test BEFORE the substitution in each
|
||||||
|
sub-phase.
|
||||||
|
|
||||||
|
2. **ACME ≠ Chorizite/WorldBuilder.** ACME is a downstream fork of WB with
|
||||||
|
additional retail-faithful filters that upstream WB (our submodule)
|
||||||
|
doesn't have. When a visual discrepancy appears, check ACME's source
|
||||||
|
(`references/WorldBuilder-ACME-Edition/`) for delta filters BEFORE
|
||||||
|
investigating retail decomp directly. ACME's deltas tend to come as
|
||||||
|
coherent units — porting one filter without its companions can
|
||||||
|
over-suppress.
|
||||||
|
|
||||||
|
3. **"Whackamole" is the warning sign.** If a phase generates 3+ visual
|
||||||
|
regressions on default-on, stop, accept the cosmetic deltas as
|
||||||
|
ISSUES.md entries, ship the migration. Bugs we leave behind are
|
||||||
|
debuggable; bugs we never ship are forgotten.
|
||||||
|
|
||||||
|
4. **Subagent-driven execution holds up at this scope.** Fresh subagent
|
||||||
|
per task with the full task text inline keeps quality high without
|
||||||
|
polluting the controller's context. Each task should be self-contained
|
||||||
|
enough that a subagent without session history can complete it.
|
||||||
|
|
||||||
**Sub-phases (strangler-fig with feature flags):**
|
**Sub-phases (strangler-fig with feature flags):**
|
||||||
|
|
||||||
- **N.0 — Setup.** Submodule + project references + build green. ~1-2 hrs.
|
- **✓ SHIPPED — N.0 — Setup.** Shipped 2026-05-08 (commit `c8782c9`).
|
||||||
|
WorldBuilder fork at `github.com/eriknihlen/WorldBuilder.git` registered
|
||||||
|
as git submodule at `references/WorldBuilder/` tracking the `acdream`
|
||||||
|
branch. `AcDream.Core.csproj` references `WorldBuilder.Shared` +
|
||||||
|
`Chorizite.OpenGLSDLBackend`. Build green, all 28 scenery/terrain tests
|
||||||
|
passing.
|
||||||
- **✓ SHIPPED — N.1 — Scenery algorithm calls.** Shipped 2026-05-08.
|
- **✓ SHIPPED — N.1 — Scenery algorithm calls.** Shipped 2026-05-08.
|
||||||
Replaced `IsOnRoad` / `DisplaceObject` / slope-normal calc / rotation /
|
Replaced `IsOnRoad` / `DisplaceObject` / slope-normal calc / rotation /
|
||||||
scale inside `SceneryGenerator.Generate()` with calls to WB's
|
scale inside `SceneryGenerator.Generate()` with calls to WB's
|
||||||
|
|
@ -545,31 +575,50 @@ for our deletions/additions; merge upstream `master` periodically.
|
||||||
(road-edge tree at landblock 0xA9B1).
|
(road-edge tree at landblock 0xA9B1).
|
||||||
- **N.2 — Terrain math helpers.** Refactor `TerrainSurface.SampleZ` /
|
- **N.2 — Terrain math helpers.** Refactor `TerrainSurface.SampleZ` /
|
||||||
`SampleNormal` / `SampleSurface` to call WB's `TerrainUtils.GetHeight`
|
`SampleNormal` / `SampleSurface` to call WB's `TerrainUtils.GetHeight`
|
||||||
/ `GetNormal` internally. ~1-2 days.
|
/ `GetNormal` internally. ~1-2 days. Smallest remaining N phase, low
|
||||||
- **N.3 — Texture decoding.** Replace `TextureCache` decode pipeline
|
risk after N.1's conformance proof on GetNormal.
|
||||||
with WB's `TextureHelpers`. ~2-3 days.
|
- **N.3 — Texture decoding.** Replace our `TextureCache` decode
|
||||||
|
pipeline (`src/AcDream.App/Rendering/TextureCache.cs`) with WB's
|
||||||
|
`TextureHelpers` (INDEX16, P8, BGRA, DXT, alpha). Touches every
|
||||||
|
texture path. **Realistic estimate: 3-5 days** (was 2-3) — the GL
|
||||||
|
upload path needs adapting and we'll need conformance tests per
|
||||||
|
texture format. Handoff doc:
|
||||||
|
`docs/research/2026-05-08-phase-n3-handoff.md`.
|
||||||
- **N.4 — Object meshing.** Replace `SetupMesh.cs` + `GfxObjMesh.cs`
|
- **N.4 — Object meshing.** Replace `SetupMesh.cs` + `GfxObjMesh.cs`
|
||||||
with calls to WB's `ObjectMeshManager`. Character-appearance
|
with calls to WB's `ObjectMeshManager`. Character-appearance
|
||||||
behaviors (CreaturePalette / GfxObjRemapping / HiddenParts) remain
|
behaviors (CreaturePalette / GfxObjRemapping / HiddenParts) remain
|
||||||
ours — ACME is the secondary oracle. ~1 week.
|
ours — ACME is the secondary oracle. **Realistic estimate: 1.5-2
|
||||||
|
weeks** (was 1) — character appearance edge cases like N.1's
|
||||||
|
rotation bug will surface.
|
||||||
- **N.5 — Terrain rendering.** Replace `TerrainChunkRenderer` +
|
- **N.5 — Terrain rendering.** Replace `TerrainChunkRenderer` +
|
||||||
`TerrainAtlas` + `TerrainBlending` with WB's `TerrainRenderManager` +
|
`TerrainAtlas` + `TerrainBlending` with WB's `TerrainRenderManager` +
|
||||||
`LandSurfaceManager` + `TerrainGeometryGenerator`. ~2 weeks.
|
`LandSurfaceManager` + `TerrainGeometryGenerator`. **Realistic
|
||||||
|
estimate: 3-4 weeks** (was 2) — largest single phase, GPU-buffer
|
||||||
|
ownership shifts, integration with our streaming loader is
|
||||||
|
non-trivial.
|
||||||
- **N.6 — Static objects rendering.** Replace `StaticMeshRenderer` +
|
- **N.6 — Static objects rendering.** Replace `StaticMeshRenderer` +
|
||||||
`InstancedMeshRenderer` with WB's `StaticObjectRenderManager`.
|
`InstancedMeshRenderer` with WB's `StaticObjectRenderManager`.
|
||||||
~2 weeks.
|
**Realistic estimate: 2-3 weeks** (was 2) — interacts with N.4
|
||||||
|
output.
|
||||||
- **N.7 — EnvCells / dungeons.** Replace EnvCell rendering with WB's
|
- **N.7 — EnvCells / dungeons.** Replace EnvCell rendering with WB's
|
||||||
`EnvCellRenderManager` + `PortalRenderManager`. ~2 weeks.
|
`EnvCellRenderManager` + `PortalRenderManager`. **Realistic
|
||||||
|
estimate: 2-3 weeks** (was 2).
|
||||||
- **N.8 — Sky + particles.** Replace sky rendering + particle pipeline
|
- **N.8 — Sky + particles.** Replace sky rendering + particle pipeline
|
||||||
(#36 / C.1 work) with WB's `SkyboxRenderManager` +
|
(#36 / C.1 work) with WB's `SkyboxRenderManager` +
|
||||||
`ParticleEmitterRenderer`. ~1 week.
|
`ParticleEmitterRenderer`. **Realistic estimate: 1.5-2 weeks**
|
||||||
|
(was 1) — visual continuity matters; we just shipped C.1 and that
|
||||||
|
work flows through here.
|
||||||
- **N.9 — Visibility / culling.** Replace `CellVisibility` +
|
- **N.9 — Visibility / culling.** Replace `CellVisibility` +
|
||||||
`FrustumCuller` with WB's `VisibilityManager`. ~3-5 days.
|
`FrustumCuller` with WB's `VisibilityManager`. **Realistic
|
||||||
|
estimate: 1 week** (was 3-5 days) — affects perf and what gets
|
||||||
|
drawn.
|
||||||
- **N.10 — GL infrastructure consolidation (optional).** Replace our
|
- **N.10 — GL infrastructure consolidation (optional).** Replace our
|
||||||
`Shader` / `TextureCache` / `SamplerCache` plumbing with WB's
|
`Shader` / `TextureCache` / `SamplerCache` plumbing with WB's
|
||||||
`ManagedGL*` wrappers + `OpenGLGraphicsDevice`. ~1 week.
|
`ManagedGL*` wrappers + `OpenGLGraphicsDevice`. ~1 week.
|
||||||
|
|
||||||
**Estimated calendar:** 2-3 months. Engineering effort: 6-8 weeks.
|
**Estimated calendar:** **3-4 months / 10-12 engineering weeks for
|
||||||
|
N.2-N.9 (skipping N.10).** (Was 2-3 months / 6-8 weeks — revised
|
||||||
|
upward after N.1 landed; realistic per-phase numbers above.)
|
||||||
|
|
||||||
**Each sub-phase:**
|
**Each sub-phase:**
|
||||||
- Ships behind `ACDREAM_USE_WB_<NAME>=1` flag.
|
- Ships behind `ACDREAM_USE_WB_<NAME>=1` flag.
|
||||||
|
|
|
||||||
132
docs/research/2026-05-08-phase-n3-handoff.md
Normal file
132
docs/research/2026-05-08-phase-n3-handoff.md
Normal file
|
|
@ -0,0 +1,132 @@
|
||||||
|
# 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/<your-name> -b claude/<your-name>`.
|
||||||
|
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).
|
||||||
Loading…
Add table
Add a link
Reference in a new issue