Owner request: plugin panels (Decal/VirindiViewService-class, per the
MosswartMassacre reference usage) need to embed real DAT icons the way
FlagTrackerView.SafeSetListImage does — spell/skill art, raw portal
indices, and a window icon. This is Slice B of
docs/plans/2026-09-06-plugin-shelf-and-dat-icons.md (Slice A, the
movable/collapsible shelf, landed in 01b98ca30/4fada238e/718005b21).
What shipped:
- AcDream.Plugin.Abstractions.PluginIcons.Normalize: the one Decal-style
bare-index -> 0x06xxxxxx RenderSurface DID grammar, applied at every
icon SINK (descriptor IconSurfaceId in PluginShelfButton, and markup
<icon did>/<button icon>/<list icons> did-kind ids) rather than on the
plugin-facing records, which already carry real DIDs read straight
from the client's tables.
- PluginSpellInfo.IconId / PluginSkillInfo.IconId /
PluginInventoryItem.IconId / PluginWorldObject.IconId: additive init
properties (default 0), filled in AppAutomationSurface from
SpellMetadata.IconId (already projected from SpellBase.Icon by
RetailSpellMetadataProjector — no gap there), a new BindSkillIcons
parallel to BindSkillNames (GameWindow reads
DatReaderWriter.Types.SkillBase.IconId — confirmed via reflection over
the installed Chorizite.DatReaderWriter package, since its XML docs
don't cover Pack/Unpack-generated public fields: Description, Name,
IconId (uint), TrainedCost, SpecializedCost, Category, ChargenUse,
MinLevel, Formula, UpperBound, LowerBound, LearnMod), and
ClientObject.IconId in CaptureOwnedItems/ProjectWorldObject.
- IMarkupIconResolver (AcDream.App.UI): ResolveDid/ResolveSpell/
ResolveItem. MarkupDocument.Build gains an optional parameter (null by
default -> every icon sink resolves to nothing rather than throwing,
so pre-Slice-B callers/tests are unaffected). RetailUiRuntime.
MountPlugins builds ONE RetailMarkupIconResolver per pass from
RetailUiAssets.ResolveSprite + RetailUiAssets.Icons (the shared
IconComposer) + Toolbar.Objects (the SAME ClientObjectTable
Magic/Toolbar bindings already borrow for their own icon resolution —
no second object lookup introduced).
- New UiMarkupIcon widget (<icon x y w h did|spell|item tooltip>):
exactly one source required (FormatException at Build otherwise,
matching every other malformed-attribute rule), aspect-preserved,
centered, click-through unless a tooltip makes it a real hit-test
target.
- UiSimpleButton.IconSource and UiMarkupList.IconIdsSource/IconResolve:
additive, default null/no-op, so every existing button/list caller
(including the plugin shelf's own toggle/minimize buttons) is
unaffected. Button icon draws flush left and shifts the caption's
centering region right; list icons reserve a leading RowHeight-2
column (Decal's IconColumn) and skip rows whose id is 0 or
unresolvable.
- MarkupDocument centralizes the did/spell/item dispatch (including
PluginIcons.Normalize for did) in two small helpers (BuildIconSource
for <icon>/<button>, BuildRowIconResolve for <list>) so all three
markup surfaces share one resolver call path.
- AcDream.Plugins.Smoke ships a RegisterPanelContent (in-memory KSML,
no plugin-side .xml file) proof panel exercising every new surface:
a bare-index <icon>, a literal-hex <icon>, a composited <icon
spell=...>, a <button icon=...>, and a <list icons=... iconkind=
spell> of the first five known self-buffs with their IconId printed
alongside. Descriptor IconSurfaceId reuses the same bare index to
prove the shelf button and the panel's own icon normalize identically.
- docs/plugin-ui-markup.md is the new SSOT for the full markup
vocabulary + icon grammar + the Slice A shelf; linked from
docs/README.md and docs/plans/2026-04-24-ui-framework.md.
Design decisions where the plan left room:
- Normalize runs inside the resolver dispatch (BuildIconSource/
BuildRowIconResolve), not scattered at each markup call site, so
every did-kind sink shares one choke point.
- did/spell/item all accept either a literal (decimal or 0x-hex) or a
{Binding}, via one BindUintLiteralOrBinding helper, for symmetry —
the plan only showed spell/item as bindings but didn't forbid a
literal.
- <icon> requires exactly one source INCLUDING zero (not just two);
an icon with no source is not a coherent element.
- The button/list icon draw math (icon column extent, padding) lives
in the widgets themselves (UiSimpleButton/UiMarkupList), not in
MarkupDocument, keeping the parser only responsible for wiring
Func<(tex,w,h)> sources.
Tests: PluginIconsTests (Normalize table), MarkupIconTests (icon/button/
list resolver dispatch via a fake IMarkupIconResolver, plus draw-level
pins via the RecordingGpuDevice/TextRenderer apparatus already used by
UiAncestorClipTests/UiRenderContextDrawStringDatOutlineTests — "draws
nothing when unresolvable" and "button/list icon shifts the text"),
and AppAutomationSurfaceIconInstalledDatTests (Lane=InstalledDat: a
known spell's IconId matches the real installed SpellTable's own Icon
field exactly). Verified every new test fails to COMPILE without this
change (git-stashed the src/ changes, rebuilt the test project: CS0246
on IMarkupIconResolver) before restoring. Full App suite: 7331 passed /
97 skipped / 36 failed (identical pre-existing failure set/count to the
7306/97/36 baseline; the +25 passes are exactly the new tests).
AcDream.Plugins.MossTank.Tests (the main consumer of the touched
Plugin.Abstractions records) passes 337/337 unchanged, confirming
API-v1 binary/source compatibility. Full solution builds green.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
137 lines
7.6 KiB
Markdown
137 lines
7.6 KiB
Markdown
# acdream documentation map
|
||
|
||
This page is the entry point for project documentation. It distinguishes
|
||
current sources of truth from implementation history so an old plan or issue
|
||
banner cannot silently override the current program state.
|
||
|
||
## Current snapshot — 2026-07-27
|
||
|
||
- **Milestone state:** M3, “Cast a spell,” landed 2026-07-21. M4, “Live in the
|
||
world,” is active.
|
||
- **M4 gameplay program:** resume the pre-M4
|
||
[world-interaction completion program](plans/2026-07-23-world-interaction-completion.md).
|
||
Favorite-spell overflow, status Use/Assess, and the complete assessment
|
||
surface are user-accepted. Equipped-child picking and vendor
|
||
browse/transactions remain Slices 4–6.
|
||
- **Structural/runtime state:** all eight `GameWindow` decomposition slices,
|
||
Modern Runtime Slices A–J, and the connected visual/lifecycle gates are
|
||
complete. `GameWindow` is a 1,622-line composition/callback shell.
|
||
`AcDream.Runtime.GameRuntime` owns canonical session, entity/object,
|
||
gameplay, movement, physics, projectile, environment, and portal state;
|
||
graphical and no-window hosts borrow the same owner graph.
|
||
- **Headless state:** Slice K is complete. `AcDream.Headless` is a
|
||
presentation-free Windows/Linux host with deterministic commands/events,
|
||
shared immutable content, multi-session isolation, reconnect, resource
|
||
telemetry, and 1/5/10/30-session gates. The final two-account native-Linux
|
||
soak completed ten minutes, logged out through ACE, and converged every
|
||
ownership ledger.
|
||
- **Linux graphical state:** Slice L0 and the L1 implementation checkpoint are
|
||
complete at `66f114b2` and `11501d52`. Native Windows passes the active
|
||
modern-GL/audio/window smoke. WSLg X11/Wayland correctly reject their
|
||
missing `GL_ARB_bindless_texture`. Physical-Linux validation and L2–L6 are
|
||
explicitly deferred; resume at the supported AMD/NVIDIA L1 gate.
|
||
- **Completed gameplay gates:** R6 locomotion/collision/projectile/teleport/
|
||
radar, two-client portal-out/materialization, indoor prepared collision,
|
||
loot ordering, local/remote ground drops, and selection-marker lifetime.
|
||
- **Separate visual verification:** issue `#225`, the shared-alpha
|
||
lifestone/particle result; its connected resource-lifetime and performance
|
||
routes pass.
|
||
- **Carried behaviour debt:** issue `#153` (far teleport onto an unstreamed
|
||
edge), `#116` (narrowed slide response), `#235` (capped/RDP jump cadence),
|
||
and the active temporary-stopgap rows in the divergence register.
|
||
- **Divergence audit:** 189 active rows — IA 18, AD 38, AP 91, TS 38, and
|
||
UN 4 — plus retained struck/retired historical rows such as TS-37.
|
||
- **Latest automated baseline:** the Release build succeeds with the 17
|
||
test-project warnings tracked by issue `#228`; 8,826 tests pass and five are
|
||
intentionally skipped. App passes 3,763 / 3 skips. The L1 Windows supported
|
||
smoke and WSLg X11/Wayland negative-capability reports all end with zero
|
||
window/GL/input/audio ownership.
|
||
|
||
## Sources of truth
|
||
|
||
Read these in this order when deciding what to do next:
|
||
|
||
1. [`plans/2026-05-12-milestones.md`](plans/2026-05-12-milestones.md) — the
|
||
active playable outcome, freeze boundaries, and visual gates.
|
||
2. [`plans/2026-04-11-roadmap.md`](plans/2026-04-11-roadmap.md) — strategic
|
||
phase ledger: shipped, active, deferred, and future work.
|
||
3. [`ISSUES.md`](ISSUES.md) — tactical defects and small follow-ups. The status
|
||
inside an issue is authoritative; physical order is not.
|
||
4. [`architecture/retail-divergence-register.md`](architecture/retail-divergence-register.md)
|
||
— every known place runtime behavior can differ from retail.
|
||
5. [`architecture/acdream-architecture.md`](architecture/acdream-architecture.md)
|
||
and [`architecture/code-structure.md`](architecture/code-structure.md) —
|
||
ownership, dependency, update-thread, and extraction rules.
|
||
6. [`architecture/worldbuilder-inventory.md`](architecture/worldbuilder-inventory.md)
|
||
— rendering/DAT code already owned in-tree versus mechanisms still ours to
|
||
port.
|
||
|
||
If these disagree, milestones control the current outcome, the roadmap controls
|
||
work ordering, the issue status controls the individual defect, and the
|
||
architecture documents control implementation shape. Reconcile the stale
|
||
document in the same change; do not leave both claims standing.
|
||
|
||
## Research and implementation records
|
||
|
||
- [`research/named-retail/`](research/named-retail/) is the primary retail
|
||
oracle: named pseudo-C, headers, symbols, and types from the Sept 2013 build.
|
||
- [`research/decompiled/`](research/decompiled/) is the older Ghidra fallback.
|
||
- [`research/`](research/) contains focused pseudocode, traces, fixtures, and
|
||
gate reports. A dated research note records evidence; it does not become a
|
||
new roadmap.
|
||
- [`superpowers/specs/`](superpowers/specs/) and
|
||
[`superpowers/plans/`](superpowers/plans/) are per-slice design and execution
|
||
records. Completed plans remain historical.
|
||
- [`ci-and-releases.md`](ci-and-releases.md) is the SSOT for the Gitea CI
|
||
pipeline, the self-hosted runners, and how alpha releases are published.
|
||
Load-sensitive tests live in `Lane=Timing`; see
|
||
[`release-gate.md`](release-gate.md) before adding to it.
|
||
- [`launch-options.md`](launch-options.md) is the SSOT for every environment
|
||
variable and command-line argument the client reads, including what each one
|
||
changes about the run beyond its obvious effect. Read the side-effects column
|
||
before trusting any measurement. Enforced by
|
||
`LaunchOptionsDocumentationTests`: a flag without a row fails the build, and
|
||
so does a row whose read site was deleted.
|
||
- [`plugin-ui-markup.md`](plugin-ui-markup.md) is the SSOT for the plugin
|
||
markup vocabulary (elements, attributes, `{Binding}` rules) plus the
|
||
Decal/VirindiViewService-compatible DAT icon grammar (Slice B,
|
||
`plans/2026-09-06-plugin-shelf-and-dat-icons.md`) and the movable/
|
||
collapsible plugin shelf (Slice A of the same plan).
|
||
- [`audit/`](audit/) contains completion and conformance audits.
|
||
- [`reference/ace-commands.md`](reference/ace-commands.md) preserves the local
|
||
ACE server's complete in-game command catalog and points to the authoritative
|
||
per-command help surface.
|
||
|
||
## Durable memory
|
||
|
||
- [`../claude-memory/MEMORY.md`](../claude-memory/MEMORY.md) indexes the live
|
||
subsystem memories and the render/physics digests. Read a domain digest
|
||
before changing that subsystem, especially its DO-NOT-RETRY table.
|
||
- [`../memory/`](../memory/) contains stable engineering references such as the
|
||
modern rendering pipeline, two-tier streaming, and toolchain notes.
|
||
|
||
Memory accelerates recall; it does not outrank the canonical documents above.
|
||
When current truth changes, update the relevant canonical document and distill
|
||
only the durable lesson into memory.
|
||
|
||
## Historical and deprecated documents
|
||
|
||
- [`bugs.md`](bugs.md) is the April 2026 bug snapshot. It is preserved for
|
||
archaeology and is not an active ledger.
|
||
- Dated plans and specs describe the decision at that time. Their completion
|
||
wording is historical unless the current milestone/roadmap explicitly links
|
||
the item as active.
|
||
- Old `R1→R8` architecture sequencing is superseded. Current execution comes
|
||
from the milestones and strategic roadmap.
|
||
|
||
## Documentation maintenance rules
|
||
|
||
- Update milestone, roadmap, issue, divergence, architecture, and memory claims
|
||
in the same commit when a shipped change affects them.
|
||
- Keep one issue ID per defect. Narrow an issue in place; do not reuse another
|
||
issue's number as a shorthand.
|
||
- Mark automated, connected, and visual gates separately. An automated pass is
|
||
not a visual acceptance, and an RDP throughput sample is not a local-display
|
||
visual comparison.
|
||
- Preserve research history, but remove stale “current/next” claims from living
|
||
documents once the state advances.
|