# acdream A modern open-source C# / .NET 10 Asheron's Call client. Faithful port of the retail client's behaviour to Silk.NET with a modern, plugin-friendly architecture. The code is modern; the behaviour is retail. **Status:** playable pre-alpha; M3 ("Cast a spell") is active. The connected client supports the complete M2 combat/loot/inventory loop plus retained spellbook, component-book, favorite-spell, enchantment, portal-space, radar, chat, character, and inventory UI. Current work is verification and retail conformance, not a first-playable bring-up. Start at the [documentation map](docs/README.md) for the current milestone, roadmap, tactical issues, architecture, retail-divergence register, research, and durable memory. ## Stack - **Language:** C# .NET 10 - **Graphics:** [Silk.NET](https://github.com/dotnet/Silk.NET) (OpenGL 4.3 context; `GL_ARB_bindless_texture` and `GL_ARB_shader_draw_parameters` are mandatory) - **Audio:** OpenAL via Silk.NET - **Dat parsing:** [Chorizite.DatReaderWriter](https://github.com/Chorizite/DatReaderWriter) - **Networking:** Custom UDP + ISAAC cipher + game-message layer, wire-compatible with ACEmulator server ## What works today - ACE login, character selection, world entry, chat, client commands, and graceful logout. - Outdoor, building, cellar, and dungeon streaming with portal-space travel, terrain/scenery/EnvCell rendering, collision, lighting, sky, fog, audio, and day/night presentation. - Local and observed player/NPC/monster movement, animation, selection, radar, combat stances, melee and missile presentation, death, corpses, chests, and looting. - Inventory bags, stack splitting, paperdoll/equipment, weapon switching, quick bars, item use, giving items to NPCs, and server-authoritative item movement. - Retained retail-style gameplay UI for vitals, chat, toolbar, inventory, character/skills, spellbook/components, helpful/harmful effects, combat and spell bars, radar/compass, indicator pages, and confirmation dialogs. - Spell catalog, learned/favorite spells, component preflight, connected casts, enchantments, DAT-driven missiles/effects, recall, Hidden/UnHide, and portal materialization presentation. - Plugin host, shared input/command abstractions, and permanent ImGui developer tools behind `ACDREAM_DEVTOOLS=1`. ## Active gaps - R6's complete object-frame update path still needs the next local visual comparison; the final M3 gate is a two-client portal-out/materialization observer comparison. - Issue `#225` still needs the lifestone/particle alpha-order visual check, although its connected lifetime/performance gates pass. - Narrow behavior debt remains in issue `#153` (an unstreamed far-teleport edge case), issue `#116` (slide feel), and registered TS-50/TS-51 effect timing. - Many later retail systems remain roadmap work: advanced social/vendor/trade/ crafting UI, full weather/lightning parity, deeper combat/stat systems, graphical Linux, and a true headless multi-session bot host. See [docs/README.md](docs/README.md) for document authority and current links. ## Building + running **Requires:** - .NET 10 SDK - A retail Asheron's Call dat directory (Turbine/Microsoft property — supply your own). Contains `client_portal.dat`, `client_cell_1.dat`, `client_highres.dat`, `client_local_English.dat`. - A running ACE (ACEmulator) server on `127.0.0.1:9000` (or override via env var) **Launch (PowerShell on Windows — bash has trouble with the apostrophe in "Asheron's Call"):** ```powershell $env:ACDREAM_DAT_DIR = "$env:USERPROFILE\Documents\Asheron's Call" $env:ACDREAM_LIVE = "1" $env:ACDREAM_TEST_HOST = "127.0.0.1" $env:ACDREAM_TEST_PORT = "9000" $env:ACDREAM_TEST_USER = "testaccount" $env:ACDREAM_TEST_PASS = "testpassword" $env:ACDREAM_RETAIL_UI = "1" dotnet run --project src\AcDream.App\AcDream.App.csproj -c Release ``` Offline CLI dat inspector (no server needed): ``` dotnet run --project src/AcDream.Cli -- "C:\path\to\Asheron's Call" ``` ## Diagnostic env vars | Variable | Effect | |---|---| | `ACDREAM_DUMP_SKY=1` | Per-second dump of the interpolated `SkyKeyframe` values + per-SkyObject draw info + texture alpha histograms | | `ACDREAM_DUMP_MOTION=1` | Dump every inbound `UpdateMotion` + resulting `SetCycle` | | `ACDREAM_STREAM_RADIUS=N` | Legacy override for the configured two-tier streaming radii | | `ACDREAM_NO_AUDIO=1` | Suppress OpenAL init | | `ACDREAM_RETAIL_UI=1` | Enable retained retail gameplay UI | | `ACDREAM_DEVTOOLS=1` | Enable ImGui developer tools | | `ACDREAM_UNCAPPED_RENDER=1` | Disable normal presentation pacing for throughput measurement | | `ACDREAM_DAY_GROUP=N` | Force a specific DayGroup index for A/B-testing weather presets | | `ACDREAM_RUN_SKILL=N` / `ACDREAM_JUMP_SKILL=N` | Client-side run/jump skill (default 200) | ## Layout ``` src/ AcDream.App/ window, retained UI, rendering, audio, runtime wiring AcDream.Content/ GL-free DAT mesh/texture extraction AcDream.Core/ game state, physics, movement, world, gameplay logic AcDream.Core.Net/ UDP + ISAAC + game-message layer AcDream.UI.Abstractions/ shared UI/input ViewModels, commands, contracts AcDream.UI.ImGui/ permanent developer-tool renderer AcDream.Cli/ offline dat-inspector console app AcDream.Bake/ offline content bake tooling AcDream.Plugin.Abstractions/ plugin host interfaces AcDream.Plugins.Smoke/ example plugin tests/ AcDream.*.Tests/ layer-matched xUnit projects (6,452 passing, 5 intentional skips at the 2026-07-20 baseline) tools/ RetailTimeProbe/ Win32 P/Invoke ReadProcessMemory probe of the live retail acclient.exe — dumps TimeOfDay + sky-lighting globals so we can compare against acdream's state SkyObjectInspect/ dat-inspector for Region sky objects references/ vendored read-only reference code — ACE, ACViewer, WorldBuilder, holtburger, AC2D, Chorizite, DatReaderWriter. Gitignored. docs/ README.md documentation map + authority order architecture/ architecture, structure, divergence, WB inventory plans/ phase roadmaps + per-phase specs research/ decompile-derived research, per-phase findings, deep-dive agent reports audit/ phase-completion audits ``` ## Development workflow All AC-specific behaviour is ported from the named retail client oracle (`docs/research/named-retail/`). The workflow is: 1. **Grep named retail first.** Find the matching `class::method` in the Sept 2013 named pseudo-C and headers. 2. **Decompile only as fallback.** Use the older Ghidra chunks when the named oracle lacks the function. 3. **Cross-reference.** Check against ACE's C# port and ACViewer / WorldBuilder. 4. **Write pseudocode.** Translate C to readable pseudocode first. 5. **Port faithfully.** Translate line-by-line, preserving variable names and control flow. 6. **Conformance test.** Add tests using golden values from retail. 7. **Integrate surgically.** Minimise churn in the surrounding pipeline. Guessing at AC-specific algorithms is explicitly forbidden — see `CLAUDE.md` for the full workflow rationale and the list of failure modes we've paid for in the past. ## Reference repos We cross-reference six external projects for retail behavior: - **ACE** (ACEmulator) — authoritative server-side protocol - **ACViewer** — MonoGame dat viewer; good for character appearance - **WorldBuilder** — Silk.NET dat editor; matches our stack - **Chorizite.ACProtocol** — clean-room C# protocol library - **holtburger** — most complete non-retail client; Rust TUI, full client-side behaviour - **AC2D** — C++ AC-client emulator; has the real terrain split formula and 0xF61C movement packet format See `CLAUDE.md` for which reference is authoritative for which domain. ## Licence Not yet chosen. All external reference code is vendored under its own licence; see `references/*/LICENSE`. The acdream source code itself is unreleased — not yet distributed to the public. Once the licence choice is made it will go in a top-level `LICENSE` file. The AC dat files and the game's intellectual property remain the property of Microsoft / Turbine. This project does not distribute any of those files or assets — you must supply your own retail install.