JaneDoe-ZS/nap_gameserver/src/commands/player.rs
2024-07-31 00:41:20 +08:00

169 lines
4.7 KiB
Rust

use data::tables::{AvatarBaseID, ProcedureConfigID};
use proto::{DisconnectReason, DisconnectScNotify, PlayerSyncScNotify};
use crate::ServerState;
use super::ArgSlice;
pub async fn avatar(
args: ArgSlice<'_>,
state: &ServerState,
) -> Result<String, Box<dyn std::error::Error>> {
const USAGE: &str = "Usage: player avatar [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 should_save = {
let mut player = player_lock.lock().await;
player.basic_data_model.frontend_avatar_id = Some(avatar_id);
player.current_session_id().is_none()
};
if should_save {
state.player_mgr.save_and_remove(uid).await;
}
Ok(format!(
"changed frontend_avatar_id, you have to re-enter main city now"
))
}
pub async fn nickname(
args: ArgSlice<'_>,
state: &ServerState,
) -> Result<String, Box<dyn std::error::Error>> {
const USAGE: &str = "Usage: player nickname [uid] [nickname]";
if args.len() != 2 {
return Ok(USAGE.to_string());
}
let uid = args[0].parse::<u32>()?;
let nickname = args[1].trim();
if !matches!(nickname.len(), (4..=15)) {
return Ok(String::from(
"nickname should contain at least 4 and not more than 15 characters",
));
}
let Some(player_lock) = state.player_mgr.get_player(uid).await else {
return Ok(String::from("player not found"));
};
let (session_id, basic_info) = {
let mut player = player_lock.lock().await;
player.basic_data_model.nick_name = Some(nickname.to_string());
(
player.current_session_id(),
player.basic_data_model.player_basic_info(),
)
};
if let Some(session) = session_id.map(|id| state.session_mgr.get(id)).flatten() {
session
.notify(PlayerSyncScNotify {
basic_info: Some(basic_info),
..Default::default()
})
.await?;
} else {
state.player_mgr.save_and_remove(uid).await;
}
Ok(format!(
"successfully changed player {uid} nickname to {nickname}"
))
}
pub async fn procedure(
args: ArgSlice<'_>,
state: &ServerState,
) -> Result<String, Box<dyn std::error::Error>> {
const USAGE: &str = "Usage: player procedure [uid] [procedure_id]";
if args.len() != 2 {
return Ok(USAGE.to_string());
}
let uid = args[0].parse::<u32>()?;
let procedure_id = args[1].parse::<i32>()?;
let procedure_id = match procedure_id {
1.. => ProcedureConfigID::new(procedure_id as u32),
_ => None,
};
let Some(player_lock) = state.player_mgr.get_player(uid).await else {
return Ok(String::from("player not found"));
};
let session_id = {
let mut player = player_lock.lock().await;
player.basic_data_model.beginner_procedure_id = procedure_id;
player.current_session_id()
};
if session_id.is_none() {
state.player_mgr.save_and_remove(uid).await;
}
Ok(format!(
"successfully changed procedure_id to {procedure_id:?}"
))
}
pub async fn kick(
args: ArgSlice<'_>,
state: &ServerState,
) -> Result<String, Box<dyn std::error::Error>> {
const USAGE: &str = "Usage: player kick [player_uid]";
if args.len() > 2 {
return Ok(USAGE.to_string());
}
let uid = args[0].parse::<u32>()?;
let reason = match args.get(1) {
Some(arg) => match arg.parse::<i32>() {
Ok(val) => val,
Err(_err) => 1,
},
None => 1,
};
let reason_str = match DisconnectReason::try_from(reason) {
Ok(converted_enum) => converted_enum.as_str_name().to_owned(),
Err(_err) => reason.to_string(),
};
let Some(player_lock) = state.player_mgr.get_player(uid).await else {
return Ok(String::from("player not found"));
};
let session_id = player_lock.lock().await.current_session_id();
if let Some(session) = session_id.map(|id| state.session_mgr.get(id)).flatten() {
session
.notify(DisconnectScNotify { reason: reason })
.await?;
tokio::time::sleep(tokio::time::Duration::from_millis(50)).await;
session.shutdown().await?;
Ok(format!("kicked player, uid: {uid}, reason: {reason_str}"))
} else {
Ok(format!("player uid: {uid} is not online yet."))
}
}