feat(runtime): share chat commands and run login sequence

This commit is contained in:
Erik 2026-08-14 20:27:45 +02:00
parent 5535d0adac
commit 41b15efd4d
57 changed files with 1739 additions and 345 deletions

View file

@ -92,7 +92,7 @@ stack. Full history and the corrected contract live in
│ LayoutDesc/DAT → UiRoot retained widgets + controllers │
├─────────────────────────────────────────────────────────────┤
│ SHARED CONTRACTS │
│ ViewModels, commands, input actions, state/event services
│ ViewModels, input actions, state/event and command seams
│ ► one model and mutation path, one presentation projection │
├─────────────────────────────────────────────────────────────┤
│ Game state + events (unchanged) │
@ -100,24 +100,32 @@ stack. Full history and the corrected contract live in
└─────────────────────────────────────────────────────────────┘
```
`AcDream.UI.Abstractions` — the `IPanel`/`IPanelRenderer` contract, the
ViewModels and the commands **survives intact**. It was always
`AcDream.UI.Abstractions` — the `IPanel`/`IPanelRenderer` contract and the
ViewModels — **survives intact**. It was always
backend-agnostic, which is exactly what Code Structure Rule 3 was written to
protect, and it is what a future developer-panel host would bind to. Only the
ImGui *backend* was deleted. `ACDREAM_DEVTOOLS=1` still selects Vulkan's
debug-utils extensions and now logs that the developer UI is gone; replacing it
is issue **#258**, deliberately unscheduled.
`AcDream.UI.Abstractions` owns backend-neutral ViewModels, commands, input,
and the `IPanel`/`IPanelRenderer` devtools contract. `AcDream.App/UI` owns the
`AcDream.UI.Abstractions` owns backend-neutral ViewModels, input, and the
`IPanel`/`IPanelRenderer` devtools contract. `AcDream.App/UI` owns the
retained gameplay tree, LayoutDesc importer, window runtime, and panel
controllers. Neither presentation stack owns independent game-state truth.
Chat submission follows the same rule: both presentation stacks enter the
shared `ChatCommandRouter`, which emits distinct backend-neutral intents for a
retail client command (`ExecuteClientCommandCmd`), an ACE-owned command
(`SendServerCommandCmd`), or ordinary chat (`SendChatCmd`). App-layer
handlers and controllers translate those intents to `WorldSession`; panels
never inspect or construct wire messages.
Chat submission follows the same rule: `AcDream.Runtime/Chat` owns the shared
parser, retail command/channel/help catalogs, `ChatCommandRouter`, command bus,
and its four backend-neutral records (`ExecuteClientCommandCmd`,
`SendServerCommandCmd`, `SendChatCmd`, and `SendRawChannelCmd`). Its only
presentation callback is the four-member `IChatCommandFeedback`; retained
`ChatVM` implements that seam. Both App and Headless bind the same
`LiveChatCommandRoute` to the active `WorldSession` send delegates and exact
`RuntimeCommunicationState`/`RuntimeCharacterState` children. Panels never
inspect or construct wire messages, and Runtime has no UI or App dependency.
Configured login commands enter that identical parser/router only after the
generation's `enteredWorld` edge, in order, once per generation. The shared
generation-aware sequence cancels on replacement, applies the configured
inter-command delay, and reports each isolated failure without aborting the
session or plugin lifetime.
Plugins register retained gameplay markup through the BCL-only
`AcDream.Plugin.Abstractions.IUiRegistry`; they do not import App or
presentation assemblies. `IPluginHost.HasUi` is the explicit capability edge:
@ -251,6 +259,9 @@ src/
RuntimeInitialCreateContinuationExecutor.cs -> retry-idempotent
adoption + retail Create tail + strict-order
FIFO/replay execution over the residence
Chat/ -> LA6 parser/router/catalog and four command
intents; shared live route + generation-scoped
configured-login sequence for both hosts
Gameplay/
RuntimeCommunicationState.cs -> one chat/social owner + ordered stream
RuntimeInventoryState.cs -> exact object-table borrower + inventory