Implement native inventory manager workflows (#62)
All checks were successful
Native code generation / deterministic (push) Successful in 13m14s
Imaging and meshing gate / native (push) Successful in 4m13s
Native Rust workspace compile / compile (push) Successful in 4m19s

This commit is contained in:
2026-08-10 06:00:28 +00:00
parent eb7be428c6
commit 61d6721287
15 changed files with 5564 additions and 576 deletions

View File

@@ -16,8 +16,10 @@ on:
- "tools/check_milestone_09_issue_59.py"
- "tools/check_milestone_09_issue_60.py"
- "tools/check_milestone_09_issue_61.py"
- "tools/check_milestone_09_issue_62.py"
- "crates/libremetaverse/src/agent_movement.rs"
- "crates/libremetaverse/src/inventory.rs"
- "crates/libremetaverse/src/inventory_manager.rs"
- "docs/agent-movement.md"
- "docs/inventory.md"
- "crates/libremetaverse/Cargo.toml"
@@ -32,6 +34,8 @@ on:
- "tests/compat/tests/wire_semantics.rs"
- "tests/compat/tests/appearance_visual_semantics.rs"
- "tests/compat/tests/inventory_store_semantics.rs"
- "tests/compat/tests/inventory_manager_semantics.rs"
- "tests/compat/tests/task_inventory_semantics.rs"
- "tests/compat/tests/misclassified_link_semantics.rs"
- "tests/upstream-tests.json"
pull_request:
@@ -49,8 +53,10 @@ on:
- "tools/check_milestone_09_issue_59.py"
- "tools/check_milestone_09_issue_60.py"
- "tools/check_milestone_09_issue_61.py"
- "tools/check_milestone_09_issue_62.py"
- "crates/libremetaverse/src/agent_movement.rs"
- "crates/libremetaverse/src/inventory.rs"
- "crates/libremetaverse/src/inventory_manager.rs"
- "docs/agent-movement.md"
- "docs/inventory.md"
- "crates/libremetaverse/Cargo.toml"
@@ -65,6 +71,8 @@ on:
- "tests/compat/tests/wire_semantics.rs"
- "tests/compat/tests/appearance_visual_semantics.rs"
- "tests/compat/tests/inventory_store_semantics.rs"
- "tests/compat/tests/inventory_manager_semantics.rs"
- "tests/compat/tests/task_inventory_semantics.rs"
- "tests/compat/tests/misclassified_link_semantics.rs"
- "tests/upstream-tests.json"
workflow_dispatch:
@@ -90,6 +98,7 @@ jobs:
python3 tools/check_milestone_09_issue_59.py
python3 tools/check_milestone_09_issue_60.py
python3 tools/check_milestone_09_issue_61.py
python3 tools/check_milestone_09_issue_62.py
cargo check --manifest-path tests/api-compile/Cargo.toml --locked
- name: Test generated wire codecs and translated parity cases
run: |
@@ -98,6 +107,8 @@ jobs:
cargo test -p libremetaverse --test packet_osd
cargo test -p libremetaverse-compat-tests --test wire_semantics
cargo test -p libremetaverse-compat-tests --test inventory_store_semantics
cargo test -p libremetaverse-compat-tests --test inventory_manager_semantics
cargo test -p libremetaverse-compat-tests --test task_inventory_semantics
cargo test -p libremetaverse-compat-tests --test misclassified_link_semantics
- name: Test generated visual and foliage catalogs
run: |

View File

@@ -30,5 +30,6 @@ jobs:
python3 tools/check_milestone_09_issue_59.py
python3 tools/check_milestone_09_issue_60.py
python3 tools/check_milestone_09_issue_61.py
python3 tools/check_milestone_09_issue_62.py
- name: Compile every workspace target with bounded memory
run: cargo check --workspace --all-targets --locked -j 1

View File

@@ -357,3 +357,13 @@ The versioned 64 MiB-bounded cache validates complete snapshots before install
and uses same-directory temporary replacement with rollback. The compatibility
and persistence contract is documented in
[`docs/inventory.md`](docs/inventory.md).
The client-owned `InventoryManager` now implements the packet-level create,
update, move, copy, remove, fetch, search, give, rez/derez, script-state, and
task-inventory workflows. Callback IDs and concurrent item/task waiters are
bounded and cancellation-safe; generated multi-block packets retain the UDP
codec's MTU-aware splitting. Capability replies and UDP replies are validated
before store reconciliation, and legacy task inventory uses a 16 MiB-bounded
`ReplyTaskInventory`/`RequestXfer` state machine. Focused translated and native
fake-packet tests cover correlation, stale replies, offers, bulk completion,
capability task inventory, and malformed transfer sizes.

View File

@@ -4,7 +4,7 @@ Generated by `python3 tools/generate_api_shims.py`; do not edit by hand.
| Assembly | Types | Members | Status |
|---|---:|---:|---|
| `LibreMetaverse` | 2,711 | 27,281 | native implementation: 153 types / 14,746 members; remaining surface is callable failure-only shims |
| `LibreMetaverse` | 2,711 | 27,281 | native implementation: 164 types / 14,877 members; remaining surface is callable failure-only shims |
| `LibreMetaverse.Imaging.Abstractions` | 3 | 20 | native implementation: 3 types / 20 members; no generated shims remain |
| `LibreMetaverse.Imaging.Skia` | 1 | 3 | native implementation: 1 type / 3 members; no generated shims remain |
| `LibreMetaverse.LslTools` | 164 | 768 | callable failure-only shim |

View File

@@ -359,9 +359,10 @@ async fn run_seed_requests(weak: Weak<CapsInner>, cancellation: CancellationToke
let Some(simulator) = inner.simulator() else {
return;
};
if !simulator.native_is_connected() {
return;
}
// Seed discovery is HTTP-only. It is valid for composed/fake clients
// to install a simulator and query capabilities before a UDP circuit
// is started, and tying this request to UDP connectivity creates an
// unnecessary race for every capability-backed manager.
let http = simulator.client.native_http_caps_client();
let response = http
.post_with_uri_osd_format_osd_cancellation_token_i_progress(

View File

@@ -118,6 +118,7 @@ struct ClientRuntime {
caps_rate_limiter: Mutex<crate::caps_http::CapsRateLimiter>,
network_manager: Mutex<std::sync::Weak<crate::network_manager::NetworkManagerInner>>,
agent_manager: Mutex<std::sync::Weak<crate::agent_manager::AgentManagerInner>>,
inventory_manager: Mutex<Option<Arc<crate::inventory_manager::InventoryManagerInner>>>,
shutdown_complete: Condvar,
shutdown_wait: Mutex<()>,
}
@@ -146,6 +147,7 @@ impl ClientRuntime {
caps_rate_limiter: Mutex::new(caps_rate_limiter),
network_manager: Mutex::new(std::sync::Weak::new()),
agent_manager: Mutex::new(std::sync::Weak::new()),
inventory_manager: Mutex::new(None),
shutdown_complete: Condvar::new(),
shutdown_wait: Mutex::new(()),
}
@@ -218,6 +220,10 @@ impl ClientRuntime {
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner)
.take();
self.inventory_manager
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner)
.take();
self.http_caps_client
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner)
@@ -239,6 +245,30 @@ impl ClientRuntime {
}
}
/// A non-owning route back to a live client runtime.
///
/// Manager caches can hold this handle without creating an `Arc` cycle. The
/// settings and time provider are immutable client composition data and are
/// cloned only when a manager needs to perform an operation.
#[derive(Clone)]
pub(crate) struct ClientWeakHandle {
runtime: std::sync::Weak<ClientRuntime>,
settings: Settings,
time_provider: TimeProvider,
}
impl ClientWeakHandle {
pub(crate) fn upgrade(&self) -> Option<GridClient> {
Some(GridClient {
settings: self.settings.clone(),
time_provider: self.time_provider.clone(),
runtime: self.runtime.upgrade()?,
network_manager: None,
agent_manager: None,
})
}
}
/// Native owner for the mapped C# `GridClient` lifecycle slice.
///
/// Construction is side-effect free: it creates no runtime, task, socket, or
@@ -386,6 +416,40 @@ impl GridClient {
Ok(manager)
}
pub(crate) fn native_weak_handle(&self) -> ClientWeakHandle {
ClientWeakHandle {
runtime: Arc::downgrade(&self.runtime),
settings: self.settings.clone(),
time_provider: self.time_provider.clone(),
}
}
pub(crate) fn native_inventory(&self) -> Result<crate::InventoryManager, crate::Error> {
let mut cached = self
.runtime
.inventory_manager
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
if let Some(inner) = cached.as_ref() {
return Ok(
crate::inventory_manager::InventoryManager::native_from_inner(Arc::clone(inner)),
);
}
let manager =
crate::inventory_manager::InventoryManager::native_new(Some(Arc::new(self.clone())))?;
*cached = Some(manager.native_inner());
Ok(manager)
}
#[allow(clippy::needless_pass_by_value)] // The mapped C# property setter owns its value.
pub(crate) fn native_set_inventory(&mut self, value: crate::InventoryManager) {
*self
.runtime
.inventory_manager
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner) = Some(value.native_inner());
}
#[allow(clippy::needless_pass_by_value)] // The mapped C# property setter owns its value.
pub(crate) fn native_set_network(&mut self, value: crate::NetworkManager) {
*self

File diff suppressed because it is too large Load Diff

View File

@@ -1462,6 +1462,16 @@ impl Inventory {
.and_then(|value| value.clone_as::<T>()))
}
/// Returns the shared item portion regardless of the concrete inventory
/// subclass stored for the UUID.
pub(crate) fn native_item_value(&self, uuid: UUID) -> Option<InventoryItem> {
read(&self.inner.state)
.items
.get(&uuid)
.and_then(InventoryNode::value)
.and_then(|value| value.item().cloned())
}
pub fn try_get_value_with_uuid_inventory_base(
&self,
uuid: UUID,

File diff suppressed because it is too large Load Diff

View File

@@ -15,6 +15,7 @@ mod download_manager;
mod event_queue;
mod gesture;
mod inventory;
mod inventory_manager;
#[rustfmt::skip] // Deterministic machine output is formatted by the pinned generator.
mod foliage_catalog;
mod generated;

View File

@@ -1216,6 +1216,10 @@ impl Simulator {
.map(|inner| Caps::native_from_inner(inner, self.native_clone_without_caps()))
}
pub(crate) fn native_id(&self) -> UUID {
self.data.id
}
pub(crate) fn native_from_weak(data: &Weak<SimulatorData>) -> Option<Self> {
data.upgrade().map(|data| Self { caps: None, data })
}

View File

@@ -36,3 +36,36 @@ The focused compatibility suites are
`inventory_store_semantics` and `misclassified_link_semantics`; native unit
tests additionally cover concrete cache round trips, permissions, corruption,
unknown versions, system-folder sorting, and callback re-entry.
## UDP inventory manager
`InventoryManager` now owns the live inventory protocol boundary. Login installs
the agent and library skeletons in the transport-free store, while validated
`UpdateCreateInventoryItem`, `BulkUpdateInventory`, `FetchInventoryReply`, and
`InventoryDescendents` replies populate or reconcile it. Create and copy callback
IDs, item fetches, task replies, and inventory offers are correlated independently;
cancelling one waiter removes only that waiter. A cleanup worker bounds abandoned
requests to one minute, and the manager rejects more than 4,096 pending operations.
Outbound create, update, move, copy, remove, give, rez/derez, script-state, and
task-inventory operations build the generated protocol packet types. Generated
multi-block packets use the packet codec's `encode_multiple` path, so large batches
are split according to the UDP transport bounds while retaining the same agent,
session, transaction, callback, owner, and permission data. Capability-backed
inventory fetch and folder-content responses are parsed before becoming visible in
the store. Asset, material, script, notecard, and thumbnail upload bodies remain a
separate asset-pipeline concern.
Legacy task inventory uses a correlated `ReplyTaskInventory` filename followed by
a `RequestXfer` transfer. The implementation confirms packets, handles duplicate
or out-of-order packet numbers deterministically, aborts cancelled transfers, and
rejects announced or accumulated data above 16 MiB. Task text parsing is capped at
100,000 entries and accepts both plain asset IDs and the reference shadow-ID XOR
encoding. The capability path applies the same byte and entry limits.
No store lock is held across an await, a packet send, or an observer callback.
Reply data is decoded and validated before store mutation, and event registries
snapshot subscribers before invoking them. Focused coverage lives in
`inventory_manager_semantics`, `task_inventory_semantics`, and the native
`inventory_manager::tests` fake-packet cases for callback isolation, bulk-copy
completion, stale folder versions, offers, capability events, and bounded Xfer.

View File

@@ -0,0 +1,152 @@
#!/usr/bin/env python3
"""Audit issue 62's native UDP inventory-manager boundary."""
from __future__ import annotations
from pathlib import Path
import re
import generate_api_shims
ROOT = Path(__file__).resolve().parents[1]
SOURCE = ROOT / "crates" / "libremetaverse" / "src" / "inventory_manager.rs"
DOC = ROOT / "docs" / "inventory.md"
MANAGER_TESTS = ROOT / "tests" / "compat" / "tests" / "inventory_manager_semantics.rs"
TASK_TESTS = ROOT / "tests" / "compat" / "tests" / "task_inventory_semantics.rs"
STUB_RE = re.compile(r"\b(?:not_implemented|unimplemented_api)\b|\b(?:todo|unimplemented)!\s*\(")
REQUIRED_TYPES = {
"T:LibreMetaverse.FindObjectByPathReplyEventArgs",
"T:LibreMetaverse.FolderUpdatedEventArgs",
"T:LibreMetaverse.InventoryManager",
"T:LibreMetaverse.InventoryManager.CopyItemsResult",
"T:LibreMetaverse.InventoryManager.FolderUpdateResult",
"T:LibreMetaverse.InventoryObjectOfferedEventArgs",
"T:LibreMetaverse.ItemReceivedEventArgs",
"T:LibreMetaverse.SaveAssetToInventoryEventArgs",
"T:LibreMetaverse.ScriptRunningReplyEventArgs",
"T:LibreMetaverse.TaskInventoryReplyEventArgs",
"T:LibreMetaverse.TaskItemReceivedEventArgs",
}
REQUIRED_MEMBERS = {
"E:LibreMetaverse.InventoryManager.FindObjectByPathReply",
"E:LibreMetaverse.InventoryManager.FolderUpdated",
"E:LibreMetaverse.InventoryManager.InventoryObjectOffered",
"E:LibreMetaverse.InventoryManager.ItemReceived",
"E:LibreMetaverse.InventoryManager.ScriptRunningReply",
"E:LibreMetaverse.InventoryManager.TaskInventoryReply",
"E:LibreMetaverse.InventoryManager.TaskItemReceived",
"M:LibreMetaverse.InventoryManager.#ctor(LibreMetaverse.GridClient)",
"M:LibreMetaverse.InventoryManager.CreateFolder(LibreMetaverse.UUID,System.String,LibreMetaverse.FolderType)",
"M:LibreMetaverse.InventoryManager.CreateItemAsync(LibreMetaverse.UUID,System.String,System.String,LibreMetaverse.AssetType,LibreMetaverse.UUID,LibreMetaverse.InventoryType,LibreMetaverse.WearableType,LibreMetaverse.PermissionMask,System.Threading.CancellationToken)",
"M:LibreMetaverse.InventoryManager.CreateLinkAsync(LibreMetaverse.UUID,LibreMetaverse.UUID,System.String,System.String,LibreMetaverse.InventoryType,LibreMetaverse.UUID,System.Threading.CancellationToken)",
"M:LibreMetaverse.InventoryManager.FetchItemAsync(LibreMetaverse.UUID,LibreMetaverse.UUID,System.Threading.CancellationToken)",
"M:LibreMetaverse.InventoryManager.FindObjectByPathAsync(LibreMetaverse.UUID,LibreMetaverse.UUID,System.String,System.Threading.CancellationToken)",
"M:LibreMetaverse.InventoryManager.FolderContentsAsync(LibreMetaverse.UUID,LibreMetaverse.UUID,System.Boolean,System.Boolean,LibreMetaverse.InventorySortOrder,System.Threading.CancellationToken,System.Boolean)",
"M:LibreMetaverse.InventoryManager.GetTaskInventoryAsync(LibreMetaverse.UUID,System.UInt32,LibreMetaverse.Simulator,System.Threading.CancellationToken)",
"M:LibreMetaverse.InventoryManager.GiveFolderAsync(LibreMetaverse.UUID,System.String,LibreMetaverse.UUID,System.Boolean,System.Threading.CancellationToken)",
"M:LibreMetaverse.InventoryManager.GiveItem(LibreMetaverse.UUID,System.String,LibreMetaverse.AssetType,LibreMetaverse.UUID,System.Boolean)",
"M:LibreMetaverse.InventoryManager.MoveFolders(System.Collections.Generic.Dictionary{LibreMetaverse.UUID,LibreMetaverse.UUID},System.Threading.CancellationToken)",
"M:LibreMetaverse.InventoryManager.MoveItemsAsync(System.Collections.Generic.Dictionary{LibreMetaverse.UUID,LibreMetaverse.UUID},System.Threading.CancellationToken)",
"M:LibreMetaverse.InventoryManager.RemoveItemsAsync(System.Collections.Generic.IEnumerable{LibreMetaverse.UUID},System.Threading.CancellationToken)",
"M:LibreMetaverse.InventoryManager.RequestCopyItemsWithResultAsync(System.Collections.Generic.List{LibreMetaverse.UUID},System.Collections.Generic.List{LibreMetaverse.UUID},System.Collections.Generic.List{System.String},LibreMetaverse.UUID,System.Threading.CancellationToken)",
"M:LibreMetaverse.InventoryManager.RequestDeRezToInventory(System.UInt32,LibreMetaverse.DeRezDestination,LibreMetaverse.UUID,LibreMetaverse.UUID)",
"M:LibreMetaverse.InventoryManager.RequestFetchInventoryAsync(System.Collections.Generic.Dictionary{LibreMetaverse.UUID,LibreMetaverse.UUID},System.Threading.CancellationToken,System.Action{System.Collections.Generic.List{LibreMetaverse.InventoryItem}})",
"M:LibreMetaverse.InventoryManager.RequestRezFromInventory(LibreMetaverse.Simulator,LibreMetaverse.UUID,LibreMetaverse.Quaternion,LibreMetaverse.Vector3,LibreMetaverse.InventoryItem,LibreMetaverse.UUID,LibreMetaverse.UUID,System.Boolean)",
"M:LibreMetaverse.InventoryManager.RequestTaskInventory(System.UInt32,LibreMetaverse.Simulator)",
"M:LibreMetaverse.InventoryManager.RequestUpdateItems(System.Collections.Generic.List{LibreMetaverse.InventoryItem},LibreMetaverse.UUID)",
"M:LibreMetaverse.InventoryManager.UpdateTaskInventory(System.UInt32,LibreMetaverse.InventoryItem,LibreMetaverse.Simulator,System.Boolean)",
"M:LibreMetaverse.InventoryManager.WaitForNextInventoryOfferAsync(System.Threading.CancellationToken)",
}
def require_markers(path: Path, markers: tuple[str, ...]) -> None:
source = path.read_text()
missing = [marker for marker in markers if marker not in source]
if missing:
raise SystemExit(f"{path.name}: audit evidence missing: " + ", ".join(missing))
def main() -> None:
native_types = (
generate_api_shims.NATIVE_TYPES.keys()
| generate_api_shims.NATIVE_DECLARATIONS.keys()
)
missing_types = sorted(REQUIRED_TYPES - native_types)
if missing_types:
raise SystemExit("issue 62 native types missing: " + ", ".join(missing_types))
missing_members = sorted(
REQUIRED_MEMBERS - generate_api_shims.NATIVE_MEMBER_BODIES.keys()
)
if missing_members:
raise SystemExit("issue 62 native members missing: " + ", ".join(missing_members))
update_task = (
"M:LibreMetaverse.InventoryManager.UpdateTaskInventory(System.UInt32,"
"LibreMetaverse.InventoryItem,LibreMetaverse.Simulator,System.Boolean)"
)
if "only_mod_meta.unwrap_or(true)" not in generate_api_shims.NATIVE_MEMBER_BODIES[update_task]:
raise SystemExit("UpdateTaskInventory must retain the C# metadata-only default")
for update_member in (
"M:LibreMetaverse.InventoryManager.RequestUpdateItem(LibreMetaverse.InventoryItem)",
"M:LibreMetaverse.InventoryManager.RequestUpdateItems(System.Collections.Generic.List{LibreMetaverse.InventoryItem})",
):
if "UUID::random()?" not in generate_api_shims.NATIVE_MEMBER_BODIES[update_member]:
raise SystemExit(f"{update_member} must generate a transaction ID")
if STUB_RE.search(SOURCE.read_text()):
raise SystemExit("issue 62 owned Rust stubs remain in inventory_manager.rs")
require_markers(
SOURCE,
(
"MAX_TASK_INVENTORY_BYTES",
"MAX_PENDING_REQUESTS",
"encode_multiple",
"pending_created",
"pending_fetches",
"pending_task_replies",
"callbacks are not invoked while an inventory lock is held",
"cancelling_one_fetch_waiter_preserves_concurrent_correlation",
"fake_bulk_copy_reply_waits_for_every_block",
"asset_type_without_folder_type_falls_back_to_inventory_root",
"stale_descendents_packet_cannot_mutate_store",
"task_xfer_rejects_announced_data_above_bound",
),
)
require_markers(
DOC,
(
"UDP inventory manager",
"4,096 pending operations",
"16 MiB",
"RequestXfer",
"No store lock is held across an await",
),
)
require_markers(
MANAGER_TESTS,
(
"inventory_manager_null_throws",
"encrypt_decrypt_round_trip",
"item_crc_is_deterministic_and_changes_when_fields_change",
"create_inventory_item_returns_correct_subclass",
),
)
require_markers(
TASK_TESTS,
(
"cap_available_returns_contents_folder_and_decrypts_shadow_id",
"plain_asset_id_parses_without_decryption",
"non_success_status_returns_contents_folder_only",
"no_capability_does_not_make_http_request",
),
)
print(
"issue 62 audit: native inventory packet mappings, bounded correlation and Xfer, "
"lock-free callback evidence, documentation, and translated compatibility cases are present"
)
if __name__ == "__main__":
main()

View File

@@ -82,12 +82,22 @@ NATIVE_TYPES = {
"T:LibreMetaverse.InventoryObjectAddedEventArgs": "crate::inventory::InventoryObjectAddedEventArgs",
"T:LibreMetaverse.InventoryObjectRemovedEventArgs": "crate::inventory::InventoryObjectRemovedEventArgs",
"T:LibreMetaverse.InventoryObjectUpdatedEventArgs": "crate::inventory::InventoryObjectUpdatedEventArgs",
"T:LibreMetaverse.InventoryObjectOfferedEventArgs": "crate::inventory_manager::InventoryObjectOfferedEventArgs",
"T:LibreMetaverse.InventoryManager.CopyItemsResult": "crate::inventory_manager::InventoryManagerCopyItemsResult",
"T:LibreMetaverse.InventoryManager.FolderUpdateResult": "crate::inventory_manager::InventoryManagerFolderUpdateResult",
"T:LibreMetaverse.ItemReceivedEventArgs": "crate::inventory_manager::ItemReceivedEventArgs",
"T:LibreMetaverse.InventorySettings": "crate::inventory::InventorySettings",
"T:LibreMetaverse.InventorySnapshot": "crate::inventory::InventorySnapshot",
"T:LibreMetaverse.InventorySound": "crate::inventory::InventorySound",
"T:LibreMetaverse.InventoryTexture": "crate::inventory::InventoryTexture",
"T:LibreMetaverse.InventoryWearable": "crate::inventory::InventoryWearable",
"T:LibreMetaverse.Permissions": "crate::inventory::Permissions",
"T:LibreMetaverse.FindObjectByPathReplyEventArgs": "crate::inventory_manager::FindObjectByPathReplyEventArgs",
"T:LibreMetaverse.FolderUpdatedEventArgs": "crate::inventory_manager::FolderUpdatedEventArgs",
"T:LibreMetaverse.SaveAssetToInventoryEventArgs": "crate::inventory_manager::SaveAssetToInventoryEventArgs",
"T:LibreMetaverse.ScriptRunningReplyEventArgs": "crate::inventory_manager::ScriptRunningReplyEventArgs",
"T:LibreMetaverse.TaskInventoryReplyEventArgs": "crate::inventory_manager::TaskInventoryReplyEventArgs",
"T:LibreMetaverse.TaskItemReceivedEventArgs": "crate::inventory_manager::TaskItemReceivedEventArgs",
"T:LibreMetaverse.ChatEventArgs": "crate::agent_messages::ChatEventArgs",
"T:LibreMetaverse.ChatSessionMember": "crate::agent_messages::ChatSessionMember",
"T:LibreMetaverse.ChatSessionMemberAddedEventArgs": "crate::agent_messages::ChatSessionMemberAddedEventArgs",
@@ -251,6 +261,7 @@ NATIVE_TYPES = {
NATIVE_DECLARATIONS = {
"T:LibreMetaverse.AgentManager": "crate::agent_manager::AgentManager",
"T:LibreMetaverse.GridClient": "crate::client_core::GridClient",
"T:LibreMetaverse.InventoryManager": "crate::inventory_manager::InventoryManager",
"T:LibreMetaverse.NetworkManager": "crate::network_manager::NetworkManager",
"T:LibreMetaverse.Settings": "crate::client_core::Settings",
"T:LibreMetaverse.Simulator": "crate::network_manager::Simulator",
@@ -322,12 +333,192 @@ NATIVE_MEMBER_BODIES = {
"self.native_http_caps_client()",
"P:LibreMetaverse.GridClient.HttpCapsClient#set":
"self.native_set_http_caps_client(value)",
"P:LibreMetaverse.GridClient.Inventory":
"self.native_inventory().unwrap_or_else(|_| panic!(\"failed to construct InventoryManager\"))",
"P:LibreMetaverse.GridClient.Inventory#set":
"self.native_set_inventory(value)",
"P:LibreMetaverse.GridClient.Network":
"self.native_network().unwrap_or_else(|_| panic!(\"failed to construct NetworkManager\"))",
"P:LibreMetaverse.GridClient.Network#set":
"self.native_set_network(value)",
"P:LibreMetaverse.GridClient.Self":
"self.native_self()",
"E:LibreMetaverse.InventoryManager.FindObjectByPathReply":
"self.native_subscribe_find_object_by_path_reply(handler)",
"E:LibreMetaverse.InventoryManager.FolderUpdated":
"self.native_subscribe_folder_updated(handler)",
"E:LibreMetaverse.InventoryManager.InventoryObjectOffered":
"self.native_subscribe_inventory_object_offered(handler)",
"E:LibreMetaverse.InventoryManager.ItemReceived":
"self.native_subscribe_item_received(handler)",
"E:LibreMetaverse.InventoryManager.SaveAssetToInventory":
"self.native_subscribe_save_asset_to_inventory(handler)",
"E:LibreMetaverse.InventoryManager.ScriptRunningReply":
"self.native_subscribe_script_running_reply(handler)",
"E:LibreMetaverse.InventoryManager.TaskInventoryReply":
"self.native_subscribe_task_inventory_reply(handler)",
"E:LibreMetaverse.InventoryManager.TaskItemReceived":
"self.native_subscribe_task_item_received(handler)",
"F:LibreMetaverse.InventoryManager.MAGIC_ID":
"crate::inventory_manager::InventoryManager::native_magic_id()",
"M:LibreMetaverse.InventoryManager.#ctor(LibreMetaverse.GridClient)":
"crate::inventory_manager::InventoryManager::native_new(client)",
"M:LibreMetaverse.InventoryManager.CreateInventoryItem(LibreMetaverse.InventoryType,LibreMetaverse.UUID)":
"crate::inventory_manager::InventoryManager::native_create_inventory_item(type_, id)",
"M:LibreMetaverse.InventoryManager.CopyItemAsync(LibreMetaverse.UUID,LibreMetaverse.UUID,System.String,LibreMetaverse.UUID,System.Threading.CancellationToken)":
"self.native_copy_item(item, new_parent, new_name, old_owner_id, cancellation_token).await",
"M:LibreMetaverse.InventoryManager.CopyItemAsync(LibreMetaverse.UUID,LibreMetaverse.UUID,System.String,System.Threading.CancellationToken)":
"self.native_copy_item_default_owner(item, new_parent, new_name, cancellation_token).await",
"M:LibreMetaverse.InventoryManager.CopyScriptToTask(System.UInt32,LibreMetaverse.InventoryItem,System.Boolean,LibreMetaverse.Simulator)":
"self.native_copy_script_to_task(object_local_id, item, enable_script, simulator)",
"M:LibreMetaverse.InventoryManager.CreateFolder(LibreMetaverse.UUID,System.String)":
"self.native_create_folder(parent_id, name, libremetaverse_types::FolderType::None)",
"M:LibreMetaverse.InventoryManager.CreateFolder(LibreMetaverse.UUID,System.String,LibreMetaverse.FolderType)":
"self.native_create_folder(parent_id, name, preferred_type)",
"M:LibreMetaverse.InventoryManager.CreateItemAsync(LibreMetaverse.UUID,System.String,System.String,LibreMetaverse.AssetType,LibreMetaverse.UUID,LibreMetaverse.InventoryType,LibreMetaverse.PermissionMask,System.Threading.CancellationToken)":
"self.native_create_item(parent_folder, name, description, type_, asset_transaction_id, inv_type, libremetaverse_types::WearableType::Shape, next_owner_mask, cancellation_token).await",
"M:LibreMetaverse.InventoryManager.CreateItemAsync(LibreMetaverse.UUID,System.String,System.String,LibreMetaverse.AssetType,LibreMetaverse.UUID,LibreMetaverse.InventoryType,LibreMetaverse.WearableType,LibreMetaverse.PermissionMask,System.Threading.CancellationToken)":
"self.native_create_item(parent_folder, name, description, type_, asset_transaction_id, inv_type, wearable_type, next_owner_mask, cancellation_token).await",
"M:LibreMetaverse.InventoryManager.CreateLinkAsync(LibreMetaverse.UUID,LibreMetaverse.UUID,System.String,System.String,LibreMetaverse.InventoryType,LibreMetaverse.UUID,System.Threading.CancellationToken)":
"self.native_create_link(folder_id, item_id, name, description, inv_type, transaction_id, cancellation_token).await",
"M:LibreMetaverse.InventoryManager.CreateLinksAsync(LibreMetaverse.UUID,System.Collections.Generic.IEnumerable{System.ValueTuple{LibreMetaverse.InventoryBase,System.String}},System.Action{System.Boolean},System.Threading.CancellationToken)":
"self.native_create_links(folder_id, links_to_create, callback, cancellation_token).await",
"M:LibreMetaverse.InventoryManager.CreateOrRetrieveInventoryItem(LibreMetaverse.InventoryType,LibreMetaverse.UUID)":
"self.native_create_or_retrieve_inventory_item(inv_type, item_id)",
"M:LibreMetaverse.InventoryManager.DecryptShadowID(LibreMetaverse.UUID)":
"crate::inventory_manager::InventoryManager::native_decrypt_shadow_id(shadow_id)",
"M:LibreMetaverse.InventoryManager.Dispose":
"self.native_dispose()",
"M:LibreMetaverse.InventoryManager.EncryptAssetID(LibreMetaverse.UUID)":
"crate::inventory_manager::InventoryManager::native_encrypt_asset_id(asset_id)",
"M:LibreMetaverse.InventoryManager.EmptyFolder(LibreMetaverse.UUID)":
"self.native_empty_folder(folder_id)",
"M:LibreMetaverse.InventoryManager.EmptyLostAndFoundAsync(System.Threading.CancellationToken)":
"self.native_empty_system_folder(libremetaverse_types::FolderType::LostAndFound, cancellation_token).await",
"M:LibreMetaverse.InventoryManager.EmptyTrashAsync(System.Threading.CancellationToken)":
"self.native_empty_system_folder(libremetaverse_types::FolderType::Trash, cancellation_token).await",
"M:LibreMetaverse.InventoryManager.FetchItemAsync(LibreMetaverse.UUID,LibreMetaverse.UUID,System.Threading.CancellationToken)":
"self.native_fetch_item(item_id, owner_id, cancellation_token, false).await",
"M:LibreMetaverse.InventoryManager.FetchItemHttpAsync(LibreMetaverse.UUID,LibreMetaverse.UUID,System.Threading.CancellationToken)":
"self.native_fetch_item(item_id, owner_id, token, true).await",
"M:LibreMetaverse.InventoryManager.FindFolderForType(LibreMetaverse.AssetType)":
"Ok(self.native_find_folder_for_asset_type(type_))",
"M:LibreMetaverse.InventoryManager.FindFolderForType(LibreMetaverse.FolderType)":
"Ok(self.native_find_folder_for_type(type_))",
"M:LibreMetaverse.InventoryManager.FindObjectByPathAsync(LibreMetaverse.UUID,LibreMetaverse.UUID,System.String,System.Threading.CancellationToken)":
"self.native_find_object_by_path(base_folder, inventory_owner, path, cancellation_token).await",
"M:LibreMetaverse.InventoryManager.FolderContentsAsync(LibreMetaverse.UUID,LibreMetaverse.UUID,System.Boolean,System.Boolean,LibreMetaverse.InventorySortOrder,System.Threading.CancellationToken,System.Boolean)":
"self.native_folder_contents(folder, owner, fetch_folders, fetch_items, order, cancellation_token, follow_links.unwrap_or(false)).await",
"M:LibreMetaverse.InventoryManager.GetInventoryRecursiveAsync(LibreMetaverse.UUID,LibreMetaverse.UUID,System.Collections.Generic.List{LibreMetaverse.InventoryFolder},System.Collections.Generic.List{LibreMetaverse.InventoryItem},System.Threading.CancellationToken)":
"self.native_get_inventory_recursive(folder_id, owner, cats, items, cancellation_token).await",
"M:LibreMetaverse.InventoryManager.GetTaskInventoryAsync(LibreMetaverse.UUID,System.UInt32,LibreMetaverse.Simulator,System.Threading.CancellationToken)":
"self.native_get_task_inventory(object_id, object_local_id, simulator, cancellation_token).await",
"M:LibreMetaverse.InventoryManager.GiveFolderAsync(LibreMetaverse.UUID,System.String,LibreMetaverse.UUID,System.Boolean,System.Threading.CancellationToken)":
"self.native_give_folder(folder_id, folder_name, recipient, do_effect, cancellation_token).await",
"M:LibreMetaverse.InventoryManager.GiveItem(LibreMetaverse.UUID,System.String,LibreMetaverse.AssetType,LibreMetaverse.UUID,System.Boolean)":
"self.native_give_item(item_id, item_name, asset_type, recipient, do_effect)",
"M:LibreMetaverse.InventoryManager.ItemCRC(LibreMetaverse.InventoryItem)":
"crate::inventory_manager::InventoryManager::native_item_crc(&iitem)",
"M:LibreMetaverse.InventoryManager.ParseTaskInventory(System.String)":
"crate::inventory_manager::InventoryManager::native_parse_task_inventory(task_data)",
"M:LibreMetaverse.InventoryManager.LocalFind(LibreMetaverse.UUID,System.String[],System.Int32,System.Boolean)":
"self.native_local_find(base_folder, path, level, first_only)",
"M:LibreMetaverse.InventoryManager.Move(LibreMetaverse.InventoryBase,LibreMetaverse.InventoryFolder)":
"self.native_move_object(item, new_parent)",
"M:LibreMetaverse.InventoryManager.MoveFolder(LibreMetaverse.UUID,LibreMetaverse.UUID,System.Threading.CancellationToken)":
"self.native_move_folders(std::collections::HashMap::from([(folder_id, new_parent_id)]), cancellation_token)",
"M:LibreMetaverse.InventoryManager.MoveFolderAsync(LibreMetaverse.UUID,LibreMetaverse.UUID,System.Threading.CancellationToken)":
"self.native_move_folders_async(std::collections::HashMap::from([(folder_id, new_parent_id)]), cancellation_token).await",
"M:LibreMetaverse.InventoryManager.MoveFolders(System.Collections.Generic.Dictionary{LibreMetaverse.UUID,LibreMetaverse.UUID},System.Threading.CancellationToken)":
"self.native_move_folders(folders_new_parents, cancellation_token)",
"M:LibreMetaverse.InventoryManager.MoveFoldersAsync(System.Collections.Generic.Dictionary{LibreMetaverse.UUID,LibreMetaverse.UUID},System.Threading.CancellationToken)":
"self.native_move_folders_async(folders_new_parents, cancellation_token).await",
"M:LibreMetaverse.InventoryManager.MoveItem(LibreMetaverse.UUID,LibreMetaverse.UUID,System.String,System.Threading.CancellationToken)":
"self.native_move_items(std::collections::HashMap::from([(item_id, (folder_id, new_name))]), cancellation_token)",
"M:LibreMetaverse.InventoryManager.MoveItem(LibreMetaverse.UUID,LibreMetaverse.UUID,System.Threading.CancellationToken)":
"self.native_move_items(std::collections::HashMap::from([(item_id, (folder_id, String::new()))]), cancellation_token)",
"M:LibreMetaverse.InventoryManager.MoveItemAsync(LibreMetaverse.UUID,LibreMetaverse.UUID,System.String,System.Threading.CancellationToken)":
"self.native_move_items_async(std::collections::HashMap::from([(item_id, (folder_id, new_name))]), cancellation_token).await",
"M:LibreMetaverse.InventoryManager.MoveItemAsync(LibreMetaverse.UUID,LibreMetaverse.UUID,System.Threading.CancellationToken)":
"self.native_move_items_async(std::collections::HashMap::from([(item_id, (folder_id, String::new()))]), cancellation_token).await",
"M:LibreMetaverse.InventoryManager.MoveItems(System.Collections.Generic.Dictionary{LibreMetaverse.UUID,LibreMetaverse.UUID},System.Threading.CancellationToken)":
"self.native_move_items(items_new_folders.into_iter().map(|(item, folder)| (item, (folder, String::new()))).collect(), cancellation_token)",
"M:LibreMetaverse.InventoryManager.MoveItemsAsync(System.Collections.Generic.Dictionary{LibreMetaverse.UUID,LibreMetaverse.UUID},System.Threading.CancellationToken)":
"self.native_move_items_async(items_new_folders.into_iter().map(|(item, folder)| (item, (folder, String::new()))).collect(), cancellation_token).await",
"M:LibreMetaverse.InventoryManager.MoveTaskInventory(System.UInt32,LibreMetaverse.UUID,LibreMetaverse.UUID,LibreMetaverse.Simulator)":
"self.native_move_task_inventory(object_local_id, task_item_id, inventory_folder_id, simulator)",
"M:LibreMetaverse.InventoryManager.RemoveDescendantsAsync(LibreMetaverse.UUID,System.Threading.CancellationToken)":
"self.native_remove_descendants(folder, cancellation_token).await",
"M:LibreMetaverse.InventoryManager.RemoveFolderAsync(LibreMetaverse.UUID,System.Threading.CancellationToken)":
"self.native_remove_inventory_objects(Vec::new(), vec![folder], cancellation_token).await",
"M:LibreMetaverse.InventoryManager.RemoveItemAsync(LibreMetaverse.UUID,System.Threading.CancellationToken)":
"self.native_remove_inventory_objects(vec![item], Vec::new(), cancellation_token).await",
"M:LibreMetaverse.InventoryManager.RemoveItemsAsync(System.Collections.Generic.IEnumerable{LibreMetaverse.UUID},System.Threading.CancellationToken)":
"self.native_remove_inventory_objects(items.collect(), Vec::new(), cancellation_token).await",
"M:LibreMetaverse.InventoryManager.RemoveTaskInventory(System.UInt32,LibreMetaverse.UUID,LibreMetaverse.Simulator)":
"self.native_remove_task_inventory(object_local_id, task_item_id, simulator)",
"M:LibreMetaverse.InventoryManager.RequestCopyItemAsync(LibreMetaverse.UUID,LibreMetaverse.UUID,System.String,LibreMetaverse.UUID,System.Threading.CancellationToken)":
"self.native_copy_item(item, new_parent, new_name, old_owner_id, cancellation_token).await",
"M:LibreMetaverse.InventoryManager.RequestCopyItemAsync(LibreMetaverse.UUID,LibreMetaverse.UUID,System.String,System.Threading.CancellationToken)":
"self.native_copy_item_default_owner(item, new_parent, new_name, cancellation_token).await",
"M:LibreMetaverse.InventoryManager.RequestCopyItemFromNotecardAsync(LibreMetaverse.UUID,LibreMetaverse.UUID,LibreMetaverse.UUID,LibreMetaverse.UUID,System.Threading.CancellationToken,System.IProgress{LibreMetaverse.HttpCapsClient.ProgressReport})":
"self.native_copy_item_from_notecard(object_id, notecard_id, folder_id, item_id, cancellation_token, progress).await",
"M:LibreMetaverse.InventoryManager.RequestCopyItemsAsync(System.Collections.Generic.List{LibreMetaverse.UUID},System.Collections.Generic.List{LibreMetaverse.UUID},System.Collections.Generic.List{System.String},LibreMetaverse.UUID,System.Threading.CancellationToken)":
"self.native_copy_items(items, target_folders, new_names, old_owner_id, cancellation_token).await",
"M:LibreMetaverse.InventoryManager.RequestCopyItemsWithResultAsync(System.Collections.Generic.List{LibreMetaverse.UUID},System.Collections.Generic.List{LibreMetaverse.UUID},System.Collections.Generic.List{System.String},LibreMetaverse.UUID,System.Threading.CancellationToken)":
"self.native_copy_items(items, target_folders, new_names, old_owner_id, cancellation_token).await",
"M:LibreMetaverse.InventoryManager.RequestDeRezToInventory(System.UInt32)":
"self.native_de_rez_to_objects_folder(object_local_id)",
"M:LibreMetaverse.InventoryManager.RequestDeRezToInventory(System.UInt32,LibreMetaverse.DeRezDestination,LibreMetaverse.UUID,LibreMetaverse.UUID)":
"self.native_de_rez_to_inventory(object_local_id, dest_type, dest_folder, transaction_id)",
"M:LibreMetaverse.InventoryManager.RequestFetchInventory(LibreMetaverse.UUID,LibreMetaverse.UUID,System.Threading.CancellationToken)":
"self.native_request_fetch_inventory(std::collections::HashMap::from([(item_id, owner_id)]), cancellation_token)",
"M:LibreMetaverse.InventoryManager.RequestFetchInventory(System.Collections.Generic.Dictionary{LibreMetaverse.UUID,LibreMetaverse.UUID},System.Threading.CancellationToken)":
"self.native_request_fetch_inventory(items, cancellation_token)",
"M:LibreMetaverse.InventoryManager.RequestFetchInventoryAsync(LibreMetaverse.UUID,LibreMetaverse.UUID,System.Threading.CancellationToken)":
"self.native_request_fetch_inventory_async(std::collections::HashMap::from([(item_id, owner_id)]), cancellation_token, None).await",
"M:LibreMetaverse.InventoryManager.RequestFetchInventoryAsync(System.Collections.Generic.Dictionary{LibreMetaverse.UUID,LibreMetaverse.UUID},System.Threading.CancellationToken,System.Action{System.Collections.Generic.List{LibreMetaverse.InventoryItem}})":
"self.native_request_fetch_inventory_async(items, cancellation_token, callback).await",
"M:LibreMetaverse.InventoryManager.RequestFindObjectByPathAsync(LibreMetaverse.UUID,LibreMetaverse.UUID,System.String,System.Threading.CancellationToken)":
"self.native_find_object_by_path(base_folder, inventory_owner, path, cancellation_token).await.map(|_| ())",
"M:LibreMetaverse.InventoryManager.RequestFolderContentsAsync(LibreMetaverse.UUID,LibreMetaverse.UUID,System.Boolean,System.Boolean,LibreMetaverse.InventorySortOrder,System.Threading.CancellationToken)":
"self.native_request_folder_contents(folder_id, owner_id, fetch_folders, fetch_items, order, cancellation_token).await",
"M:LibreMetaverse.InventoryManager.RequestFolderContentsAsync(System.Collections.Generic.List{LibreMetaverse.InventoryFolder},System.Uri,System.Boolean,System.Boolean,LibreMetaverse.InventorySortOrder,System.Threading.CancellationToken)":
"self.native_request_folder_contents_batch(batch, capability_uri, fetch_folders, fetch_items, order, cancellation_token).await",
"M:LibreMetaverse.InventoryManager.RequestFolderUpdateAsync(LibreMetaverse.UUID,LibreMetaverse.UUID,System.Boolean,System.Boolean,LibreMetaverse.InventorySortOrder,System.Threading.CancellationToken)":
"self.native_request_folder_update(folder_id, owner_id, fetch_folders.unwrap_or(true), fetch_items.unwrap_or(true), order.unwrap_or(crate::InventorySortOrder::BY_NAME), cancellation_token).await",
"M:LibreMetaverse.InventoryManager.RequestGetScriptRunning(LibreMetaverse.UUID,LibreMetaverse.UUID)":
"self.native_request_get_script_running(object_id, script_id)",
"M:LibreMetaverse.InventoryManager.RequestRestoreRezFromInventory(LibreMetaverse.Simulator,LibreMetaverse.InventoryItem,LibreMetaverse.UUID)":
"self.native_restore_rez_from_inventory(simulator, item, query_id)",
"M:LibreMetaverse.InventoryManager.RequestRezFromInventory(LibreMetaverse.Simulator,LibreMetaverse.Quaternion,LibreMetaverse.Vector3,LibreMetaverse.InventoryItem)":
"self.native_rez_from_inventory_default(simulator, rotation, position, item, None)",
"M:LibreMetaverse.InventoryManager.RequestRezFromInventory(LibreMetaverse.Simulator,LibreMetaverse.Quaternion,LibreMetaverse.Vector3,LibreMetaverse.InventoryItem,LibreMetaverse.UUID)":
"self.native_rez_from_inventory_default(simulator, rotation, position, item, Some(group_owner))",
"M:LibreMetaverse.InventoryManager.RequestRezFromInventory(LibreMetaverse.Simulator,LibreMetaverse.UUID,LibreMetaverse.Quaternion,LibreMetaverse.Vector3,LibreMetaverse.InventoryItem,LibreMetaverse.UUID,LibreMetaverse.UUID,System.Boolean)":
"self.native_rez_from_inventory(simulator, task_id, rotation, position, item, group_owner, query_id, rez_selected)",
"M:LibreMetaverse.InventoryManager.RequestSetScriptRunning(LibreMetaverse.UUID,LibreMetaverse.UUID,System.Boolean)":
"self.native_request_set_script_running(object_id, script_id, running)",
"M:LibreMetaverse.InventoryManager.RequestTaskInventory(System.UInt32)":
"self.native_request_task_inventory(object_local_id, None)",
"M:LibreMetaverse.InventoryManager.RequestTaskInventory(System.UInt32,LibreMetaverse.Simulator)":
"self.native_request_task_inventory(object_local_id, simulator)",
"M:LibreMetaverse.InventoryManager.RequestUpdateItem(LibreMetaverse.InventoryItem)":
"self.native_request_update_items(vec![item], libremetaverse_types::UUID::random()?)",
"M:LibreMetaverse.InventoryManager.RequestUpdateItems(System.Collections.Generic.List{LibreMetaverse.InventoryItem})":
"self.native_request_update_items(items, libremetaverse_types::UUID::random()?)",
"M:LibreMetaverse.InventoryManager.RequestUpdateItems(System.Collections.Generic.List{LibreMetaverse.InventoryItem},LibreMetaverse.UUID)":
"self.native_request_update_items(items, transaction_id)",
"M:LibreMetaverse.InventoryManager.UpdateFolderProperties(LibreMetaverse.UUID,LibreMetaverse.UUID,System.String,LibreMetaverse.FolderType)":
"self.native_update_folder_properties(folder_id, parent_id, name, type_)",
"M:LibreMetaverse.InventoryManager.UpdateTaskInventory(System.UInt32,LibreMetaverse.InventoryItem,LibreMetaverse.Simulator,System.Boolean)":
"self.native_update_task_inventory(object_local_id, item, simulator, only_mod_meta.unwrap_or(true))",
"M:LibreMetaverse.InventoryManager.WaitForNextInventoryOfferAsync(System.Threading.CancellationToken)":
"self.native_wait_for_next_inventory_offer(cancellation_token).await",
"P:LibreMetaverse.InventoryManager.NoResults":
"crate::inventory_manager::InventoryManager::native_no_results()",
"P:LibreMetaverse.InventoryManager.Store":
"self.native_store()",
"E:LibreMetaverse.AgentManager.IM":
"self.native_subscribe_im(handler)",
"E:LibreMetaverse.AgentManager.AgentDataReply":

View File

@@ -994,6 +994,7 @@ def validate_generated_shims() -> None:
"crate::gesture::",
"crate::json_codec::",
"crate::inventory::",
"crate::inventory_manager::",
"crate::message_codec::",
"crate::message_decoder::",
"crate::notation::",