feat(chat): route retail lifestone commands

Separate retail client actions, ACE server commands, and ordinary chat at the shared router. Port lifestone/lif/ls from the named retail registry through a typed App controller to game action 0x0063, keep unknown verbs on ACE Talk, and cover both UI backends plus exact outbound bytes.

Co-Authored-By: Codex <codex@openai.com>
This commit is contained in:
Erik 2026-07-13 11:43:19 +02:00
parent 5090aa7217
commit 5a45a7ac7f
19 changed files with 604 additions and 78 deletions

View file

@ -100,6 +100,12 @@ history and the corrected contract live in
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.
Plugins register retained gameplay markup through the BCL-only
`AcDream.Plugin.Abstractions.IUiRegistry`; they do not import App or ImGui
assemblies. Core `SelectionState` is the sole selected-object owner for world,