Implement grid and directory discovery (#71)
All checks were successful
Native code generation / deterministic (push) Successful in 15m16s
Imaging and meshing gate / native (push) Successful in 5m9s
JPEG 2000 feature / linux (push) Successful in 2m47s
Native Rust workspace compile / compile (push) Successful in 5m14s
Skia feature / linux (push) Successful in 31m28s

This commit is contained in:
2026-08-10 17:45:08 +00:00
parent d537a37172
commit 66fbb87b3f
14 changed files with 3949 additions and 1541 deletions

43
docs/discovery.md Normal file
View File

@@ -0,0 +1,43 @@
# Grid and directory discovery
`GridClient.Grid`, `GridClient.Directory`, and `GridClient.InterestList` are
client-owned managers. Repeated property access returns handles to the same
state, and disposing the client releases their packet and capability
subscriptions.
`GridManager` uses the advertised `MapLayer` capability with an LLUDP fallback,
and sends standard map-name, map-block, map-item, and region-handle LLUDP
requests. Replies update the name, handle, and UUID indexes
before observers run. Region names are indexed case-insensitively, repeated
blocks replace older values, and entries expire after fifteen minutes using
the client's injectable clock. Async lookups use `MapRequestTimeout`, observe
the caller or client cancellation token, and return the cache result available
at timeout. Map coordinates use 256-metre region origins; `MapItem` exposes
the corresponding local coordinates and region handle, retains every raw
reply field, and provides typed payloads for telehubs, agent clusters, land
sales, and events. Coarse-location updates report complete current positions
plus added and removed agent IDs.
`DirectoryManager` sends correlated people, group, event, classified, parcel,
land, place, and event-info requests. Query IDs are random and returned to the
caller, reply pages are capped at 1,024 records, strings are bounded to the
LLUDP variable-field limit, and negative page/price/area inputs are rejected.
Reply events retain the server query or transaction ID so callers can combine
pages without mixing concurrent searches. Maturity, category, sort, price,
area, and ownership flags are sent unchanged. High-level search entry points
start the same real server queries and return live `IAsyncEnumerable` streams
that yield decoded records in reply order until cancellation, timeout, or a
terminal page. Typed reply events remain available for callback-oriented
consumers.
`SlurlParser` accepts raw locations, `secondlife://` locations, maps URLs,
legacy start locations, and `secondlife:///app` commands. It applies the
reference coordinate defaults, decodes query values, and generates stable,
percent-escaped application and location URLs. Inputs and query counts are
bounded.
`InterestListManager` posts LLSD to each simulator's `InterestList`
capability. A mode is committed only after a successful response; missing
capabilities return `false` for per-simulator calls. `SimulatorFeatures`
atomically replaces its map after bounded LLSD validation and deliberately
retains unknown feature keys for forward compatibility.