fix(chat): round 4 — no user-visible meta text, real /help groups, indicator buttons toggle
Item 3 (#364): every honesty marker is now gone from user-visible /help text. AllegianceOverview/HouseOverview's "[IMPLEMENTED]" tags and trailing "Subcommands NOT marked..." sentences, and Day/Log/Render/Motd's appended "NOT YET IMPLEMENTED in acdream" tails, are removed; the underlying retail text is corrected/completed against the pseudo-C's own pristine consolidated data dumps (Log and Motd had been silently truncated; Render was entirely acdream-authored and is replaced with the real retail usage string). The three PARTIAL /help group topics (channels/chatting/commands) are now COMPLETE verbatim listings: HelpStupidChannelHack's three "vtable slot" operands, previously believed undecodable, are the same pooled/mislabeled-data artifact this campaign has hit before (AP-113's precedent) — reading the function's own disassembly for the push imm32 preceding each constructor call resolves all three directly. messagetypes is now a real ported construction (IsLegalChannel's 14-id whitelist + LogTextTypeToString's name table + the exact join/wrap format) instead of an acdream summary. Register row AP-184 retired. Item 5: the main window's 1/2/3/4 indicator buttons now toggle their floating chat window on click, per the user's retail memory overruling the earlier decomp-only reading. UIElement_Button::HandleButtonClick has its own generic click-driven action dispatch (property 0x12) reaching the same DoVisibilityToggleAction the Alt+1..4 keybinds use; the button fixture confirms this half is genuinely armed, but the floating-window fixture authors no matching listener-registration property, so the generic mechanism has no proven target in the data on hand. Per CLAUDE.md, the user's retail memory is the axiom regardless: ChatWindowController.BindIndicatorClicks wires each indicator's click through the same ToggleFloatingChatWindow chokepoint the keybinds use, as explicit user-directed retail behavior. SetIndicatorOpen stays the sole writer of the Selected mirror so the visual stays consistent through the click round trip. Full reconciliation in docs/research/2026-08-09-chat-retail-window-shell.md §1.4. Campaign plan gets the round-4 findings section; items 1+2 (text-style) are under parallel research, item 4 passed, item 6 deferred to the settings track. Suite: 12,579 passed / 4 skipped / 0 failed (Release, complete solution), up from baseline 12,553/4/0 — net +26 tests, zero regressions. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
8b166f3ea2
commit
5b54387b8e
10 changed files with 1129 additions and 239 deletions
|
|
@ -382,32 +382,48 @@ user gate round 3; closed in the goal-window follow-up).
|
|||
|
||||
## #364 — Three `/help` group topics still partial: HelpStupidChannelHack unresolved
|
||||
|
||||
**Status:** OPEN — filed 2026-08-09, Campaign CH user-gate round 2, item 3.
|
||||
**Status:** CLOSED 2026-08-10 — Campaign CH round 4. The blocker in the
|
||||
original filing (below) was a wrong belief, not a real limitation:
|
||||
`ClientCommunicationSystem::HelpStupidChannelHack @0x0056f290`'s three
|
||||
"vtable slot" operands are the SAME pooled/mislabeled-data artifact this
|
||||
file's register entry AP-113 already documented elsewhere — real DATA
|
||||
pointers into `.rdata`, not vtable dispatch. Reading the function's own
|
||||
disassembly for the `push imm32` immediately preceding each
|
||||
`PStringBase::PStringBase` constructor call (instead of trusting Binary
|
||||
Ninja's line-grouped rendering, which hides the true instruction order)
|
||||
resolves all three operands directly: the function builds
|
||||
`"@" + tag + " - Sends a broadcast to your " + ChannelName + ".\n"`, where
|
||||
`tag` is one character sliced out of a shared wide literal `U"fvpca"`
|
||||
(reading a WIDE string through a NARROW `char*` truncates at the first
|
||||
zero high byte — the "hack" the function's own retail name calls out) and
|
||||
`ChannelName` comes from `ChannelSystem::GetChannelName`'s own literal
|
||||
switch table (also read directly: "Allegiance", "Co-vassals", "Monarch",
|
||||
"Patron", "Vassals", "Fellowship"). `ChannelsGroupDetail`,
|
||||
`ChattingGroupDetail` (whose "@reply" entry also needed
|
||||
`HelpReply@0x00577A50`'s Summary-branch decoded — it unconditionally
|
||||
concatenates reply+pr+mr, a genuine retail quirk ported as found), and
|
||||
`CommandsGroupDetail` (`HelpAllGroup`, a straight-line concatenation of
|
||||
every other group's Detail branch, including a CONFIRMED retail
|
||||
saveui/loadui duplicate) are now COMPLETE verbatim listings, matching the
|
||||
four (death/status/text/allegiances) already complete. Register row
|
||||
AP-184 RETIRED with the full citation trail. The 5 remaining
|
||||
`ByVerb`-only channel one-liners (fellowship/monarch/patron/vassals/
|
||||
covassal, as standalone `/help f`-style lookups rather than group-listing
|
||||
entries) are UNCHANGED — their own standalone help registration was never
|
||||
confirmed independently of this mechanism, so they are deliberately left
|
||||
as acdream summaries rather than spliced in speculatively.
|
||||
|
||||
**Original filing (2026-08-09, Campaign CH user-gate round 2, item 3):**
|
||||
The user caught `/help death` printing an acdream meta-message instead of
|
||||
retail's real listing; all 7 `ClientCommunicationSystem::HelpXxxGroup`
|
||||
nodes were re-extracted verbatim from the PDB-paired binary via a
|
||||
generalized `tools/pdb-extract/sweep_weenie_strings.py --ascii-only`.
|
||||
4 of 7 (death/status/text/allegiances) are now COMPLETE verbatim listings
|
||||
(`RetailCommandHelpTable.DeathGroupDetail` etc.). 3 remain PARTIAL
|
||||
(`ChannelsGroupDetail`, `ChattingGroupDetail`, `CommandsGroupDetail`):
|
||||
their detail text is built (in full or in part) by
|
||||
`ClientCommunicationSystem::HelpStupidChannelHack @0x0056f290`, which
|
||||
constructs its output from three string fragments Binary Ninja
|
||||
mis-attributes to unrelated vtable slots (the classic BN pooled/
|
||||
mislabeled-data artifact — `&ClientCommunicationSystem::\`vftable'.
|
||||
RecvNotice_StartBarberNotice` etc. are NOT real vtable dispatch)
|
||||
concatenated around a live `ChannelSystem::GetChannelName` call —
|
||||
genuinely not decodable from a static string sweep. Each partial group
|
||||
keeps its own summary line (fully verbatim) and an explicit UNVERIFIED
|
||||
note citing the address; `chatting` additionally resolves 7 of its 8
|
||||
detail entries (only the 5 HelpStupidChannelHack-delegated channel-alias
|
||||
lines are missing). The same mechanism also blocks 5 of ~35 channel
|
||||
one-liners in `ByVerb` (fellowship/monarch/patron/vassals/covassal
|
||||
family), which stay acdream-authored summaries. Resolving
|
||||
HelpStupidChannelHack requires reading the three mislabeled string
|
||||
fragments directly out of `.rdata` by address (not by BN symbol name) and
|
||||
confirming the channel-name substring logic — a focused follow-up, not
|
||||
guessed.
|
||||
4 of 7 (death/status/text/allegiances) were COMPLETE verbatim listings
|
||||
(`RetailCommandHelpTable.DeathGroupDetail` etc.); 3 remained PARTIAL
|
||||
(`ChannelsGroupDetail`, `ChattingGroupDetail`, `CommandsGroupDetail`) with
|
||||
an explicit UNVERIFIED note, believed genuinely not decodable from a
|
||||
static string sweep — see the CLOSED note above for why that turned out
|
||||
to be wrong.
|
||||
|
||||
**Campaign:** `docs/plans/2026-08-09-chat-parity-campaign.md` (Campaign CH,
|
||||
user gate round 2).
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -48,11 +48,19 @@ CODE-COMPLETE 2026-08-10** under this session's hard constraints (no
|
|||
subagents, no client launches) — see its ledger row and Slices bullet.
|
||||
**CH6c (opacity) landed CODE-COMPLETE 2026-08-10**, same constraints —
|
||||
see its ledger row and Slices bullet; the full three-sub-slice CH6 window
|
||||
shell is now CODE-COMPLETE. Status stays CODE-COMPLETE pending the next
|
||||
user gate round (still needed for CH6a's own visual confirmation, CH6b's
|
||||
keybind/mirror/filter behavior, CH6c's focus-driven fade and Settings
|
||||
slider, round 3's fixes, and a final in-client visual pass on everything
|
||||
fixed so far).
|
||||
shell is now CODE-COMPLETE. **User gate round 4 ran 2026-08-10 and found
|
||||
six findings; see "User gate — round 4" below.** Items 3 (user-visible
|
||||
`/help` meta-markers leaking into live output, closing #364) and 5 (the
|
||||
main window's 1/2/3/4 indicator buttons now toggle their floating window
|
||||
on click, per the user's retail memory) are fixed in this round's commit;
|
||||
item 4 passed with no action needed; items 1+2 (text-style findings) were
|
||||
under parallel read-only research this session, concurrent with this
|
||||
commit's item 3+5 work; item 6 is deferred to the settings track. Status
|
||||
stays CODE-COMPLETE pending the next user gate round (still needed for
|
||||
CH6a's own visual confirmation, CH6b's keybind/mirror/filter behavior,
|
||||
CH6c's focus-driven fade and Settings slider, round 3's fixes, round 4's
|
||||
item 3+5 fixes, and a final in-client visual pass on everything fixed so
|
||||
far).
|
||||
|
||||
**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.
|
||||
|
|
@ -289,7 +297,8 @@ implementer per slice against a pinned contract (per
|
|||
| CH6b floating windows 1–4 | `22020ef2`, reworked `1aa77099` | 12,420 passed / 4 skipped / 0 failed | REJECT (docs/research/2026-08-10-ch6ab-review-findings.md) → reworked `1aa77099` — SHOULD-FIXES 2/3/4/5 + NITs 1-5 applied | pending — no client launches this session (hard constraint); needs the next connected round for keybind/mirror/filter visual confirmation, plus the new 0x2100005B fixture's resolved-type assumptions |
|
||||
| CH6c opacity | `a819687c` | 12,459 passed / 4 skipped / 0 failed | APPROVE-WITH-FIXES; fixed this commit — BLOCKER (out-of-box `DefaultOpacity` 0.5→1.0), AP-190 reworded + two new decomp-verified clauses (retail's per-tick ease, retail's entry-field-specific focus predicate), NITs (`UiElement.cs` stale comment, `WindowUnregistered` detach, post-Dispose `Set*` guards, `DrawString`/outline-pass alpha tests) | pending — needs the next connected round for visual confirmation (window fade on focus change, Settings slider live-apply) |
|
||||
| Goal-window #363/#367 interface-text seam | `09453eca` | 12,542 passed / 4 skipped / 0 failed | implementer-only, no subagent review this session (hard constraint) | pending — needs the next connected round to confirm the SpewBox now flashes for the reclassified refusals (see "Goal-window follow-up" below) |
|
||||
| Consolidated review — retail `/help` Detail extraction, seam wiring test | this commit | 12,553 passed / 4 skipped / 0 failed | APPROVE-WITH-FIXES; fixed this commit — SHOULD-FIX 1 (42 of 47 catalog leaf verbs given retail Detail_HelpType text, 4 confirmed-null, 1 honest UNVERIFIED, retiring the class doc's overclaim), SHOULD-FIX 2 (`ComposedChatViewModelWiresOnInterfaceTextToSpewBox` — the a5a7eb4f defect class had no test), SHOULD-FIX 3 (AP-113 RETIRED — Lifestone's and Marketplace's own bespoke bad-args refusal text recovered byte-exact), SHOULD-FIX 4 (register header's stale 0.5/1.0 sentence corrected), NITs (a)-(d) (`HeadlessDiagnosticWriter` instead of `Console.WriteLine`, bounded non-quiescent-pump liveness diagnostic, hydration test doc-comment contradiction, 0x26 fallback dispatches on its own `Type`) | pending — needs the next connected round to confirm `/help <verb>` now shows retail's exact wording (see "Consolidated review" below) |
|
||||
| Consolidated review — retail `/help` Detail extraction, seam wiring test | `f7a6f46b` | 12,553 passed / 4 skipped / 0 failed | APPROVE-WITH-FIXES; fixed this commit — SHOULD-FIX 1 (42 of 47 catalog leaf verbs given retail Detail_HelpType text, 4 confirmed-null, 1 honest UNVERIFIED, retiring the class doc's overclaim), SHOULD-FIX 2 (`ComposedChatViewModelWiresOnInterfaceTextToSpewBox` — the a5a7eb4f defect class had no test), SHOULD-FIX 3 (AP-113 RETIRED — Lifestone's and Marketplace's own bespoke bad-args refusal text recovered byte-exact), SHOULD-FIX 4 (register header's stale 0.5/1.0 sentence corrected), NITs (a)-(d) (`HeadlessDiagnosticWriter` instead of `Console.WriteLine`, bounded non-quiescent-pump liveness diagnostic, hydration test doc-comment contradiction, 0x26 fallback dispatches on its own `Type`) | pending — needs the next connected round to confirm `/help <verb>` now shows retail's exact wording (see "Consolidated review" below) |
|
||||
| User gate round 4 — items 3+5 (no meta text, indicator click-toggle) | this commit | 12,579 passed / 4 skipped / 0 failed | implementer-only, no subagent review this session (hard constraint) | pending — needs the next connected round to confirm `/help channels`/`chatting`/`commands`/`messagetypes` show complete retail text and clicking each indicator button toggles its floating window (see "User gate — round 4" below) |
|
||||
|
||||
### CH4 closeout (2026-08-09)
|
||||
|
||||
|
|
@ -1071,3 +1080,32 @@ connected round should confirm `/help die`, `/help lifestone`,
|
|||
show retail's exact wording instead of the old acdream summaries, and that
|
||||
`/help index`/`/clist`/`/on`/`/off` now show "Unknown command" via the
|
||||
SpewBox.
|
||||
|
||||
## User gate — round 4 (2026-08-10)
|
||||
|
||||
The user tested the goal-window build live and reported six findings. A
|
||||
parallel read-only research agent investigated items 1+2 (text-style
|
||||
presentation) concurrently with this session's items 3+5 fix work; this
|
||||
session owned all builds/commits (hard constraint: one commit).
|
||||
|
||||
| # | User finding (condensed) | Disposition |
|
||||
|---|---|---|
|
||||
| 1 | Text-style/presentation finding under the on-screen interface-text and/or `/help` surfaces. | **Research in flight** — a parallel read-only research agent investigated this concurrently with items 3+5; not fixed in this commit. Follow up in the next session once its findings land. |
|
||||
| 2 | A second text-style/presentation finding, same surface family as item 1. | **Research in flight** — same parallel agent as item 1. |
|
||||
| 3 | User-visible meta-markers ("IMPLEMENTED", "acdream has not yet extracted…"-style notices) leaking into live `/help` output. | **FIXED this commit, closes ISSUES.md #364.** Every honesty marker is now gone from user-visible text: `AllegianceOverview`/`HouseOverview`'s `[IMPLEMENTED]` tags and trailing "Subcommands NOT marked…" sentences, and `Day`/`Log`/`Render`/`Motd`'s appended "NOT YET IMPLEMENTED in acdream" tails are all removed, with the underlying retail text corrected/completed against the pseudo-C's own pristine consolidated data dumps (`Log` and `Motd` had also been silently truncated; `Render` had been entirely acdream-authored and is replaced with the real retail usage string). The three PARTIAL `/help` group topics (channels/chatting/commands) are now COMPLETE verbatim listings — `ClientCommunicationSystem::HelpStupidChannelHack @0x0056f290`'s three "vtable slot" operands, previously believed undecodable, are the same pooled/mislabeled-data artifact this campaign has hit before (AP-113's precedent); reading the function's own disassembly for the `push imm32` preceding each constructor call resolves all three directly. `messagetypes` is now a real ported construction (`LogTextTypeEnumMapper::IsLegalChannel`'s 14-id whitelist + `LogTextTypeToString`'s name table + the exact join/wrap format) instead of an acdream summary. Register row AP-184 RETIRED. See `RetailCommandHelpTable`'s class remarks and `RetailCommandHelpTableTests` (51 tests, all passing) for the full citation trail. |
|
||||
| 4 | (Not detailed to this session — reported as passed.) | **User-passed**, no action needed this round. |
|
||||
| 5 | The main window's 1/2/3/4 indicator buttons don't open/close the floating chat windows on click — the user's retail memory says clicking should toggle them. | **FIXED this commit.** CH6b's decomp grep (`gmMainChatUI::ListenToElementMessage @0x004CDA80` has no click case for these ids) was TRUE but incomplete — it never checked `UIElement_Button`'s own generic click handler. `UIElement_Button::HandleButtonClick @0x00471E50` reads an Enum property (`0x12`) off the button itself and, if present, routes through `ICIDM`'s action map to `UIElementManager::DoVisibilityToggleAction @0x0045B660` (the SAME function the `Alt+1..4` keybinds reach), which broadcasts element message `0x31` to every element registered as a listener for that action id (via property `0x24`, read once by `UIElement::Initialize`) — the receiving element's generic `UIElement::ListenToElementMessage` base-class handler then toggles its own visibility per its OWN property `0x58`. The committed fixture (`chat_2100006f.json`) confirms the button HALF is genuinely armed: all four indicators carry a real Enum-kind property `0x12` = `0x10000514`-`0x10000517`. But the floating-window fixture (`chat_floaty_2100005b.json`) authors NO matching property `0x24`/`0x58` anywhere, so nothing in the shipped DAT registers a floating chat window as that action's listener — the generic mechanism is real and armed on the button side but has no proven target in the data available to us. Per CLAUDE.md, the user's retail memory is the axiom regardless: `ChatWindowController.BindIndicatorClicks` (new) wires each indicator's click to the SAME `ToggleFloatingChatWindow(windowId)` chokepoint the keybinds use, explicitly as USER-DIRECTED retail behavior. `SetIndicatorOpen` stays the sole writer of the `Selected` mirror (`SuppressSelfToggle` stays `true`) so the visual stays consistent through the click round trip. Full reconciliation in `docs/research/2026-08-09-chat-retail-window-shell.md` §1.4 (the `@0x004CDA80` citation stays true as a statement about that one function; the CONCLUSION is corrected). New tests in `ChatLayoutConformanceTests.cs` exercise the click round trip and confirm keybind and click drive the same chokepoint. |
|
||||
| 6 | A settings-surface finding. | **Deferred to the settings track** — out of this commit's scope; no code change this round. |
|
||||
|
||||
Suite: 12,579 passed / 4 skipped / 0 failed (Release, complete solution —
|
||||
`AcDream.slnx`), up from the goal-window baseline 12,553/4/0 — net +26
|
||||
tests, zero regressions. Evidence: this commit's diff +
|
||||
`tests/AcDream.UI.Abstractions.Tests/Panels/Chat/RetailCommandHelpTableTests.cs`
|
||||
(51 tests) + `tests/AcDream.App.Tests/UI/Layout/ChatLayoutConformanceTests.cs`
|
||||
(new/updated indicator-button tests). No subagent review this session (hard
|
||||
constraint); no connected user gate for this commit's own changes (hard
|
||||
constraint — no client launches) — the next connected round should confirm
|
||||
`/help channels`/`/help chatting`/`/help commands`/`/help messagetypes` now
|
||||
show complete retail text with no meta-notice, and that clicking each of the
|
||||
four chat-window indicator buttons now opens/closes its floating window
|
||||
while the button's lit/unlit state stays correct.
|
||||
|
|
|
|||
|
|
@ -184,19 +184,123 @@ exactly two element ids: `0x1000046f` (max/min, dispatching
|
|||
(`idMessage == 7`, checked against `this->m_pCCS` / a `0x1000000b` attribute
|
||||
read). There is no case, anywhere in that function or its base-class fallback
|
||||
(`ChatInterface::ListenToElementMessage`, called unconditionally at the
|
||||
function's tail), for `0x10000522`–`0x10000525`. **Clicking a chat-window
|
||||
indicator button does NOTHING in retail — reading (a), pure indicator, is
|
||||
correct; reading (b) is refuted.** The `0x24` input-action-property theory
|
||||
in reading (b) does not even apply to a mouse click on the button itself: that
|
||||
property only wires *keyboard* dispatch (`UIElementManager::
|
||||
DoVisibilityToggleAction` in §1.3), not a button's own `UIElement` click
|
||||
message, which routes to its LISTENING PARENT — and that parent's handler has
|
||||
no case for these four ids. acdream ports this exactly: the four indicator
|
||||
buttons (`ChatWindowController._indicatorButtons`) carry no `OnClick` at all;
|
||||
`ChatWindowController.SetIndicatorOpen` is their only writer, called only from
|
||||
`RetailUiRuntime.OnWindowVisibilityChanged` in response to the floating
|
||||
window's own visibility changing (keybind or otherwise) — a pure one-directional
|
||||
mirror, matching retail exactly.
|
||||
function's tail), for `0x10000522`–`0x10000525`. **This citation is still a
|
||||
true statement about `gmMainChatUI::ListenToElementMessage` — see the round-4
|
||||
correction below for why it is the wrong function to have grepped.**
|
||||
|
||||
---
|
||||
|
||||
**ROUND-4 CORRECTION (2026-08-10) — the user's own retail memory ("clicking
|
||||
opens/closes the window") overruled the CONCLUSION above, and re-attacking the
|
||||
question with that as the starting axiom (per CLAUDE.md: the user's retail
|
||||
memory is the axiom, not a hypothesis to be argued down) found the exact
|
||||
mechanism the CH6b pass missed.**
|
||||
|
||||
The CH6b pass's mistake was scope, not accuracy: it proved
|
||||
`gmMainChatUI::ListenToElementMessage` has no click case for these ids, then
|
||||
reasoned "a button's click message… routes to its LISTENING PARENT" and
|
||||
stopped there. **That's wrong — `UIElement_Button` (Type 1, the class every
|
||||
one of these four indicators actually is) overrides its OWN click handling
|
||||
and never asks its parent window first:**
|
||||
|
||||
```
|
||||
UIElement_Button::HandleButtonClick @0x00471E50
|
||||
00471e65 if (UIElement::GetAttribute_Enum(this, 0x12, &actionId)) // reads its OWN property
|
||||
00471e72 if (actionId != 1)
|
||||
00471e95 build an InputEvent(actionId)
|
||||
00471eb2 ICIDM::GetActionMap()… dispatch through the action map
|
||||
```
|
||||
|
||||
Property `0x12` here is the SAME kind of "input action" enum as `0x24` — not
|
||||
the parent-window dispatch §1.4's original text assumed didn't apply to
|
||||
clicks. This IS the generic mechanism a click uses to reach
|
||||
`UIElementManager::DoVisibilityToggleAction @0x0045B660` (§1.3's own citation,
|
||||
previously assumed keybind-only) → `BroadcastElementMessage(target, 0x31,
|
||||
actionId, 0)` for every element registered under that action id via
|
||||
`RegisterElementForInputAction` (§1.3's property-`0x24` registration —
|
||||
confirmed as the ONLY call site of `RegisterElementForInputAction` in the
|
||||
whole binary) → the RECEIVING element's generic base-class handler:
|
||||
|
||||
```
|
||||
UIElement::ListenToElementMessage @0x00462340
|
||||
00462447 case 8: // idMessage - 0x29 == 8, i.e. raw idMessage 0x31
|
||||
0046244f GetAttribute_Enum(this, 0x58, &mode) // reads the RECEIVER's OWN property
|
||||
00462459 if (mode == 1) SetVisible(!currentlyVisible) // toggle
|
||||
0046245c else if (mode == 2) SetVisible(1) // force-show
|
||||
0046245f else if (mode == 3) SetVisible(0) // force-hide
|
||||
```
|
||||
|
||||
Neither `gmMainChatUI`, `gmFloatyChatUI`, nor `ChatInterface` overrides
|
||||
`ListenToElementMessage` for raw idMessage `0x31` (confirmed by reading all
|
||||
three switches directly — none has a case landing on it), so EVERY window
|
||||
falls through to this base-class handler unconditionally. This is a complete,
|
||||
generic, working "click toggles a registered listener's visibility" system —
|
||||
exactly the "authored button behavior" this reconciliation task hypothesized
|
||||
— and it is NOT gated on keyboard input the way the original §1.3 text
|
||||
assumed; `UIElementManager::KeyPressEvent`'s call to `DoVisibilityToggleAction`
|
||||
is simply ONE caller among the several that can reach it (the button's own
|
||||
`HandleButtonClick` is another).
|
||||
|
||||
**What the authored DATA shows, checked directly against the committed
|
||||
fixtures:**
|
||||
|
||||
- `chat_2100006f.json` — all four indicator elements (`0x10000522`-`0x10000525`)
|
||||
DO author an Enum-kind property `0x12` (confirmed by `Kind: 0` = Enum in the
|
||||
fixture's own property dump, matching `LayoutImporter.ConvertProperty`'s
|
||||
`EnumBaseProperty → UiPropertyKind.Enum` mapping exactly), with values
|
||||
`0x10000514`-`0x10000517` in element-id order. This is a real, present,
|
||||
correctly-typed action id — the button-click half of the generic mechanism
|
||||
is genuinely armed.
|
||||
- `chat_floaty_2100005b.json` — the floating chat window's own fixture
|
||||
authors **NO Enum-kind property `0x24` anywhere** (its only hit on property
|
||||
number 36 decimal is `Kind: 4` = Integer, an unrelated attribute — not the
|
||||
registration property) and **no property `0x58` at all**. Since
|
||||
`RegisterElementForInputAction` has exactly one call site in the entire
|
||||
binary (the property-`0x24` handler in `UIElement::Initialize`; no class
|
||||
anywhere calls it directly from code), nothing in the shipped floating chat
|
||||
window LayoutDesc ever registers it as a listener for ANY action id.
|
||||
`DoVisibilityToggleAction` would look up the button's action id, find zero
|
||||
registered listeners, and silently return — the click would fire a real
|
||||
message with no receiver.
|
||||
- The four action-id VALUES (`0x10000514`-`0x10000517`) are also not
|
||||
chat-specific: the identical four numbers, in the identical order, are
|
||||
`gmFriendsUI::PostInit`'s own child-element ids for its Add/Remove/Tell
|
||||
buttons and friends listbox (`UIElement::GetChildRecursive(this,
|
||||
0x10000514)` etc., confirmed by direct read). This is almost certainly a
|
||||
coincidence of Turbine's global per-dat-file asset-id allocator (ids are
|
||||
assigned client-wide, not scoped per panel), not a cross-reference —
|
||||
nothing in `gmFriendsUI` registers for input actions either.
|
||||
|
||||
**Conclusion: the generic UI action system is real, it exists, and the
|
||||
buttons genuinely arm their half of it — but the authored DATA available to
|
||||
us (both committed fixtures, generated from the installed DAT) does not wire
|
||||
a target for it.** This is consistent with, not a refutation of, the original
|
||||
CH6b grep of `gmMainChatUI::ListenToElementMessage` — that citation was
|
||||
looking in the wrong function, but its NEGATIVE RESULT (retail's window-level
|
||||
message handlers never claim these clicks) still holds; the generic
|
||||
mechanism, if it does connect the dots in real retail, does so entirely
|
||||
below the level either grep could see. **Per CLAUDE.md, the user's retail
|
||||
memory is the axiom regardless: acdream now wires each indicator's click to
|
||||
toggle its floating window through the SAME `ToggleFloatingChatWindow`
|
||||
chokepoint the `Alt+1..4` keybinds use
|
||||
(`ChatWindowController.BindIndicatorClicks`, called by `RetailUiRuntime`
|
||||
right after mounting the main chat window) — explicitly as USER-DIRECTED
|
||||
retail behavior, not a claim that the generic-action-system data path has
|
||||
been proven end-to-end.** `SetIndicatorOpen` stays the ONLY writer of the
|
||||
indicator's `Selected` mirror (`UiButton.SuppressSelfToggle` stays `true`);
|
||||
the click drives the real toggle, and the mirror reports the outcome back —
|
||||
so the visual stays consistent through the round trip even though the write
|
||||
is now two-way at the FEATURE level.
|
||||
|
||||
---
|
||||
|
||||
acdream ports this exactly: the four indicator buttons
|
||||
(`ChatWindowController._indicatorButtons`) now carry a real `OnClick`
|
||||
(`ChatWindowController.BindIndicatorClicks`, round 4); the mirror half is
|
||||
unchanged — `ChatWindowController.SetIndicatorOpen` is still the ONLY writer
|
||||
of `Selected`, still called from `RetailUiRuntime.OnWindowVisibilityChanged`
|
||||
in response to the floating window's own visibility changing, regardless of
|
||||
what triggered it (click, keybind, or a restored layout).
|
||||
|
||||
### 1.5 Closing a floaty window from its own title bar
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue