Files
open-wc/docs/modules/coordinate-mapping.md
T
sindoring 0ce3cae208 docs(M02): publish terrain query handoff
Work-Package: M02-GMP-TERRAIN-QUERY-001
Agent: sindo-main-codex
Tests: coordination and documentation gates; diff check
Fidelity: documents inherited height/snap regression and remaining collision evidence gap
2026-07-14 23:11:23 +04:00

16 KiB

Coordinate Mapping

Metadata

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, M02-GMP-TERRAIN-QUERY-001 consumer migration
Owners Foundation/domain
Last verified a45d521, 2026-07-14
Profiles/capabilities All profiles; contract version 2

Purpose

Provide scene-free value objects and one pure CoordinateMapper for positions, ADT grid ownership and world-facing yaw. The module makes every source space explicit before renderer, network, gameplay and authoring consumers migrate.

Non-goals

  • Reading ADT, packet, SQL or scene data.
  • Constructing Vector3, Transform3D, Node or Resource values.
  • Correcting M2/WMO local axes or MDDF/MODF Euler rotations.
  • Selecting maps, validating terrain height or owning streaming focus.
  • Persisting coordinate values in this work package.

Context and boundaries

flowchart LR
    Server[Server / movement X,Y,Z] --> ServerPosition[ServerWorldPosition]
    ADT[MDDF/MODF X,height,Z] --> AdtPosition[AdtPlacementPosition]
    ServerPosition --> Mapper[CoordinateMapper]
    AdtPosition --> Mapper
    Mapper --> Canonical[CanonicalWowWorldPosition]
    Canonical --> Tile[AdtTileCoordinate + AdtTileLocalPosition]
    Canonical --> GodotPosition[GodotWorldPosition]
    GodotPosition --> Adapter[Future scene/render adapter]
    Adapter --> Vector[Vector3 at boundary]
    Scene[Node / Camera3D / scene lookup] -. forbidden .-> Mapper

Allowed dependencies:

  • GDScript scalar math and RefCounted lifetime;
  • other value objects in src/domain/coordinates;
  • callers in network, gameplay, render and server-data adapters.

Forbidden dependencies:

  • Node, Resource, SceneTree, Camera3D and global scene lookup;
  • packet buffers, SQL rows, asset parsers and renderer state;
  • Vector3 as a public mapper input or output;
  • model-specific placement corrections.

Public API

Symbol Kind Purpose Thread/lifetime Errors
CanonicalWowWorldPosition Immutable value Client/server X/Y/Z in yards Any thread; caller-owned reference No bounds validation
ServerWorldPosition Immutable value Server/wire X/Y/Z in yards Any thread; caller-owned reference No adapter validation
AdtPlacementPosition Immutable value MDDF/MODF X/height/Z fields Any thread; caller-owned reference No file validation
GodotWorldPosition Immutable value Godot east/up/south scalars Any thread; caller-owned reference Does not create Vector3
AdtTileCoordinate Immutable value Map_tileX_tileY.adt indices Any thread; caller-owned reference is_within_map_grid() reports invalid indices
AdtTileLocalPosition Immutable value East/height/south offsets from tile north-west corner Any thread; caller-owned reference Values are intentionally unclamped
AdtChunkCoordinate Immutable value MCNK X-east/Y-south indices inside one tile Any thread; caller-owned reference is_within_map_grid() reports invalid indices
CanonicalWowWorldYaw Immutable value Canonical world yaw in radians Any thread; caller-owned reference Constructor does not normalize
ServerWorldYaw Immutable value Movement orientation in radians Any thread; caller-owned reference Constructor does not normalize
GodotWorldYaw Immutable value Godot Y-axis world yaw in radians Any thread; caller-owned reference Constructor does not normalize
CoordinateMapper.server_to_canonical / inverse Pure static methods Preserve server X/Y/Z as canonical Synchronous; new result value Null input is a caller contract violation
CoordinateMapper.canonical_to_godot / inverse Pure static methods Apply Y-up renderer basis and map offset Synchronous; new result value Non-finite scalars propagate
CoordinateMapper.godot_to_adt_tile Pure static method Resolve filename indices from typed renderer position Synchronous; new result value Result remains unclamped
CoordinateMapper.godot_to_adt_tile_local Pure static method Resolve east/height/south offsets from typed renderer position Synchronous; new result value Caller validates ownership/range
CoordinateMapper.adt_tile_local_to_godot Pure static method Compose typed renderer position from tile/local values Synchronous; new result value Non-finite scalars propagate
CoordinateMapper.canonical_to_adt_placement / inverse Pure static methods Convert ADT placement field basis Synchronous; new result value Non-finite scalars propagate
CoordinateMapper.canonical_to_adt_tile Pure static method Compute unclamped filename indices Synchronous; new result value Out-of-map result remains invalid
CoordinateMapper.canonical_to_adt_tile_local / inverse Pure static methods Split/reconstruct tile-local position Synchronous; new result value Caller validates tile ownership
CoordinateMapper.adt_tile_local_to_chunk Pure static method Compute unclamped MCNK indices Synchronous; new result value Boundary/out-of-range remains diagnosable
World-yaw mapper methods Pure static methods Normalize and cross the world-basis boundary Synchronous; new result value Non-finite input is unsupported

Inputs and outputs

Direction Contract/data Producer Consumer Ownership Thread/lifetime
Input ServerWorldPosition, ServerWorldYaw Future protocol/server adapter CoordinateMapper Immutable caller value Any thread, call duration
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/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

Side effects:

  • none;
  • no scene mutation, file/cache write, network send, database access or logging.

Data flow

flowchart LR
    ServerFixture[Pinned AzerothCore spawn] --> FixtureVerifier[Golden fixture verifier]
    RawADTFixture[Raw ADT numeric metadata] --> FixtureVerifier
    ClientFixture[Build 12340 observations] --> FixtureVerifier
    FixtureVerifier --> Mapper
    ServerFixture --> SpawnManifest[Server spawn render manifest]
    SpawnManifest --> SpawnVerifier[Renderer checkpoint verifier]
    SpawnVerifier --> Capture[Live renderer capture]
    Capture --> Marker[Diagnostic marker at mapped spawn]
    Server[ServerWorldPosition X,Y,Z] -->|identity components| Canonical[CanonicalWowWorldPosition]
    ADT[AdtPlacementPosition X,height,Z] -->|half extent - horizontal| Canonical
    Canonical -->|tileX from Y; tileY from X| Tile[AdtTileCoordinate]
    Canonical -->|north-west edge offsets| Local[AdtTileLocalPosition]
    Local -->|floor offset / chunk size| Chunk[AdtChunkCoordinate]
    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]

Lifecycle/state

The module is stateless. Each call reads immutable scalar inputs and returns a new value object. There is no initialization, shutdown, cancellation or retry state machine.

Main sequence

No cross-layer asynchronous sequence occurs inside this module. Producers parse or validate their external format first, call the mapper synchronously, and then pass only typed results across the next boundary.

Ownership, threading and resources

  • Value objects own only scalar fields and, for chunks, one immutable tile reference.
  • Callers own returned RefCounted references.
  • Methods do not mutate inputs or shared state and are safe for worker use.
  • No Node, RID, file, socket, database or cache resource is acquired.

Errors, cancellation and recovery

Failure Detection Behavior Diagnostic Recovery
Tile/chunk outside standard grid is_within_map_grid() Unclamped indices are preserved Caller reports source and map context Reject or apply explicit map policy
Tile-local value outside half-open tile Consumer boundary validation Value is preserved Caller reports source coordinate Recompute ownership or reject malformed input
Null value object Static typing/call failure Programming contract violation GDScript error with call site Fix producer; no fallback value
NaN/infinite scalar Adapter validation Arithmetic propagates invalid value Adapter must report source field Reject malformed external input

There is no cancellation because every conversion is constant-time scalar math.

Configuration and capabilities

Setting/capability Default Profile Runtime mutable Effect
Contract version 2 All No Corrected filename/chunk axes in ADR 0001
Godot units per WoW yard 1 Blizzlike335 and current tools No Preserves current renderer scale
ADT grid 64 tiles/axis, 16 chunks/tile WotLK 3.3.5a No Defines index and boundary math

Persistence, cache and migration

Production code adds no persisted format, cache or migration. Test schema 1 in coordinate_golden_points.json persists explicit source provenance, coordinate contract version 2, tolerances, source-space values and expected outputs. It contains no proprietary bytes, database dump or original-client image. Existing dictionaries, native Vector3 payloads and renderer conversion helpers remain compatible. Consumer migration is ordered after this contract and must remove old manual conversions only after its producer/consumer tests pass.

Any future serialized coordinate must store a schema version and explicit space; raw three-number arrays are not an accepted new persistence contract.

Diagnostics and observability

  • Logs: none in production mapper.
  • Metrics: none; conversion cost is constant and outside frame-budget concern.
  • Debug views: headless contract probe prints one PASS summary.
  • Correlation IDs: supplied by external adapters if an invalid source is reported.

Verification

  • Unit/contract tests: src/tools/verify_coordinate_mapper.gd.
  • Cross-source golden test: src/tools/verify_coordinate_golden_fixtures.gd.
  • 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 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).
  • Fidelity evidence: five build-12340 camera positions from the M00 manifest map within 0.002 yard; a pinned AzerothCore human-warrior spawn and one raw MCNK header observation independently confirm tile (32,48) and chunk (3,12); independent reference formulas are recorded in ADR 0001.
  • Performance budgets: constant-time arithmetic; no scene or file access.
  • Manual diagnostics: not required for the pure contract; renderer checkpoints are required when consumers migrate.

Extension points

  • Add typed map IDs around positions without changing axis semantics.
  • Add a format-specific placement-orientation adapter with its own fixtures.
  • Add serialization only with explicit space/version fields and migrations.
  • Add consumer adapters that construct engine-native vectors at their boundary.

Capability status

Capability Status Evidence Gap/next step
Canonical/server/Godot position mapping Implemented Headless round-trip, five M00 golden points and migrated GDScript consumers Network/server adapters remain future consumers
ADT placement mapping Implemented Synthetic/direct round-trip fixtures Compare native parsed placements during migration
ADT tile/local/chunk ownership Implemented Center/extent boundaries, raw Azeroth_31_49.adt evidence and direct Godot adapter round-trip Native parser remains explicit boundary
World-facing yaw mapping Implemented Cardinal/wrap round-trip fixtures Placement Euler remains separate
Scene-free production contract Implemented Source boundary, headless tests and repository-wide conversion gate Maintain gate with new consumers
Cross-source coordinate fixture Implemented Pinned AzerothCore spawn, raw ADT MCNK metadata and five build-12340 points pass one headless verifier Add live adapter/renderer integration
TrinityCore populated spawn equivalence Not verified The base development schema has no pinned populated row used by this fixture Pin and verify a TDB snapshot before claiming parity
Visual/server-spawn integration Implemented Dedicated manifest/verifier plus cold/warm GUI capture of the mapped AzerothCore spawn This is coordinate/renderer integration evidence, not original-client visual parity

Known gaps and risks

  • Native ADT/WDT parsing retains one shared boundary formula because worker parsers cannot call GDScript; the gate prevents additional definitions.
  • Contract version 1 briefly transposed ADT filename/chunk axes; version 2 fixes the defect before any consumer migration.
  • MDDF/MODF rotation comments and implementations disagree across existing paths; this package deliberately does not generalize them into world yaw.
  • Finite-number validation belongs to external format adapters and is not yet implemented.
  • Arithmetic agreement does not prove terrain, placement, camera direction or visual parity.
  • The golden server row is verified against pinned AzerothCore data only; no TrinityCore equivalence claim is made without a pinned populated TDB snapshot.

Source map

Path Responsibility
src/domain/coordinates/coordinate_mapper.gd Constants and all coordinate-axis conversions
src/domain/coordinates/*_position.gd Immutable typed position values
src/domain/coordinates/adt_tile_coordinate.gd ADT filename tile indices and bounds
src/domain/coordinates/adt_chunk_coordinate.gd MCNK indices and bounds
src/domain/coordinates/*_yaw.gd Immutable typed world-facing yaw values
src/tools/verify_coordinate_mapper.gd Headless fixtures and boundary regressions
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