Three findings from the user's first Configure Keyboard look (OP8 gate, 2026-08-14), each root-caused against the named retail decomp: - #394 row-caption font: the synthesized action-label UiText never set DatFont and fell to the debug bitmap font. The authored row template (0x21000009/0x1000002F, retail UIOption_ActionKeyMap) carries FontDid 0x4000000A (18px serif) — Bind now takes resolveTemplateFont and applies the template's own authored font, resolved once per template pair. - #395 key captions: raw enum spellings ("Shift+ShiftLeft") replaced by the port of CInputManager_WIN32::GetNameFromKey @0x00687F40 / GetNameFromKey_Internal @0x00687800 (RetailKeyNames): DAT string-table override by DIK-name hash (key enum 4 -> 0x2300000A, meta enum 5 -> 0x2300000B, delimiter enum 3 -> 0x23000007 — GetDIDByEnum category 4, live-probed), else the OS keyboard layout's own key name ("SKIFT") via PlatformKeyNameProvider (Win32 GetKeyNameTextW — register row AD-96 for the DirectInput-vs-GetKeyNameText adaptation), else the DIK-suffix spelling. Bare modifier-key bindings show only the key name. - #396 capture feedback: clicking a mapping button now opens retail's instruction dialog (InitiateBinding @0x004899D0 -> OpenMapWarnDialog @0x00488A00): a type-2 WAIT dialog on retail's MapWarn queue key 0x10000001 with ID_ActionKeyMap_MapInstructions (0x23000004, ACTION variable interpolated), closed on key hit or ESC through the capture callback; capture is not armed if the dialog cannot open, matching retail. New RetailWaitDialogView (wait root 0x31 — same authored popup/message pair 0x3D/0x3E as the confirmation root, live-DAT probed) behind a shared IRetailDialogView presenter seam. Probe evidence (env-gated, kept): KeyboardConfigLiveMountProbeTests.ProbeKeyboardFontsAndKeyNameStrings. Register: AD-96 filed. Gate script OP8 section updated (step 4 rewritten; the "pressed/active state is enough" contract is retired). Full Release solution suite green (13,424 passed / 4 skips). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
1528e5693b
commit
30fa6ee507
16 changed files with 1105 additions and 24 deletions
|
|
@ -24,6 +24,62 @@ What does NOT go here:
|
|||
- Every session: scan OPEN issues at start; promote/close anything we touched during the session before ending.
|
||||
- Promoting to a Phase: mark as `DONE (promoted to Phase X)` + commit SHA where the Phase entry landed.
|
||||
|
||||
## #396 — Configure Keyboard: no capture-instruction dialog on a mapping-button click
|
||||
|
||||
**Status:** ROOT-CAUSED + FIXED (this commit) — pending the user's re-gate.
|
||||
Filed 2026-08-14 at the OP8 re-gate (user report: "nothing happens when I
|
||||
press an option button", with the retail screenshot showing the instruction
|
||||
dialog). The OP8 port armed `InputDispatcher.BeginCapture` with no visible
|
||||
feedback; retail's `UIOption_ActionKeyMap::InitiateBinding @0x004899D0`
|
||||
opens a type-2 WAIT dialog (`OpenMapWarnDialog @0x00488A00`: queue key
|
||||
`0x10000001`, text `ID_ActionKeyMap_MapInstructions` from table `0x23000004`
|
||||
with the row's action label as its ACTION variable — "The next key you press
|
||||
or mouse button that you click will be mapped to the '…' action. … Press the
|
||||
ESC key to cancel.") BEFORE registering the key handler, and refuses to arm
|
||||
capture if the dialog cannot open. Fix: `RetailWaitDialogView` (wait root
|
||||
`0x31` — same authored popup/message pair `0x3D`/`0x3E` as the confirmation
|
||||
root, live-DAT probed) + `RetailDialogFactory.MakeWait` +
|
||||
`KeyboardConfigController.Bindings.Open/CloseCaptureInstructions`, closed on
|
||||
key hit or ESC through the capture callback. Retail's own text supplies the
|
||||
ESC line; ESC handling stays in the dispatcher's modal capture (a dialog-side
|
||||
cancel would race it).
|
||||
|
||||
## #395 — Configure Keyboard: key captions show raw enum spellings, not retail's localized key names
|
||||
|
||||
**Status:** ROOT-CAUSED + FIXED (this commit) — pending the user's re-gate.
|
||||
Filed 2026-08-14 at the OP8 re-gate (user report: acdream shows
|
||||
"Shift+ShiftLeft" where retail shows "SKIFT" on their Swedish layout).
|
||||
`DescribeChord` printed Silk enum spellings; retail's
|
||||
`CInputManager_WIN32::GetNameFromKey @0x00687F40` resolves each control
|
||||
through `GetNameFromKey_Internal @0x00687800`: DAT string-table override by
|
||||
ELF hash of the DIK name (key table enum 4 → `0x2300000A`, meta enum 5 →
|
||||
`0x2300000B` — GetDIDByEnum category 4, live-probed; the shipped tables
|
||||
author exactly `DIK_LCONTROL` → "Left Ctrl" and `DIK_LMENU` → "Left Alt"),
|
||||
else the OS keyboard layout's own name, with modifier prefixes joined by the
|
||||
authored `ID_KeyDescDelimiter` ("+", `0x23000007`) and a bare modifier-key
|
||||
binding showing only the key name (retail's walk-mode row is meta-mode 0).
|
||||
Fix: `RetailKeyNames` (the pipeline port) + `PlatformKeyNameProvider`
|
||||
(Win32 `GetKeyNameTextW` — register row AD-96 for the
|
||||
DirectInput-vs-GetKeyNameText adaptation and the non-Windows fallback).
|
||||
|
||||
## #394 — Configure Keyboard: row captions render in the debug bitmap font, not the authored 18px serif
|
||||
|
||||
**Status:** ROOT-CAUSED + FIXED (this commit) — pending the user's re-gate.
|
||||
Filed 2026-08-14 at the OP8 re-gate (user side-by-side screenshot: acdream's
|
||||
"Move Forward" label vs retail's serif). The controller-synthesized row
|
||||
caption (`BuildActionRow`'s composed `UiText`) never set `DatFont`, so it
|
||||
fell back to the debug bitmap font; the authored action-row template
|
||||
(`0x21000009` element `0x1000002F`, retail type `UIOption_ActionKeyMap`)
|
||||
carries `FontDid 0x4000000A` — the 18px serif retail draws the label with
|
||||
(live-DAT probed: header `0x1000002E` = `0x4000000F` 30px gothic, key
|
||||
buttons `0x10000030-32` = `0x40000001` 18px serif — the buttons already
|
||||
resolved their authored font through the production template build; only the
|
||||
synthesized caption was wrong). Fix: `Bind` takes `resolveTemplateFont`,
|
||||
resolved once per template pair from the row template's own authored FontDid
|
||||
and applied to the caption `UiText`. Probe evidence:
|
||||
`KeyboardConfigLiveMountProbeTests.ProbeKeyboardFontsAndKeyNameStrings`
|
||||
(env-gated, kept).
|
||||
|
||||
## #393 — Texture detail options: retail's "High Resolution Textures" toggle + Landscape/Environment TextureDetail mip-skip
|
||||
|
||||
**Status:** OPEN — filed 2026-08-14 from the highres-texture verification
|
||||
|
|
|
|||
|
|
@ -188,6 +188,7 @@ readiness/requeue adaptation. See
|
|||
| AD-91 | **Filed 2026-08-13 at the #390 port.** acdream's display-change clamp covers ALL registered floating windows; retail's does not — every retail floaty overrides `MoveTo` with the clamp `x = max(0, min(x, parentW − selfW))` EXCEPT `gmFloatyChatUI` (floating chats 2–4), which has no clamp and can genuinely strand off-screen on a resolution change (decomp finding, `docs/research/2026-08-13-retail-ui-display-change.md`). The display block's product requirement ("UI windows must stay reachable on resolution change", the 2026-08-13 /goal) overrides the exception. | `src/AcDream.App/UI/RetailWindowLayoutPersistence.cs` (`ClampAllToScreen` — clamps every attached handle, floating chats included) | User-directed reachability beats reproducing a retail defect-shaped gap; the clamp math itself is retail's own, applied uniformly. | A retail-parity comparison that deliberately strands a floating chat window will find acdream rescuing it where retail leaves it lost. | `UIElementManager::RefreshEvent @0x0045C530`; `UIElement::UpdateForParentSizeChange @0x00462640`; the per-floaty `MoveTo` clamp overrides; docs/research/2026-08-13-retail-ui-display-change.md |
|
||||
| AD-92 | **Filed 2026-08-13 at the #376/#388 review fix round (blast M6 / mechanism M4).** Two switcher adaptations with no retail counterpart: (1) the fullscreen refresh rate is the monitor's HIGHEST for the picked WxH — retail passed the device mode's own refresh as-is (`Device::ForceDisplayResolution`); (2) an invalid/unsupported fullscreen request is a logged refusal that leaves the window unchanged — retail attempted the switch and surfaced the device error. The persisted-flag divergence a refusal leaves behind is ISSUES #392. | `src/AcDream.App/Settings/DisplayModeSwitching.cs` (`TryFindRefreshRate`, the refusal paths); `src/AcDream.App/Settings/RuntimeSettingsTargets.cs` (`Apply`'s refused-mode logging) | Highest-refresh is strictly better on modern variable-refresh panels (retail predates them); refuse-and-log is #388's own no-crash requirement. | A capture comparing retail's exact chosen refresh for a mode will differ; a server/tooling flow expecting an error dialog on an invalid mode sees a console line instead. | `Device::ForceDisplayResolution @gmClient::Init 0x004047af`; docs/research/2026-08-13-376-388-{mechanism,blast}-review.md |
|
||||
| AD-94 | **Filed 2026-08-14 at the secure-trade feature.** Retail's `Event_AcceptTrade` payload (`Trade::Pack @0x005B9FF0`) appends two `PackableList<ContentProfile>` staged-item lists after the six fixed fields; acdream sends both as ZERO-COUNT lists. ACE parses and then discards the ENTIRE payload (`HandleActionAcceptTrade()` takes zero arguments — server trade state is fully self-derived; lane B §quirks), so the difference is unobservable against ACE; a byte-capture comparison against a real retail client would differ from offset 40. | `src/AcDream.Core.Net/Messages/TradeRequests.cs` (`BuildAcceptTrade`) | The `ContentProfile` pack layout was not byte-verified (ACE never reads it — no reader to check against), and guessing a wire struct violates the workflow; zero-count lists are well-formed `PackableList`s. | A future server that actually validates the accept echo would see empty item lists and could refuse or desync the accept. | `Trade::Pack @0x005B9FF0`; `GameActionAcceptTrade.cs:11-16`; `docs/research/2026-08-14-trade-laneB-wire.md` Table 1 |
|
||||
| AD-96 | **Filed 2026-08-14 at the OP8 re-gate fix round (key-name display).** Retail's `GetNameFromKey_Internal @0x00687800` falls back from the DAT string tables (key enum 4 → `0x2300000A`, meta enum 5 → `0x2300000B`) to the OS keyboard layout's own key name via DirectInput `IDirectInputDevice8::GetObjectInfo` (`tszName` — "SKIFT" on a Swedish layout). acdream reads the SAME layout-resident name data through Win32 `GetKeyNameTextW` instead (no DirectInput device exists in-process); on non-Windows hosts there is no OS lookup at all and the DIK-suffix spelling shows (un-localized English, e.g. "LSHIFT"). Mouse chords keep the pre-existing enum spelling — retail names them through the DirectInput mouse device. | `src/AcDream.App/Platform/PlatformKeyNameProvider.cs`; `src/AcDream.App/UI/Layout/RetailKeyNames.cs` (`Describe`, the mouse-device early-out) | GetKeyNameText and DirectInput's key names both come from the active keyboard-layout tables; adding a DirectInput device solely for name strings would be a heavyweight, dead-end dependency. Linux graphical work is parked at Slice L1. | A key whose GetKeyNameTextW name differs from DirectInput's `tszName` on some layout shows a slightly different caption than retail did; Linux graphical shows English DIK-suffix names where retail-on-Wine would localize; a mouse-chord caption reads as the Silk enum, not retail's device string. | `CInputManager_WIN32::GetNameFromKey_Internal @0x00687800`; `GetNameFromKey @0x00687F40`; `ControlSpecification::GetDIKName @0x0068ACB0`; `DBCache::GetDIDFromEnumStatic` category-4 probe 2026-08-14 (`KeyboardConfigLiveMountProbeTests.ProbeKeyboardFontsAndKeyNameStrings`) |
|
||||
| AD-93 | **Filed 2026-08-13 at social gate round 2, item 5 (the refused-drop notice port).** Two narrow gaps in the `ServerSaysAttemptFailed @0x0058EAE0` port: (1) **latched-guid preference** — retail's 0x00A0 dispatcher (`@0x0055B342`) PREFERS `prevRequestObjectID` over the wire guid when picking the item to name; acdream's `InventoryTransactionState.OnMoveFailed` instead REQUIRES the wire guid to match the latch (unobservable against ACE, which always sends the request's own guid on 0x00A0, and it protects a stale latch from mislabeling an unrelated failure — acdream has no retail-style latch timeout). (2) **unlatched request kinds** — retail latches `IR_MOVE`/`IR_WIELD` too; acdream's kind enum has no Move/Wield rows because wields ride `AutoWieldController` outside the single-request gate, so a refused wield/3D-move shows only the generic `HandleFailureEvent` leg, never "The X can't be wielded/moved". | `src/AcDream.Core/Items/InventoryTransactionState.cs` (`OnMoveFailed`); `src/AcDream.Core/Chat/InventoryFailureMessages.cs` (`Compose`'s absent Move/Wield rows); `src/AcDream.App/UI/ItemInteractionController.cs` (`OnInventoryRequestFailed`) | The match requirement is the compensating guard for the missing latch timeout; adding Wield/Move kinds means routing those sends through the single-request gate they deliberately bypass today — a behavior change beyond this gate item. | Only observable against a server that sends 0x00A0 with a guid that differs from the request's item (ACE never does), or on a refused wield/move, which shows no "can't be wielded/moved" verb line where retail would show one. | `ACCWeenieObject::ServerSaysAttemptFailed @0x0058EAE0`; the 0x00A0 dispatcher `@0x0055B342`; `ACCWeenieObject::RecordRequest @0x0058C220`; `docs/research/2026-08-13-confirm-and-weenie-error-display.md` §2 |
|
||||
|
||||
---
|
||||
|
|
|
|||
|
|
@ -942,6 +942,28 @@ Three live runs against local ACE (`127.0.0.1:9000`, `+Acdream`,
|
|||
> Save As...), Command + Mapping 1-3 column headers, and NOTHING
|
||||
> rendered above or outside the framed panel.
|
||||
|
||||
> **Re-gate note (2026-08-14 fix round — #394/#395/#396):** three findings
|
||||
> from the first OP8 look at this screen, all fixed:
|
||||
> 1. **Row-caption font (#394):** the action labels ("Move Forward", …)
|
||||
> now draw in the row template's authored 18px serif (FontDid
|
||||
> `0x4000000A`), not the debug bitmap font. The gothic section headers
|
||||
> and the key-button captions were already using their authored fonts.
|
||||
> 2. **Key caption text (#395):** key buttons now show retail's localized
|
||||
> key names — DAT overrides first ("Left Ctrl"/"Left Alt" are the only
|
||||
> authored ones), then YOUR keyboard layout's own name (a Swedish
|
||||
> layout shows "SKIFT" for the Shift key, exactly like your retail
|
||||
> screenshot), modifiers joined with "+" (chords like "SKIFT+M"), and a
|
||||
> binding to a bare modifier key shows just the key name — never
|
||||
> "Shift+ShiftLeft". Mouse chords keep enum spellings (AD-96).
|
||||
> 3. **Capture-instruction dialog (#396):** clicking a mapping button now
|
||||
> opens retail's own instruction dialog ("The next key you press or
|
||||
> mouse button that you click will be mapped to the '<action>'
|
||||
> action. … Press the ESC key to cancel.") — the wait-dialog shape from
|
||||
> your retail screenshot, with the row's action name interpolated. It
|
||||
> closes when you press the new key OR press ESC. Step 4 below is
|
||||
> REWRITTEN accordingly; the old "a pressed/active state is enough"
|
||||
> contract is retired.
|
||||
|
||||
**Known, tracked behaviors — do NOT file as defects (read before testing):**
|
||||
|
||||
- **Shared combat keys prompt a false conflict (ISSUES #373).** Retail
|
||||
|
|
@ -989,11 +1011,13 @@ line calling it INERT no longer applies.
|
|||
### Rebind a movement key live
|
||||
|
||||
4. **On the Movement tab, find "Move Forward"** (should show two bound
|
||||
keys, "W" and "Up"). Click the SECOND key button (currently "Up").
|
||||
The button should visually indicate it is listening for input
|
||||
(retail's own capture-prompt text is not wired to a tooltip in this
|
||||
port — a simple pressed/active state is enough to confirm capture
|
||||
started).
|
||||
keys — "W" and your layout's name for the up-arrow key). Click the
|
||||
SECOND key button. **Retail's capture-instruction dialog opens**
|
||||
(#396 re-gate): "The next key you press or mouse button that you
|
||||
click will be mapped to the 'Move Forward' action. …Press the ESC
|
||||
key to cancel." — naming THIS row's action. Press ESC once first:
|
||||
the dialog closes and nothing changes. Click the button again to
|
||||
re-open it for step 5.
|
||||
5. **Press a different key**, e.g. `U`. The button should immediately
|
||||
update to show "U".
|
||||
6. **Move your character forward using W and U** (both should now work
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue