Adds two design docs and a roadmap entry for the strategic shift from "port retail rendering algorithms ourselves" to "depend on a fork of Chorizite/WorldBuilder for rendering + dat-handling." - docs/superpowers/specs/2026-05-08-phase-n-worldbuilder-migration-design.md — parent design: integration model (fork + submodule), 10 sub-phases (N.0 setup through N.10 GL consolidation), strangler-fig phasing with per-phase feature flags, retail-decomp boundary clarified for what WB does NOT cover (network, physics, animation, motion, UI, plugin, audio, chat). - docs/superpowers/specs/2026-05-08-phase-n1-scenery-via-wb-helpers-design.md — N.1 detailed design: replace IsOnRoad / DisplaceObject / slope-normal calc / rotation / scale inside SceneryGenerator.Generate() with calls to WB's SceneryHelpers + TerrainUtils. Keep data flow, ScenerySpawn shape, and renderer integration. Add small LandBlock → TerrainEntry[] adapter. Feature flag ACDREAM_USE_WB_SCENERY=1. - docs/plans/2026-04-11-roadmap.md — Phase N entry added between Phase M and Phase J. Lists all 10 sub-phases with effort estimates. Fork already created at https://github.com/eriknihlen/WorldBuilder. N.0 setup (replace references/WorldBuilder/ snapshot with submodule, add project references, build green) is the next implementation step. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
9.9 KiB
Phase N — WorldBuilder Rendering Migration: Design
Date: 2026-05-08 Status: Design complete, awaiting plan generation for N.1.
Goal
Stop re-porting AC-specific rendering and dat-handling algorithms from
retail decomp. Instead, depend on a fork of WorldBuilder
(github.com/Chorizite/WorldBuilder, MIT) for terrain, scenery, static
objects, EnvCells, portals, sky, particles, texture decoding, mesh
extraction, and visibility / culling. Acdream keeps its own network,
physics, animation, motion, UI, plugin, audio, and chat layers — those
are not in WorldBuilder.
Why
acdream has accumulated a recurring pattern of subtle porting bugs in
its own rendering algorithms (the latest: a tree near the road at
landblock 0xA9B1 that retail and WorldBuilder do not show but our
re-port did, despite the algorithm code looking byte-identical to
WorldBuilder's). The triangle-Z bug, the hover-over-terrain bug, and
the edge-vertex spawn bug are all in the same family: small porting
errors that survive surface-level review.
WorldBuilder is verified by visual inspection to render the AC world correctly. It uses the same Silk.NET + .NET stack we already target. It is MIT-licensed. It has fewer subtle bugs because its developers have run it against the entire client_cell + client_portal dat content and fixed everything users have reported.
The cost of "we re-port retail algorithms ourselves" is now higher than the cost of "we depend on someone else's tested port and inherit their fixes." Migrating the rendering+dat layer to WorldBuilder is the right call.
Inventory reference
The full taxonomy of "what WorldBuilder has, what we keep porting
ourselves" lives at
docs/architecture/worldbuilder-inventory.md.
Before re-implementing any rendering or dat-handling algorithm, check
the inventory first. CLAUDE.md is updated to enforce this.
Architecture
Integration model
Fork upstream WorldBuilder, depend on the fork via git submodule.
- Fork:
https://github.com/eriknihlen/WorldBuilder(already created; upstream:Chorizite/WorldBuilder). - Long-lived branch in fork:
acdream. Upstreammastermerges intoacdreamperiodically; our acdream-specific changes (delete editor files, expose hooks for our scene state) live onacdream. - The current read-only snapshot at
references/WorldBuilder/is replaced by a git submodule pointing at the fork'sacdreambranch. Existing CLAUDE.md path references and research docs that citereferences/WorldBuilder/...keep working. - Our solution adds two
<ProjectReference>s:references/WorldBuilder/Chorizite.OpenGLSDLBackend/Chorizite.OpenGLSDLBackend.csprojreferences/WorldBuilder/WorldBuilder.Shared/WorldBuilder.Shared.csproj
- Transitive NuGet dependencies (
Chorizite.Core,Chorizite.DatReaderWriter.Extensions,BCnEncoder.Net,SixLabors.ImageSharp,Silk.NET.SDL,MP3Sharp) flow through. - Editor-only files in WorldBuilder (Modules/Landscape/{Tools, Commands, Services, Migrations, Hubs}, LandscapeDocument, etc.) stay in the fork's source tree but are simply not referenced by acdream. They impose no runtime cost. We can prune later if upstream stays well-organized.
Phasing — strangler fig, subsystem by subsystem
Each sub-phase is independently shippable behind a feature flag
(ACDREAM_USE_WB_<NAME>=1). After visual verification the flag becomes
default-on, then is removed and the old code is deleted. This gives us
a one-line revert if a phase regresses.
| # | Sub-phase | Effort | Risk |
|---|---|---|---|
| N.0 | Submodule + project references + build green | 1-2 hrs | Low |
| N.1 | Scenery algorithm calls | 1-2 days | Low |
| N.2 | Terrain math helpers | 1-2 days | Low |
| N.3 | Texture decoding | 2-3 days | Medium |
| N.4 | Object meshing (Setup/GfxObj) | 1 week | Medium |
| N.5 | Terrain rendering (full pipeline) | 2 weeks | High |
| N.6 | Static objects rendering | 2 weeks | High |
| N.7 | EnvCells / dungeons | 2 weeks | High |
| N.8 | Sky + particles | 1 week | Medium |
| N.9 | Visibility / culling | 3-5 days | Medium |
| N.10 | GL infrastructure consolidation (optional) | 1 week | Medium |
Total estimated calendar: 2-3 months. Engineering effort: 6-8 weeks.
What WorldBuilder does NOT cover (keep porting from retail decomp)
- Network protocol (UDP, ISAAC, ACE messages) — keep ours
- Physics: collision, BSP queries, sphere sweeps, walkable validation — keep ours (partial), continue porting from retail decomp
- Animation: motion sequencer, cycle/non-cycle parts — keep ours
- Movement: WASD → MoveToState wire, remote-entity motion via UpdateMotion + dead-reckoning — keep ours
- Game UI: chat, vitals, inventory, spell book — keep ours (ImGui today, custom-toolkit later)
- Plugin API: IGameState, IEvents, IActions, IPacketPipeline, IOverlay — keep ours (acdream-unique)
- Game events: combat, allegiance, spell casting — keep ours
- Audio (OpenAL pipeline) — keep ours
- TurbineChat + slash commands — keep ours
- Login + character selection flow — keep ours
Per CLAUDE.md update, these still follow the
"grep named → decompile → verify → port" workflow against retail decomp
at docs/research/named-retail/.
Network reference posture
references/Chorizite.ACProtocol/ (separate Chorizite repo) remains
the Primary Oracle for protocol field order and packed-dword
conventions per CLAUDE.md's reference table. No fork needed there. We
will lean on it harder during future network-conformance phases (Phase
M is already on the roadmap for that).
Components
N.0 — Setup (must land before N.1)
Files / actions:
- Remove
references/WorldBuilder/from working tree (it's currently a checked-in snapshot). Add it back as a submodule pointing atgit@github.com:eriknihlen/WorldBuilder.gittracking theacdreambranch (created offmaster). - Add
<ProjectReference>entries insrc/AcDream.Core/AcDream.Core.csprojandsrc/AcDream.App/AcDream.App.csprojfor the two WB projects. - Update
.gitmodulesto reflect the new submodule. - Verify
dotnet buildanddotnet testare green. - Commit.
Done criteria:
git submodule statusshowsreferences/WorldBuilderat the fork'sacdreamHEAD.- Solution builds clean with no new warnings.
- Existing 870+ tests still pass.
N.1 — Scenery algorithm calls
See companion design doc:
2026-05-08-phase-n1-scenery-via-wb-helpers-design.md.
Brief: replace the algorithm guts inside SceneryGenerator.Generate()
with calls to WB's SceneryHelpers (Displace, RotateObj, ScaleObj,
ObjAlign, CheckSlope) and TerrainUtils (OnRoad, GetNormal). Keep our
data flow, our ScenerySpawn shape, our renderer integration. Add a
small adapter LandBlock → TerrainEntry[].
N.2-N.10 — separately brainstormed when we get there
Each sub-phase will get its own brainstorm + spec when we reach it. Estimating ahead is unreliable for the bigger phases (N.5, N.6, N.7); we'll know more after N.1 ships and we have hands-on experience with the WB integration.
Risks
-
Chorizite.Core dependency footprint. Each render manager we take pulls in
Chorizite.Core.LibandChorizite.Core.Render. Mitigation: take the NuGet dep, don't try to strip it. Risk is mostly cosmetic (an extra package). -
WB's data-flow is editor-shaped.
LandscapeDocument,LandscapeChunk, etc. are editor concepts. Mitigation: write small adapters that produce the editor-shaped data from our dat reads. Phase N.1 is intentionally chosen to avoid this — we use only the stateless helpers, not the fullSceneryRenderManager. Larger phases (N.5+) will need real adapter layers. -
Upstream divergence. WB's
masterwill keep moving. Mitigation: merge upstreammasterinto ouracdreambranch periodically (at minimum, before each new phase starts). Our acdream-specific changes are isolated to deletions and additions on theacdreambranch, which merges cleanly with upstream most of the time. -
Behaviors WB doesn't have. WB is a dat editor; some in-game-only behaviors (creature appearance via CreaturePalette / GfxObjRemapping / HiddenParts) aren't in WB and we'll still need to handle them ourselves at the integration boundary. Mitigation: ACME's
StaticObjectManager.cscovers these and is documented in CLAUDE.md as the secondary oracle for character appearance. -
Visual regression during migration. Mitigation: feature flag per phase. Visual verification at known-good locations (Holtburg, Foundry statue, dungeon entrances) before flag becomes default-on.
Testing
- N.0: existing 870+ tests stay green;
dotnet buildclean. - N.1: new conformance test that runs both our
SceneryGeneratorand a parallel call into WB's helpers against the same fixture data, asserts identical spawn list. Visual verification at landblock0xA9B1— the offending tree should be gone, Issue #49's missing scenery should still be visible. - N.2-N.10: each phase will define its own conformance and visual verification criteria when brainstormed.
Documentation impact
docs/architecture/worldbuilder-inventory.md— created.CLAUDE.md— updated with new posture (top-level rule + reference table + per-domain oracle hierarchy).docs/plans/2026-04-11-roadmap.md— add Phase N entry alongside L, M, etc. (this happens in the same commit as the spec).docs/architecture/acdream-architecture.md— needs an acknowledging note that the rendering layer is now WB-backed; can follow in a later commit, not blocking.
Out of scope for this design
- Phase N.2-N.10 detailed scope (each gets own brainstorm).
- Network conformance work (separate Phase M).
- Animation, physics, motion ports (continue against retail decomp, not WB).
- UI, plugin, chat work (separate phases, not affected).