Implement native agent movement and teleportation (#60)
All checks were successful
Native code generation / deterministic (push) Successful in 12m6s
Imaging and meshing gate / native (push) Successful in 4m6s
Native Rust workspace compile / compile (push) Successful in 4m10s

This commit is contained in:
2026-08-09 23:07:30 +00:00
parent 9c9d5b91f1
commit 0791e0a69e
13 changed files with 4060 additions and 936 deletions

View File

@@ -14,6 +14,9 @@ on:
- "tools/check_codegen_gate.py" - "tools/check_codegen_gate.py"
- "tools/check_milestone_08.py" - "tools/check_milestone_08.py"
- "tools/check_milestone_09_issue_59.py" - "tools/check_milestone_09_issue_59.py"
- "tools/check_milestone_09_issue_60.py"
- "crates/libremetaverse/src/agent_movement.rs"
- "docs/agent-movement.md"
- "crates/libremetaverse/Cargo.toml" - "crates/libremetaverse/Cargo.toml"
- "crates/libremetaverse/src/generated.rs" - "crates/libremetaverse/src/generated.rs"
- "crates/libremetaverse/src/packets.rs" - "crates/libremetaverse/src/packets.rs"
@@ -39,6 +42,9 @@ on:
- "tools/check_codegen_gate.py" - "tools/check_codegen_gate.py"
- "tools/check_milestone_08.py" - "tools/check_milestone_08.py"
- "tools/check_milestone_09_issue_59.py" - "tools/check_milestone_09_issue_59.py"
- "tools/check_milestone_09_issue_60.py"
- "crates/libremetaverse/src/agent_movement.rs"
- "docs/agent-movement.md"
- "crates/libremetaverse/Cargo.toml" - "crates/libremetaverse/Cargo.toml"
- "crates/libremetaverse/src/generated.rs" - "crates/libremetaverse/src/generated.rs"
- "crates/libremetaverse/src/packets.rs" - "crates/libremetaverse/src/packets.rs"
@@ -72,6 +78,7 @@ jobs:
python3 tools/check_api_coverage.py python3 tools/check_api_coverage.py
python3 tools/check_milestone_08.py python3 tools/check_milestone_08.py
python3 tools/check_milestone_09_issue_59.py python3 tools/check_milestone_09_issue_59.py
python3 tools/check_milestone_09_issue_60.py
cargo check --manifest-path tests/api-compile/Cargo.toml --locked cargo check --manifest-path tests/api-compile/Cargo.toml --locked
- name: Test generated wire codecs and translated parity cases - name: Test generated wire codecs and translated parity cases
run: | run: |

View File

@@ -25,7 +25,9 @@ jobs:
components: rustfmt components: rustfmt
- name: Check formatting - name: Check formatting
run: cargo fmt --all -- --check run: cargo fmt --all -- --check
- name: Audit native AgentManager boundary - name: Audit native AgentManager boundaries
run: python3 tools/check_milestone_09_issue_59.py run: |
python3 tools/check_milestone_09_issue_59.py
python3 tools/check_milestone_09_issue_60.py
- name: Compile every workspace target with bounded memory - name: Compile every workspace target with bounded memory
run: cargo check --workspace --all-targets --locked -j 1 run: cargo check --workspace --all-targets --locked -j 1

View File

@@ -339,3 +339,12 @@ and UDP download paths. An offline fake grid verifies capability discovery and
the resulting chat, animation, and sound packets. The ownership, cancellation, the resulting chat, animation, and sound packets. The ownership, cancellation,
limits, and compatibility rules are documented in limits, and compatibility rules are documented in
[`docs/agent-manager.md`](docs/agent-manager.md). [`docs/agent-manager.md`](docs/agent-manager.md).
Native movement now covers all control flags, camera frame math, periodic and
manual `AgentUpdate`, flying/crouching/jumping/sitting/standing, always-run,
FOV, and autopilot packets. Teleport requests and UDP/CAPS progress messages
share cancellation-safe waiters, while region handoffs use a bounded,
diagnosable crossing state machine with recovery to the old simulator. Paused
time tests and a loopback fake grid verify exact wire fields and clean worker
shutdown. The compatibility and lifecycle contract is documented in
[`docs/agent-movement.md`](docs/agent-movement.md).

View File

@@ -4,7 +4,7 @@ Generated by `python3 tools/generate_api_shims.py`; do not edit by hand.
| Assembly | Types | Members | Status | | Assembly | Types | Members | Status |
|---|---:|---:|---| |---|---:|---:|---|
| `LibreMetaverse` | 2,711 | 27,281 | native implementation: 121 types / 14,470 members; remaining surface is callable failure-only shims | | `LibreMetaverse` | 2,711 | 27,281 | native implementation: 128 types / 14,611 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.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.Imaging.Skia` | 1 | 3 | native implementation: 1 type / 3 members; no generated shims remain |
| `LibreMetaverse.LslTools` | 164 | 768 | callable failure-only shim | | `LibreMetaverse.LslTools` | 164 | 768 | callable failure-only shim |

View File

@@ -25,19 +25,18 @@ use crate::{
ViewerBenefitsEventArgs, ViewerBenefitsEventArgs,
}; };
use crate::{ use crate::{
AgentFlags, AgentManagerAgentMovement, AgentManagerAgentMovementAgentCamera, AgentState, AgentManagerAgentMovement, ChatSessionMember, ChatType, EffectType, Error, GridClient,
ChatSessionMember, ChatType, EffectType, Error, GridClient, InstantMessageDialog, InstantMessageDialog, InstantMessageOnline, LookAtType, MoneyTransactionType, MuteEntry,
InstantMessageOnline, LookAtType, MoneyTransactionType, MuteEntry, PointAtType, Simulator, PointAtType, Simulator, TransactionFlags, network_manager::CapsEventQueueCallback,
TransactionFlags, network_manager::CapsEventQueueCallback,
}; };
use libremetaverse_structured_data::{OSD, OSDMap, OSDParser}; use libremetaverse_structured_data::{OSD, OSDMap, OSDParser};
use libremetaverse_types::compat::{EventHandler, Subscription, Uri}; use libremetaverse_types::compat::{EventHandler, Subscription, Uri};
use libremetaverse_types::{Color4, Quaternion, UUID, Vector3, Vector3d}; use libremetaverse_types::{Color4, UUID, Vector3, Vector3d};
use std::collections::{BTreeMap, HashMap}; use std::collections::{BTreeMap, HashMap};
use std::fmt; use std::fmt;
use std::panic::{AssertUnwindSafe, catch_unwind}; use std::panic::{AssertUnwindSafe, catch_unwind};
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering}; use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
use std::sync::{Arc, Mutex, RwLock}; use std::sync::{Arc, Mutex, OnceLock, RwLock};
use std::time::{Duration, Instant, UNIX_EPOCH}; use std::time::{Duration, Instant, UNIX_EPOCH};
const MAX_CHAT_BYTES: usize = 1023; const MAX_CHAT_BYTES: usize = 1023;
@@ -127,12 +126,12 @@ fn parse_mute_list(text: &str) -> HashMap<String, MuteEntry> {
result result
} }
struct EventRegistryState<T> { pub(crate) struct EventRegistryState<T> {
next_id: AtomicU64, next_id: AtomicU64,
handlers: Mutex<Vec<(u64, EventHandler<T>)>>, handlers: Mutex<Vec<(u64, EventHandler<T>)>>,
} }
struct EventRegistry<T> { pub(crate) struct EventRegistry<T> {
state: Arc<EventRegistryState<T>>, state: Arc<EventRegistryState<T>>,
} }
@@ -148,7 +147,7 @@ impl<T> Default for EventRegistry<T> {
} }
impl<T: Clone + 'static> EventRegistry<T> { impl<T: Clone + 'static> EventRegistry<T> {
fn subscribe(&self, handler: EventHandler<T>) -> Subscription { pub(crate) fn subscribe(&self, handler: EventHandler<T>) -> Subscription {
let id = self.state.next_id.fetch_add(1, Ordering::Relaxed); let id = self.state.next_id.fetch_add(1, Ordering::Relaxed);
mutex(&self.state.handlers).push((id, handler)); mutex(&self.state.handlers).push((id, handler));
let state = Arc::downgrade(&self.state); let state = Arc::downgrade(&self.state);
@@ -159,7 +158,7 @@ impl<T: Clone + 'static> EventRegistry<T> {
}) })
} }
fn emit(&self, value: T) { pub(crate) fn emit(&self, value: T) {
let handlers: Vec<_> = mutex(&self.state.handlers) let handlers: Vec<_> = mutex(&self.state.handlers)
.iter() .iter()
.map(|(_, handler)| Arc::clone(handler)) .map(|(_, handler)| Arc::clone(handler))
@@ -345,6 +344,7 @@ pub(crate) struct AgentManagerInner {
network: Mutex<Option<crate::NetworkManager>>, network: Mutex<Option<crate::NetworkManager>>,
raw_packet_subscription: Mutex<Option<Subscription>>, raw_packet_subscription: Mutex<Option<Subscription>>,
caps_subscriptions: Mutex<Vec<Subscription>>, caps_subscriptions: Mutex<Vec<Subscription>>,
movement: OnceLock<Arc<crate::agent_movement::AgentMovementRuntime>>,
chat_from_simulator: EventRegistry<ChatEventArgs>, chat_from_simulator: EventRegistry<ChatEventArgs>,
money_balance: EventRegistry<BalanceEventArgs>, money_balance: EventRegistry<BalanceEventArgs>,
money_balance_reply: EventRegistry<MoneyBalanceReplyEventArgs>, money_balance_reply: EventRegistry<MoneyBalanceReplyEventArgs>,
@@ -397,6 +397,7 @@ impl Default for AgentManagerInner {
network: Mutex::new(None), network: Mutex::new(None),
raw_packet_subscription: Mutex::new(None), raw_packet_subscription: Mutex::new(None),
caps_subscriptions: Mutex::new(Vec::new()), caps_subscriptions: Mutex::new(Vec::new()),
movement: OnceLock::new(),
chat_from_simulator: EventRegistry::default(), chat_from_simulator: EventRegistry::default(),
money_balance: EventRegistry::default(), money_balance: EventRegistry::default(),
money_balance_reply: EventRegistry::default(), money_balance_reply: EventRegistry::default(),
@@ -420,6 +421,13 @@ impl Default for AgentManagerInner {
impl AgentManagerInner { impl AgentManagerInner {
fn handle_raw_packet(&self, event: crate::network_manager::RawPacketReceivedEventArgs) { fn handle_raw_packet(&self, event: crate::network_manager::RawPacketReceivedEventArgs) {
if let Some(movement) = self.movement.get()
&& movement
.handle_raw_packet(event.packet_type, &event.data, event.simulator.clone())
.unwrap_or(false)
{
return;
}
let result = match event.packet_type { let result = match event.packet_type {
crate::packets::PacketType::ChatFromSimulator => { crate::packets::PacketType::ChatFromSimulator => {
self.handle_chat_packet(&event.data, event.simulator) self.handle_chat_packet(&event.data, event.simulator)
@@ -716,6 +724,29 @@ impl AgentManagerInner {
} }
} }
pub(crate) fn native_ids(&self, network: &crate::NetworkManager) -> (UUID, UUID) {
let agent_id = *self
.agent_id
.read()
.unwrap_or_else(std::sync::PoisonError::into_inner);
let session_id = *self
.session_id
.read()
.unwrap_or_else(std::sync::PoisonError::into_inner);
(
if agent_id == UUID::zero() {
network.native_agent_id()
} else {
agent_id
},
if session_id == UUID::zero() {
network.native_session_id()
} else {
session_id
},
)
}
fn handle_caps_event( fn handle_caps_event(
self: &Arc<Self>, self: &Arc<Self>,
client: Arc<GridClient>, client: Arc<GridClient>,
@@ -723,6 +754,13 @@ impl AgentManagerInner {
message: &dyn crate::interfaces::IMessage, message: &dyn crate::interfaces::IMessage,
simulator: Simulator, simulator: Simulator,
) { ) {
if let Some(movement) = self.movement.get()
&& movement
.handle_caps_event(name, message, simulator.clone())
.unwrap_or(false)
{
return;
}
let result = match name { let result = match name {
"ChatterBoxInvitation" => self.handle_chat_invitation(client, message, simulator), "ChatterBoxInvitation" => self.handle_chat_invitation(client, message, simulator),
"ChatterBoxSessionEventReply" => self.handle_chat_session_event_reply(client, message), "ChatterBoxSessionEventReply" => self.handle_chat_session_event_reply(client, message),
@@ -926,7 +964,7 @@ pub struct AgentManager {
pub movement: AgentManagerAgentMovement, pub movement: AgentManagerAgentMovement,
pub mute_list: Arc<RwLock<HashMap<String, MuteEntry>>>, pub mute_list: Arc<RwLock<HashMap<String, MuteEntry>>>,
pub signaled_animations: Arc<RwLock<HashMap<UUID, i32>>>, pub signaled_animations: Arc<RwLock<HashMap<UUID, i32>>>,
client: Arc<GridClient>, pub(crate) client: Arc<GridClient>,
inner: Arc<AgentManagerInner>, inner: Arc<AgentManagerInner>,
} }
@@ -980,6 +1018,9 @@ impl AgentManager {
"ChatterBoxSessionAgentListUpdates", "ChatterBoxSessionAgentListUpdates",
"SetDisplayNameReply", "SetDisplayNameReply",
"NavMeshStatusUpdate", "NavMeshStatusUpdate",
"TeleportFinish",
"TeleportFailed",
"CrossedRegion",
] { ] {
let weak_inner = Arc::downgrade(&inner); let weak_inner = Arc::downgrade(&inner);
let weak_client = Arc::downgrade(&client); let weak_client = Arc::downgrade(&client);
@@ -996,16 +1037,17 @@ impl AgentManager {
} }
} }
} }
let movement_runtime = Arc::clone(inner.movement.get_or_init(|| {
crate::agent_movement::AgentMovementRuntime::new(
Arc::clone(&client),
network.clone(),
Arc::downgrade(&inner),
)
}));
Ok(Self { Ok(Self {
agent_state_status: None, agent_state_status: None,
group_chat_sessions: Arc::clone(&inner.group_chat_sessions), group_chat_sessions: Arc::clone(&inner.group_chat_sessions),
movement: AgentManagerAgentMovement { movement: AgentManagerAgentMovement::from_runtime(movement_runtime),
body_rotation: Quaternion::identity(),
camera: AgentManagerAgentMovementAgentCamera { far: 128.0 },
flags: AgentFlags::NONE,
head_rotation: Quaternion::identity(),
state: AgentState::NONE,
},
mute_list: Arc::clone(&inner.mute_list), mute_list: Arc::clone(&inner.mute_list),
signaled_animations: Arc::clone(&inner.signaled_animations), signaled_animations: Arc::clone(&inner.signaled_animations),
client, client,
@@ -1040,6 +1082,9 @@ impl AgentManager {
} }
mutex(&self.inner.raw_packet_subscription).take(); mutex(&self.inner.raw_packet_subscription).take();
mutex(&self.inner.caps_subscriptions).clear(); mutex(&self.inner.caps_subscriptions).clear();
if let Some(movement) = self.inner.movement.get() {
movement.stop();
}
mutex(&self.inner.network).take(); mutex(&self.inner.network).take();
mutex(&self.inner.mute_xfers).clear(); mutex(&self.inner.mute_xfers).clear();
self.group_chat_sessions self.group_chat_sessions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -6,6 +6,7 @@ extern crate self as libremetaverse;
mod attention_catalog; mod attention_catalog;
mod agent_manager; mod agent_manager;
mod agent_messages; mod agent_messages;
mod agent_movement;
mod bit_pack; mod bit_pack;
mod caps; mod caps;
mod caps_http; mod caps_http;

View File

@@ -1011,6 +1011,7 @@ pub struct SimulatorData {
pub wind_speeds: Option<Vec<Vector2>>, pub wind_speeds: Option<Vec<Vector2>>,
endpoint: std::net::SocketAddr, endpoint: std::net::SocketAddr,
connected: AtomicBool, connected: AtomicBool,
movement_complete: AtomicBool,
handshake_complete: AtomicBool, handshake_complete: AtomicBool,
handshake_wait: Condvar, handshake_wait: Condvar,
handshake_wait_lock: Mutex<()>, handshake_wait_lock: Mutex<()>,
@@ -1173,6 +1174,7 @@ impl Simulator {
wind_speeds: None, wind_speeds: None,
endpoint: address, endpoint: address,
connected: AtomicBool::new(false), connected: AtomicBool::new(false),
movement_complete: AtomicBool::new(false),
handshake_complete: AtomicBool::new(false), handshake_complete: AtomicBool::new(false),
handshake_wait: Condvar::new(), handshake_wait: Condvar::new(),
handshake_wait_lock: Mutex::new(()), handshake_wait_lock: Mutex::new(()),
@@ -1483,6 +1485,10 @@ impl Simulator {
Ok(self.caps_running() || self.current_sim_caps_running()) Ok(self.caps_running() || self.current_sim_caps_running())
} }
pub(crate) fn native_start_event_queue(&self) {
self.start_current_event_queue();
}
fn caps_running(&self) -> bool { fn caps_running(&self) -> bool {
read(&self.caps_state).as_ref().is_some_and(|inner| { read(&self.caps_state).as_ref().is_some_and(|inner| {
Caps::native_from_inner(Arc::clone(inner), self.native_clone_without_caps()) Caps::native_from_inner(Arc::clone(inner), self.native_clone_without_caps())
@@ -1615,6 +1621,15 @@ impl Simulator {
self.connected.load(Ordering::Acquire) self.connected.load(Ordering::Acquire)
} }
#[must_use]
pub(crate) fn native_agent_movement_complete(&self) -> bool {
self.movement_complete.load(Ordering::Acquire)
}
pub(crate) fn native_set_agent_movement_complete(&self, value: bool) {
self.movement_complete.store(value, Ordering::Release);
}
#[cfg(test)] #[cfg(test)]
pub(crate) fn native_set_connected_for_tests(&self, connected: bool) { pub(crate) fn native_set_connected_for_tests(&self, connected: bool) {
self.connected.store(connected, Ordering::Release); self.connected.store(connected, Ordering::Release);

65
docs/agent-movement.md Normal file
View File

@@ -0,0 +1,65 @@
# Agent movement, camera, teleport, and region crossing
`AgentManager::movement` is backed by native Rust state and emits the same
LLUDP messages as LibreMetaverse's C# `AgentMovement`. The 32 control flags keep
their protocol bit positions. `ResetControlFlags` preserves away, fly,
mouselook, and crouch (`UP_NEG`), and automatic reset happens only after an
`AgentUpdate` was actually sent. Duplicate idle updates are limited to the same
ten transmissions as the reference implementation.
The camera retains the reference `CoordinateFrame` behavior, including the
public wrapper's deliberate axis mapping: `AtAxis` exposes frame Y and
`LeftAxis` exposes frame X, while `LookDirection` writes the requested forward
vector to frame X. Roll, pitch, yaw, heading, look-at, and orthonormalization
are native floating-point operations. Non-finite inputs return the mapped
argument error instead of placing invalid values on the wire.
## Update lifecycle
The update worker starts after a successful login only when
`SendUpdatesRegularly` is enabled. It uses the configured
`AgentUpdateInterval`, wakes immediately when that interval changes, pauses on
disconnect, and is joined by `Dispose` or normal destruction. A condition variable
drives cadence and shutdown, so the implementation neither polls nor
uses arbitrary sleeps. Manual updates remain available when periodic updates
are disabled. Both paths refuse to send before simulator movement/handshake
completion, as required by their respective C# methods.
Locomotion methods send real packets: flying, crouching, jumping, standing,
ground sitting, object sitting, always-run, FOV, and autopilot use
`AgentUpdate`, `AgentRequestSit`, `AgentSit`, `SetAlwaysRun`, `AgentFOV`, and
`GenericMessage` with the reference field layout and reliability choices.
## Teleports and simulator crossings
Landmark, location, named-region, and lure requests share a generation-tagged
teleport waiter. UDP `TeleportStart`, `TeleportProgress`, `TeleportFailed`,
`TeleportCancel`, `TeleportLocal`, and `TeleportFinish` packets, together with
their CAPS finish/failure equivalents, update status before raising
`TeleportProgress`. Finish, failure, cancellation, timeout, disposal, and a
superseding request all resolve the waiter exactly once. Cancellation and
timeouts are executor-driven and do not leave a task or callback registered.
`CrossedRegion` starts a bounded native state machine with the C# states and
failure reasons. It connects the destination simulator, retries failed
connections up to three times, waits for that simulator's
`AgentMovementComplete`, restores the old simulator after rejection, timeout,
or manual cancellation, disconnects a partial destination, and raises
`RegionCrossed` after state mutation. `GetCrossingState`,
`GetCrossingFailureReason`, `GetCrossingDetails`, `IsCrossing`, and
`CancelCrossing` expose the same diagnostic surface. Crossing and periodic
update threads use weak ownership, cancellation wakeups, and joined handles.
When `MultipleSims` is enabled, movement completion also snapshots presence,
position, rotation, and update time per simulator. Velocity near a region edge
raises `RegionCrossingPredicted` with the matching cardinal direction, and the
reference child-agent request bookkeeping is maintained with its 30-second
deduplication and two-minute expiry windows. Border-object visibility is
tracked through `TrackObjectInSimulator`, `UntrackObjectInSimulator`, and
`GetSimulatorsForObject`; disconnected simulator entries are pruned without
holding locks while callbacks run.
Tests use paused Tokio time for teleport timeout/cancellation and loopback UDP
fake grids for packet-level movement. They decode the emitted control flags,
camera/FOV values, always-run state, and invariant-culture autopilot parameters
rather than accepting method invocation alone as evidence.

View File

@@ -0,0 +1,106 @@
#!/usr/bin/env python3
"""Audit issue 60's native movement, teleport, and crossing 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" / "agent_movement.rs"
DOC = ROOT / "docs" / "agent-movement.md"
STUB_RE = re.compile(r"\b(?:not_implemented|unimplemented_api)\b|\b(?:todo|unimplemented)!\s*\(")
REQUIRED_TYPES = {
"T:LibreMetaverse.AgentManager.AgentMovement",
"T:LibreMetaverse.AgentManager.AgentMovement.AgentCamera",
"T:LibreMetaverse.AvatarSitResponseEventArgs",
"T:LibreMetaverse.CameraConstraintEventArgs",
"T:LibreMetaverse.RegionCrossedEventArgs",
"T:LibreMetaverse.RegionCrossingPredictionEventArgs",
"T:LibreMetaverse.TeleportEventArgs",
}
REQUIRED_MEMBERS = {
"E:LibreMetaverse.AgentManager.AvatarSitResponse",
"E:LibreMetaverse.AgentManager.CameraConstraint",
"E:LibreMetaverse.AgentManager.RegionCrossed",
"E:LibreMetaverse.AgentManager.RegionCrossingPredicted",
"E:LibreMetaverse.AgentManager.TeleportProgress",
"M:LibreMetaverse.AgentManager.AutoPilot(System.Double,System.Double,System.Double)",
"M:LibreMetaverse.AgentManager.CancelCrossing",
"M:LibreMetaverse.AgentManager.CompleteAgentMovement(LibreMetaverse.Simulator)",
"M:LibreMetaverse.AgentManager.Crouch(System.Boolean)",
"M:LibreMetaverse.AgentManager.Fly(System.Boolean)",
"M:LibreMetaverse.AgentManager.GetCrossingDetails",
"M:LibreMetaverse.AgentManager.GetCrossingFailureReason",
"M:LibreMetaverse.AgentManager.GetCrossingState",
"M:LibreMetaverse.AgentManager.GetSimulatorsForObject(LibreMetaverse.UUID)",
"M:LibreMetaverse.AgentManager.IsCrossing",
"M:LibreMetaverse.AgentManager.IsNearBorder(LibreMetaverse.Vector3,System.UInt32,System.UInt32,System.Single)",
"M:LibreMetaverse.AgentManager.Jump(System.Boolean)",
"M:LibreMetaverse.AgentManager.RequestSit(LibreMetaverse.UUID,LibreMetaverse.Vector3)",
"M:LibreMetaverse.AgentManager.RequestTeleport(System.UInt64,LibreMetaverse.Vector3,LibreMetaverse.Vector3,System.Boolean)",
"M:LibreMetaverse.AgentManager.Sit",
"M:LibreMetaverse.AgentManager.Stand",
"M:LibreMetaverse.AgentManager.TeleportAsync(System.UInt64,LibreMetaverse.Vector3,LibreMetaverse.Vector3,System.Threading.CancellationToken)",
"M:LibreMetaverse.AgentManager.TrackObjectInSimulator(LibreMetaverse.UUID,LibreMetaverse.Simulator)",
"M:LibreMetaverse.AgentManager.UntrackObjectInSimulator(LibreMetaverse.UUID,LibreMetaverse.Simulator)",
}
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:
missing_types = sorted(REQUIRED_TYPES - generate_api_shims.NATIVE_TYPES.keys())
if missing_types:
raise SystemExit("issue 60 native types missing: " + ", ".join(missing_types))
missing_members = sorted(
REQUIRED_MEMBERS - generate_api_shims.NATIVE_MEMBER_BODIES.keys()
)
if missing_members:
raise SystemExit("issue 60 native members missing: " + ", ".join(missing_members))
if STUB_RE.search(SOURCE.read_text()):
raise SystemExit("issue 60 owned Rust stubs remain in agent_movement.rs")
require_markers(
SOURCE,
(
"libremetaverse-agent-update",
"libremetaverse-region-crossing",
"TeleportLocal",
"AgentMovementComplete",
"fake_grid_decodes_locomotion_camera_and_autopilot_packets",
"fake_grids_complete_a_region_crossing_and_raise_the_final_event",
"multi_simulator_prediction_and_object_visibility_match_reference_rules",
"teleport_completion_timeout_and_cancellation_are_deterministic",
"camera_math_preserves_the_reference_frame_axis_mapping",
),
)
require_markers(
DOC,
(
"ResetControlFlags",
"condition variable",
"generation-tagged",
"GetCrossingFailureReason",
"loopback UDP",
),
)
print(
"issue 60 audit: native movement/camera mappings, teleport and crossing "
"state machines, deterministic tests, documentation, and fake-grid wire "
"coverage are present"
)
if __name__ == "__main__":
main()

View File

@@ -44,7 +44,10 @@ NATIVE_TYPES = {
"T:LibreMetaverse.AgentAccessEventArgs": "crate::agent_messages::AgentAccessEventArgs", "T:LibreMetaverse.AgentAccessEventArgs": "crate::agent_messages::AgentAccessEventArgs",
"T:LibreMetaverse.AgentExperiencesEventArgs": "crate::agent_messages::AgentExperiencesEventArgs", "T:LibreMetaverse.AgentExperiencesEventArgs": "crate::agent_messages::AgentExperiencesEventArgs",
"T:LibreMetaverse.AgentPreferencesEventArgs": "crate::agent_messages::AgentPreferencesEventArgs", "T:LibreMetaverse.AgentPreferencesEventArgs": "crate::agent_messages::AgentPreferencesEventArgs",
"T:LibreMetaverse.AgentManager.AgentMovement": "crate::agent_movement::AgentManagerAgentMovement",
"T:LibreMetaverse.AgentManager.AgentMovement.AgentCamera": "crate::agent_movement::AgentManagerAgentMovementAgentCamera",
"T:LibreMetaverse.AnimationsChangedEventArgs": "crate::agent_messages::AnimationsChangedEventArgs", "T:LibreMetaverse.AnimationsChangedEventArgs": "crate::agent_messages::AnimationsChangedEventArgs",
"T:LibreMetaverse.AvatarSitResponseEventArgs": "crate::agent_movement::AvatarSitResponseEventArgs",
"T:LibreMetaverse.AvatarRenderInfoEventArgs": "crate::agent_messages::AvatarRenderInfoEventArgs", "T:LibreMetaverse.AvatarRenderInfoEventArgs": "crate::agent_messages::AvatarRenderInfoEventArgs",
"T:LibreMetaverse.BalanceEventArgs": "crate::agent_messages::BalanceEventArgs", "T:LibreMetaverse.BalanceEventArgs": "crate::agent_messages::BalanceEventArgs",
"T:LibreMetaverse.CapabilitiesReceivedEventArgs": "crate::caps::CapabilitiesReceivedEventArgs", "T:LibreMetaverse.CapabilitiesReceivedEventArgs": "crate::caps::CapabilitiesReceivedEventArgs",
@@ -64,6 +67,7 @@ NATIVE_TYPES = {
"T:LibreMetaverse.ChatSessionMember": "crate::agent_messages::ChatSessionMember", "T:LibreMetaverse.ChatSessionMember": "crate::agent_messages::ChatSessionMember",
"T:LibreMetaverse.ChatSessionMemberAddedEventArgs": "crate::agent_messages::ChatSessionMemberAddedEventArgs", "T:LibreMetaverse.ChatSessionMemberAddedEventArgs": "crate::agent_messages::ChatSessionMemberAddedEventArgs",
"T:LibreMetaverse.ChatSessionMemberLeftEventArgs": "crate::agent_messages::ChatSessionMemberLeftEventArgs", "T:LibreMetaverse.ChatSessionMemberLeftEventArgs": "crate::agent_messages::ChatSessionMemberLeftEventArgs",
"T:LibreMetaverse.CameraConstraintEventArgs": "crate::agent_movement::CameraConstraintEventArgs",
"T:LibreMetaverse.Assets.AssetGesture": "crate::gesture::AssetGesture", "T:LibreMetaverse.Assets.AssetGesture": "crate::gesture::AssetGesture",
"T:LibreMetaverse.Assets.GestureStep": "crate::gesture::GestureStep", "T:LibreMetaverse.Assets.GestureStep": "crate::gesture::GestureStep",
"T:LibreMetaverse.Assets.GestureStepAnimation": "crate::gesture::GestureStepAnimation", "T:LibreMetaverse.Assets.GestureStepAnimation": "crate::gesture::GestureStepAnimation",
@@ -76,7 +80,10 @@ NATIVE_TYPES = {
"T:LibreMetaverse.GroupChatJoinedEventArgs": "crate::agent_messages::GroupChatJoinedEventArgs", "T:LibreMetaverse.GroupChatJoinedEventArgs": "crate::agent_messages::GroupChatJoinedEventArgs",
"T:LibreMetaverse.RegionExperiencesEventArgs": "crate::agent_messages::RegionExperiencesEventArgs", "T:LibreMetaverse.RegionExperiencesEventArgs": "crate::agent_messages::RegionExperiencesEventArgs",
"T:LibreMetaverse.SetDisplayNameReplyEventArgs": "crate::agent_messages::SetDisplayNameReplyEventArgs", "T:LibreMetaverse.SetDisplayNameReplyEventArgs": "crate::agent_messages::SetDisplayNameReplyEventArgs",
"T:LibreMetaverse.TeleportEventArgs": "crate::agent_movement::TeleportEventArgs",
"T:LibreMetaverse.ProductInfoEventArgs": "crate::agent_messages::ProductInfoEventArgs", "T:LibreMetaverse.ProductInfoEventArgs": "crate::agent_messages::ProductInfoEventArgs",
"T:LibreMetaverse.RegionCrossedEventArgs": "crate::agent_movement::RegionCrossedEventArgs",
"T:LibreMetaverse.RegionCrossingPredictionEventArgs": "crate::agent_movement::RegionCrossingPredictionEventArgs",
"T:LibreMetaverse.ViewerBenefitsEventArgs": "crate::agent_messages::ViewerBenefitsEventArgs", "T:LibreMetaverse.ViewerBenefitsEventArgs": "crate::agent_messages::ViewerBenefitsEventArgs",
"T:LibreMetaverse.Messages.Linden.ProductInfoRequestMessage": "crate::agent_manager::ProductInfoRequestMessage", "T:LibreMetaverse.Messages.Linden.ProductInfoRequestMessage": "crate::agent_manager::ProductInfoRequestMessage",
"T:LibreMetaverse.Messages.Linden.ProductInfoRequestMessage.ProductInfo": "crate::agent_manager::ProductInfoRequestMessageProductInfo", "T:LibreMetaverse.Messages.Linden.ProductInfoRequestMessage.ProductInfo": "crate::agent_manager::ProductInfoRequestMessageProductInfo",
@@ -302,6 +309,10 @@ NATIVE_MEMBER_BODIES = {
"self.native_subscribe_agent_data_reply(handler)", "self.native_subscribe_agent_data_reply(handler)",
"E:LibreMetaverse.AgentManager.AnimationsChanged": "E:LibreMetaverse.AgentManager.AnimationsChanged":
"self.native_subscribe_animations_changed(handler)", "self.native_subscribe_animations_changed(handler)",
"E:LibreMetaverse.AgentManager.AvatarSitResponse":
"self.native_subscribe_avatar_sit_response(handler)",
"E:LibreMetaverse.AgentManager.CameraConstraint":
"self.native_subscribe_camera_constraint(handler)",
"E:LibreMetaverse.AgentManager.ChatFromSimulator": "E:LibreMetaverse.AgentManager.ChatFromSimulator":
"self.native_subscribe_chat_from_simulator(handler)", "self.native_subscribe_chat_from_simulator(handler)",
"E:LibreMetaverse.AgentManager.MoneyBalance": "E:LibreMetaverse.AgentManager.MoneyBalance":
@@ -324,6 +335,10 @@ NATIVE_MEMBER_BODIES = {
"self.native_subscribe_viewer_benefits_updated(handler)", "self.native_subscribe_viewer_benefits_updated(handler)",
"E:LibreMetaverse.AgentManager.ProductInfoUpdated": "E:LibreMetaverse.AgentManager.ProductInfoUpdated":
"self.native_subscribe_product_info_updated(handler)", "self.native_subscribe_product_info_updated(handler)",
"E:LibreMetaverse.AgentManager.RegionCrossed":
"self.native_subscribe_region_crossed(handler)",
"E:LibreMetaverse.AgentManager.RegionCrossingPredicted":
"self.native_subscribe_region_crossing_predicted(handler)",
"E:LibreMetaverse.AgentManager.MuteListUpdated": "E:LibreMetaverse.AgentManager.MuteListUpdated":
"self.native_subscribe_mute_list_updated(handler)", "self.native_subscribe_mute_list_updated(handler)",
"E:LibreMetaverse.AgentManager.GroupChatJoined": "E:LibreMetaverse.AgentManager.GroupChatJoined":
@@ -336,6 +351,8 @@ NATIVE_MEMBER_BODIES = {
"self.native_subscribe_set_display_name_reply(handler)", "self.native_subscribe_set_display_name_reply(handler)",
"E:LibreMetaverse.AgentManager.NavMeshStatusUpdate": "E:LibreMetaverse.AgentManager.NavMeshStatusUpdate":
"self.native_subscribe_nav_mesh_status_update(handler)", "self.native_subscribe_nav_mesh_status_update(handler)",
"E:LibreMetaverse.AgentManager.TeleportProgress":
"self.native_subscribe_teleport_progress(handler)",
"M:LibreMetaverse.AgentManager.#ctor(LibreMetaverse.GridClient)": "M:LibreMetaverse.AgentManager.#ctor(LibreMetaverse.GridClient)":
"crate::agent_manager::AgentManager::native_new(client)", "crate::agent_manager::AgentManager::native_new(client)",
"M:LibreMetaverse.AgentManager.Dispose": "M:LibreMetaverse.AgentManager.Dispose":
@@ -348,18 +365,34 @@ NATIVE_MEMBER_BODIES = {
"self.native_animation_start(animation, reliable)", "self.native_animation_start(animation, reliable)",
"M:LibreMetaverse.AgentManager.AnimationStop(LibreMetaverse.UUID,System.Boolean)": "M:LibreMetaverse.AgentManager.AnimationStop(LibreMetaverse.UUID,System.Boolean)":
"self.native_animation_stop(animation, reliable)", "self.native_animation_stop(animation, reliable)",
"M:LibreMetaverse.AgentManager.AutoPilot(System.Double,System.Double,System.Double)":
"self.native_autopilot_f64(global_x, global_y, z)",
"M:LibreMetaverse.AgentManager.AutoPilot(System.UInt64,System.UInt64,System.Single)":
"self.native_autopilot_u64(global_x, global_y, z)",
"M:LibreMetaverse.AgentManager.AutoPilotCancel":
"self.native_autopilot_cancel()",
"M:LibreMetaverse.AgentManager.AutoPilotLocal(System.Int32,System.Int32,System.Single)":
"self.native_autopilot_local(local_x, local_y, z)",
"M:LibreMetaverse.AgentManager.CancelCrossing":
"Ok(self.native_cancel_crossing())",
"M:LibreMetaverse.AgentManager.BeamEffect(LibreMetaverse.UUID,LibreMetaverse.UUID,LibreMetaverse.Vector3d,LibreMetaverse.Color4,System.Single,LibreMetaverse.UUID)": "M:LibreMetaverse.AgentManager.BeamEffect(LibreMetaverse.UUID,LibreMetaverse.UUID,LibreMetaverse.Vector3d,LibreMetaverse.Color4,System.Single,LibreMetaverse.UUID)":
"self.native_viewer_effect(source_avatar, target_object, global_offset, color, duration, effect_id, crate::EffectType::Beam, None)", "self.native_viewer_effect(source_avatar, target_object, global_offset, color, duration, effect_id, crate::EffectType::Beam, None)",
"M:LibreMetaverse.AgentManager.Chat(System.String,System.Int32,LibreMetaverse.ChatType,System.Boolean)": "M:LibreMetaverse.AgentManager.Chat(System.String,System.Int32,LibreMetaverse.ChatType,System.Boolean)":
"self.native_chat(message, channel, type_, split_large_messages)", "self.native_chat(message, channel, type_, split_large_messages)",
"M:LibreMetaverse.AgentManager.ChatterBoxAcceptInviteAsync(LibreMetaverse.UUID,System.Threading.CancellationToken)": "M:LibreMetaverse.AgentManager.ChatterBoxAcceptInviteAsync(LibreMetaverse.UUID,System.Threading.CancellationToken)":
"self.native_chatter_box_accept_invite(session_id, cancellation_token).await", "self.native_chatter_box_accept_invite(session_id, cancellation_token).await",
"M:LibreMetaverse.AgentManager.CompleteAgentMovement(LibreMetaverse.Simulator)":
"self.native_complete_agent_movement(simulator)",
"M:LibreMetaverse.AgentManager.Crouch(System.Boolean)":
"self.native_crouch(crouching)",
"M:LibreMetaverse.AgentManager.DeactivateGesture(LibreMetaverse.UUID)": "M:LibreMetaverse.AgentManager.DeactivateGesture(LibreMetaverse.UUID)":
"self.native_deactivate_gesture(inv_id)", "self.native_deactivate_gesture(inv_id)",
"M:LibreMetaverse.AgentManager.DeleteClassified(LibreMetaverse.UUID)": "M:LibreMetaverse.AgentManager.DeleteClassified(LibreMetaverse.UUID)":
"self.native_delete_classified(classified_id)", "self.native_delete_classified(classified_id)",
"M:LibreMetaverse.AgentManager.FindExperienceByNameAsync(System.String,System.Int32,System.Int32,System.Threading.CancellationToken)": "M:LibreMetaverse.AgentManager.FindExperienceByNameAsync(System.String,System.Int32,System.Int32,System.Threading.CancellationToken)":
"self.native_find_experience_by_name(query, page, page_size, cancellation_token).await", "self.native_find_experience_by_name(query, page, page_size, cancellation_token).await",
"M:LibreMetaverse.AgentManager.Fly(System.Boolean)":
"self.native_fly(start)",
"M:LibreMetaverse.AgentManager.ForgetExperiencePermissionAsync(LibreMetaverse.UUID,System.Threading.CancellationToken)": "M:LibreMetaverse.AgentManager.ForgetExperiencePermissionAsync(LibreMetaverse.UUID,System.Threading.CancellationToken)":
"self.native_forget_experience_permission(experience_id, cancellation_token).await", "self.native_forget_experience_permission(experience_id, cancellation_token).await",
"M:LibreMetaverse.AgentManager.GetAdminExperiencesAsync(System.Threading.CancellationToken)": "M:LibreMetaverse.AgentManager.GetAdminExperiencesAsync(System.Threading.CancellationToken)":
@@ -376,6 +409,14 @@ NATIVE_MEMBER_BODIES = {
"self.native_get_avatar_render_info(cancellation_token).await", "self.native_get_avatar_render_info(cancellation_token).await",
"M:LibreMetaverse.AgentManager.GetCreatorExperiencesAsync(System.Threading.CancellationToken)": "M:LibreMetaverse.AgentManager.GetCreatorExperiencesAsync(System.Threading.CancellationToken)":
"self.native_get_creator_experiences(cancellation_token).await", "self.native_get_creator_experiences(cancellation_token).await",
"M:LibreMetaverse.AgentManager.GetCrossingDetails":
"Ok(self.native_crossing_details())",
"M:LibreMetaverse.AgentManager.GetCrossingFailureReason":
"Ok(self.native_crossing_failure_reason())",
"M:LibreMetaverse.AgentManager.GetCrossingState":
"Ok(self.native_crossing_state())",
"M:LibreMetaverse.AgentManager.GetSimulatorsForObject(LibreMetaverse.UUID)":
"Ok(self.native_get_simulators_for_object(object_id))",
"M:LibreMetaverse.AgentManager.GetExperienceInfoAsync(System.Collections.Generic.IEnumerable{LibreMetaverse.UUID},System.Threading.CancellationToken)": "M:LibreMetaverse.AgentManager.GetExperienceInfoAsync(System.Collections.Generic.IEnumerable{LibreMetaverse.UUID},System.Threading.CancellationToken)":
"self.native_get_experience_info(experience_ids, cancellation_token).await", "self.native_get_experience_info(experience_ids, cancellation_token).await",
"M:LibreMetaverse.AgentManager.GetExperiencePermissionAsync(LibreMetaverse.UUID,System.Threading.CancellationToken)": "M:LibreMetaverse.AgentManager.GetExperiencePermissionAsync(LibreMetaverse.UUID,System.Threading.CancellationToken)":
@@ -390,6 +431,12 @@ NATIVE_MEMBER_BODIES = {
"self.native_get_region_experiences(cancellation_token).await", "self.native_get_region_experiences(cancellation_token).await",
"M:LibreMetaverse.AgentManager.GetViewerBenefitsAsync(System.Threading.CancellationToken)": "M:LibreMetaverse.AgentManager.GetViewerBenefitsAsync(System.Threading.CancellationToken)":
"self.native_get_viewer_benefits(cancellation_token).await", "self.native_get_viewer_benefits(cancellation_token).await",
"M:LibreMetaverse.AgentManager.GoHomeAsync(System.Threading.CancellationToken)":
"self.native_teleport_landmark(libremetaverse_types::UUID::zero(), cancellation_token).await",
"M:LibreMetaverse.AgentManager.IsCrossing":
"Ok(self.native_is_crossing())",
"M:LibreMetaverse.AgentManager.IsNearBorder(LibreMetaverse.Vector3,System.UInt32,System.UInt32,System.Single)":
"Ok(self.native_is_near_border(position, region_size_x, region_size_y, threshold.unwrap_or(32.0)))",
"M:LibreMetaverse.AgentManager.GiveAvatarMoney(LibreMetaverse.UUID,System.Int32)": "M:LibreMetaverse.AgentManager.GiveAvatarMoney(LibreMetaverse.UUID,System.Int32)":
"self.native_give_avatar_money(target, amount, String::new())", "self.native_give_avatar_money(target, amount, String::new())",
"M:LibreMetaverse.AgentManager.GiveAvatarMoney(LibreMetaverse.UUID,System.Int32,System.String)": "M:LibreMetaverse.AgentManager.GiveAvatarMoney(LibreMetaverse.UUID,System.Int32,System.String)":
@@ -422,6 +469,8 @@ NATIVE_MEMBER_BODIES = {
"self.native_is_experience_role(\"IsExperienceContributor\", experience_id, cancellation_token).await", "self.native_is_experience_role(\"IsExperienceContributor\", experience_id, cancellation_token).await",
"M:LibreMetaverse.AgentManager.IsGroupMessage(LibreMetaverse.InstantMessage)": "M:LibreMetaverse.AgentManager.IsGroupMessage(LibreMetaverse.InstantMessage)":
"Ok(self.native_is_group_message(message))", "Ok(self.native_is_group_message(message))",
"M:LibreMetaverse.AgentManager.Jump(System.Boolean)":
"self.native_jump(jumping)",
"M:LibreMetaverse.AgentManager.LookAtEffect(LibreMetaverse.UUID,LibreMetaverse.UUID,LibreMetaverse.Vector3d,LibreMetaverse.LookAtType,LibreMetaverse.UUID)": "M:LibreMetaverse.AgentManager.LookAtEffect(LibreMetaverse.UUID,LibreMetaverse.UUID,LibreMetaverse.Vector3d,LibreMetaverse.LookAtType,LibreMetaverse.UUID)":
"self.native_look_at_effect(source_avatar, target_object, global_offset, type_, effect_id)", "self.native_look_at_effect(source_avatar, target_object, global_offset, type_, effect_id)",
"M:LibreMetaverse.AgentManager.ModerateChatSessions(LibreMetaverse.UUID,LibreMetaverse.UUID,System.String,System.Boolean,System.Threading.CancellationToken)": "M:LibreMetaverse.AgentManager.ModerateChatSessions(LibreMetaverse.UUID,LibreMetaverse.UUID,System.String,System.Boolean,System.Threading.CancellationToken)":
@@ -454,6 +503,14 @@ NATIVE_MEMBER_BODIES = {
"self.native_leave_group_chat(group_id)", "self.native_leave_group_chat(group_id)",
"M:LibreMetaverse.AgentManager.RequestMuteList": "M:LibreMetaverse.AgentManager.RequestMuteList":
"self.native_request_mute_list()", "self.native_request_mute_list()",
"M:LibreMetaverse.AgentManager.RequestSit(LibreMetaverse.UUID,LibreMetaverse.Vector3)":
"self.native_request_sit(target_id, offset)",
"M:LibreMetaverse.AgentManager.RequestTeleport(LibreMetaverse.UUID)":
"self.native_request_teleport_landmark(landmark)",
"M:LibreMetaverse.AgentManager.RequestTeleport(System.UInt64,LibreMetaverse.Vector3)":
"self.native_request_teleport_location(region_handle, position, libremetaverse_types::Vector3::unit_y(), Some(false))",
"M:LibreMetaverse.AgentManager.RequestTeleport(System.UInt64,LibreMetaverse.Vector3,LibreMetaverse.Vector3,System.Boolean)":
"self.native_request_teleport_location(region_handle, position, look_at, ignore_caps_status)",
"M:LibreMetaverse.AgentManager.RequestNavMeshGenerationStatusAsync(System.Threading.CancellationToken)": "M:LibreMetaverse.AgentManager.RequestNavMeshGenerationStatusAsync(System.Threading.CancellationToken)":
"self.native_request_nav_mesh_generation_status(cancellation_token).await", "self.native_request_nav_mesh_generation_status(cancellation_token).await",
"M:LibreMetaverse.AgentManager.RequestNavMeshRebakeAsync(System.Threading.CancellationToken)": "M:LibreMetaverse.AgentManager.RequestNavMeshRebakeAsync(System.Threading.CancellationToken)":
@@ -468,6 +525,16 @@ NATIVE_MEMBER_BODIES = {
"self.native_send_postcard(jpeg_image_data, to_email, from_name, subject, message, global_position, cancellation_token).await", "self.native_send_postcard(jpeg_image_data, to_email, from_name, subject, message, global_position, cancellation_token).await",
"M:LibreMetaverse.AgentManager.SendViewerStatsAsync(LibreMetaverse.Messages.Linden.ViewerStatsMessage,System.Threading.CancellationToken)": "M:LibreMetaverse.AgentManager.SendViewerStatsAsync(LibreMetaverse.Messages.Linden.ViewerStatsMessage,System.Threading.CancellationToken)":
"self.native_send_viewer_stats(stats, cancellation_token).await", "self.native_send_viewer_stats(stats, cancellation_token).await",
"M:LibreMetaverse.AgentManager.SendTeleportLure(LibreMetaverse.UUID)":
"self.native_send_teleport_lure(target_id, None)",
"M:LibreMetaverse.AgentManager.SendTeleportLure(LibreMetaverse.UUID,System.String)":
"self.native_send_teleport_lure(target_id, Some(message))",
"M:LibreMetaverse.AgentManager.SendTeleportLureRequest(LibreMetaverse.UUID)":
"self.native_send_teleport_lure_request(target_id, target_id, \"Let me join you in your location\".into())",
"M:LibreMetaverse.AgentManager.SendTeleportLureRequest(LibreMetaverse.UUID,LibreMetaverse.UUID,System.String)":
"self.native_send_teleport_lure_request(target_id, session_id, message)",
"M:LibreMetaverse.AgentManager.SendTeleportLureRequest(LibreMetaverse.UUID,System.String)":
"self.native_send_teleport_lure_request(target_id, target_id, message)",
"M:LibreMetaverse.AgentManager.SetAgentAccessAsync(System.String,System.Threading.CancellationToken)": "M:LibreMetaverse.AgentManager.SetAgentAccessAsync(System.String,System.Threading.CancellationToken)":
"self.native_set_agent_access_async(access, cancellation_token).await", "self.native_set_agent_access_async(access, cancellation_token).await",
"M:LibreMetaverse.AgentManager.SetDisplayNameAsync(System.String,System.String,System.Threading.CancellationToken)": "M:LibreMetaverse.AgentManager.SetDisplayNameAsync(System.String,System.String,System.Threading.CancellationToken)":
@@ -484,6 +551,30 @@ NATIVE_MEMBER_BODIES = {
"self.native_start_im_conference(participants, tmp_session_id, cancellation_token).await", "self.native_start_im_conference(participants, tmp_session_id, cancellation_token).await",
"M:LibreMetaverse.AgentManager.SetHoverHeightAsync(System.Double,System.Threading.CancellationToken)": "M:LibreMetaverse.AgentManager.SetHoverHeightAsync(System.Double,System.Threading.CancellationToken)":
"self.native_set_hover_height_async(hover_height, cancellation_token).await", "self.native_set_hover_height_async(hover_height, cancellation_token).await",
"M:LibreMetaverse.AgentManager.Sit":
"self.native_sit()",
"M:LibreMetaverse.AgentManager.SitOnGround":
"self.native_sit_on_ground()",
"M:LibreMetaverse.AgentManager.Stand":
"self.native_stand()",
"M:LibreMetaverse.AgentManager.TeleportAsync(LibreMetaverse.UUID,System.Threading.CancellationToken)":
"self.native_teleport_landmark(landmark, cancellation_token).await",
"M:LibreMetaverse.AgentManager.TeleportAsync(System.String,LibreMetaverse.Vector3,LibreMetaverse.Vector3,System.Threading.CancellationToken)":
"self.native_teleport_name(sim_name, position, look_at, cancellation_token).await",
"M:LibreMetaverse.AgentManager.TeleportAsync(System.String,LibreMetaverse.Vector3,System.Threading.CancellationToken)":
"self.native_teleport_name(sim_name, position, libremetaverse_types::Vector3::unit_y(), cancellation_token).await",
"M:LibreMetaverse.AgentManager.TeleportAsync(System.UInt64,LibreMetaverse.Vector3,LibreMetaverse.Vector3,System.Threading.CancellationToken)":
"self.native_teleport_location(region_handle, position, look_at, cancellation_token).await",
"M:LibreMetaverse.AgentManager.TeleportAsync(System.UInt64,LibreMetaverse.Vector3,System.Threading.CancellationToken)":
"self.native_teleport_location(region_handle, position, libremetaverse_types::Vector3::unit_y(), cancellation_token).await",
"M:LibreMetaverse.AgentManager.TeleportFailedEventHandler(System.String,LibreMetaverse.Interfaces.IMessage,LibreMetaverse.Simulator)":
"self.native_movement_runtime().handle_caps_event(\"TeleportFailed\", message.as_ref(), simulator).map(|_| ())",
"M:LibreMetaverse.AgentManager.TeleportLureRespond(LibreMetaverse.UUID,LibreMetaverse.UUID,System.Boolean)":
"self.native_teleport_lure_respond(requester_id, session_id, accept)",
"M:LibreMetaverse.AgentManager.TrackObjectInSimulator(LibreMetaverse.UUID,LibreMetaverse.Simulator)":
"Ok(self.native_track_object_in_simulator(object_id, sim))",
"M:LibreMetaverse.AgentManager.UntrackObjectInSimulator(LibreMetaverse.UUID,LibreMetaverse.Simulator)":
"Ok(self.native_untrack_object_in_simulator(object_id, &sim))",
"M:LibreMetaverse.AgentManager.UpdateAgentLanguageAsync(System.String,System.Boolean,System.Threading.CancellationToken)": "M:LibreMetaverse.AgentManager.UpdateAgentLanguageAsync(System.String,System.Boolean,System.Threading.CancellationToken)":
"self.native_update_agent_language(language, is_public, cancellation_token).await", "self.native_update_agent_language(language, is_public, cancellation_token).await",
"M:LibreMetaverse.AgentManager.UpdateClassifiedInfo(LibreMetaverse.UUID,LibreMetaverse.DirectoryManager.ClassifiedCategories,LibreMetaverse.UUID,System.Int32,LibreMetaverse.Vector3d,System.String,System.String,System.Boolean)": "M:LibreMetaverse.AgentManager.UpdateClassifiedInfo(LibreMetaverse.UUID,LibreMetaverse.DirectoryManager.ClassifiedCategories,LibreMetaverse.UUID,System.Int32,LibreMetaverse.Vector3d,System.String,System.String,System.Boolean)":
@@ -578,6 +669,42 @@ NATIVE_MEMBER_BODIES = {
"self.native_session_id()", "self.native_session_id()",
"P:LibreMetaverse.AgentManager.SessionID#set": "P:LibreMetaverse.AgentManager.SessionID#set":
"self.native_set_session_id(value)", "self.native_set_session_id(value)",
"P:LibreMetaverse.AgentManager.Acceleration":
"self.native_movement_runtime().acceleration()",
"P:LibreMetaverse.AgentManager.AngularVelocity":
"self.native_movement_runtime().angular_velocity()",
"P:LibreMetaverse.AgentManager.GlobalPosition":
"self.native_movement_runtime().global_position()",
"P:LibreMetaverse.AgentManager.HomePosition":
"self.native_movement_runtime().home_position()",
"P:LibreMetaverse.AgentManager.LastPositionUpdate":
"self.native_movement_runtime().last_position_update()",
"P:LibreMetaverse.AgentManager.LastPositionUpdate#set":
"self.native_movement_runtime().set_last_position_update(value)",
"P:LibreMetaverse.AgentManager.RelativePosition":
"self.native_movement_runtime().relative_position()",
"P:LibreMetaverse.AgentManager.RelativePosition#set":
"self.native_movement_runtime().set_relative_position(value)",
"P:LibreMetaverse.AgentManager.RelativePositionEstimate":
"self.native_movement_runtime().relative_position_estimate()",
"P:LibreMetaverse.AgentManager.RelativePositionEstimate#set":
"self.native_movement_runtime().set_relative_position(value)",
"P:LibreMetaverse.AgentManager.RelativeRotation":
"self.native_movement_runtime().relative_rotation()",
"P:LibreMetaverse.AgentManager.RelativeRotation#set":
"self.native_movement_runtime().set_relative_rotation(value)",
"P:LibreMetaverse.AgentManager.SimPosition":
"self.native_movement_runtime().sim_position()",
"P:LibreMetaverse.AgentManager.SimRotation":
"self.native_movement_runtime().sim_rotation()",
"P:LibreMetaverse.AgentManager.SittingOn":
"self.native_movement_runtime().sitting_on()",
"P:LibreMetaverse.AgentManager.TeleportMessage":
"self.native_movement_runtime().teleport_message()",
"P:LibreMetaverse.AgentManager.TeleportMessage#set":
"self.native_movement_runtime().set_teleport_message(value)",
"P:LibreMetaverse.AgentManager.Velocity":
"self.native_movement_runtime().velocity()",
"E:LibreMetaverse.NetworkManager.Disconnected": "E:LibreMetaverse.NetworkManager.Disconnected":
"self.native_subscribe_disconnected(handler)", "self.native_subscribe_disconnected(handler)",
"E:LibreMetaverse.NetworkManager.EventQueueRunning": "E:LibreMetaverse.NetworkManager.EventQueueRunning":

View File

@@ -984,6 +984,7 @@ def validate_generated_shims() -> None:
"NotImplemented::new(", "NotImplemented::new(",
"crate::agent_manager::", "crate::agent_manager::",
"crate::agent_messages::", "crate::agent_messages::",
"crate::agent_movement::",
"crate::byte_order::", "crate::byte_order::",
"crate::attention_catalog::", "crate::attention_catalog::",
"crate::binary::", "crate::binary::",