Complete first release candidate audit (#107)
Some checks failed
API and SemVer surface / api-surface (push) Failing after 1m34s
Native code generation / deterministic (push) Has been cancelled
Concurrency and resource soak audit / soak (push) Has been cancelled
Documentation / documentation (push) Has been cancelled
performance evidence / audit (push) Has been cancelled
First release candidate / non-fuzz-release-gate (push) Has been cancelled
Release platform and feature matrix / audit (push) Has been cancelled
Release platform and feature matrix / matrix (false, linux-stable-minimal, x86_64-unknown-linux-gnu, stable) (push) Has been cancelled
Release platform and feature matrix / matrix (false, macos-stable-portable, x86_64-apple-darwin, stable) (push) Has been cancelled
Release platform and feature matrix / matrix (false, windows-stable-portable, x86_64-pc-windows-gnu, stable) (push) Has been cancelled
Release platform and feature matrix / matrix (true, linux-msrv-portable, x86_64-unknown-linux-gnu, 1.96.0) (push) Has been cancelled
Release platform and feature matrix / matrix (true, linux-stable-default, x86_64-unknown-linux-gnu, stable) (push) Has been cancelled
Release platform and feature matrix / matrix (true, linux-stable-features, x86_64-unknown-linux-gnu, stable) (push) Has been cancelled
Release platform and feature matrix / matrix (true, linux-stable-release-surface, x86_64-unknown-linux-gnu, stable) (push) Has been cancelled
Dependency and supply-chain audit / audit (push) Has been cancelled
Native release artifact audit / audit (push) Has been cancelled
Imaging and meshing gate / native (push) Failing after 53s
JPEG 2000 feature / linux (push) Successful in 2m49s
Native Rust workspace compile / compile (push) Failing after 59s
Skia feature / linux (push) Has been cancelled
Some checks failed
API and SemVer surface / api-surface (push) Failing after 1m34s
Native code generation / deterministic (push) Has been cancelled
Concurrency and resource soak audit / soak (push) Has been cancelled
Documentation / documentation (push) Has been cancelled
performance evidence / audit (push) Has been cancelled
First release candidate / non-fuzz-release-gate (push) Has been cancelled
Release platform and feature matrix / audit (push) Has been cancelled
Release platform and feature matrix / matrix (false, linux-stable-minimal, x86_64-unknown-linux-gnu, stable) (push) Has been cancelled
Release platform and feature matrix / matrix (false, macos-stable-portable, x86_64-apple-darwin, stable) (push) Has been cancelled
Release platform and feature matrix / matrix (false, windows-stable-portable, x86_64-pc-windows-gnu, stable) (push) Has been cancelled
Release platform and feature matrix / matrix (true, linux-msrv-portable, x86_64-unknown-linux-gnu, 1.96.0) (push) Has been cancelled
Release platform and feature matrix / matrix (true, linux-stable-default, x86_64-unknown-linux-gnu, stable) (push) Has been cancelled
Release platform and feature matrix / matrix (true, linux-stable-features, x86_64-unknown-linux-gnu, stable) (push) Has been cancelled
Release platform and feature matrix / matrix (true, linux-stable-release-surface, x86_64-unknown-linux-gnu, stable) (push) Has been cancelled
Dependency and supply-chain audit / audit (push) Has been cancelled
Native release artifact audit / audit (push) Has been cancelled
Imaging and meshing gate / native (push) Failing after 53s
JPEG 2000 feature / linux (push) Successful in 2m49s
Native Rust workspace compile / compile (push) Failing after 59s
Skia feature / linux (push) Has been cancelled
This commit is contained in:
@@ -159,6 +159,7 @@ pub(crate) struct AppearanceManagerInner {
|
||||
appearance_cancel: Mutex<Option<CancellationTokenSource>>,
|
||||
appearance_gate: Arc<tokio::sync::Semaphore>,
|
||||
events: AppearanceEvents,
|
||||
login_callback: Mutex<Option<crate::NetworkManagerLoginResponseCallback>>,
|
||||
network_subscriptions: Mutex<Vec<Subscription>>,
|
||||
}
|
||||
|
||||
@@ -232,11 +233,35 @@ fn handle_appearance_packet(
|
||||
match packet_type {
|
||||
PacketType::AgentWearablesUpdate => handle_wearables_update(inner, data),
|
||||
PacketType::AgentCachedTextureResponse => handle_cached_bakes(inner, data),
|
||||
PacketType::AvatarAppearance => handle_avatar_appearance(inner, data),
|
||||
PacketType::RebakeAvatarTextures => handle_rebake_request(inner, data),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_avatar_appearance(inner: &Arc<AppearanceManagerInner>, data: Vec<u8>) {
|
||||
let mut offset = 0;
|
||||
let Ok(packet) =
|
||||
crate::packets::AvatarAppearancePacket::new_with_bytes_int32(data, &mut offset)
|
||||
else {
|
||||
return;
|
||||
};
|
||||
let Some(client) = inner.client.upgrade() else {
|
||||
return;
|
||||
};
|
||||
let Ok(network) = client.native_network() else {
|
||||
return;
|
||||
};
|
||||
if packet.sender.id != network.native_agent_id() {
|
||||
return;
|
||||
}
|
||||
if let Some(appearance) = packet.appearance_data.first() {
|
||||
inner
|
||||
.last_cof_version
|
||||
.fetch_max(appearance.cof_version, Ordering::AcqRel);
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_wearables_update(inner: &Arc<AppearanceManagerInner>, data: Vec<u8>) {
|
||||
let mut offset = 0;
|
||||
let Ok(packet) = AgentWearablesUpdatePacket::new_with_bytes_int32(data, &mut offset) else {
|
||||
@@ -371,9 +396,31 @@ impl AppearanceManager {
|
||||
appearance_cancel: Mutex::new(None),
|
||||
appearance_gate: Arc::new(tokio::sync::Semaphore::new(1)),
|
||||
events: AppearanceEvents::default(),
|
||||
login_callback: Mutex::new(None),
|
||||
network_subscriptions: Mutex::new(Vec::new()),
|
||||
});
|
||||
let weak = Arc::downgrade(&inner);
|
||||
let login_callback = crate::NetworkManagerLoginResponseCallback::from_handler(
|
||||
move |success, redirect, _message, _reason, response| {
|
||||
if success
|
||||
&& !redirect
|
||||
&& let (Some(inner), Some(response)) = (weak.upgrade(), response)
|
||||
{
|
||||
inner.last_cof_version.fetch_max(
|
||||
i32::try_from(response.cof_version()).unwrap_or(i32::MAX),
|
||||
Ordering::AcqRel,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
client
|
||||
.native_network()?
|
||||
.native_register_login_response_callback(
|
||||
login_callback.clone(),
|
||||
Some(vec!["cof_version".to_owned()]),
|
||||
)?;
|
||||
*mutex(&inner.login_callback) = Some(login_callback);
|
||||
let weak = Arc::downgrade(&inner);
|
||||
let subscription = client
|
||||
.native_network()?
|
||||
.subscribe_raw_packet(Arc::new(move |event| {
|
||||
@@ -463,6 +510,12 @@ impl AppearanceManager {
|
||||
|
||||
#[allow(clippy::unnecessary_wraps)] // The mapped Dispose API is fallible.
|
||||
pub(crate) fn native_dispose(&self) -> Result<(), Error> {
|
||||
if let Some(callback) = mutex(&self.inner.login_callback).take()
|
||||
&& let Some(client) = self.inner.client.upgrade()
|
||||
&& let Ok(network) = client.native_network()
|
||||
{
|
||||
network.native_unregister_login_response_callback(&callback)?;
|
||||
}
|
||||
self.inner.disposed.store(true, Ordering::Release);
|
||||
write(&self.inner.wearables).clear();
|
||||
self.inner
|
||||
@@ -1049,6 +1102,70 @@ impl AppearanceManager {
|
||||
)))
|
||||
}
|
||||
|
||||
pub(crate) async fn native_apply_archetype(
|
||||
&self,
|
||||
archetype: crate::GenepoolArchetype,
|
||||
) -> Result<(), Error> {
|
||||
let parameters = archetype.params();
|
||||
{
|
||||
let mut assets = write(&self.inner.wearable_assets);
|
||||
for asset in assets.values_mut() {
|
||||
for parameter in ¶meters {
|
||||
if let Some(value) = asset.params.get_mut(¶meter.id()) {
|
||||
*value = parameter.value();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
self.inner
|
||||
.server_visual_parameters
|
||||
.store(false, Ordering::Release);
|
||||
self.native_request_set_appearance(true).await
|
||||
}
|
||||
|
||||
pub(crate) async fn native_blend_to_archetype(
|
||||
&self,
|
||||
archetype: crate::GenepoolArchetype,
|
||||
amount: f32,
|
||||
) -> Result<(), Error> {
|
||||
if !amount.is_finite() {
|
||||
return Err(Error::Argument);
|
||||
}
|
||||
if amount <= 0.0 {
|
||||
return Ok(());
|
||||
}
|
||||
let amount = amount.min(1.0);
|
||||
let parameters = archetype.params();
|
||||
{
|
||||
let mut assets = write(&self.inner.wearable_assets);
|
||||
for asset in assets.values_mut() {
|
||||
for parameter in ¶meters {
|
||||
if let Some(current) = asset.params.get_mut(¶meter.id()) {
|
||||
*current += amount * (parameter.value() - *current);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
self.inner
|
||||
.server_visual_parameters
|
||||
.store(false, Ordering::Release);
|
||||
self.native_request_set_appearance(true).await
|
||||
}
|
||||
|
||||
pub(crate) async fn native_randomize_appearance(
|
||||
&self,
|
||||
random: Option<libremetaverse_types::compat::RandomSource>,
|
||||
) -> Result<(), Error> {
|
||||
let archetypes = crate::Genepool::archetypes();
|
||||
let maximum = i32::try_from(archetypes.len()).map_err(|_| Error::IndexOutOfRange)?;
|
||||
let index = random.unwrap_or_default().next(maximum)?;
|
||||
let archetype = archetypes
|
||||
.into_iter()
|
||||
.nth(usize::try_from(index).map_err(|_| Error::IndexOutOfRange)?)
|
||||
.ok_or(Error::IndexOutOfRange)?;
|
||||
self.native_apply_archetype(archetype).await
|
||||
}
|
||||
|
||||
pub(crate) fn native_server_baking_region(&self) -> Result<bool, Error> {
|
||||
let protocols = self
|
||||
.client()?
|
||||
@@ -2303,7 +2420,7 @@ mod tests {
|
||||
let delivered_handler = Arc::clone(&delivered);
|
||||
let releasing = Arc::clone(&released);
|
||||
let healthy = registry.subscribe(Arc::new(move |value| {
|
||||
let _keep_alive = &releasing;
|
||||
std::hint::black_box(&releasing);
|
||||
delivered_handler.fetch_add(value as u64, Ordering::AcqRel);
|
||||
}));
|
||||
drop(released);
|
||||
@@ -2555,6 +2672,40 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn self_avatar_appearance_advances_cof_version_monotonically() {
|
||||
let client = GridClient::new().unwrap();
|
||||
let manager = client.appearance();
|
||||
let mut packet = crate::packets::AvatarAppearancePacket::new_with_constructor().unwrap();
|
||||
packet.sender.id = client.network().native_agent_id();
|
||||
let mut appearance =
|
||||
crate::packets::AvatarAppearancePacketAppearanceDataBlock::new_with_constructor()
|
||||
.unwrap();
|
||||
appearance.cof_version = 17;
|
||||
packet.appearance_data.push(appearance);
|
||||
|
||||
handle_appearance_packet(
|
||||
&manager.inner,
|
||||
PacketType::AvatarAppearance,
|
||||
packet.to_bytes_with_method().unwrap(),
|
||||
);
|
||||
assert_eq!(manager.native_last_cof_version(), 17);
|
||||
|
||||
let mut older = crate::packets::AvatarAppearancePacket::new_with_constructor().unwrap();
|
||||
older.sender.id = client.network().native_agent_id();
|
||||
let mut older_data =
|
||||
crate::packets::AvatarAppearancePacketAppearanceDataBlock::new_with_constructor()
|
||||
.unwrap();
|
||||
older_data.cof_version = 3;
|
||||
older.appearance_data.push(older_data);
|
||||
handle_appearance_packet(
|
||||
&manager.inner,
|
||||
PacketType::AvatarAppearance,
|
||||
older.to_bytes_with_method().unwrap(),
|
||||
);
|
||||
assert_eq!(manager.native_last_cof_version(), 17);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn failed_appearance_request_emits_failure_and_empty_cache_request_does_not_wait() {
|
||||
let client = GridClient::new().unwrap();
|
||||
|
||||
Reference in New Issue
Block a user