Files
MetaCrate/docs/assets.md
Chili Palmer 52f62d8c39
Some checks failed
Native code generation / deterministic (push) Failing after 2m18s
Imaging and meshing gate / native (push) Failing after 1m30s
JPEG 2000 feature / linux (push) Successful in 2m40s
Native Rust workspace compile / compile (push) Failing after 57s
Skia feature / linux (push) Successful in 31m8s
Implement native asset pipeline and cache (#64)
2026-08-10 07:51:17 +00:00

50 lines
3.2 KiB
Markdown

# Asset models, transfers, and cache
The native asset layer owns the client-facing asset boundary from typed bytes to
transport and persistence. `Asset` retains its UUID, asset type, temporary flag,
and mutable raw payload. Concrete animation, sound, script, calling-card,
landmark, settings, mesh, texture, wearable, and notecard models enforce a 64 MiB
input ceiling and reject malformed structured formats with typed errors. Mesh and
settings parsing use StructuredData. Texture encode/decode uses the imaging
crate's bounded JPEG 2000 adapter, while PCM conversion streams bounded planar
blocks through the cross-platform Ogg Vorbis encoder; neither API exposes codec
implementation types.
`AssetManager` is client-owned and shares one `DownloadManager` and `AssetCache`.
ViewerAsset, GetMesh, GetTexture, and server-bake requests check the cache before
network I/O. Equal HTTP URIs share one in-flight request and its progress sinks;
each awaiting subscriber retains an independent cancellation token, so cancelling
one waiter cannot cancel the shared request for the others. Capability discovery
waits for the seed request's bounded completion rather than racing it.
When ViewerAsset is unavailable, asset and authenticated inventory requests use
LLUDP `TransferRequest`, `TransferInfo`, and `TransferPacket`. The receiver filters
by transfer UUID, preserves priority and source type, reassembles out-of-order
packets, limits announced data to 64 MiB, and sends `TransferAbort` on cancellation
or timeout. Inventory transfers include the agent, session, owner, task, item,
asset, and type parameters. Legacy Xfer downloads confirm each packet, enforce the
same bound, and publish only completely assembled results.
Small and large uploads use the simulator's `AssetUploadRequest`/Xfer handshake,
including packet confirmation and progress events. Baked texture and inventory or
task material uploads use their two-stage capability contracts and require a
complete response containing the new asset UUID. Upload size, cancellation, and
timeout failures remove their pending correlation state.
The disk cache uses UUID-only filenames by default and confines custom filename
callbacks to the configured cache directory. Reads reject empty, oversized, or
non-regular files. Writes use uniquely named same-directory files, flush them,
and atomically rename them into place, making concurrent writers deterministic.
Pruning removes least-recently-accessed regular cache entries until usage is below 90% of
the configured maximum. Automatic pruning is activity-driven at the configured
millisecond interval, avoiding a permanent timer thread; cancellation is checked
between deletions. Clearing and pruning never inspect or delete files outside the
configured project/application cache directory.
Focused native tests in `asset_pipeline_semantics` cover real sound and texture
codec output, model typing, malformed mesh data, atomic cache replacement, cache
corruption, cached-image reconstruction, and pruning. The `caps_http`
deduplication case proves independent subscriber cancellation. Translated asset,
material, mesh, capability-upload, and cache compatibility cases provide the API
contract checks for this issue.