forked from NewEriduPubSec/JaneDoe-ZS
Networking improvement and player nickname change console command
split TcpStream into read and write halves, so it's possible to recv and send concurrently implement 'player nickname' command
This commit is contained in:
parent
9af61cd33f
commit
4b86d62d3f
3 changed files with 66 additions and 10 deletions
|
@ -79,5 +79,6 @@ impl CommandManager {
|
|||
|
||||
commands! {
|
||||
player::avatar "[player_uid] [avatar_id]" "changes player avatar for main city";
|
||||
player::nickname "[player_uid] [nickname]" "changes player nickname";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use data::tables;
|
||||
use proto::PlayerSyncScNotify;
|
||||
|
||||
use crate::ServerState;
|
||||
|
||||
|
@ -37,3 +38,54 @@ pub async fn avatar(
|
|||
"changed frontend_avatar_id, you have to re-enter main city now"
|
||||
))
|
||||
}
|
||||
|
||||
pub async fn nickname(
|
||||
args: &[&str],
|
||||
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_id) = session_id {
|
||||
if let Some(session) = state.session_mgr.get(session_id) {
|
||||
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}"
|
||||
))
|
||||
}
|
||||
|
|
|
@ -9,8 +9,11 @@ use common::{
|
|||
use proto::{CmdID, NapMessage, PacketHead};
|
||||
use tokio::{
|
||||
io::AsyncWriteExt,
|
||||
net::TcpStream,
|
||||
sync::{Mutex, MutexGuard, OnceCell},
|
||||
net::{
|
||||
tcp::{OwnedReadHalf, OwnedWriteHalf},
|
||||
TcpStream,
|
||||
},
|
||||
sync::{Mutex, OnceCell},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
|
@ -30,7 +33,8 @@ static SECRET_KEY: LazyLock<MhyXorpad> = LazyLock::new(|| {
|
|||
|
||||
pub struct NetSession {
|
||||
id: u64,
|
||||
stream: Mutex<TcpStream>,
|
||||
reader: Mutex<OwnedReadHalf>,
|
||||
writer: Mutex<OwnedWriteHalf>,
|
||||
session_key: OnceCell<MhyXorpad>,
|
||||
packet_id_counter: AtomicU32,
|
||||
state: AtomicNetSessionState,
|
||||
|
@ -75,9 +79,12 @@ pub enum SessionError {
|
|||
|
||||
impl NetSession {
|
||||
pub fn new(id: u64, stream: TcpStream) -> Self {
|
||||
let (reader, writer) = stream.into_split();
|
||||
|
||||
Self {
|
||||
id,
|
||||
stream: Mutex::new(stream),
|
||||
reader: Mutex::new(reader),
|
||||
writer: Mutex::new(writer),
|
||||
session_key: OnceCell::new(),
|
||||
packet_id_counter: AtomicU32::new(0),
|
||||
state: AtomicNetSessionState::new(NetSessionState::StartEnterGameWorld),
|
||||
|
@ -90,7 +97,7 @@ impl NetSession {
|
|||
let mut last_save_time = util::cur_timestamp();
|
||||
|
||||
let result = loop {
|
||||
let packet = match NetPacket::read(&mut *self.stream().await).await {
|
||||
let packet = match NetPacket::read(&mut *self.reader.lock().await).await {
|
||||
Ok(packet) => packet,
|
||||
Err(DecodeError::IoError(_)) => break Ok(()),
|
||||
Err(err) => break Err(SessionError::PacketDecode(err)),
|
||||
|
@ -195,11 +202,7 @@ impl NetSession {
|
|||
self.xor_payload(packet.cmd_id, &mut packet.body);
|
||||
|
||||
let buf = packet.encode();
|
||||
self.stream().await.write_all(&buf).await
|
||||
}
|
||||
|
||||
async fn stream(&self) -> MutexGuard<'_, TcpStream> {
|
||||
self.stream.lock().await
|
||||
self.writer.lock().await.write_all(&buf).await
|
||||
}
|
||||
|
||||
pub fn id(&self) -> u64 {
|
||||
|
|
Loading…
Reference in a new issue