diff --git a/CLAUDE.md b/CLAUDE.md index c5889c16..d5439c7a 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -25,14 +25,6 @@ The codebase is organized by layer (see architecture doc). Current phase state lives in memory (`memory/project_*.md`), plans in `docs/plans/`, research in `docs/research/`. -**UI strategy:** three-layer split — swappable backend (Hexa.NET.ImGui for -Phase D.2a short-term, custom retail-look toolkit for D.2b later) / -stable `AcDream.UI.Abstractions` layer (ViewModels + Commands + `IPanel` -/ `IPanelRenderer`) / unchanged game state. **All plugin-facing UI -targets `AcDream.UI.Abstractions` — never import a backend namespace -from a panel.** Full design: `docs/plans/2026-04-24-ui-framework.md`. -Memory crib: `memory/project_ui_architecture.md`. - ## How to operate **You are the lead engineer AND architect on this project at all times.** diff --git a/docs/architecture/acdream-architecture.md b/docs/architecture/acdream-architecture.md index e5f7f856..3fb1e969 100644 --- a/docs/architecture/acdream-architecture.md +++ b/docs/architecture/acdream-architecture.md @@ -66,32 +66,6 @@ game state through well-defined interfaces that the retail client never had. └──────────────────────────────────────────────────────────────┘ ``` -### UI Architecture (companion stack, spans Layers 1 & 5) - -The UI is split into its own three-layer stack with a swappable backend, -designed 2026-04-24. Full design: `docs/plans/2026-04-24-ui-framework.md`. - -``` -┌─────────────────────────────────────────────────────────────┐ -│ UI BACKEND (swappable) │ -│ Hexa.NET.ImGui (Phase D.2a, short-term) │ -│ or custom retail-look toolkit (Phase D.2b, later) │ -├─────────────────────────────────────────────────────────────┤ -│ AcDream.UI.Abstractions (stable contract) │ -│ ViewModels, Commands, IPanel, IPanelHost, IPanelRenderer │ -│ ► plugin-facing UI API lives HERE, not in the backend │ -├─────────────────────────────────────────────────────────────┤ -│ Game state + events (unchanged) │ -│ IGameState / IEvents / WorldSession — UI only reads │ -└─────────────────────────────────────────────────────────────┘ -``` - -The backend is pluggable; ViewModels / Commands / `IPanelRenderer` are -stable across the swap. ImGui persists forever as the -`ACDREAM_DEVTOOLS=1` devtools overlay regardless of which backend owns -the game UI. See `memory/project_ui_architecture.md` for the session -crib-sheet version. - --- ## Project Structure (target) @@ -232,12 +206,6 @@ exposes them as `WorldEntitySnapshot`. GameWindow becomes thin. 6. Plugin tick └── Fire IEvents, drain IActions queue - -6a. UI tick - IPanelHost.Draw → iterate registered IPanel instances, build - ViewModels from IGameState, dispatch user Commands via ICommandBus. - Backend-agnostic — ImGui or custom retail-look draws here depending - on which is compiled in. See docs/plans/2026-04-24-ui-framework.md. ``` --- diff --git a/docs/plans/2026-04-11-roadmap.md b/docs/plans/2026-04-11-roadmap.md index 15595904..ddbced35 100644 --- a/docs/plans/2026-04-11-roadmap.md +++ b/docs/plans/2026-04-11-roadmap.md @@ -142,14 +142,17 @@ Plus polish that doesn't get its own phase number: **Sub-pieces:** - **D.1 — 2D ortho overlay + font rendering.** ✅ SHIPPED 2026-04-17 as the dev-facing debug overlay (StbTrueTypeSharp system-font atlas + `TextRenderer` + `DebugOverlay`). -- **D.2a — Hexa.NET.ImGui scaffold + `AcDream.UI.Abstractions` layer.** NEW pre-piece introduced 2026-04-24. Wires Hexa.NET.ImGui as the short-term backend behind `ACDREAM_DEVTOOLS=1`. Defines `IPanel` / `IPanelHost` / `IPanelRenderer` / `ICommandBus` + the first ViewModels (`VitalsVM` etc.) in the new `AcDream.UI.Abstractions` project. First real panel: `VitalsPanel` reading HP/stam/mana from `IGameState`. This is what gets game-logic iteration moving; looks like a debugger, acceptable. -- **D.2b — Custom retail-look backend.** Implements the same `IPanel` / `IPanelRenderer` contracts using a custom retained-mode toolkit sourced from retail dat assets. Requires D.2a shipped. Panels get reskinned one at a time; ImGui stays as the `ACDREAM_DEVTOOLS=1` overlay forever. The original 2026-04-17 scaffold research (`UiRoot` / `UiElement` / `UiPanel` / `UiHost` + retail event codes + focus / drag-drop state machine + `WorldMouseFallThrough`) is the implementation foundation here — see `docs/research/retail-ui/`. -- **D.3 — AcFont from portal.dat.** Replace stb_truetype system font with retail `Font` DBObjs (`0x40000000..0x40000FFF`) baked from `RenderSurface` source sheets — see research slice 03 §4. Preserves retail visual identity. **(D.2b dependency — needs the custom renderer.)** -- **D.4 — Dat sprites + 9-slice panel backgrounds.** Load `RenderSurface` (`0x06xxxxxx`) as GL textures; add `DrawSprite` to `UiRenderContext`. Enables retail panel art. **(D.2b dependency.)** -- **D.5 — Core panels.** Attributes (`chunk_00470000.c:FUN_0047ba70`), Skills (same), Paperdoll (`chunk_004A0000.c:FUN_004A5200`), Inventory, Spellbook (`chunk_004C0000.c`), Fellowship, Allegiance. Each uses the port sketches in slice 05. **(Targets `AcDream.UI.Abstractions` — ships with D.2a using ImGui-rendered widgets; reskinned by D.2b.)** -- **D.6 — HUD.** Vital orbs (scissor-rect partial fill, dat sprites `0x060013B2`), radar (`0x06001388` / `0x06004CC1`, 1.18× range factor), compass strip (scrolling U), target name plate, damage floaters, selection indicator. See slice 06. **(Targets `AcDream.UI.Abstractions` — ships with D.2a; reskinned by D.2b.)** -- **D.7 — Cursor manager.** OS + dat-sourced custom cursors (`FUN_0043c1c0` GDI HCURSOR builder pattern from slice 03). **(D.2b dependency.)** -- ~~**D.8 — Sound.**~~ **Superseded — shipped as Phase E.2** (`SoundTable`/`Sound` dat decode, OpenAL 16-voice engine, per-entity 3D positional audio via `AudioHookSink`). Entry kept here for history; see the shipped table. +- **D.2 — Retail UI framework + first panels.** Research + scaffold landed 2026-04-17 (see `docs/research/retail-ui/`). Ships: + - `UiRoot` + `UiElement` + `UiPanel` + `UiHost` with retail-faithful event codes (`0x01` click, `0x15` drag-begin, `0x3E` drop, `0x201` WM_LBUTTONDOWN, tooltip delay ~1000ms, etc.) + - Focus / modal / capture / drag-drop / hover state machine + - `WorldMouseFallThrough` / `WorldKeyFallThrough` preserves existing camera+player controls + - First concrete panel (chat window) uses wire messages Phase 4.7 already parses +- **D.3 — AcFont from portal.dat.** Replace stb_truetype system font with retail `Font` DBObjs (`0x40000000..0x40000FFF`) baked from `RenderSurface` source sheets — see research slice 03 §4. Preserves retail visual identity. +- **D.4 — Dat sprites + 9-slice panel backgrounds.** Load `RenderSurface` (`0x06xxxxxx`) as GL textures; add `DrawSprite` to `UiRenderContext`. Enables retail panel art. +- **D.5 — Core panels.** Attributes (`chunk_00470000.c:FUN_0047ba70`), Skills (same), Paperdoll (`chunk_004A0000.c:FUN_004A5200`), Inventory, Spellbook (`chunk_004C0000.c`), Fellowship, Allegiance. Each uses the port sketches in slice 05. +- **D.6 — HUD.** Vital orbs (scissor-rect partial fill, dat sprites `0x060013B2`), radar (`0x06001388` / `0x06004CC1`, 1.18× range factor), compass strip (scrolling U), target name plate, damage floaters, selection indicator. See slice 06. +- **D.7 — Cursor manager.** OS + dat-sourced custom cursors (`FUN_0043c1c0` GDI HCURSOR builder pattern from slice 03). +- **D.8 — Sound.** `SoundTable` parser, `Sound` dat decode, audio engine (OpenAL via Silk.NET.OpenAL), per-entity 3D positional audio, optional music. **Reference docs:** `docs/research/retail-ui/00-master-synthesis.md` + slices 01-06. Every AC-specific behavior has a decompiled FUN_ / DAT_ citation. @@ -181,7 +184,7 @@ Research: R1 + R2 + R6 + R8 + UI slices 04/05. - **F.2 — Item + inventory model.** `ItemInstance` / `Container` / `PropertyBundle`. Appraise round-trip (`0x00C8` → `0x00C9`). Burden math. See `r06-items-inventory.md` + `src/AcDream.Core/Items/`. - **F.3 — Combat math + damage flow.** Damage formula, per-body-part AL, crit, hit-chance sigmoid. Server broadcasts damage events; client displays + HP bar. See `r02-combat-system.md` + `src/AcDream.Core/Combat/`. - **F.4 — Spell cast state machine.** `SpellCastStateMachine` + active buff tracking. Buffs + recalls first, projectile spells later. Fizzle sigmoid + mana conversion. See `r01-spell-system.md` + `src/AcDream.Core/Spells/`. -- **F.5 — Core panels.** Attributes / Skills / Paperdoll / Inventory / Spellbook — using the retail-ui framework from Phase D.2. See `05-panels.md` under retail-ui. **(Targets `AcDream.UI.Abstractions`; unblocked by D.2a — ships with ImGui widgets — and reskinned when D.2b lands.)** +- **F.5 — Core panels.** Attributes / Skills / Paperdoll / Inventory / Spellbook — using the retail-ui framework from Phase D.2. See `05-panels.md` under retail-ui. **Acceptance:** equip a weapon, swing at a monster, see damage numbers, buff yourself, recall to the lifestone. @@ -199,7 +202,7 @@ Research: R9 + R12 + R13. Research: R7 + R10 + R11 + UI slice 05. -- **H.1 — Chat window.** UI panel + all 6 wire opcodes (Channel, Tell, System, HearSpeech, HearRangedSpeech, TurbineChat). *(Wire layer already shipped per the shipped table; remaining work is the panel, which targets `AcDream.UI.Abstractions` — unblocked by D.2a, reskinned when D.2b lands.)* +- **H.1 — Chat window.** UI panel + all 6 wire opcodes (Channel, Tell, System, HearSpeech, HearRangedSpeech, TurbineChat). - **H.2 — Allegiance.** Tree model + XP pass-up math + 5 allegiance chat channels + MOTD. See `r11-allegiance.md`. - **H.3 — Emote scripts + quests + dialogs.** 122 EmoteType × 39 Trigger mini-VM. Contract tracker UI. NPC dialog rendered via chat with `` markup. See `r10-quest-dialogs.md`. - **H.4 — Character creation.** `0xE000002 CharGen` dat + 13 heritages + templates + appearance picker + preview renderer. See `r07-character-creation.md`. diff --git a/docs/research/retail-ui/00-master-synthesis.md b/docs/research/retail-ui/00-master-synthesis.md index 7882a9cb..7c9975bb 100644 --- a/docs/research/retail-ui/00-master-synthesis.md +++ b/docs/research/retail-ui/00-master-synthesis.md @@ -1,16 +1,5 @@ # Retail AC Client GUI — Master Synthesis -> **Scope note (2026-04-24):** This document describes retail's Keystone -> UI toolkit — it is the research foundation for **Phase D.2b (custom -> retail-look backend)**, not **Phase D.2a (Hexa.NET.ImGui scaffold)**. -> When reading this for implementation guidance, assume D.2a has shipped -> a working `AcDream.UI.Abstractions` layer (`IPanel`, `IPanelRenderer`, -> ViewModels, Commands) and you are building the custom retained-mode -> toolkit that implements the same contracts using dat-sourced fonts / -> sprites / cursors. See `docs/plans/2026-04-24-ui-framework.md` for the -> staged UI strategy and `memory/project_ui_architecture.md` for the -> one-page crib-sheet. - **Date:** 2026-04-17 **Sources:** 6 parallel Opus research passes over the decompiled `acclient.exe` (22,225 functions / 688K lines). Individual deep dives: diff --git a/memory/project_ui_architecture.md b/memory/project_ui_architecture.md deleted file mode 100644 index 2d6240de..00000000 --- a/memory/project_ui_architecture.md +++ /dev/null @@ -1,74 +0,0 @@ -# Project: UI architecture — three-layer stable pattern - -**Agreed 2026-04-24.** Read once per session. Full design: -[`docs/plans/2026-04-24-ui-framework.md`](../docs/plans/2026-04-24-ui-framework.md). - -## The separation - -``` -┌─────────────────────────────────────────┐ -│ UI backend (ImGui today / custom later)│ ← swappable -├─────────────────────────────────────────┤ -│ ViewModels + Commands (per-panel) │ ← stable contracts -├─────────────────────────────────────────┤ -│ Game state + events + net (unchanged) │ ← game logic -└─────────────────────────────────────────┘ -``` - -- **UI backend** (bottom swap axis): `Hexa.NET.ImGui` for Phase D.2a - (short-term, debugger-look, validates game logic fast). Custom - retail-look toolkit for Phase D.2b (long-term, uses dat assets). - ImGui stays **forever** as the `ACDREAM_DEVTOOLS=1` overlay. -- **ViewModels + Commands** (the stable contract): per-panel data - records (`VitalsVM`, `InventoryVM`, `ChatVM`, …) and action records - (`UseItemCmd`, `SendChatCmd`, `CastSpellCmd`, …). Lives in - `AcDream.UI.Abstractions`. **Does not change across the backend swap.** -- **Game state + events + net**: existing `IGameState`, `IEvents`, - `WorldSession`, etc. Unchanged. UI only reads/subscribes; never - touches these. - -## Module layout (future) - -- `src/AcDream.UI.Abstractions/` — `IPanel`, `IPanelHost`, - `IPanelRenderer`, `ICommandBus`, all ViewModels + Commands. Backend- - agnostic. -- `src/AcDream.UI.ImGui/` — Hexa.NET.ImGui-based implementation of - `IPanelRenderer` + ImGui bootstrap. Phase D.2a. -- `src/AcDream.UI.Retail/` (later) — custom retained-mode toolkit using - dat assets, same `IPanelRenderer` contract. Phase D.2b. - -## Hard rules - -1. **No panel references a backend namespace.** If a panel imports - `Hexa.NET.ImGui` or a custom-toolkit widget class directly, it's a - bug. -2. **Plugin API targets the abstraction layer only.** Plugins define - `IPanel` instances; they never see which backend draws them. -3. **Features that only ImGui can express → not in `IPanelRenderer`.** - If a feature can't be expressed by a future retained-mode toolkit - with dat-sourced sprites/fonts, don't expose it in the abstraction. -4. **D.3 AcFont / D.4 dat sprites / D.7 cursor manager are D.2b - dependencies** — they plug into the custom backend only. -5. **D.5 core panels / D.6 HUD ship against the abstraction**, not - against a specific backend. They render via ImGui first, reskin - under custom later. - -## Why staged (not pure custom from day one) - -- Gets the whole game-logic loop validated in weeks: chat-send, - inventory-click, vitals-bar-read-from-real-state. Requires zero - widget art. -- Forces the abstraction design to pass a real backend test before we - commit to the custom toolkit. If `IPanelRenderer` is wrong, we - discover it during Phase D.2a, not after Phase D.2b lands with a - dozen broken panels. -- Custom retail-look toolkit then delivers the aesthetic layer without - the plugin API or game logic needing to change. - -## Links - -- Full design: `docs/plans/2026-04-24-ui-framework.md` -- Roadmap entry: `docs/plans/2026-04-11-roadmap.md` Phase D (see the - 2026-04-24 callout block). -- Custom-backend research (applies to D.2b, NOT D.2a): - `docs/research/retail-ui/00-master-synthesis.md` + slices 01-06. diff --git a/src/AcDream.App/Rendering/GameWindow.cs b/src/AcDream.App/Rendering/GameWindow.cs index cbd4b27f..44359db0 100644 --- a/src/AcDream.App/Rendering/GameWindow.cs +++ b/src/AcDream.App/Rendering/GameWindow.cs @@ -1066,21 +1066,7 @@ public sealed class GameWindow : IDisposable try { - // Resolve DNS names (e.g. play.coldeve.ac) as well as literal - // IP addresses. `IPAddress.Parse` throws on hostnames; fall - // back to `Dns.GetHostAddresses` and prefer IPv4 (ACE + retail - // use IPv4 UDP exclusively). - System.Net.IPAddress ip; - if (!System.Net.IPAddress.TryParse(host, out ip!)) - { - var addrs = System.Net.Dns.GetHostAddresses(host); - ip = System.Array.Find(addrs, - a => a.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) - ?? (addrs.Length > 0 ? addrs[0] : throw new System.Exception( - $"DNS resolved no addresses for '{host}'")); - Console.WriteLine($"live: resolved {host} → {ip}"); - } - var endpoint = new System.Net.IPEndPoint(ip, int.Parse(portStr)); + var endpoint = new System.Net.IPEndPoint(System.Net.IPAddress.Parse(host), int.Parse(portStr)); Console.WriteLine($"live: connecting to {endpoint} as {user}"); _liveSession = new AcDream.Core.Net.WorldSession(endpoint); _liveSession.EntitySpawned += OnLiveEntitySpawned;