gmp(M02): extract player terrain query
Work-Package: M02-GMP-TERRAIN-QUERY-001 Agent: sindo-main-codex Tests: terrain query, player input and movement regressions; asset-free scene; renderer dry-run; coordinate, streaming, documentation and coordination gates Fidelity: preserves existing ADT outer-grid interpolation and player ground snap; build-12340 collision parity remains unverified
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
| Domain identities | Implemented contract | [`domain-identities.md`](domain-identities.md) |
|
||||
| Player input | Partial | [`player-input.md`](player-input.md) |
|
||||
| Local player movement | Implemented | [`local-player-movement.md`](local-player-movement.md) |
|
||||
| Terrain query | Implemented | [`terrain-query.md`](terrain-query.md) |
|
||||
| Renderer | Partial | [`world-renderer.md`](world-renderer.md), [`../../RENDER.md`](../../RENDER.md) |
|
||||
| Network/session | Planned | [`../../targets/roadmap/03-network-and-session.md`](../../targets/roadmap/03-network-and-session.md) |
|
||||
| Gameplay | Prototype/Planned | [`../../targets/roadmap/04-gameplay-systems.md`](../../targets/roadmap/04-gameplay-systems.md) |
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
| Field | Value |
|
||||
|---|---|
|
||||
| Status | Implemented |
|
||||
| Target/work package | `M01-FND-COORDS-001`, `M01-FND-COORD-TILE-AXIS-002`, `M01-QAR-COORD-FIXTURES-001`, `M01-FND-COORD-BOUNDARY-GATE-001`, `M01-QAR-SERVER-SPAWN-RENDERER-001` |
|
||||
| Target/work package | `M01-FND-COORDS-001`, `M01-FND-COORD-TILE-AXIS-002`, `M01-QAR-COORD-FIXTURES-001`, `M01-FND-COORD-BOUNDARY-GATE-001`, `M01-QAR-SERVER-SPAWN-RENDERER-001`, `M02-GMP-TERRAIN-QUERY-001` consumer migration |
|
||||
| Owners | Foundation/domain |
|
||||
| Last verified | Worktree `work/sindo-main-codex/m01-server-spawn-renderer`, 2026-07-13 |
|
||||
| Last verified | `working tree`, 2026-07-14 |
|
||||
| Profiles/capabilities | All profiles; contract version 2 |
|
||||
|
||||
## Purpose
|
||||
@@ -86,7 +86,7 @@ Forbidden dependencies:
|
||||
| Input | `AdtPlacementPosition` | Future ADT adapter | `CoordinateMapper` | Immutable caller value | Any thread, call duration |
|
||||
| Input | `CanonicalWowWorldPosition`, `CanonicalWowWorldYaw` | Gameplay/content/domain | `CoordinateMapper` | Immutable caller value | Any thread, call duration |
|
||||
| Output | `CanonicalWowWorldPosition` | `CoordinateMapper` | Gameplay/content/adapters | New immutable value | Caller-owned reference |
|
||||
| Output | `AdtTileCoordinate`, `AdtTileLocalPosition`, `AdtChunkCoordinate` | `CoordinateMapper` | Streaming/content adapters | New immutable values | Caller-owned references |
|
||||
| Output | `AdtTileCoordinate`, `AdtTileLocalPosition`, `AdtChunkCoordinate` | `CoordinateMapper` | Streaming/content/terrain-query adapters | New immutable values | Caller-owned references |
|
||||
| Output | `GodotWorldPosition`, `GodotWorldYaw` | `CoordinateMapper` | Future render/scene adapter | New immutable values | Caller-owned references |
|
||||
| Test input | `coordinate_golden_points.json` schema 1 | Pinned public server row plus private numeric observations | Headless fixture verifier | Versioned repository fixture | Test-process lifetime |
|
||||
|
||||
@@ -115,6 +115,10 @@ flowchart LR
|
||||
Canonical -->|half extent - Y; Z; half extent - X| Godot[GodotWorldPosition]
|
||||
Godot -->|typed direct adapter| Tile
|
||||
Godot -->|typed direct adapter| Local
|
||||
Godot --> TerrainQuery[AdtTerrainQuery consumer]
|
||||
TerrainQuery --> Tile
|
||||
TerrainQuery --> Local
|
||||
TerrainQuery --> Chunk
|
||||
Tile -->|tile plus local| Godot
|
||||
ServerYaw[ServerWorldYaw] -->|normalize only| CanonicalYaw[CanonicalWowWorldYaw]
|
||||
CanonicalYaw -->|same numeric world angle| GodotYaw[GodotWorldYaw]
|
||||
@@ -185,7 +189,8 @@ raw three-number arrays are not an accepted new persistence contract.
|
||||
- Boundary enforcement: `src/tools/verify_coordinate_conversion_boundaries.gd`.
|
||||
- Server-spawn renderer contract: `src/tools/verify_server_spawn_renderer.gd`
|
||||
validates the dedicated manifest against the same pinned fixture before GUI capture.
|
||||
- Integration/E2E: sky, player, streamer and terrain probe use mapper boundaries;
|
||||
- Integration/E2E: sky, player spawn, streamer, terrain probe and the extracted
|
||||
`AdtTerrainQuery` use mapper boundaries;
|
||||
`StreamingFocus` provides typed renderer focus, and the pinned AzerothCore
|
||||
Human Warrior spawn is captured in the Eastern Kingdoms renderer at ADT
|
||||
`(32,48)`, chunk `(3,12)`.
|
||||
@@ -243,6 +248,7 @@ raw three-number arrays are not an accepted new persistence contract.
|
||||
| `src/tests/fixtures/coordinate_golden_points.json` | Versioned cross-source values, provenance and tolerances |
|
||||
| `src/tools/verify_coordinate_golden_fixtures.gd` | Cross-source fixture schema and mapper validation |
|
||||
| `src/tools/verify_coordinate_conversion_boundaries.gd` | Repository-wide manual conversion and required-consumer gate |
|
||||
| `src/gameplay/terrain/adt_terrain_query.gd` | Typed Godot-position consumer for ADT tile/local/chunk lookup |
|
||||
| `src/tools/server_spawn_render_manifest.json` | Pinned server-spawn camera, player, marker and expected ADT ownership |
|
||||
| `src/tools/verify_server_spawn_renderer.gd` | Fixture-to-renderer manifest contract verifier |
|
||||
| `docs/adr/0001-canonical-world-coordinates.md` | Normative axes, units, boundaries and rollout decision |
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
| Status | Implemented |
|
||||
| Target/work package | M02 / M02-GMP-MOVEMENT-001 |
|
||||
| Owners | Gameplay local movement state; scene composition owns the instance |
|
||||
| Last verified | `435e1c9`, 2026-07-14 |
|
||||
| Last verified | `working tree`, 2026-07-14 |
|
||||
| Profiles/capabilities | Current render sandbox; production/debug profile gate pending |
|
||||
|
||||
## Purpose
|
||||
@@ -37,7 +37,7 @@ flowchart LR
|
||||
Scene[ThirdPersonWowController] --> Basis
|
||||
Displacement --> Scene
|
||||
Scene --> Transform[Player world transform]
|
||||
Scene --> Terrain[Ground snap adapter]
|
||||
Scene --> Terrain[TerrainQuery and ground snap adapter]
|
||||
Velocity --> Presentation[Visual facing and animation adapter]
|
||||
```
|
||||
|
||||
@@ -153,7 +153,7 @@ sequenceDiagram
|
||||
| Negative physics delta | `advance` guard | Returns zero displacement; velocity unchanged | Unit regression | Resume with valid non-negative delta |
|
||||
| Missing scene basis owner | Scene composition defect | Controller cannot be called correctly | Scene/parser error or boundary test | Restore explicit scene dependency |
|
||||
| Flight toggle during motion | Command path | Velocity clears before next step | State-transition regression | Continue from zero velocity |
|
||||
| Missing terrain data | Outside module | Scene skips existing ground snap | Existing terrain diagnostics | TerrainQuery extraction will own policy |
|
||||
| Missing terrain data | `TerrainGroundSample.is_available == false` | Scene skips existing ground snap | Stable terrain failure code | Replace/recover query backend |
|
||||
|
||||
There is no asynchronous cancellation, retry or rollback. Recreating the
|
||||
controller resets velocity and flight state deterministically.
|
||||
@@ -211,7 +211,8 @@ separate versioned movement snapshot contract.
|
||||
| Scene-free local velocity state | Implemented | Pure controller and source boundary regression | Integrate target checklist after review |
|
||||
| Existing planar acceleration/speeds | Implemented | Exact numeric unit cases and real scene regression | Compare with build 12340 before fidelity claim |
|
||||
| Existing camera-relative free flight | Implemented | Pitched-basis and toggle/reset cases | Restrict to sandbox profile |
|
||||
| Terrain/collision movement policy | Planned | Outside module by design | Extract `TerrainQuery` next |
|
||||
| Terrain height query | Implemented | Typed `TerrainQuery` and injected player regression | Ground-snap policy remains scene-owned |
|
||||
| Terrain collision movement policy | Planned | Height-only query does not model collision | Add slopes/holes/collision later |
|
||||
| Jump/fall/swim | Planned | M02/M09 roadmap | Requires terrain/liquid and server contracts |
|
||||
| Prediction/reconciliation | Planned | M08/M09 roadmap | Requires movement snapshot/network contract |
|
||||
|
||||
@@ -220,7 +221,8 @@ separate versioned movement snapshot contract.
|
||||
- Numeric defaults preserve the existing sandbox but are not original-client evidence.
|
||||
- Configuration is captured at scene `_ready`; runtime mutation of exported speed
|
||||
properties does not reconfigure an existing controller.
|
||||
- Ground snap remains in the player scene until `TerrainQuery` extraction.
|
||||
- Ground snap remains in the player scene, but its ADT data access is now behind
|
||||
a replaceable `TerrainQuery`.
|
||||
- Sprint and free flight still lack a typed sandbox capability gate.
|
||||
- The module uses Godot math value types; a future engine-independent gameplay
|
||||
predictor may require scalar/domain movement contracts.
|
||||
@@ -230,6 +232,7 @@ separate versioned movement snapshot contract.
|
||||
| Path | Responsibility |
|
||||
|---|---|
|
||||
| `src/gameplay/movement/local_player_movement_controller.gd` | Owned velocity/flight state and deterministic integration |
|
||||
| `src/gameplay/terrain/terrain_query.gd` | Replaceable ground-height input boundary |
|
||||
| `src/scenes/player/third_person_wow_controller.gd` | Composition, basis selection, displacement/terrain/presentation adapters |
|
||||
| `src/tools/verify_local_player_movement.gd` | Pure numeric, state-transition and dependency regression |
|
||||
| `src/tests/scenes/player_input_regression.tscn` | Asset-free integrated player fixture |
|
||||
|
||||
@@ -0,0 +1,251 @@
|
||||
# Terrain Query
|
||||
|
||||
## Metadata
|
||||
|
||||
| Field | Value |
|
||||
|---|---|
|
||||
| Status | Implemented |
|
||||
| Target/work package | M02 / M02-GMP-TERRAIN-QUERY-001 |
|
||||
| Owners | Gameplay terrain-query contract; ADT adapter owns parsed tile cache |
|
||||
| Last verified | `working tree`, 2026-07-14 |
|
||||
| Profiles/capabilities | Current sandbox ADT ground height; renderer/physics backend planned |
|
||||
|
||||
## Purpose
|
||||
|
||||
Provide a replaceable, scene-free ground-height query for player movement.
|
||||
Isolate native ADT loading, per-tile caching, chunk selection and legacy outer
|
||||
height-grid interpolation from the player scene behind a typed
|
||||
`GodotWorldPosition → TerrainGroundSample` contract.
|
||||
|
||||
## Non-goals
|
||||
|
||||
- Own player transforms, movement velocity or ground-snap policy.
|
||||
- Provide collision normals, slopes, holes, liquids, WMO/M2 collision or ray queries.
|
||||
- Change ADT topology, coordinate conversion, renderer caches or native parser format.
|
||||
- Claim original-client terrain-contact parity from height regression alone.
|
||||
- Couple gameplay to the monolithic streaming renderer before a public backend exists.
|
||||
|
||||
## Context and boundaries
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
Scene[ThirdPersonWowController adapter] --> Position[GodotWorldPosition]
|
||||
Position --> Contract[TerrainQuery]
|
||||
Contract --> Adapter[AdtTerrainQuery]
|
||||
Adapter --> Mapper[CoordinateMapper]
|
||||
Adapter --> Native[ADTLoader]
|
||||
Native --> Tile[ADT tile Dictionary]
|
||||
Tile --> Cache[Owned tile cache]
|
||||
Cache --> Sample[TerrainGroundSample]
|
||||
Sample --> Scene
|
||||
Scene --> Snap[Existing ground-snap policy]
|
||||
```
|
||||
|
||||
Allowed dependencies:
|
||||
|
||||
- Typed `GodotWorldPosition` and `CoordinateMapper` contracts.
|
||||
- Existing native `ADTLoader` at the ADT adapter boundary.
|
||||
- Dynamic dictionaries only inside the native-format adapter.
|
||||
- Player scene composition may inject any `TerrainQuery` implementation.
|
||||
|
||||
Forbidden dependencies:
|
||||
|
||||
- `TerrainQuery` contract depending on Nodes, cameras, input or renderer state.
|
||||
- Player scene loading/parsing ADT data or owning a parsed tile cache.
|
||||
- Manual WoW/Godot/ADT world-coordinate conversion outside `CoordinateMapper`.
|
||||
- Terrain query mutating transforms, gameplay movement state or visual meshes.
|
||||
|
||||
## Public API
|
||||
|
||||
| Symbol | Kind | Purpose | Thread/lifetime | Errors |
|
||||
|---|---|---|---|---|
|
||||
| `TerrainGroundSample.available(height_units)` | Immutable value factory | Creates a finite Godot-world ground height | Any thread; caller-held value | Non-finite height becomes unavailable |
|
||||
| `TerrainGroundSample.unavailable(failure_code)` | Immutable value factory | Creates explicit unavailable result | Any thread; caller-held value | Empty code normalizes to `terrain_unavailable` |
|
||||
| `TerrainQuery.sample_ground_height(position)` | Replaceable boundary | Samples ground at typed Godot world position | Implementation-defined; current adapter main-thread owned | Base reports `terrain_query_not_implemented` |
|
||||
| `AdtTerrainQuery.new(extracted_directory, map_directory_name, loader_override)` | Adapter constructor | Configures one map and optional test/data-source loader | Query lifetime | Production validates native loader and file presence lazily |
|
||||
| `AdtTerrainQuery.sample_ground_height(position)` | Adapter method | Loads/caches tile and interpolates ADT outer heights | Main thread; cache lives with query | Returns stable failure code |
|
||||
| `ThirdPersonWowController.set_terrain_query(query)` | Composition method | Replaces terrain backend independently of movement/presentation | Call before scene ready or on main thread | Null is rejected and current query retained |
|
||||
|
||||
## Inputs and outputs
|
||||
|
||||
| Direction | Contract/data | Producer | Consumer | Ownership | Thread/lifetime |
|
||||
|---|---|---|---|---|---|
|
||||
| Input | `GodotWorldPosition` | Player scene adapter | `TerrainQuery` | Immutable caller-held value | One query |
|
||||
| Input | Extracted directory/map name | Scene composition | `AdtTerrainQuery` | Copied strings | Query lifetime |
|
||||
| Input | ADT file/dictionary | Filesystem/native loader or injected loader | `AdtTerrainQuery` | Adapter-owned cached dictionary | Query lifetime |
|
||||
| Output | `TerrainGroundSample` | Terrain query | Player ground-snap adapter | Immutable caller-held value | One query |
|
||||
| Output | Failure code | Terrain query | Diagnostics/tests | Immutable `StringName` | Sample lifetime |
|
||||
|
||||
Side effects:
|
||||
|
||||
- Production adapter performs lazy file existence check and native ADT parse on first tile query.
|
||||
- Adapter mutates only its per-query tile/failure caches.
|
||||
- No scene tree, transform, renderer RID, network, database or persisted setting mutation occurs.
|
||||
|
||||
## Data flow
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
Position[GodotWorldPosition] --> TileCoord[CoordinateMapper tile/local/chunk]
|
||||
TileCoord --> Lookup{Tile cached?}
|
||||
Lookup -->|no| Load[ADTLoader or injected loader]
|
||||
Load --> Cache[Cache Dictionary or unavailable result]
|
||||
Lookup -->|yes| Cache
|
||||
Cache --> Chunk[Select MCNK by origin]
|
||||
Chunk --> Heights[Validate 145 heights]
|
||||
Heights --> Bilinear[Interpolate 9x9 outer grid]
|
||||
Bilinear --> Available[TerrainGroundSample available]
|
||||
Cache -->|missing/invalid| Unavailable[TerrainGroundSample unavailable]
|
||||
```
|
||||
|
||||
## Lifecycle/state
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> TileUnknown
|
||||
TileUnknown --> TileAvailable: first query / successful load
|
||||
TileUnknown --> TileUnavailable: first query / missing or failed
|
||||
TileAvailable --> TileAvailable: cached queries
|
||||
TileUnavailable --> TileUnavailable: cached queries
|
||||
TileAvailable --> [*]: query released
|
||||
TileUnavailable --> [*]: query released
|
||||
```
|
||||
|
||||
Unavailable tiles are cached intentionally to avoid repeated filesystem/native
|
||||
work each physics tick. Recovery after files appear requires replacing the query
|
||||
instance; hot-reload invalidation is outside this M02 package.
|
||||
|
||||
## Main sequence
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Player as ThirdPersonWowController
|
||||
participant Query as TerrainQuery
|
||||
participant ADT as AdtTerrainQuery
|
||||
participant Mapper as CoordinateMapper
|
||||
participant Native as ADTLoader
|
||||
Player->>Query: sample_ground_height(GodotWorldPosition)
|
||||
Query->>ADT: implementation dispatch
|
||||
ADT->>Mapper: tile/local/chunk coordinates
|
||||
alt tile not cached
|
||||
ADT->>Native: load_adt(absolute path)
|
||||
Native-->>ADT: ADT Dictionary
|
||||
end
|
||||
ADT->>ADT: select chunk and interpolate heights
|
||||
ADT-->>Player: TerrainGroundSample
|
||||
Player->>Player: apply existing offset/snap if available
|
||||
```
|
||||
|
||||
## Ownership, threading and resources
|
||||
|
||||
- Player scene owns the active `TerrainQuery` reference.
|
||||
- `AdtTerrainQuery` exclusively owns tile/failure dictionaries until released.
|
||||
- Current production calls and cache mutations occur on the main physics thread.
|
||||
- Native loader result dictionaries do not cross the adapter boundary.
|
||||
- Samples and typed positions are immutable caller-held values.
|
||||
- The module creates no Nodes, Resources, RIDs or background jobs.
|
||||
- Future worker-backed queries require an explicit async/result contract rather
|
||||
than concurrent mutation of the current dictionaries.
|
||||
|
||||
## Errors, cancellation and recovery
|
||||
|
||||
| Failure | Detection | Behavior | Diagnostic | Recovery |
|
||||
|---|---|---|---|---|
|
||||
| Base contract used directly | Base method | Unavailable sample | `terrain_query_not_implemented` | Inject implementation |
|
||||
| Native loader absent | ClassDB check | Cache unavailable tile | `adt_loader_unavailable` | Load extension and replace query |
|
||||
| ADT file absent | File check | Cache unavailable tile | `adt_source_missing` | Restore corpus and replace query |
|
||||
| Native parse empty/fails | Result validation | Cache unavailable tile | `adt_load_failed` | Inspect source/parser; replace query |
|
||||
| Injected loader returns wrong type | Type check | Cache unavailable tile | `adt_loader_result_invalid` | Fix adapter |
|
||||
| Chunk absent | Chunk lookup | Unavailable sample | `adt_chunk_missing` | Validate ADT dictionary |
|
||||
| Height array shorter than 145 | Size check | Unavailable sample | `adt_chunk_heights_invalid` | Fix parser/source |
|
||||
| Non-finite interpolated height | Sample invariant | Unavailable sample | `terrain_height_not_finite` | Inspect source values |
|
||||
| Null query injection | Scene guard | Existing query retained | Player composition error | Pass valid query |
|
||||
|
||||
There are no asynchronous operations to cancel. Replacing/releasing the query
|
||||
is the deterministic cache-reset and recovery path.
|
||||
|
||||
## Configuration and capabilities
|
||||
|
||||
| Setting/capability | Default | Profile | Runtime mutable | Effect |
|
||||
|---|---|---|---|---|
|
||||
| Extracted directory | Player `extracted_dir` | Current sandbox | Captured at creation | ADT source root |
|
||||
| Map directory name | Player `map_name` | Current sandbox | Captured at creation | ADT filename/path |
|
||||
| Loader override | Invalid callable | Test/custom data source | Constructor only | Bypasses production ClassDB/file loading |
|
||||
| Tile cache | Enabled | All current uses | Cleared by replacing query | Avoids repeated parse/failure work |
|
||||
| Height policy | 9x9 outer-grid bilinear | Current sandbox | Fixed | Preserves pre-extraction behavior |
|
||||
|
||||
## Persistence, cache and migration
|
||||
|
||||
The cache is in-memory and unversioned because it holds native loader output for
|
||||
one query lifetime. No disk cache, schema or migration changes are introduced.
|
||||
Existing ADT/native/cache format versions remain unchanged.
|
||||
|
||||
## Diagnostics and observability
|
||||
|
||||
- Logs: dedicated verifier emits `TERRAIN_QUERY PASS` or named failures.
|
||||
- Structured status: every unavailable sample has a stable `failure_code`.
|
||||
- Metrics: synthetic verifier counts loader calls to prove one load per tile.
|
||||
- Debug views: none.
|
||||
- Correlation IDs: not applicable to synchronous local query.
|
||||
|
||||
## Verification
|
||||
|
||||
- Contract: available/unavailable/base/non-finite result invariants.
|
||||
- Pure synthetic adapter: typed coordinate mapping, exact chunk selection,
|
||||
145-height layout and bilinear interpolation within `0.002` units (Vector3
|
||||
source precision), plus cached second query.
|
||||
- Failures: empty tile and invalid height array produce stable codes.
|
||||
- Integration: asset-free player scene accepts injected flat query and preserves
|
||||
spawn offset `0.05` plus physics ground snap.
|
||||
- Boundary: source regression rejects ADT loader/cache/chunk helpers in player.
|
||||
- Fidelity evidence: existing interpolation and snap behavior only; no
|
||||
original-client or collision parity claim.
|
||||
- Performance budget: one dictionary cache lookup and scalar interpolation per
|
||||
cached query; native parse only on first tile access.
|
||||
|
||||
## Extension points
|
||||
|
||||
- Streaming renderer or physics backend may implement `TerrainQuery` without changing player/movement.
|
||||
- Future result may grow separate slope, surface, liquid or collision contracts;
|
||||
incompatible additions require a versioned contract rather than Dictionary fields.
|
||||
- Test/authoring data sources may use constructor loader override.
|
||||
- Async streaming requires a separate availability/update model.
|
||||
|
||||
## Capability status
|
||||
|
||||
| Capability | Status | Evidence | Gap/next step |
|
||||
|---|---|---|---|
|
||||
| Typed replaceable ground-height query | Implemented | Contract and injected player regression | Integrate target checklist after review |
|
||||
| Existing ADT height interpolation | Implemented | Synthetic fractional-grid fixture | Compare terrain contact with build 12340 |
|
||||
| Per-tile success/failure cache | Implemented | Loader call-count regression | Add explicit invalidation only with authoring/hot reload |
|
||||
| Renderer/streaming cache backend | Planned | Boundary permits replacement | M03 renderer facade/public terrain backend |
|
||||
| Holes/slopes/collision | Planned | Outside height-only contract | Later movement/physics package |
|
||||
| Liquid/swim query | Planned | Outside contract | M09/M12 world gameplay |
|
||||
|
||||
## Known gaps and risks
|
||||
|
||||
- Bilinear outer-grid height is the inherited sandbox approximation; exact ADT
|
||||
triangle choice, holes and collision are not represented.
|
||||
- Query is synchronous; first access may parse an ADT on the main thread exactly
|
||||
as before extraction. A streaming/backend replacement is future work.
|
||||
- Unavailable results remain cached until query replacement.
|
||||
- Player still owns ground offset/snap policy; only data access is extracted.
|
||||
- Existing native dictionaries remain dynamic inside the adapter.
|
||||
|
||||
## Source map
|
||||
|
||||
| Path | Responsibility |
|
||||
|---|---|
|
||||
| `src/gameplay/terrain/terrain_ground_sample.gd` | Immutable available/unavailable result |
|
||||
| `src/gameplay/terrain/terrain_query.gd` | Replaceable typed query boundary |
|
||||
| `src/gameplay/terrain/adt_terrain_query.gd` | Native ADT adapter, cache, chunk selection and interpolation |
|
||||
| `src/scenes/player/third_person_wow_controller.gd` | Query composition and existing ground-snap consumer |
|
||||
| `src/tools/verify_terrain_query.gd` | Synthetic contract/cache/failure/injection regression |
|
||||
| `src/tests/scenes/player_input_regression.tscn` | Asset-free player composition fixture |
|
||||
|
||||
## Related decisions and references
|
||||
|
||||
- ADR: none; no coordinate, format or authority decision changed.
|
||||
- Upstream/reference: `targets/02-player-decomposition.md`,
|
||||
`targets/roadmap/02-rendering-and-graphics.md`,
|
||||
`targets/roadmap/04-gameplay-systems.md`, `docs/ARCHITECTURE.md`.
|
||||
Reference in New Issue
Block a user