acdream/docs/superpowers/specs/2026-05-08-phase-n-worldbuilder-migration-design.md
Erik 8a06fce7a5 spec(rendering): Phase N WorldBuilder migration design + N.1 scenery
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>
2026-05-08 08:47:23 +02:00

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. Upstream master merges into acdream periodically; our acdream-specific changes (delete editor files, expose hooks for our scene state) live on acdream.
  • The current read-only snapshot at references/WorldBuilder/ is replaced by a git submodule pointing at the fork's acdream branch. Existing CLAUDE.md path references and research docs that cite references/WorldBuilder/... keep working.
  • Our solution adds two <ProjectReference>s:
    • references/WorldBuilder/Chorizite.OpenGLSDLBackend/Chorizite.OpenGLSDLBackend.csproj
    • references/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 at git@github.com:eriknihlen/WorldBuilder.git tracking the acdream branch (created off master).
  • Add <ProjectReference> entries in src/AcDream.Core/AcDream.Core.csproj and src/AcDream.App/AcDream.App.csproj for the two WB projects.
  • Update .gitmodules to reflect the new submodule.
  • Verify dotnet build and dotnet test are green.
  • Commit.

Done criteria:

  • git submodule status shows references/WorldBuilder at the fork's acdream HEAD.
  • 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

  1. Chorizite.Core dependency footprint. Each render manager we take pulls in Chorizite.Core.Lib and Chorizite.Core.Render. Mitigation: take the NuGet dep, don't try to strip it. Risk is mostly cosmetic (an extra package).

  2. 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 full SceneryRenderManager. Larger phases (N.5+) will need real adapter layers.

  3. Upstream divergence. WB's master will keep moving. Mitigation: merge upstream master into our acdream branch periodically (at minimum, before each new phase starts). Our acdream-specific changes are isolated to deletions and additions on the acdream branch, which merges cleanly with upstream most of the time.

  4. 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.cs covers these and is documented in CLAUDE.md as the secondary oracle for character appearance.

  5. 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 build clean.
  • N.1: new conformance test that runs both our SceneryGenerator and a parallel call into WB's helpers against the same fixture data, asserts identical spawn list. Visual verification at landblock 0xA9B1 — 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).