# acdream — strategic roadmap **Status:** Living document. Updated 2026-04-11 after Phase 6, 7.1, 9.1, 9.2 landed. **Purpose:** One source of truth for where the project is and where it's going. Every observed defect or missing feature has a named phase that owns it; when something looks wrong in-game, look here to find the phase that'll address it. Implementation details live in per-phase specs under `docs/superpowers/specs/`, not in this file. --- ## Phases already shipped | Phase | What landed | Verification | |---|---|---| | 1 | Terrain rendering, plugin host scaffold | Visual ✓ | | 2a | Static stabs/buildings (126 entities) | Visual ✓ | | 2b | Textured 3×3 landblock grid + FlyCamera + IGameState | Visual ✓ | | 2c | Procedural scenery (419 trees/rocks/bushes) | Visual ✓ | | 2d | Interior EnvCell walker (475 static interior objects) | Visual ✓ | | 3a/3b | Directional sun lighting + per-vertex terrain normals | Visual ✓ | | 3c | Per-cell terrain texture blending (alpha atlas) | Visual ✓ | | 4 | Full UDP codec + handshake + character login + WorldSession | Live ✓ | | 5 | ObjDesc: AnimPartChange + TextureChanges + SubPalettes + ObjScale + Placement.Resting | Live ✓ | | 6.1 | Idle motion frame resolution (MotionResolver MVP) | Live ✓ | | 6.2 | Server-sent `MovementData` stance + forward command honored | Live ✓ | | 6.3 | Server-supplied `MotionTableId` override (fixes drudge statue) | Live ✓ | | 6.4 | Per-frame animation playback (breathing, idle cycles) | Live ✓ | | 6.5 | Slerp between keyframes for smooth animation | Live ✓ | | 6.6 | `UpdateMotion` (0xF74C) parser + dispatch to animation tick | Live ✓ | | 6.7 | `UpdatePosition` (0xF748) parser + position reseating | Live ✓ | | 7.1 | EnvCell room geometry — walls/floors/ceilings via CellStruct + Environment dats | Visual ✓ | | 9.1 | Translucent render pass (AlphaBlend / Additive / InvAlpha + per-kind blend funcs) | Visual ✓ | | 9.2 | Back-face culling in translucent pass (fixes lifestone crystal) | Visual ✓ | | A.1 | Streaming landblock loader — runtime-configurable visible window (default 5×5, `ACDREAM_STREAM_RADIUS`), camera-centered offline / player-centered live, hysteresis-based unloads, pending-spawn list for late CreateObject events | Live ✓ | | A.2 | Frustum culling — per-landblock AABB test (Gribb-Hartmann), terrain + static-mesh renderers skip culled landblocks, perf overlay in window title | Visual ✓ | | A.3 | Background net receive thread — dedicated daemon thread buffers UDP into Channel, render thread drains | Visual ✓ | | B.3 | Physics collision engine — TerrainSurface (heightmap Z), CellSurface (indoor floor polygon projection), PhysicsEngine (resolver with step-height + cell transitions). Populated from streaming pipeline. | Tests ✓ | | B.2 | Player movement mode — Tab-toggled WASD ground walking, walk/run/idle animations, third-person chase camera, MoveToState + AutonomousPosition outbound, portal entry. Outdoor-only MVP. | Live ✓ | Plus polish that doesn't get its own phase number: - FlyCamera default speed lowered + Shift-to-boost - SurfaceDecoder: PFID_P8 / PFID_R8G8B8 / PFID_X8R8G8B8 decoders - GfxObjMesh: emit both pos and neg sides of double-sided polygons - EnvCell mesh Z-lift to fix ground-floor / terrain flicker --- ## Phases ahead — agreed order ### Phase A — Foundation (in progress) **Goal:** walk across 10+ landblocks without crashes, without hitches at landblock boundaries, and without framerate cratering. **Sub-pieces:** - **✓ SHIPPED — A.1 — Streaming landblock loader.** Runtime-configurable visible window (default 5×5, `ACDREAM_STREAM_RADIUS` env var override). Center follows the fly camera offline and the server-sent player position in live mode. Currently runs **synchronously** on the render thread — the original async-worker design hit DatCollection's lack of thread safety and was reverted for correctness. The Channel-based outbox API is preserved so async loading can return cleanly when `Phase A.3` introduces a thread-safe dat wrapper. Pending-spawn list in `GpuWorldState` parks live `CreateObject` events whose target landblock hasn't been streamed in yet and back-fills them when it arrives, so spawn-vs-streaming races are no longer racy at all. `MaxCompletionsPerFrame=4` spreads the 5×5 first-frame load over ~7 frames (~116ms) to avoid GPU OOM. - **✓ SHIPPED — A.2 — Frustum culling.** Per-landblock AABB test (Gribb-Hartmann plane extraction + positive-vertex AABB test) in both `TerrainRenderer.Draw` and `StaticMeshRenderer.Draw`. Per-entity culling deferred. LOD deferred to Phase C. Performance overlay in window title shows FPS, frame time, visible/total landblock ratio, entity count, animated count. ~160fps uncapped at 5×5 radius. - **✓ SHIPPED — A.3 — Background net receive thread.** Dedicated daemon thread continuously pulls raw UDP datagrams from the kernel buffer into a `Channel`. Render thread's `Tick()` drains the channel. All decode, fragment assembly, ISAAC crypto, event dispatch, and ack-sending remain on the render thread — minimal change that prevents packet drops during frame stalls. Thread starts after `EnterWorld()` completes; `PumpOnce()` during handshake still reads the socket directly. - **A.4 — Async dat decoding.** Folded into the streaming worker — it's the worker's read path, not a separate subsystem. Called out here because regressions in dat caching could land on this surface. **Acceptance:** - Walk across 10+ landblocks in any direction, no crashes, no empty voids. - Landblock-boundary crossings produce no visible hitch. - Runtime window radius toggleable via environment variable. **Detailed spec:** `docs/superpowers/specs/2026-04-11-foundation-phase-design.md` --- ### Phase B — Gameplay / interaction **Goal:** actually play the game — walk the character on the server, click NPCs, pick up items, chat, basic combat loop. **Sub-pieces:** - **✓ SHIPPED — B.1 — Outbound ack pump.** Shipped as Phase 4.9 — per-packet ACK_SEQUENCE, not periodic. Server no longer drops idle clients. - **✓ SHIPPED — B.2 — Player movement mode.** Tab-toggled WASD ground walking with collision-resolved outdoor terrain, walk/run/idle/turn-right animations, third-person chase camera, outbound MoveToState (0xF61C) + AutonomousPosition (0xF753) server messages, portal entry works. Outdoor→indoor transition disabled for MVP (CellSurface floor polygons too aggressive without portal-based detection). Minor polish remaining: strafe animation, turn-left animation. Spec: `docs/superpowers/specs/2026-04-12-player-movement-design.md`. - **✓ SHIPPED — B.3 — Physics collision engine.** TerrainSurface (heightmap bilinear Z), CellSurface (indoor floor polygon projection via barycentric interpolation), PhysicsEngine (top-level resolver with step-height enforcement, outdoor↔indoor cell transitions, gravity reporting). Populated from streaming pipeline. 16 unit tests with fake data. Spec: `docs/superpowers/specs/2026-04-12-physics-collision-engine-design.md`. - **B.4 — `Use` / `UseWithTarget` / `PickUp`.** Outbound interaction messages. Drives opening doors, looting, talking to vendors. - **B.5 — Chat.** `SendTell`, `SendChat` outbound + receive/display inbound (display side depends on Phase D.1). **References:** - `references/ACE/Source/ACE.Server/Network/Handlers/MovementHandler.cs` - `references/ACE/Source/ACE.Server/Network/Handlers/UseObjectHandler.cs` - `references/holtburger/src/session/send.rs` for outbound packet-building patterns **Acceptance:** walk on-server with your character, open a door, talk to an NPC, send a chat message and see the echo. --- ### Phase C — Polish / visuals **Goal:** close the visible gaps that make the world read as "old / broken" compared to retail. **Sub-pieces:** - **C.1 — VFX / particle system.** `PhysicsScript` parser, per-entity `ParticleEmitter` state, billboarded-quad particle renderer that lives in the Phase 9.1/9.2 translucent pass. Delivers **portal swirls, chimney smoke, and fireplace flames** in one implementation. - **C.2 — Dynamic point lights.** Fireplaces and lamps need local lighting; small upgrade to the mesh shader to accumulate N (e.g., 4) nearest point lights per draw. Uniform-buffer or UBO-friendly layout. - **C.3 — Palette range tuning.** Small per-range offset/length tweaks to match retail skin/hair/eye colors. Mostly diff and verify work, no architecture change. - **C.4 — Double-sided translucent polys.** Edge case left by Phase 9.2: neg-side translucent polys are culled because cull is always BACK. Fix by tracking per-sub-mesh `CullMode` and flipping GL state per draw (or drawing twice with opposite cull). Minor. - **C.5 — Shadow mapping (optional).** Deferred unless it becomes a bottleneck in screenshots — dynamic shadows are a known complexity trap. **References:** - `references/ACE/Source/ACE.DatLoader/FileTypes/PhysicsScript.cs` for the emitter schema - `references/ACViewer/ACViewer/Physics/Particles/` for the visual model - `references/WorldBuilder/Chorizite.OpenGLSDLBackend/Lib/ParticleBatcher.cs` for the Silk.NET-flavored implementation **Acceptance:** portals look like swirly gates, chimneys smoke, fireplaces burn, character skin matches retail screenshots. --- ### Phase D — UI / HUD + Sound **Goal:** chat window, nameplates, inventory, and audio. Can run concurrently with Phase B or C because it doesn't touch gameplay/net/rendering surfaces. **Sub-pieces:** - **D.1 — 2D ortho overlay + font rendering.** Separate shader and render pass drawn after 3D. Font: FreeType via Silk.NET bindings, or bitmap fonts as a simpler first pass. - **D.2 — Chat window + nameplates.** First UI widgets. Chat consumes Phase B.5 messages; nameplates render per-entity 3D-to-2D projected labels. - **D.3 — Inventory / character / spell panels.** Requires a widget framework (layout, focus, input routing). Scope unbounded — ship minimum viable first. - **D.4 — Sound.** `SoundTable` parser, `Sound` dat decode, audio engine (OpenAL via Silk.NET.OpenAL), per-entity 3D positional audio, optional music. **Acceptance:** see other players' chat in a chat window, see nameplates above NPCs, hear footsteps and sword hits. --- ### Phase E — Long-tail Not detailed here; each gets its own brainstorm when it becomes relevant. - **Dungeon landblocks** (`0xAAAA0000` family) + teleport-on-door-click + server-side portal handling - **Phase 7.2 multi-floor stair walking** — cells reachable via portals the cell-walker doesn't cross - **Player character full rig** (held weapons, spell effects, death/revive animation) - **Weather + day/night cycle** - **Spellcasting pipeline** - **Group/fellowship UI** --- ## Cross-cutting work tracked in parallel - **Test coverage.** Each phase lands with unit + integration tests in `tests/`. Current count: 98 Core + 96 Core.Net = 194. Keep the ratio as new phases land. - **Memory files.** Project state under `memory/project_phase_*_state.md` is updated when a phase ships. `MEMORY.md` is the index. - **`CLAUDE.md` discipline.** Check all four references (ACE, ACViewer, WorldBuilder, Chorizite) before committing to an approach. WorldBuilder is the closest stack match and should be checked first. --- ## Explicitly out of scope - **Server emulation** — we use ACE for server, never reimplement. - **Account creation** — direct user to ACE tooling. - **Anti-cheat / GM tools / live-ops** — irrelevant for personal use. - **Cross-platform support** — Windows-only; the dat path assumptions depend on retail Windows install layout. Silk.NET is cross-platform but we don't promise. - **Custom game content** — this is a client for existing AC data, not a toolchain. --- ## "When will my specific complaint be fixed?" — quick lookup | Observation | Phase | |---|---| | Drudge statue in wrong pose | **6.3 FIXED** ✓ | | Characters in T-pose / wrong idle | **6.1 FIXED** ✓ | | No breathing on NPCs | **6.4 + sentinel fix FIXED** ✓ | | Lifestone crystal has one side missing | **9.2 FIXED** ✓ | | Ground floor flickering with terrain | **7.1 FIXED** ✓ | | Houses missing second floors / walls | **7.1 FIXED** ✓ (interior mesh landed) | | Character clothing missing / wrong | **5 FIXED** ✓ | | Statue wrong color / wrong scale | **5 FIXED** ✓ | | Holtburg sign half-buried | **5 FIXED** ✓ | | Can't walk past the loaded 3×3 window | **A.1 FIXED** ✓ (5×5 default, `ACDREAM_STREAM_RADIUS` to tune) | | Frame hitch crossing landblock boundary | **Phase A.3** (synchronous loader for now; async returns when DatCollection is thread-safe) | | Walking around doesn't move me on the server | **Phase B (Gameplay)** | | Can't talk to NPCs | **Phase B** | | Can't open a door | **Phase B** | | Portals render as a rotating black disk | **Phase C.1 (VFX)** | | Chimneys have no smoke | **Phase C.1** | | Houses have no fireplace fire | **Phase C.1** | | No fireplace / torch lighting | **Phase C.2** | | Skin/hair color slightly off | **Phase C.3** | | No chat window | **Phase D.2** | | No sound | **Phase D.4** | | Dungeons / foundry interior missing | **Phase E** | If you see something not on this list, add it here and assign a phase.