refactor(input): own gameplay action routing
Move the sole semantic action-priority graph, combat and diagnostic commands, and retained-root item-drop lifetime behind focused typed owners. Preserve retail toggle behavior, explicit auto-wield cancellation, shutdown quiescence, and symmetric callback cleanup. Co-authored-by: Codex <codex@openai.com>
This commit is contained in:
parent
8b8afeefa3
commit
4eae9b4f5a
25 changed files with 2608 additions and 418 deletions
|
|
@ -27,12 +27,13 @@ What does NOT go here:
|
|||
## Current queue — 2026-07-22
|
||||
|
||||
- **Active structural work:** `GameWindow` decomposition. Slices 1–7 are
|
||||
complete; Slice 8 checkpoints A–E now own native callbacks, live-session
|
||||
complete; Slice 8 checkpoints A–F now own native callbacks, live-session
|
||||
composition, world-environment state, reversible device input/raw pointer,
|
||||
and physical framebuffer publication outside the shell.
|
||||
physical framebuffer publication, gameplay action priority, typed commands,
|
||||
and the retained-root item-drop edge outside the shell.
|
||||
`GameWindow.OnUpdate` and `GameWindow.OnRender` are typed orchestration
|
||||
handoffs and the class is 4,266 lines / 194 fields / 65 methods. Remaining
|
||||
Slice 8 action-routing/settings/composition/shutdown
|
||||
handoffs and the class is 4,057 lines / 198 fields / 54 methods. Remaining
|
||||
Slice 8 settings/resource/composition/shutdown
|
||||
cleanup is active in
|
||||
[`docs/architecture/code-structure.md`](architecture/code-structure.md).
|
||||
This is the behavior-preserving prerequisite before new M4 feature bodies.
|
||||
|
|
|
|||
|
|
@ -625,11 +625,12 @@ The accepted host order above is preserved as TS-53; it is not overclaimed as
|
|||
the exact retail `Client::UseTime` order. See the completed Slice 6 ledger and
|
||||
`memory/project_gamewindow_decomposition.md`.
|
||||
|
||||
The render callback currently owns the GPU frame boundary and draw graph. Slice
|
||||
7 extracts that graph without changing its order: per-resource frame begins and
|
||||
render-thread uploads; world/PView and its two shared-alpha scopes; portal and
|
||||
paperdoll private viewports; retained gameplay UI; ImGui devtools; screenshot;
|
||||
then the GPU-flight close in `finally`. Both UI stacks coexist in the same frame.
|
||||
`GameWindow.OnRender` likewise owns only one handoff to the shipped
|
||||
`RenderFrameOrchestrator`. Its frozen graph begins per-resource frames and
|
||||
render-thread uploads; draws world/PView and its two shared-alpha scopes;
|
||||
renders portal and paperdoll private viewports, retained gameplay UI, ImGui
|
||||
devtools, and screenshots; then closes the GPU-flight transaction in
|
||||
`finally`. Both UI stacks coexist in the same frame.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -828,10 +829,11 @@ Current movement/collision ownership:
|
|||
routers; Slice 4 moved hydration, teardown, inbound authority, network
|
||||
updates, and reusable motion-runtime policy over canonical
|
||||
`LiveEntityRuntime`. Slices 5–7 complete landblock presentation and the
|
||||
update/render frame graphs. Slice 8 checkpoints A–E now own the native
|
||||
update/render frame graphs. Slice 8 checkpoints A–F now own the native
|
||||
callback shell, live-session composition, world environment, reversible
|
||||
input/pointer lifetime, and physical framebuffer publication. Gameplay action
|
||||
routing is the next checkpoint. The reconciled ledger and sequence live in
|
||||
input/pointer lifetime, physical framebuffer publication, the sole gameplay
|
||||
action-priority graph, typed commands, and the retained-root item-drop edge.
|
||||
Two-phase runtime settings is the next checkpoint. The reconciled ledger and sequence live in
|
||||
`docs/architecture/code-structure.md`. This decision does not reclassify the
|
||||
remaining L.2 conformance work or Track LH.
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@ after Slice 5 closeout 8,811 lines / 247 fields / 153 method
|
|||
after Slice 6 closeout 7,026 lines / 241 fields / 108 methods
|
||||
after Slice 7 draw-frame cutover 4,666 lines / 196 fields / 70 methods
|
||||
after Slice 8 checkpoint D 4,330 lines / 192 fields / 67 methods
|
||||
after Slice 8 checkpoint E 4,266 lines / 194 fields / 65 methods
|
||||
after Slice 8 checkpoint F 4,057 lines / 198 fields / 54 methods
|
||||
```
|
||||
|
||||
`GameWindow` is the single object that:
|
||||
|
|
@ -690,15 +692,21 @@ slices. `OnClosing` delegates to the existing retryable shutdown transaction.
|
|||
Silk callbacks become narrow calls into the input, update, render, resize,
|
||||
focus, and shutdown owners.
|
||||
|
||||
Checkpoint E is complete. `CameraPointerInputController` owns raw pointer,
|
||||
Checkpoints E and F are complete. `CameraPointerInputController` owns raw pointer,
|
||||
camera cursor/focus/scroll/sensitivity behavior; `FramebufferResizeController`
|
||||
alone publishes physical framebuffer changes. All Silk, dispatcher, retained
|
||||
UI, and optional devtools device edges are reversible, transactional, and
|
||||
terminal after disposal. Logical cutoff precedes live-session retirement;
|
||||
physical detach follows it, so neither copied callbacks nor a failed event
|
||||
remove can interfere with graceful transport teardown. `GameWindow` is now
|
||||
4,266 raw lines / 194 fields / 65 methods. Checkpoints F–L remain active, with
|
||||
gameplay action routing next.
|
||||
remove can interfere with graceful transport teardown.
|
||||
|
||||
`GameplayInputActionRouter` is now the sole `InputDispatcher.Fired`
|
||||
subscriber and preserves the accepted input-priority graph. Focused combat,
|
||||
diagnostic, and general command owners replace the remaining window command
|
||||
bodies. The retained-root item-drop edge has one reversible owner, while its
|
||||
deferred toolbar targets become inert before session retirement. `GameWindow`
|
||||
is now 4,057 raw lines / 198 fields / 54 methods. Checkpoints G–L remain
|
||||
active, with two-phase runtime settings next.
|
||||
|
||||
### 4.4 Exit criteria
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# acdream — strategic roadmap
|
||||
|
||||
**Status:** Living document. Updated 2026-07-22. **M3 landed; M4 is next after the active `GameWindow` structural prerequisite.** M3's retail casting/UI, R6 locomotion/collision/projectile/teleport/radar rebaseline, deterministic fresh-login/portal world lifecycle, and final two-client portal observer flow are user-gated. The current program is the behavior-preserving ownership campaign in [`docs/architecture/code-structure.md`](../architecture/code-structure.md); Slices 1–7 and Slice 8 checkpoints A–E are complete, with the remaining composition/shutdown checkpoints active. New M4 quest/emote/character-creation feature bodies wait until that campaign is complete. Issue #225's lifestone/particle alpha comparison remains a separate rendering visual gate.
|
||||
**Status:** Living document. Updated 2026-07-22. **M3 landed; M4 is next after the active `GameWindow` structural prerequisite.** M3's retail casting/UI, R6 locomotion/collision/projectile/teleport/radar rebaseline, deterministic fresh-login/portal world lifecycle, and final two-client portal observer flow are user-gated. The current program is the behavior-preserving ownership campaign in [`docs/architecture/code-structure.md`](../architecture/code-structure.md); Slices 1–7 and Slice 8 checkpoints A–F are complete, with the remaining composition/shutdown checkpoints active. New M4 quest/emote/character-creation feature bodies wait until that campaign is complete. Issue #225's lifestone/particle alpha comparison remains a separate rendering visual gate.
|
||||
**Purpose:** One source of truth for where the project is and where it's going. Every observed defect or missing feature has a named phase that owns it; when something looks wrong in-game, look here to find the phase that'll address it. Implementation details live in per-phase specs under `docs/superpowers/specs/`, not in this file.
|
||||
|
||||
---
|
||||
|
|
@ -79,7 +79,7 @@ second synchronized soak pass with graceful exits, and the six stable PNG
|
|||
checkpoints preserve Slice 6 presentation. Issue #232 tracks the coarse
|
||||
process-residency gate's diagnostic blind spot; no tolerance was loosened.
|
||||
|
||||
Final Slice 8 composition/shutdown cleanup is active. Checkpoints A–E now own
|
||||
Final Slice 8 composition/shutdown cleanup is active. Checkpoints A–F now own
|
||||
the frozen shell boundary, all nine native callback edges, live-session
|
||||
reset/selection/entry/route composition, and world clock/sky/day/weather/
|
||||
AdminEnvirons state. Checkpoint E adds reversible, transactional Silk,
|
||||
|
|
@ -87,9 +87,12 @@ dispatcher, retained-UI, and devtools input edges; a focused raw pointer owner;
|
|||
and one physical framebuffer-size publisher. Logical callback cutoff and
|
||||
live-session retirement precede physical removal, so failed device detach
|
||||
cannot block graceful transport close. `GameWindow` is 4,266 lines / 194
|
||||
fields / 65 methods; the Checkpoint E Release suite passes 7,477 tests / 5
|
||||
skips. Gameplay routing, settings, startup/resource transfer, shutdown, soak,
|
||||
and closeout checkpoints F–L remain.
|
||||
fields / 65 methods. Checkpoint F adds the sole gameplay action-priority
|
||||
subscriber, typed combat/diagnostic/general commands, and a reversible
|
||||
retained-root item-drop binding. `GameWindow` is now 4,057 lines / 198 fields /
|
||||
54 methods; the Checkpoint F Release suite passes 7,524 tests / 5 skips.
|
||||
Settings, startup/resource transfer, shutdown, soak, and closeout checkpoints
|
||||
G–L remain.
|
||||
|
||||
This is a behavior-preserving structural program. Severe regressions still get
|
||||
root-cause fixes in separate commits; ordinary feature work resumes with M4
|
||||
|
|
|
|||
|
|
@ -39,15 +39,17 @@ diagnostic owners preserve the accepted draw/failure graph. `GameWindow` is
|
|||
campaign baseline. The full Release suite passes 7,341 tests / 5 skips; the
|
||||
315.6-second capped/reconnect lifecycle gate and 395.2-second synchronized
|
||||
nine-destination soak pass with graceful exits, and six stable PNG checkpoints
|
||||
preserve Slice 6 presentation. Final Slice 8 checkpoints A–E are complete:
|
||||
preserve Slice 6 presentation. Final Slice 8 checkpoints A–F are complete:
|
||||
native callbacks and live-session composition now have explicit retryable
|
||||
owners. Checkpoint D adds the sole world-environment owner for clock, DAT sky,
|
||||
day group, weather, and AdminEnvirons state. Checkpoint E adds terminal,
|
||||
transactional ownership for Silk/dispatcher/retained/devtools input, the raw
|
||||
camera pointer, focus, and physical framebuffer size. Graceful live-session
|
||||
retirement now precedes physical callback removal. `GameWindow` is 4,266 lines
|
||||
/ 194 fields / 65 methods; 7,477 Release tests pass / 5 skip. Checkpoints F–L
|
||||
remain active. Issue #232 tracks process-residency variance in the soak without
|
||||
retirement now precedes physical callback removal. Checkpoint F adds the sole
|
||||
gameplay action-priority owner, typed combat/diagnostic/general commands, and a
|
||||
reversible retained-root item-drop binding. `GameWindow` is 4,057 lines / 198
|
||||
fields / 54 methods; 7,524 Release tests pass / 5 skip. Checkpoints G–L remain
|
||||
active. Issue #232 tracks process-residency variance in the soak without
|
||||
loosening its leak threshold.
|
||||
|
||||
Carried:
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ audit.
|
|||
- [x] D — extract retail world-environment/day/weather behavior.
|
||||
- [x] E — extract two-phase raw pointer/camera input, focus, and framebuffer
|
||||
resize behind symmetric named subscriptions.
|
||||
- [ ] F — extract the sole gameplay input-action router plus focused combat and
|
||||
- [x] F — extract the sole gameplay input-action router plus focused combat and
|
||||
diagnostic command owners.
|
||||
- [ ] G — extract two-phase persisted settings/display/quality ownership.
|
||||
- [ ] H — give terrain atlas, sky shader, retained `UiHost`, and both frame roots
|
||||
|
|
@ -527,6 +527,23 @@ connected lifecycle and visual gates.
|
|||
- Make Combat, Camera, dispatcher, and retained-root subscriptions named,
|
||||
transactional, and symmetrically detached.
|
||||
|
||||
Result: `GameplayInputActionRouter` is the sole gameplay subscriber to
|
||||
`InputDispatcher.Fired` and preserves the frozen pointer → scroll → combat →
|
||||
Press/DoubleClick gate → retained UI → selection → movement → command
|
||||
priority. Focused command owners now route combat, diagnostics, window/player
|
||||
mode, item-target mode, and Escape without calling feature bodies on
|
||||
`GameWindow`. `RetainedUiGameplayBinding` owns the outside-UI item-drop edge;
|
||||
the combat/diagnostic deferred slots release their targets before session
|
||||
retirement, and the retained binding detaches transactionally afterward.
|
||||
Named-retail review
|
||||
also corrected `ToggleCombatMode @ 0x0056C8C0`: active combat short-circuits to
|
||||
peace without an equipment lookup, while an incompatible Held object prints
|
||||
the exact retail notice and sends no mode request. Three corrected-diff review
|
||||
loops are clean; 54 focused App tests, 20 Core combat tests, the App suite
|
||||
(3,155 pass / 3 intentional skips), the Release build, and the complete suite
|
||||
(7,524 pass / 5 intentional skips) pass. `GameWindow` is 4,057 raw lines / 198
|
||||
fields / 54 methods.
|
||||
|
||||
### G — two-phase runtime settings
|
||||
|
||||
- Construct `RuntimeSettingsController` before Window.Create and source startup
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
## Sources
|
||||
|
||||
- `ClientCombatSystem::GetDefaultCombatMode @ 0x0056B310`
|
||||
- `ClientCombatSystem::SetCombatMode @ 0x0056BE30`
|
||||
- `ClientCombatSystem::ToggleCombatMode @ 0x0056C8C0`
|
||||
- `ACCWeenieObject::GetObjectAtLocation @ 0x0058CE00`
|
||||
- `CM_Physics::DispatchSB_ParentEvent @ 0x006ACAF0`
|
||||
- `SmartBox::HandleParentEvent @ 0x004535D0`
|
||||
|
|
@ -52,10 +54,28 @@ GetDefaultCombatMode(showError):
|
|||
return Magic
|
||||
|
||||
if showError == false:
|
||||
print the retail cannot-use-held-item notice
|
||||
print "You can't enter combat mode while wielding the %s"
|
||||
formatted with held.GetObjectName(NAME_APPROPRIATE)
|
||||
return NonCombat
|
||||
```
|
||||
|
||||
`ToggleCombatMode` preserves that rejected result verbatim:
|
||||
|
||||
```text
|
||||
ToggleCombatMode():
|
||||
if current combat mode != NonCombat:
|
||||
SetCombatMode(NonCombat, send = true)
|
||||
return
|
||||
|
||||
requested = GetDefaultCombatMode(showError = false)
|
||||
SetCombatMode(requested, send = true)
|
||||
```
|
||||
|
||||
`SetCombatMode` immediately returns when `requested == current`. Therefore an
|
||||
incompatible Held object prints the notice in `GetDefaultCombatMode`, returns
|
||||
`NonCombat`, and produces no wire request or local mode transition. It is not
|
||||
coerced to unarmed Melee.
|
||||
|
||||
`GetObjectAtLocation` walks the player's ordered inventory-placement list and
|
||||
returns the first entry whose location intersects the requested mask (and whose
|
||||
priority intersects the requested priority when that priority is non-zero).
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue