use newtypes for template ids, pros: 1) enforces id validation 2) ease of use (helper method for getting template struct right away)
57 lines
1.6 KiB
Rust
57 lines
1.6 KiB
Rust
use data::tables::AvatarBaseID;
|
|
use proto::{AddAvatarPerformType, AddAvatarScNotify, PlayerSyncScNotify};
|
|
|
|
use crate::ServerState;
|
|
|
|
use super::ArgSlice;
|
|
|
|
pub async fn add(
|
|
args: ArgSlice<'_>,
|
|
state: &ServerState,
|
|
) -> Result<String, Box<dyn std::error::Error>> {
|
|
const USAGE: &str = "Usage: avatar add [player_uid] [avatar_id]";
|
|
|
|
if args.len() != 2 {
|
|
return Ok(USAGE.to_string());
|
|
}
|
|
|
|
let uid = args[0].parse::<u32>()?;
|
|
let avatar_id = args[1].parse::<u32>()?;
|
|
let Some(avatar_id) = AvatarBaseID::new(avatar_id) else {
|
|
return Ok(format!("avatar with id {avatar_id} doesn't exist"));
|
|
};
|
|
|
|
let Some(player_lock) = state.player_mgr.get_player(uid).await else {
|
|
return Ok(String::from("player not found"));
|
|
};
|
|
|
|
let (session_id, avatar_sync) = {
|
|
let mut player = player_lock.lock().await;
|
|
|
|
player.role_model.add_avatar(avatar_id);
|
|
(player.current_session_id(), player.role_model.avatar_sync())
|
|
};
|
|
|
|
if let Some(session) = session_id.map(|id| state.session_mgr.get(id)).flatten() {
|
|
session
|
|
.notify(AddAvatarScNotify {
|
|
avatar_id: avatar_id.value(),
|
|
perform_type: AddAvatarPerformType::Gacha.into(),
|
|
..Default::default()
|
|
})
|
|
.await?;
|
|
|
|
session
|
|
.notify(PlayerSyncScNotify {
|
|
avatar: Some(avatar_sync),
|
|
..Default::default()
|
|
})
|
|
.await?;
|
|
} else {
|
|
state.player_mgr.save_and_remove(uid).await;
|
|
}
|
|
|
|
Ok(format!(
|
|
"successfully added avatar {avatar_id} to player {uid}"
|
|
))
|
|
}
|