feat(chat): Campaign CH slice CH3 — side-channel membership, wire, and echo parity
Ports retail's SendTurbineChat (@0x0057db10) local pre-send membership gate so Roleplay/Society/Olthoi stop silently swallowing outbound chat: a new TurbineChatMembershipGate checks Turbine availability and the player's own Hear*Chat option before sending, raising "Turbine chat is not available." or the 0x0551 YouAreNotListeningTo_Channel refusal through the CH2 AddText chokepoint instead. Wired into both the graphical (LiveSessionCommandRouter) and headless (DirectGameRuntimeCommandAdapter) send paths so they can't diverge. Retracts the 26-day-old false "ACE doesn't run a TurbineChat server" claim from ISSUES.md, the roadmap, and project_chat_pipeline.md — ACE's TurbineChat implementation is complete and on by default; the real bug was treating Hear*Chat as a display filter instead of room membership. Also: implements SetSingleCharacterOption (0x0005), the only wire message that actually joins/leaves a Turbine room, and wires the five Settings Chat toggles to it (publish on Save, changed bits only) plus seeds ChatSettings from the server's own CharacterOptions2 on every PlayerDescription. Fixes the legacy-channel double-print (Fellow/Vassals/Patron/Monarch/CoVassals skip the local echo now that ChatChannelInfo.IsSelfEchoChannel is finally consulted). Routes /a to Turbine unconditionally (retail's @a never falls back to the legacy bitflag) and adds /ab for the legacy AllegianceBroadcast verb retail actually has. Surfaces a nonzero TurbineChat ack HResult instead of discarding it silently. Deletes the malformed, callerless SetCharacterOptions (0x01A1) and AddChannel/RemoveChannel (0x0145/0x0146) builders. Files every AC-specific algorithm change cites the named retail decomp (SendTurbineChat 0x0057db10, StartupTurbineChatSystem 0x0057EFB0, GameActionSetSingleCharacterOption) plus ACE/holtburger cross-checks. Register rows AP-181 (no client-side spam throttle) and UN-9 (an incidentally-discovered CharacterOptions1.Default literal mismatch, not investigated further) filed per the divergence-register rule. 11,957 passed / 4 skipped / 0 failed (full Release suite, up from the 11,916/4/0 baseline). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
fc9590e4fc
commit
614a1e055f
35 changed files with 1453 additions and 229 deletions
|
|
@ -15229,7 +15229,7 @@ parallel to existing handlers (no behavior change).
|
|||
|
||||
**Closed:** 2026-04-25
|
||||
**Commit:** `ca968fc`
|
||||
**Resolution:** Full `0xF7DE` codec with three payload variants (`EventSendToRoom`, `RequestSendToRoomById`, `Response`), UTF-16LE strings with variable-length prefix, `SetTurbineChatChannels (0x0295)` parser, unified `ChatChannelInfo` (Legacy + Turbine variants), `TurbineChatState`. **Note: ACE doesn't run a TurbineChat server — codec is ready for retail-server-emulating setups.**
|
||||
**Resolution:** Full `0xF7DE` codec with three payload variants (`EventSendToRoom`, `RequestSendToRoomById`, `Response`), UTF-16LE strings with variable-length prefix, `SetTurbineChatChannels (0x0295)` parser, unified `ChatChannelInfo` (Legacy + Turbine variants), `TurbineChatState`. **Correction (Campaign CH slice CH3, 2026-08-09): the "ACE doesn't run a TurbineChat server" note above was FALSE.** ACE has a complete TurbineChat implementation (`TurbineChatHandler.cs`, 387 lines), on by default (`use_turbine_chat = true`), and our own launch logs have shown parsed `SetTurbineChatChannels` room ids since at least 2026-05-21. See `docs/research/2026-08-09-chat-side-channels-vs-ace.md` §1.
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -426,7 +426,7 @@ W1 plan: [`docs/superpowers/plans/2026-06-02-unified-cell-graph-stage1.md`](../s
|
|||
| I.3 | `LiveCommandBus` + `WorldSession.SendTalk` / `SendTell` / `SendChannel` — replaces `NullCommandBus.Instance` with a real handler-registry `ICommandBus`. New `SendChatCmd` record + `ChannelResolver` legacy-id mapping (per holtburger). 3-line wrappers around existing `ChatRequests.BuildTalk/Tell/ChatChannel`. | Tests ✓ |
|
||||
| I.4 | `ChatPanel` input field + slash commands — Enter-to-submit input field; `ChatInputParser` recognises `/say` `/t` `/tell` `/r` `/g` `/f` `/a` `/m` `/p` `/v` `/cv` `/lfg` `/trade` `/role` `/society` `/olthoi`; `ChatVM.LastIncomingTellSender` tracks for `/r` reply. `ImGui.WantCaptureKeyboard` already suppresses WASD on focus. | Live ✓ |
|
||||
| I.5 | Holtburger inbound chat parity + Windows-1252 codec — `EmoteText (0x01E0)`, `SoulEmote (0x01E2)`, `ServerMessage (0xF7E0)`, `PlayerKilled (0x019E)` parsers + `WeenieError` routing through `GameEventWiring`. Global string codec switch from `Encoding.ASCII` to `Encoding.GetEncoding(1252)` so accented names round-trip per retail + holtburger. | Tests ✓ |
|
||||
| I.6 | TurbineChat codec + `ChatChannelInfo` — full `0xF7DE` codec with three payload variants (`EventSendToRoom`, `RequestSendToRoomById`, `Response`), UTF-16LE strings with variable-length prefix, `SetTurbineChatChannels (0x0295)` parser, unified `ChatChannelInfo` (Legacy + Turbine variants), `TurbineChatState`. **ACE doesn't host a TurbineChat server — codec is ready when retail-emulating servers exist.** | Tests ✓ |
|
||||
| I.6 | TurbineChat codec + `ChatChannelInfo` — full `0xF7DE` codec with three payload variants (`EventSendToRoom`, `RequestSendToRoomById`, `Response`), UTF-16LE strings with variable-length prefix, `SetTurbineChatChannels (0x0295)` parser, unified `ChatChannelInfo` (Legacy + Turbine variants), `TurbineChatState`. **Correction (Campaign CH slice CH3, 2026-08-09): the "ACE doesn't host a TurbineChat server" note above was FALSE — ACE has a complete, on-by-default TurbineChat implementation; see `docs/research/2026-08-09-chat-side-channels-vs-ace.md` §1.** | Tests ✓ |
|
||||
| I.7 | `CombatChatTranslator` — retail-faithful combat-text formatters into `ChatLog` ("You hit drudge for 50 slashing damage (87%)"). Subscribes to `CombatState`'s `DamageTaken` / `DamageDealtAccepted` / `EvadedIncoming` / `MissedOutgoing` / `KillLanded`; `AttackDone` is control-only and deliberately silent. | Tests ✓ |
|
||||
| K | Input architecture — `Action` enum, `KeyChord`, `KeyBindings`, multicast `InputDispatcher` with scope-stack + modal capture, retail-default keymap (152 bindings), `keybinds.json` persistence, F11 Settings panel with click-to-rebind + conflict detection, main menu bar + View menu | Live ✓ |
|
||||
| L.0 | Full retail-style Settings interface — F11 tabbed panel with 6 tabs (Keybinds + Display + Audio + Gameplay + Chat + Character). `settings.json` at `%LOCALAPPDATA%\acdream\`, per-toon `Character` keying (swapped on EnterWorld). Display GL knobs (Resolution / Fullscreen / VSync / FOV / ShowFps) + Audio (Master / SFX) live-wired; Gameplay / Chat / Character settings persist for server-sync wiring later. Tab API extension to `IPanelRenderer`; chat Copy mode (read-only multi-line); per-panel layout reset; FramebufferResize handler keeps GL viewport + camera aspect + panel positions in sync. | Live ✓ |
|
||||
|
|
|
|||
|
|
@ -6,7 +6,9 @@ gate (`77c8296e`, REJECT-reviewed at
|
|||
`docs/research/2026-08-09-ch2-review-findings.md`, reworked `e0e78883`,
|
||||
re-reviewed APPROVE-WITH-FIXES with nits applied this commit) — the sole
|
||||
outstanding item is the in-client user gate (jump-in-air / jump-loaded
|
||||
refusals showing on-screen, not in chat). CH3 (side channels) next.
|
||||
refusals showing on-screen, not in chat). CH3 (side channels)
|
||||
CODE-COMPLETE, pending the connected user gate — see the CH3 row below and
|
||||
`docs/research/2026-08-09-chat-side-channels-vs-ace.md`.
|
||||
|
||||
**Why now:** first track of the alpha-release program (chat is the most
|
||||
visible daily surface for the friend-alpha). User-directed 2026-08-09.
|
||||
|
|
@ -106,6 +108,76 @@ implementer per slice against a pinned contract (per
|
|||
| R1–R4 research | `see docs/research/2026-08-09-chat-retail-*` | — | — | — |
|
||||
| CH1 colors | `172c6f9a` | 11,835 passed / 4 skipped / 0 failed | APPROVE-WITH-FIXES; fixed `34d8a3c0` | pending |
|
||||
| CH2 interface text | `77c8296e`, reworked `e0e78883` | 11,916 passed / 4 skipped / 0 failed | REJECT → reworked `e0e78883` → re-review APPROVE-WITH-FIXES → nits `233c30d1` | pending |
|
||||
| CH3 side channels | — | — | — | — |
|
||||
| CH3 side channels | `PENDING-SHA` | 11,957 passed / 4 skipped / 0 failed | not yet reviewed | pending (connected gate — see handoff below) |
|
||||
| CH4 commands | — | — | — | — |
|
||||
| CH5 closeout | — | — | — | — |
|
||||
|
||||
### CH3 closeout handoff (2026-08-09)
|
||||
|
||||
All nine steps of the research doc's §6 fix list landed:
|
||||
|
||||
1. **The false "ACE doesn't run a TurbineChat server" claim retracted** in
|
||||
`docs/ISSUES.md` (#19) and `docs/plans/2026-04-11-roadmap.md` (I.6, ×2).
|
||||
2. **`TurbineChatMembershipGate`** (new, `AcDream.Runtime.Gameplay`) ports
|
||||
retail's `SendTurbineChat @0x0057db10` local pre-send gate — Turbine
|
||||
off/room-0 → `"Turbine chat is not available."`; Hear-option off →
|
||||
`0x0551 YouAreNotListeningTo_Channel` — both raised through
|
||||
`RuntimeCommunicationState.AddText`. Wired into BOTH
|
||||
`LiveSessionCommandRouter` (graphical) and `DirectGameRuntimeCommandAdapter`
|
||||
(headless) so the two hosts can't diverge. `RuntimeCharacterState.IsOlthoiPlayer`
|
||||
added (heritage-gated, not an option) for the Olthoi room.
|
||||
3. **`SetSingleCharacterOption (0x0005)`** implemented end to end (codec,
|
||||
`WorldSession.SendSetSingleCharacterOption`, `IRuntimeCharacterCommands.
|
||||
SetSingleOption`, both adapters, `LiveSessionCommandRouter` registration)
|
||||
and wired to the 5 Settings Chat toggles via `RuntimeSettingsController.
|
||||
SaveChat` (publishes only the CHANGED bits) through a hoisted
|
||||
`LiveSessionCommandSurface` now shared with `RuntimeSettingsTargets`.
|
||||
No 6th (Allegiance) toggle was added — `ChatSettings` has never had one
|
||||
and retail's own Settings UI was not confirmed to have one either; flagged
|
||||
for the user rather than guessed.
|
||||
4. **`ChatSettings` seeded from server truth** — `RuntimeSettingsController.
|
||||
SyncChatFromServerOptions` reseeds both the persisted snapshot and any
|
||||
live unsaved draft from `CharacterOptions2` whenever a fresh
|
||||
PlayerDescription lands (`LiveCharacterSessionBindings.
|
||||
OnCharacterOptionsChanged`, new optional hook).
|
||||
5. **Self-echo double-print fixed** — `LiveSessionCommandRouter.
|
||||
RouteLegacyChannel` now consults `ChatChannelInfo.Legacy(...).
|
||||
IsSelfEchoChannel()`; Fellow/Vassals/Patron/Monarch/CoVassals skip the
|
||||
local echo (server resends with `""` sender), AllegianceBroadcast/Say/Tell
|
||||
keep it. Existing `TellAndLegacyChannel_PreserveOutboundAndEchoPolicy`
|
||||
test corrected to the fixed (single-print) expectation.
|
||||
6. **TurbineChat ack HResult surfaced** — `LiveSessionEventRouter.
|
||||
RouteTurbineChat` now switches on `Payload.Response{HResult}`; nonzero
|
||||
surfaces as a system chat line, zero (the common case) stays silent
|
||||
matching retail.
|
||||
7. **`/a` routes to Turbine unconditionally** — `ChatChannelKind.Allegiance`
|
||||
is exhaustively dispatched to the Turbine pipeline (never falls through to
|
||||
legacy); a new `ChatChannelKind.AllegianceBroadcast` + `/ab` verb owns the
|
||||
legacy `0x02000000` path retail's own `@ab` verb uses.
|
||||
`/allegiancebroadcast` was deliberately NOT added — the retail command
|
||||
registry (`docs/research/2026-08-09-chat-retail-command-registry.md`)
|
||||
only has `ab`, not that long form.
|
||||
8. **Malformed builders resolved** — `SocialActions.BuildSetCharacterOptions`
|
||||
(0x01A1, no caller), `BuildAddChannel`/`BuildRemoveChannel` (0x0145/0x0146,
|
||||
wrong payload type, no caller) DELETED along with their entire call chain
|
||||
(`WorldSession.SendSetCharacterOptions`, `IRuntimeCharacterCommands.
|
||||
SetOptions1`, `SetCharacterOptionsRuntimeCmd`) — replaced by
|
||||
`SetSingleCharacterOption`, the message step 3 actually needed.
|
||||
9. **Register + memory** — AP-181 (no client-side chat spam throttle) and
|
||||
UN-9 (an incidentally-discovered, unexplained one-byte
|
||||
`CharacterOptions1.Default` mismatch vs ACE's own literal — not
|
||||
investigated further, flagged for a future pass) filed in
|
||||
`docs/architecture/retail-divergence-register.md`.
|
||||
`claude-memory/project_chat_pipeline.md` line ~111 corrected.
|
||||
|
||||
**Deviations from the literal ordered list:** none structural; the two
|
||||
notes above (no 6th Allegiance toggle, no `/allegiancebroadcast` verb) are
|
||||
scope-narrowing decisions made against the retail command registry and the
|
||||
existing `ChatSettings` shape, not skipped work.
|
||||
|
||||
**What the connected gate must verify (not run this session — build+test
|
||||
only per the CH3 task's hard constraint):** General/Trade/LFG round-trip
|
||||
send+receive; Roleplay is now silent-but-correctly-refused until the user
|
||||
turns it on via Settings (then works); `/a` with and without an allegiance;
|
||||
`/ab`; the legacy family no longer double-prints; the TurbineChat ack
|
||||
HResult line never appears on an ordinary successful send.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue