Prove clean native release artifacts (#106)
Some checks failed
API and SemVer surface / api-surface (push) Failing after 1m28s
Native release artifact audit / audit (push) Failing after 1h6m34s
Native code generation / deterministic (push) Failing after 2m15s
Concurrency and resource soak audit / soak (push) Failing after 6m33s
Documentation / documentation (push) Failing after 2m0s
Imaging and meshing gate / native (push) Failing after 55s
JPEG 2000 feature / linux (push) Successful in 2m46s
performance evidence / audit (push) Failing after 13m45s
Release platform and feature matrix / audit (push) Successful in 1m3s
Native Rust workspace compile / compile (push) Failing after 55s
Skia feature / linux (push) Successful in 31m58s
Dependency and supply-chain audit / audit (push) Failing after 9m34s
Release platform and feature matrix / matrix (false, linux-stable-minimal, x86_64-unknown-linux-gnu, stable) (push) Failing after 10m2s
Release platform and feature matrix / matrix (false, macos-stable-portable, x86_64-apple-darwin, stable) (push) Failing after 2m0s
Release platform and feature matrix / matrix (false, windows-stable-portable, x86_64-pc-windows-gnu, stable) (push) Failing after 1m56s
Release platform and feature matrix / matrix (true, linux-msrv-portable, x86_64-unknown-linux-gnu, 1.96.0) (push) Failing after 6m19s
Release platform and feature matrix / matrix (true, linux-stable-default, x86_64-unknown-linux-gnu, stable) (push) Failing after 6m57s
Release platform and feature matrix / matrix (true, linux-stable-features, x86_64-unknown-linux-gnu, stable) (push) Failing after 7m6s
Release platform and feature matrix / matrix (true, linux-stable-release-surface, x86_64-unknown-linux-gnu, stable) (push) Failing after 8m8s
Some checks failed
API and SemVer surface / api-surface (push) Failing after 1m28s
Native release artifact audit / audit (push) Failing after 1h6m34s
Native code generation / deterministic (push) Failing after 2m15s
Concurrency and resource soak audit / soak (push) Failing after 6m33s
Documentation / documentation (push) Failing after 2m0s
Imaging and meshing gate / native (push) Failing after 55s
JPEG 2000 feature / linux (push) Successful in 2m46s
performance evidence / audit (push) Failing after 13m45s
Release platform and feature matrix / audit (push) Successful in 1m3s
Native Rust workspace compile / compile (push) Failing after 55s
Skia feature / linux (push) Successful in 31m58s
Dependency and supply-chain audit / audit (push) Failing after 9m34s
Release platform and feature matrix / matrix (false, linux-stable-minimal, x86_64-unknown-linux-gnu, stable) (push) Failing after 10m2s
Release platform and feature matrix / matrix (false, macos-stable-portable, x86_64-apple-darwin, stable) (push) Failing after 2m0s
Release platform and feature matrix / matrix (false, windows-stable-portable, x86_64-pc-windows-gnu, stable) (push) Failing after 1m56s
Release platform and feature matrix / matrix (true, linux-msrv-portable, x86_64-unknown-linux-gnu, 1.96.0) (push) Failing after 6m19s
Release platform and feature matrix / matrix (true, linux-stable-default, x86_64-unknown-linux-gnu, stable) (push) Failing after 6m57s
Release platform and feature matrix / matrix (true, linux-stable-features, x86_64-unknown-linux-gnu, stable) (push) Failing after 7m6s
Release platform and feature matrix / matrix (true, linux-stable-release-surface, x86_64-unknown-linux-gnu, stable) (push) Failing after 8m8s
This commit is contained in:
@@ -12,8 +12,8 @@ default = []
|
||||
jpeg2000 = ["dep:libremetaverse-openjpeg"]
|
||||
|
||||
[dependencies]
|
||||
libremetaverse-types = { path = "../libremetaverse-types" }
|
||||
libremetaverse-openjpeg = { path = "../libremetaverse-openjpeg", optional = true }
|
||||
libremetaverse-types = { version = "0.0.1", path = "../libremetaverse-types" }
|
||||
libremetaverse-openjpeg = { version = "0.0.1", path = "../libremetaverse-openjpeg", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
stats_alloc = "0.1.10"
|
||||
|
||||
@@ -8,7 +8,7 @@ repository.workspace = true
|
||||
description = "Native LSL lexer and parser tooling for the MetaCrate LibreMetaverse rewrite"
|
||||
|
||||
[dependencies]
|
||||
libremetaverse-types = { path = "../libremetaverse-types" }
|
||||
libremetaverse-types = { version = "0.0.1", path = "../libremetaverse-types" }
|
||||
unicode-general-category = "1.1"
|
||||
regex = "1"
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
[package]
|
||||
name = "libremetaverse-openjpeg"
|
||||
version = "0.0.1"
|
||||
edition = "2024"
|
||||
rust-version = "1.96"
|
||||
license = "BSD-3-Clause"
|
||||
publish = false
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
license.workspace = true
|
||||
repository.workspace = true
|
||||
description = "Safe, bounded OpenJPEG 2.5.4 adapter for MetaCrate"
|
||||
build = "build.rs"
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ rust-version.workspace = true
|
||||
license.workspace = true
|
||||
repository.workspace = true
|
||||
description = "Safe system-libopus adapter for MetaCrate"
|
||||
publish = false
|
||||
build = "build.rs"
|
||||
|
||||
[build-dependencies]
|
||||
|
||||
@@ -8,8 +8,8 @@ repository.workspace = true
|
||||
description = "Primitive meshing shims for the MetaCrate LibreMetaverse rewrite"
|
||||
|
||||
[dependencies]
|
||||
libremetaverse-imaging = { path = "../libremetaverse-imaging" }
|
||||
libremetaverse-types = { path = "../libremetaverse-types" }
|
||||
libremetaverse-imaging = { version = "0.0.1", path = "../libremetaverse-imaging" }
|
||||
libremetaverse-types = { version = "0.0.1", path = "../libremetaverse-types" }
|
||||
|
||||
[dev-dependencies]
|
||||
stats_alloc = "0.1.10"
|
||||
|
||||
@@ -9,12 +9,12 @@ description = "Bounded native MeshFoundry renderer for the MetaCrate LibreMetave
|
||||
|
||||
[dependencies]
|
||||
flate2 = "1.1.2"
|
||||
libremetaverse = { path = "../libremetaverse" }
|
||||
libremetaverse-imaging = { path = "../libremetaverse-imaging" }
|
||||
libremetaverse-prim-mesher = { path = "../libremetaverse-prim-mesher" }
|
||||
libremetaverse-rendering-simple = { path = "../libremetaverse-rendering-simple" }
|
||||
libremetaverse-structured-data = { path = "../libremetaverse-structured-data" }
|
||||
libremetaverse-types = { path = "../libremetaverse-types" }
|
||||
libremetaverse = { version = "0.0.1", path = "../libremetaverse" }
|
||||
libremetaverse-imaging = { version = "0.0.1", path = "../libremetaverse-imaging" }
|
||||
libremetaverse-prim-mesher = { version = "0.0.1", path = "../libremetaverse-prim-mesher" }
|
||||
libremetaverse-rendering-simple = { version = "0.0.1", path = "../libremetaverse-rendering-simple" }
|
||||
libremetaverse-structured-data = { version = "0.0.1", path = "../libremetaverse-structured-data" }
|
||||
libremetaverse-types = { version = "0.0.1", path = "../libremetaverse-types" }
|
||||
|
||||
[dev-dependencies]
|
||||
stats_alloc = "0.1.10"
|
||||
|
||||
@@ -8,10 +8,10 @@ repository.workspace = true
|
||||
description = "Simple renderer shims for the MetaCrate LibreMetaverse rewrite"
|
||||
|
||||
[dependencies]
|
||||
libremetaverse = { path = "../libremetaverse" }
|
||||
libremetaverse-imaging = { path = "../libremetaverse-imaging" }
|
||||
libremetaverse-prim-mesher = { path = "../libremetaverse-prim-mesher" }
|
||||
libremetaverse-types = { path = "../libremetaverse-types" }
|
||||
libremetaverse = { version = "0.0.1", path = "../libremetaverse" }
|
||||
libremetaverse-imaging = { version = "0.0.1", path = "../libremetaverse-imaging" }
|
||||
libremetaverse-prim-mesher = { version = "0.0.1", path = "../libremetaverse-prim-mesher" }
|
||||
libremetaverse-types = { version = "0.0.1", path = "../libremetaverse-types" }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
@@ -8,7 +8,7 @@ repository.workspace = true
|
||||
description = "Bounded native RLV protocol, state, inventory, lock, camera, and permission layer"
|
||||
|
||||
[dependencies]
|
||||
libremetaverse-types = { path = "../libremetaverse-types" }
|
||||
libremetaverse-types = { version = "0.0.1", path = "../libremetaverse-types" }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
@@ -9,7 +9,7 @@ description = "OSD and LLSD shims for the MetaCrate LibreMetaverse rewrite"
|
||||
|
||||
[dependencies]
|
||||
base64 = "0.22"
|
||||
libremetaverse-types = { path = "../libremetaverse-types" }
|
||||
libremetaverse-types = { version = "0.0.1", path = "../libremetaverse-types" }
|
||||
serde = "1"
|
||||
serde_json = "1"
|
||||
|
||||
|
||||
@@ -8,9 +8,9 @@ repository.workspace = true
|
||||
description = "Utility shims for the MetaCrate LibreMetaverse rewrite"
|
||||
|
||||
[dependencies]
|
||||
libremetaverse = { path = "../libremetaverse" }
|
||||
libremetaverse-structured-data = { path = "../libremetaverse-structured-data" }
|
||||
libremetaverse-types = { path = "../libremetaverse-types" }
|
||||
libremetaverse = { version = "0.0.1", path = "../libremetaverse" }
|
||||
libremetaverse-structured-data = { version = "0.0.1", path = "../libremetaverse-structured-data" }
|
||||
libremetaverse-types = { version = "0.0.1", path = "../libremetaverse-types" }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
@@ -8,9 +8,9 @@ repository.workspace = true
|
||||
description = "Vivox voice shims for the MetaCrate LibreMetaverse rewrite"
|
||||
|
||||
[dependencies]
|
||||
libremetaverse = { path = "../libremetaverse" }
|
||||
libremetaverse-structured-data = { path = "../libremetaverse-structured-data" }
|
||||
libremetaverse-types = { path = "../libremetaverse-types" }
|
||||
libremetaverse = { version = "0.0.1", path = "../libremetaverse" }
|
||||
libremetaverse-structured-data = { version = "0.0.1", path = "../libremetaverse-structured-data" }
|
||||
libremetaverse-types = { version = "0.0.1", path = "../libremetaverse-types" }
|
||||
roxmltree = "0.21.1"
|
||||
tokio = { version = "1.47.1", features = ["io-util", "net", "time"] }
|
||||
|
||||
|
||||
@@ -9,10 +9,10 @@ description = "WebRTC voice shims for the MetaCrate LibreMetaverse rewrite"
|
||||
|
||||
[dependencies]
|
||||
hound = "3.5"
|
||||
libremetaverse = { path = "../libremetaverse" }
|
||||
libremetaverse-opus = { path = "../libremetaverse-opus" }
|
||||
libremetaverse-structured-data = { path = "../libremetaverse-structured-data" }
|
||||
libremetaverse-types = { path = "../libremetaverse-types" }
|
||||
libremetaverse = { version = "0.0.1", path = "../libremetaverse" }
|
||||
libremetaverse-opus = { version = "0.0.1", path = "../libremetaverse-opus" }
|
||||
libremetaverse-structured-data = { version = "0.0.1", path = "../libremetaverse-structured-data" }
|
||||
libremetaverse-types = { version = "0.0.1", path = "../libremetaverse-types" }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
str0m = { version = "0.22", default-features = false, features = ["rust-crypto"] }
|
||||
|
||||
@@ -19,9 +19,9 @@ bcdec_rs = { version = "0.2.0", optional = true }
|
||||
flate2 = "1.1.2"
|
||||
futures-channel = "0.3.31"
|
||||
futures-util = "0.3.31"
|
||||
libremetaverse-imaging = { path = "../libremetaverse-imaging" }
|
||||
libremetaverse-structured-data = { path = "../libremetaverse-structured-data" }
|
||||
libremetaverse-types = { path = "../libremetaverse-types" }
|
||||
libremetaverse-imaging = { version = "0.0.1", path = "../libremetaverse-imaging" }
|
||||
libremetaverse-structured-data = { version = "0.0.1", path = "../libremetaverse-structured-data" }
|
||||
libremetaverse-types = { version = "0.0.1", path = "../libremetaverse-types" }
|
||||
mac_address2 = "2.0.2"
|
||||
os_info = { version = "3.15.0", default-features = false }
|
||||
reqwest = { version = "0.13.4", default-features = false, features = ["rustls", "stream"] }
|
||||
|
||||
267
crates/libremetaverse/README.md
Normal file
267
crates/libremetaverse/README.md
Normal file
@@ -0,0 +1,267 @@
|
||||
# Rust API and C# migration guide
|
||||
|
||||
`MetaCrate` is a native Rust implementation of the API and behavior cataloged
|
||||
from `LibreMetaverse`. The compatibility reference is the
|
||||
[pinned C# source](https://github.com/cinderblocks/libremetaverse/tree/2aa70bb68513b39795da5d13c88f31b86e85a3ba);
|
||||
it is never loaded, invoked, or shipped. Exact type/member mappings live in
|
||||
[`RUST-TYPES.tsv`](https://git.rfc1437.de/hugo/MetaCrate/src/branch/main/api/RUST-TYPES.tsv) and
|
||||
[`RUST-MAPPING.tsv`](https://git.rfc1437.de/hugo/MetaCrate/src/branch/main/api/RUST-MAPPING.tsv). Search those files by C#
|
||||
documentation ID when a familiar member has a non-obvious Rust name.
|
||||
|
||||
## Choosing crates and features
|
||||
|
||||
Most applications start with `libremetaverse` and add narrower crates only when
|
||||
they use those APIs directly.
|
||||
|
||||
| Crate | Choose it for | Features or system boundary |
|
||||
| --- | --- | --- |
|
||||
| `libremetaverse` | Grid client, login, network, agents, inventory, assets, appearance, world, and social APIs | Default pure-Rust BC6H/BC7; optional `jpeg2000` and `vorbis` |
|
||||
| `libremetaverse-types` | UUIDs, vectors, matrices, colors, cancellation, compatibility collections, and boundary types | Pure Rust |
|
||||
| `libremetaverse-structured-data` | LLSD/OSD XML, JSON, binary, and notation | Pure Rust |
|
||||
| `libremetaverse-imaging` | Managed images, TGA/DDS, codec traits | Optional `jpeg2000` |
|
||||
| `libremetaverse-imaging-skia` | Common raster formats through Skia | Optional `skia`; native Skia build/cache |
|
||||
| `libremetaverse-prim-mesher` | Legacy prim and sculpt geometry | Pure Rust |
|
||||
| `libremetaverse-rendering-simple` | Deterministic reference geometry | Pure Rust |
|
||||
| `libremetaverse-rendering-mesh-foundry` | Prim, terrain, sculpt, and mesh-asset rendering | Pure Rust |
|
||||
| `libremetaverse-lsl-tools` | LSL lexing, parsing, diagnostics, and generation | Pure Rust |
|
||||
| `libremetaverse-rlv` | RLV commands, restrictions, locks, camera, and inventory policy | Pure Rust |
|
||||
| `libremetaverse-utilities` | Compatible utility helpers | Pure Rust |
|
||||
| `libremetaverse-voice-vivox` | Vivox XML control protocol | External Vivox service is explicit and never spawned |
|
||||
| `libremetaverse-voice-webrtc` | Native ICE/DTLS/SRTP/SCTP and Opus voice | System libopus; optional `real-audio` uses CPAL |
|
||||
| `libremetaverse-openjpeg` | Audited `OpenJPEG` adapter | System `OpenJPEG` 2.5.4 or newer |
|
||||
| `libremetaverse-opus` | Audited Opus encoder/decoder adapter | System libopus |
|
||||
|
||||
Features are additive. Keep defaults unless you need a codec, and enable one
|
||||
native adapter at a time while diagnosing installation problems. The
|
||||
[release CI matrix](https://git.rfc1437.de/hugo/MetaCrate/src/branch/main/docs/release-ci-matrix.md) records every validated combination.
|
||||
|
||||
## Naming and overload migration
|
||||
|
||||
C# `PascalCase` types remain recognizable while methods and properties use
|
||||
Rust `snake_case`. A property getter becomes `name()` and its setter becomes
|
||||
`set_name(value)`. Events become `subscribe_*` methods returning an owned
|
||||
subscription. Rust has no overloads, so the simplest form keeps the base name
|
||||
and additional forms receive parameter-derived suffixes. The mapping ledger is
|
||||
authoritative; do not guess a long suffix.
|
||||
|
||||
```rust
|
||||
use libremetaverse::InventoryItem;
|
||||
use libremetaverse_types::UUID;
|
||||
|
||||
let id = UUID::new_with_u_int64(42)?;
|
||||
let mut item = InventoryItem::new_with_uuid(id)?;
|
||||
item.base.set_name("Migrated item".into());
|
||||
assert_eq!(item.base.uuid(), id);
|
||||
assert_eq!(item.base.name(), "Migrated item");
|
||||
# Ok::<(), libremetaverse::Error>(())
|
||||
```
|
||||
|
||||
C# `null` usually maps to `Option<T>`, `ref`/`out` may become a return value or
|
||||
an explicit mutable reference, and interface objects become `dyn Trait` behind
|
||||
`Arc` or `Box` according to the ledger's `ownership` column.
|
||||
|
||||
## Ownership and disposal
|
||||
|
||||
Managers cloned from a `GridClient` share native state. `GridClient` owns its
|
||||
cancellation root and cached services; event guards own registrations; session
|
||||
objects own tasks and sockets. Explicit shutdown is recommended because it can
|
||||
report errors, while `Drop` remains the final idempotent safety net.
|
||||
|
||||
```rust
|
||||
use libremetaverse::{ClientLifecycleState, GridClient};
|
||||
|
||||
let client = GridClient::new()?;
|
||||
assert_eq!(client.lifecycle_state(), ClientLifecycleState::Active);
|
||||
client.dispose_with_method()?;
|
||||
client.dispose_with_method()?; // idempotent
|
||||
assert_eq!(client.lifecycle_state(), ClientLifecycleState::Disposed);
|
||||
# Ok::<(), libremetaverse::Error>(())
|
||||
```
|
||||
|
||||
The runnable version is
|
||||
[`offline_client.rs`](https://git.rfc1437.de/hugo/MetaCrate/src/branch/main/crates/libremetaverse/examples/offline_client.rs).
|
||||
Never hold a manager lock while calling user code or awaiting I/O. Services
|
||||
registered through `GridClient::builder()` must join every owned task before
|
||||
their `shutdown` method returns.
|
||||
|
||||
## Async work and cancellation
|
||||
|
||||
Async APIs borrow no hidden runtime. Call them from the application executor and
|
||||
pass `CancellationToken` explicitly where the C# API accepted one. Cloning a
|
||||
token is cheap and observes the same cancellation source. Cancellation is a
|
||||
typed `Error::Cancelled`, not a successful empty response.
|
||||
|
||||
```rust
|
||||
use libremetaverse_types::compat::CancellationTokenSource;
|
||||
|
||||
# #[tokio::main(flavor = "current_thread")]
|
||||
# async fn main() -> Result<(), libremetaverse::Error> {
|
||||
let source = CancellationTokenSource::new();
|
||||
let token = source.token();
|
||||
source.cancel();
|
||||
token.cancelled().await;
|
||||
assert!(matches!(
|
||||
token.throw_if_cancellation_requested(),
|
||||
Err(libremetaverse::Error::Cancelled)
|
||||
));
|
||||
# Ok(())
|
||||
# }
|
||||
```
|
||||
|
||||
The same code is available as
|
||||
[`cancellation.rs`](https://git.rfc1437.de/hugo/MetaCrate/src/branch/main/crates/libremetaverse/examples/cancellation.rs).
|
||||
Timeouts belong at the caller or documented operation boundary; cancellation
|
||||
must still drain and join the underlying resource owner.
|
||||
|
||||
## Errors
|
||||
|
||||
Fallible compatibility APIs return the shared `libremetaverse::Error`; native
|
||||
composition APIs may expose a narrower error such as `ClientCoreError` or
|
||||
`WebRtcError`. Match variants for control flow and use display text only for
|
||||
operators. Errors and `Debug` output redact credentials, capability URLs, and
|
||||
session secrets.
|
||||
|
||||
```rust
|
||||
use libremetaverse::http::DownloadRequest;
|
||||
use libremetaverse_types::compat::Uri;
|
||||
|
||||
let result = DownloadRequest::new(Uri("file:///not-http".into()), None, None);
|
||||
assert!(matches!(result, Err(libremetaverse::Error::Argument)));
|
||||
```
|
||||
|
||||
Do not translate C# exception swallowing into `unwrap_or_default()`. Preserve
|
||||
the mapped error contract and handle cancellation separately from protocol,
|
||||
I/O, authentication, and validation failures.
|
||||
|
||||
## Events and subscriptions
|
||||
|
||||
An `EventHandler<T>` is an `Arc` callback. Keep the returned `Subscription` for
|
||||
exactly as long as notifications are wanted; dropping it unregisters the
|
||||
callback. Dispatch clones the handler list and releases internal locks before
|
||||
calling user code. Manager event dispatch isolates subscriber panics so one
|
||||
consumer cannot stop later consumers.
|
||||
|
||||
```rust
|
||||
use libremetaverse::{GridClient, Inventory, InventoryFolder};
|
||||
use libremetaverse_types::UUID;
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
let client = Arc::new(GridClient::new()?);
|
||||
let inventory = Inventory::new_with_grid_client_uuid(Arc::clone(&client), UUID::zero())?;
|
||||
let calls = Arc::new(AtomicUsize::new(0));
|
||||
let observed = Arc::clone(&calls);
|
||||
let subscription = inventory.subscribe_inventory_object_added(Arc::new(move |_| {
|
||||
observed.fetch_add(1, Ordering::AcqRel);
|
||||
}));
|
||||
let folder = InventoryFolder::new(UUID::new_with_u_int64(7)?)?;
|
||||
inventory.update_node_for(&folder)?;
|
||||
assert_eq!(calls.load(Ordering::Acquire), 1);
|
||||
drop(subscription);
|
||||
client.dispose_with_method()?;
|
||||
# Ok::<(), libremetaverse::Error>(())
|
||||
```
|
||||
|
||||
## Threading and callbacks
|
||||
|
||||
Public shared managers use `Arc`, atomics, mutexes, channels, and cancellation
|
||||
tokens rather than a CLR synchronization context. A type being cloneable does
|
||||
not make a callback re-entrant: keep handlers short, move expensive work to a
|
||||
bounded queue, and never block an async runtime thread waiting for itself.
|
||||
Download, inventory, client, and voice diagnostics expose owned task/queue
|
||||
counts for shutdown checks. The [concurrency audit](https://git.rfc1437.de/hugo/MetaCrate/src/branch/main/docs/concurrency-hardening.md)
|
||||
defines the exact baseline and soak thresholds.
|
||||
|
||||
## Security boundaries
|
||||
|
||||
The released graph contains no CLR host, .NET assembly loader, subprocess RPC,
|
||||
or foreign `LibreMetaverse` bridge. HTTP uses rustls. Untrusted LLSD, archive,
|
||||
image, packet, event, and signaling inputs have explicit size/depth limits.
|
||||
Secrets belong in operation arguments or environment variables, never in
|
||||
diagnostics, evidence, filenames, command lines, or committed fixtures.
|
||||
|
||||
Offline/fake modes are real deterministic executions, not skipped live tests.
|
||||
Live login and every mutating smoke action require their own opt-in and literal
|
||||
confirmation. See the [live-grid boundary](https://git.rfc1437.de/hugo/MetaCrate/src/branch/main/docs/live-grid-smoke.md).
|
||||
|
||||
## Native prerequisites
|
||||
|
||||
The default client build needs no image-codec system library. Optional native
|
||||
features require:
|
||||
|
||||
- `OpenJPEG` 2.5.4 or newer for `jpeg2000`;
|
||||
- the rust-skia prerequisites/cache for `skia`;
|
||||
- system libopus for WebRTC voice and the `libremetaverse-opus` adapter;
|
||||
- ALSA development headers on Linux, `CoreAudio` on macOS, or WASAPI on Windows
|
||||
when `real-audio` enables CPAL;
|
||||
- the Vorbis encoder build prerequisites for `vorbis`.
|
||||
|
||||
Discovery uses `pkg-config` on Unix/macOS and `vcpkg` on Windows MSVC where
|
||||
applicable. The adapters remain cross-platform; Gitea workflows intentionally
|
||||
run only on `ubuntu-latest`.
|
||||
|
||||
## Live `OpenSim` setup
|
||||
|
||||
Use a dedicated `OpenSim` account and put credentials in the workspace `.env` or
|
||||
the process environment. The login URL is used directly; no Second Life host is
|
||||
substituted.
|
||||
|
||||
```text
|
||||
GRID_USER=First Last
|
||||
GRID_PASSWORD=...
|
||||
GRID_LOGIN_URL=https://your-opensim.example/login
|
||||
```
|
||||
|
||||
Start with the credential-safe audit and fake smoke, then opt into live login:
|
||||
|
||||
```sh
|
||||
cargo run -p libremetaverse-programs --bin live-grid-smoke -- --audit-only
|
||||
cargo run -p libremetaverse-programs --bin live-grid-smoke -- --fake
|
||||
cargo run -p libremetaverse-programs --bin live-grid-smoke -- \
|
||||
--allow-live-login --confirm-live-login LOGIN
|
||||
```
|
||||
|
||||
Chat, movement, and reversible inventory each require additional confirmations
|
||||
documented in the [`OpenSim` live-grid guide](https://git.rfc1437.de/hugo/MetaCrate/src/branch/main/docs/live-grid-smoke.md). A test that
|
||||
needs live credentials must fail clearly when they are absent; it must not
|
||||
silently skip.
|
||||
|
||||
## Programs and operational tools
|
||||
|
||||
All pinned upstream programs have native Rust targets and deterministic offline
|
||||
tests. Their arguments, exit statuses, fake/live boundaries, and focused test
|
||||
commands are linked from the [program operations manual](https://git.rfc1437.de/hugo/MetaCrate/src/branch/main/programs/README.md):
|
||||
|
||||
- [`osd-inspector`](https://git.rfc1437.de/hugo/MetaCrate/src/branch/main/programs/README.md#osdinspector)
|
||||
- [`simple-bot`](https://git.rfc1437.de/hugo/MetaCrate/src/branch/main/programs/README.md#simplebot)
|
||||
- [`packet-dump`](https://git.rfc1437.de/hugo/MetaCrate/src/branch/main/programs/README.md#packetdump)
|
||||
- [`prim-inspector`](https://git.rfc1437.de/hugo/MetaCrate/src/branch/main/programs/README.md#priminspector)
|
||||
- [`inventory-explorer`](https://git.rfc1437.de/hugo/MetaCrate/src/branch/main/programs/README.md#inventoryexplorer)
|
||||
- [`irc-gateway`](https://git.rfc1437.de/hugo/MetaCrate/src/branch/main/programs/README.md#ircgateway)
|
||||
- [`test-client`](https://git.rfc1437.de/hugo/MetaCrate/src/branch/main/programs/README.md#testclient)
|
||||
- [`vivox-test`](https://git.rfc1437.de/hugo/MetaCrate/src/branch/main/programs/README.md#vivoxtest)
|
||||
- [`webrtc-test`](https://git.rfc1437.de/hugo/MetaCrate/src/branch/main/programs/README.md#webrtctest)
|
||||
|
||||
For services, run the client under an external supervisor, propagate shutdown
|
||||
cancellation, bound queues/files, collect sanitized evidence, and call logout
|
||||
before disposal. The tool never invents persistence or retry policy on behalf of
|
||||
the application.
|
||||
|
||||
## Documentation validation
|
||||
|
||||
The complete documentation gate is:
|
||||
|
||||
```sh
|
||||
cargo run --locked -p metacrate-ci-matrix -- documentation-audit \
|
||||
--evidence /tmp/metacrate-documentation.json
|
||||
RUSTDOCFLAGS="-D warnings" cargo doc --workspace --no-deps --locked -j 1
|
||||
cargo test --locked -p libremetaverse --doc -j 1
|
||||
cargo test --locked -p libremetaverse --examples -j 1
|
||||
cargo run --locked -p libremetaverse --example offline_client
|
||||
cargo run --locked -p libremetaverse --example cancellation
|
||||
```
|
||||
|
||||
The generated [coverage report](https://git.rfc1437.de/hugo/MetaCrate/src/branch/main/api/DOCUMENTATION-COVERAGE.md) proves that
|
||||
every mapped member/type retains its exact C# concept ID and mapping context,
|
||||
all public crates have root docs, all local Markdown links resolve, all programs
|
||||
are linked, and every Rust fence in this guide is compiled as a doctest.
|
||||
17504
crates/libremetaverse/assets/avatar_lad.xml
Normal file
17504
crates/libremetaverse/assets/avatar_lad.xml
Normal file
File diff suppressed because it is too large
Load Diff
@@ -113,7 +113,7 @@ impl LindenAvatarDefinition {
|
||||
owned_xml = read_bounded(&file_name)?;
|
||||
owned_xml.as_str()
|
||||
} else {
|
||||
include_str!("../../../codegen/inputs/avatar_lad.xml")
|
||||
include_str!("../assets/avatar_lad.xml")
|
||||
};
|
||||
let document = Document::parse(xml).map_err(|_| Error::Argument)?;
|
||||
let mut attachment_points = Vec::new();
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
//! world, and social APIs. The appended guide covers crate selection, C# name
|
||||
//! migration, ownership, cancellation, events, security, and `OpenSim` setup.
|
||||
|
||||
#![doc = include_str!("../../../docs/rust-api-guide.md")]
|
||||
#![doc = include_str!("../README.md")]
|
||||
|
||||
extern crate self as libremetaverse;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user