gmp(M02): extract local player movement

Work-Package: M02-GMP-MOVEMENT-001
Agent: sindo-main-codex
Tests: local movement and player input regressions; asset-free scene; renderer dry-run; coordinate, streaming, documentation and coordination gates
Fidelity: preserves current sandbox speed, acceleration, sprint and camera-relative flight behavior; build-12340 parity remains unverified
This commit is contained in:
2026-07-14 22:59:33 +04:00
parent 14dead194b
commit 435e1c95d2
9 changed files with 601 additions and 56 deletions
+19 -15
View File
@@ -5,9 +5,9 @@
| Field | Value |
|---|---|
| Status | Partial |
| Target/work package | M02 / M02-GMP-INPUT-001 |
| Target/work package | M02 / M02-GMP-INPUT-001, M02-GMP-MOVEMENT-001 consumer update |
| Owners | Gameplay input boundary; `sindo-main-codex` for current package |
| Last verified | `6bd2e84`, 2026-07-14 |
| Last verified | `working tree`, 2026-07-14 |
| Profiles/capabilities | Current render-sandbox defaults; `Blizzlike335` binding semantics not yet verified |
## Purpose
@@ -31,8 +31,8 @@ flowchart LR
Devices[Keyboard and mouse] --> InputMap[Godot Input Map]
InputMap --> Source[PlayerInputSource]
Source --> Intent[MoveIntent]
Intent --> Controller[ThirdPersonWowController]
Controller --> Movement[Current sandbox movement]
Intent --> Movement[LocalPlayerMovementController]
Movement --> Controller[ThirdPersonWowController adapter]
Controller --> Camera[Current camera adapter]
```
@@ -64,7 +64,7 @@ Forbidden dependencies:
|---|---|---|---|---|---|
| Input | Movement action strengths | Godot `InputMap`/`Input` | `PlayerInputSource` | Engine-owned snapshot | Sampled on main physics tick |
| Input | Mouse action events | Godot `_unhandled_input` dispatch | Current scene controller | Engine-owned event | Current input dispatch only |
| Output | `MoveIntent` | `PlayerInputSource` | Current controller; later local movement controller | Immutable caller-held value | One physics tick |
| Output | `MoveIntent` | `PlayerInputSource` | `LocalPlayerMovementController` through scene composition | Immutable caller-held value | One physics tick |
| Output | Camera action names | `PlayerInputActions` | Current scene controller | Static constants | Process lifetime |
Side effects:
@@ -82,15 +82,16 @@ flowchart LR
Remap[User or editor remapping] --> Map
Map -->|movement strengths| Source[PlayerInputSource]
Source -->|clamp cancel normalize| Intent[MoveIntent]
Intent --> Consumer[ThirdPersonWowController]
Intent --> Consumer[LocalPlayerMovementController]
Consumer --> Adapter[ThirdPersonWowController]
```
## Lifecycle/state
The adapter is stateless. The scene composition root creates one
`PlayerInputSource` in `_ready`; each physics tick produces a new immutable
intent. Flight enabled/disabled state remains owned by the current sandbox
controller and is not hidden in the input adapter.
`PlayerInputSource` and `LocalPlayerMovementController` in `_ready`; each physics
tick produces a new immutable intent. Flight enabled/disabled state is owned by
the movement controller and is not hidden in the input adapter.
## Main sequence
@@ -99,11 +100,13 @@ sequenceDiagram
participant Engine as Godot Input
participant Source as PlayerInputSource
participant Intent as MoveIntent
participant Player as ThirdPersonWowController
participant Move as LocalPlayerMovementController
participant Player as ThirdPersonWowController adapter
Engine->>Source: movement action strengths
Source->>Intent: compose normalized axes and requests
Source-->>Player: sample_move_intent()
Player->>Player: update current sandbox movement state
Player->>Move: advance(intent, selected basis, delta)
Move-->>Player: displacement and velocity state
```
## Ownership, threading and resources
@@ -171,15 +174,15 @@ provide a settings migration once user settings are persisted.
movement consumers.
- A later input-context owner may suppress gameplay actions while preserving the
same intent contract.
- The local movement controller may replace the current scene consumer without
changing `PlayerInputSource`.
- A future server-aware movement predictor may replace the current local
movement consumer without changing `PlayerInputSource`.
## Capability status
| Capability | Status | Evidence | Gap/next step |
|---|---|---|---|
| Remappable current sandbox controls | Implemented | `verify_player_input.gd` action/default checks | Add persisted user binding settings later |
| `PlayerInputSource → MoveIntent` seam | Implemented | Pure composition and controller boundary checks | Extract local movement controller |
| `PlayerInputSource → MoveIntent` seam | Implemented | Pure composition and controller boundary checks | Local movement consumer is now extracted |
| Exact 3.3.5a default semantics | Unknown | No original-client binding fixture in this package | Capture build-12340 defaults and mouse-turn/strafe policy |
| Production profile exclusion of sprint/flight | Partial | Debug actions are named explicitly | Add typed profile/capability gate in M02 |
| Jump/fall/swim/fly gameplay semantics | Planned | M02 target and gameplay roadmap | Implement after terrain/movement state extraction |
@@ -200,7 +203,8 @@ provide a settings migration once user settings are persisted.
| `src/domain/input/move_intent.gd` | Immutable locomotion request contract |
| `src/gameplay/input/player_input_actions.gd` | Stable project action names |
| `src/gameplay/input/player_input_source.gd` | Engine Input Map adapter and pure composition |
| `src/scenes/player/third_person_wow_controller.gd` | Current consumer and camera-event adapter |
| `src/gameplay/movement/local_player_movement_controller.gd` | Scene-free movement consumer |
| `src/scenes/player/third_person_wow_controller.gd` | Composition and camera/input-event adapter |
| `src/tests/scenes/player_input_regression.tscn` | Asset-free controller movement/camera regression fixture |
| `src/tools/verify_player_input.gd` | Headless contract/integration regression |