Files
open-wc/docs/modules/wmo-placement-registry.md
T

9.5 KiB

WMO Placement Registry

Metadata

Field Value
Status Implemented extraction
Target/work package M03 / M03-RND-WMO-PLACEMENT-REGISTRY-001
Owners WMO placement-key to tile/global reference-set ownership
Last verified Worktree work/sindo-main-codex/m03-wmo-placement-registry, 2026-07-17
Profiles/capabilities Existing ADT/WDT WMO placement paths; profile-independent

Purpose

Own the reference sets that keep one resolved WMO placement active across one or more ADT tiles, or across the global WDT placement lifetime. This separates value-only placement ownership from scene and render-resource ownership.

Non-goals

  • Resolve WMO paths, placement identity or world transforms.
  • Own Nodes, Resources, RIDs, roots, jobs, queues, tasks or caches.
  • Load, instantiate, build or free WMO content.
  • Change duplicate order, budgets, retries or global-WMO behavior.
  • Claim original-client WMO visual, portal, room or material parity.

Context and boundaries

flowchart LR
    Parsed[ADT/WDT placement] --> Resolver[WmoPlacementResolver]
    Resolver --> Key[Placement key]
    Tile[Tile/global reference key] --> Loader[StreamingWorldLoader]
    Key --> Loader
    Loader --> Registry[WmoPlacementRegistry]
    Registry --> Decision[Existing or final-release decision]
    Decision --> Loader
    Loader --> NodeMap[Loader key-to-Node map]
    Loader --> Jobs[Loader jobs/queues/resources]

The registry depends only on RefCounted, Dictionary, Array and String. SceneTree, Node, Resource, RID, files, loaders, threads, locks, network, gameplay and editor UI are forbidden dependencies.

Public API

Symbol Kind Purpose Thread/lifetime Errors
add_reference(placement_key, reference_key) Command/query Idempotently add a reference; return true only when creating the placement key Renderer main thread; map session Empty key returns false and changes nothing
release_reference(placement_key, reference_key) Command/query Remove an owned reference; return true only on final removal Renderer main thread; map session Empty, unknown or non-owner input returns false
contains(placement_key) Query Test whether any reference keeps a placement active Renderer main thread; map session Empty key returns false
active_count() Query Count active placement keys, not references Renderer main thread; map session None
diagnostic_snapshot() Query Return detached, placement/reference-sorted records Renderer main thread; caller-owned result None
clear() Command Remove all ownership records idempotently Renderer main thread; reset/shutdown None

Inputs and outputs

Direction Contract/data Producer Consumer Ownership Thread/lifetime
Input Resolved uid:*, tile:*:* or global placement key WmoPlacementResolver / loader global adapter Registry Copied String dictionary key Until final release/clear
Input ADT tile key or __global__ reference key Loader Registry Copied String set key Until release/clear
Output First-placement Boolean Registry Loader creation path Value One call
Output Final-release Boolean Registry Loader cancellation/free path Value One call
Output Active count and sorted diagnostic records Registry Renderer diagnostics/verifier Detached values Caller lifetime

Data flow

flowchart TD
    Add[add placement + reference] --> Valid{Both non-empty?}
    Valid -->|no| Reject[false; unchanged]
    Valid -->|yes| Existing{Placement exists?}
    Existing -->|no| Create[Create reference set; true]
    Existing -->|yes| Retain[Idempotently add reference; false]
    Release[release placement + reference] --> Owner{Known owner reference?}
    Owner -->|no| Reject
    Owner -->|yes| Erase[Erase reference]
    Erase --> Empty{Set empty?}
    Empty -->|no| Retained[false; placement remains]
    Empty -->|yes| Final[Erase placement; true]

Lifecycle and state

The states for one placement are Absent, Referenced and back to Absent. The first valid add enters Referenced; further tile/global adds remain there. Only release of the final owned reference returns to Absent. Map reset and shutdown call clear, which is safe from either state.

stateDiagram-v2
    [*] --> Absent
    Absent --> Referenced: first valid add / true
    Referenced --> Referenced: idempotent/shared add / false
    Referenced --> Referenced: non-owner/non-final release / false
    Referenced --> Absent: final owned release / true
    Referenced --> Absent: clear

Main sequence

sequenceDiagram
    participant Loader as StreamingWorldLoader
    participant Registry as WmoPlacementRegistry
    participant Nodes as Loader Node map
    Loader->>Registry: contains(placement key)
    alt existing placement
        Loader->>Registry: add_reference(key, tile)
    else new placement built successfully
        Loader->>Nodes: store key-to-Node
        Loader->>Registry: add_reference(key, tile/global)
    end
    Loader->>Registry: release_reference(key, tile)
    alt final reference
        Registry-->>Loader: true
        Loader->>Loader: cancel render build
        Loader->>Nodes: queue-free and erase Node
    else shared/unknown reference
        Registry-->>Loader: false
    end

Ownership, threading and resources

  • The registry owns only placement-key Dictionaries and reference-key sets.
  • The loader owns the parallel placement-key-to-Node map and every Node action.
  • The loader also owns WMO roots, tile state, caches, requests, jobs, queues, retries, cancellation and render-resource lifetime.
  • Current calls are serialized on the renderer main thread. The registry has no lock and must not be mutated concurrently.

Errors, cancellation and recovery

Failure Detection Behavior Diagnostic Recovery
Empty placement/reference key API guard Reject without mutation Contract verifier Repair caller input
Duplicate add Existing set member Idempotent retain Sorted snapshot No recovery required
Unknown/non-owner release Missing placement/reference Ignore without mutation Contract verifier Release from actual owner or reset
Tile build cancellation Loader-owned condition Loader cancels job, then releases recorded refs Existing queue metrics Retry when tile becomes wanted
Final release Empty set after erase Return true and erase registry record Active count Loader cancels/free Node exactly once
Map reset/shutdown Loader lifecycle Loader frees Nodes/jobs and clears registry Shutdown regression Next map begins empty

Configuration and capabilities

There is no setting, profile branch or capacity knob. WMO tile radius, cache limits, render budgets and visibility settings remain loader-owned.

Persistence, cache and migration

No data is serialized and no cache/schema/version changes. Placement and reference keys exist only for the current renderer map session.

Diagnostics and observability

active_count backs existing WMO instance metrics. diagnostic_snapshot returns deterministic detached records for tests and future read-only diagnostics; mutating the returned arrays cannot alter registry state.

Verification

  • verify_wmo_placement_registry.gd: invalid/first/idempotent/shared/non-owner/ final/global/clear behavior, deterministic detached diagnostics, source ownership boundaries and bounded 100-by-256 shared-reference cycles.
  • WMO resolver, material, runtime-cache shutdown and the renderer regression suite verify the unchanged loader adapters and surrounding lifecycle.
  • Fidelity evidence is exact preservation of the repository's prior shared-ref and final-release semantics. Asset-backed 3.3.5a comparison is still pending.

Extension points

  • WMO build/resource state can be extracted separately without moving Nodes into this registry.
  • A future diagnostic adapter may expose the detached snapshot through the facade without exposing mutable loader internals.

Capability status

Capability Status Evidence Gap/next step
WMO placement reference ownership Implemented extraction Contract/source/timing verifier Asset-backed cross-tile corpus pending
WMO build/resource scheduling Remains in loader Existing runtime regressions Separate state/cancellation package
WMO visual/portal/material fidelity Partial Renderer baseline/material checks Original-client paired evidence pending

Known gaps and risks

  • Correctness assumes the loader records each successful placement reference in the tile wmo_refs array before unregister.
  • Old caches without positive UID retain resolver-defined per-tile identity.
  • No proprietary WMO corpus or original-client paired capture is in this package.

Source map

Path Responsibility
src/render/wmo/wmo_placement_registry.gd Placement-key/reference-set ownership
src/render/wmo/wmo_placement_resolver.gd Stable path, identity and transform rules
src/scenes/streaming/streaming_world_loader.gd Node map, instances, resources, jobs, queues and lifecycle reactions
src/tools/verify_wmo_placement_registry.gd Contract, boundary and timing regression