# MetaCrate compatibility deviations

This file records intentional differences from the C# LibreMetaverse source. Preserve or
re-evaluate these changes when importing a newer upstream version.

## Bounded login appearance recovery

- A successful login now consumes `AgentSettings.send_appearance`, initializes the shared
  `AppearanceManager`, and starts one generation-fenced appearance request after the simulator is
  ready.
- Self `AvatarAppearance` acknowledgements are accepted as complete only when required baked
  texture IDs, visual parameters, and the expected COF version are present. Transient failures use
  bounded delayed forced rebakes; disconnects and simulator changes cancel stale work.
- COF attachments are compared with simulator child prims by `AttachItemID`; only missing items are
  restored through the existing attachment API. Non-secret structured recovery events expose the
  bake path, counts, serial, retries, acknowledgement, and elapsed time.
- Baked-texture capability responses are decoded as LLSD, as required by the simulator protocol,
  instead of incorrectly treating their uploader and completion maps as JSON.

Files: `src/network_manager.rs`, `src/appearance_manager.rs`, `src/asset_manager.rs`.

## OpenSim varregion dimensions

- `GridRegion` retains the optional `MapBlockReply.Size` dimensions. Missing or zero dimensions
  fall back to 256 x 256 metres.
- `Simulator::region_size()` exposes dimensions resolved after login and is marked `must_use`,
  while the mapped public `size_x` and `size_y` fields remain unchanged for API compatibility.
- A matching map-region event updates the current simulator's resolved dimensions. Movement,
  border prediction, terrain lookup, and terrain archive export use the resolved dimensions.
- The cache distinguishes explicit `Size` blocks from the 256 x 256 fallback. Startup waits for
  an explicit size until timeout, and a later fallback reply cannot downgrade a resolved size.
- Region lookup no longer synthesizes the current simulator as a 256 x 256 `GridRegion`; it
  requests the authoritative map block.

Files: `src/grid_manager.rs`, `src/network_manager.rs`, `src/agent_movement.rs`,
`src/asset_archive.rs`.

## Asynchronous region-reply correlation

- Name and handle lookups subscribe to the continuously dispatched `GridRegion` event stream
  before sending a request.
- Each lookup accepts only the matching name or handle. Unrelated grid, object, avatar, or map
  traffic cannot complete the request early.
- Cancellation and the mapped map-request timeout still bound the one-shot waiter.
- The default map-request timeout is 15 seconds rather than 5 seconds because OpenSim map
  replies on the live varregion can arrive after 7-8 seconds during login.

Files: `src/grid_manager.rs`, `src/client_core.rs`.

## OpenSim asset transport fallback

- When the OpenSim asset capability returns no payload for an asset, the request falls back to
  the existing UDP asset transfer path instead of reporting a missing asset immediately.

File: `src/asset_manager.rs`.

## Deterministic persistent-asset LRU

- Successful immutable asset-cache reads explicitly refresh the file modification timestamp.
  Pruning uses that timestamp as its cross-platform LRU order instead of filesystem access time,
  which can be disabled or coarsened by `noatime` and `relatime` mounts.

Files: `src/asset_cache.rs`, `src/asset_pipeline_semantics.rs`.
