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>
223 lines
9.9 KiB
Markdown
223 lines
9.9 KiB
Markdown
# 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`](../../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`](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
|
|
|
|
- [x] `docs/architecture/worldbuilder-inventory.md` — created.
|
|
- [x] `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).
|