Implement native agent movement and teleportation (#60)
This commit is contained in:
@@ -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: |
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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).
|
||||||
|
|||||||
@@ -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 |
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
3479
crates/libremetaverse/src/agent_movement.rs
Normal file
3479
crates/libremetaverse/src/agent_movement.rs
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||||
|
|||||||
@@ -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
65
docs/agent-movement.md
Normal 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.
|
||||||
106
tools/check_milestone_09_issue_60.py
Normal file
106
tools/check_milestone_09_issue_60.py
Normal 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()
|
||||||
@@ -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":
|
||||||
|
|||||||
@@ -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::",
|
||||||
|
|||||||
Reference in New Issue
Block a user