Queue up Arg packets instead of sending instantly

Change send_rpc_arg to push_rpc_arg. Queue up and Send all Arg packets after handler finish
This commit is contained in:
xeon 2024-06-02 23:32:00 +03:00
parent 07560e605a
commit 1609636e90
8 changed files with 81 additions and 56 deletions

View file

@ -52,21 +52,21 @@ impl<T> PlayerOperationResult<T>
where where
T: Send + Sync, T: Send + Sync,
{ {
pub const fn unwrap(&self) -> &T { pub fn take(self) -> T {
&self.result self.result
} }
pub async fn send_changes(&mut self, session: &NetworkSession) -> Result<&T> { pub async fn send_changes(mut self, session: &NetworkSession) -> Result<T> {
if self.player_info_changes.is_some() { if self.player_info_changes.is_some() {
let ptc_player_info_changed = PtcPlayerInfoChangedArg { let ptc_player_info_changed = PtcPlayerInfoChangedArg {
player_uid: session.player_uid().raw(), player_uid: session.player_uid().raw(),
player_info: self.player_info_changes.take().unwrap(), player_info: self.player_info_changes.take().unwrap(),
}; };
session.send_rpc_arg(101, &ptc_player_info_changed).await?; session.push_rpc_arg(101, ptc_player_info_changed).await?;
} }
Ok(self.unwrap()) Ok(self.take())
} }
pub const fn ret(result: T) -> Self { pub const fn ret(result: T) -> Self {

View file

@ -421,7 +421,7 @@ impl DungeonManager {
pub fn enter_battle(&self, scene_uid: u64) -> PlayerOperationResult<PtcEnterSceneArg> { pub fn enter_battle(&self, scene_uid: u64) -> PlayerOperationResult<PtcEnterSceneArg> {
let hollow_scene_uid = *self.player.read().scene_uid.as_ref().unwrap(); let hollow_scene_uid = *self.player.read().scene_uid.as_ref().unwrap();
let hollow_scene = self.set_cur_hollow_battle(scene_uid, hollow_scene_uid); let hollow_scene = self.set_cur_hollow_battle(scene_uid, hollow_scene_uid);
let ptc_enter_scene = self.enter_scene(scene_uid).unwrap().unwrap().clone(); let ptc_enter_scene = self.enter_scene(scene_uid).unwrap().take().clone();
let player = self.player.read(); let player = self.player.read();
let dungeon_collection = player.dungeon_collection.as_ref().unwrap(); let dungeon_collection = player.dungeon_collection.as_ref().unwrap();

View file

@ -86,7 +86,7 @@ impl ItemManager {
}; };
// Unlock & equip default weapon // Unlock & equip default weapon
let weapon_uid = *self.unlock_weapon(10012).unwrap(); let weapon_uid = self.unlock_weapon(10012).take();
self.equip_weapon(weapon_uid, uid); self.equip_weapon(weapon_uid, uid);
let mut player_info = self.player_info.write(); let mut player_info = self.player_info.write();

View file

@ -21,12 +21,12 @@ pub async fn on_rpc_hollow_move(
.move_to(destination_pos, scene_uid); .move_to(destination_pos, scene_uid);
session session
.send_rpc_arg(PTC_HOLLOW_GRID_ID, &ptc_hollow_grid) .push_rpc_arg(PTC_HOLLOW_GRID_ID, ptc_hollow_grid)
.await?; .await?;
if let Some(ptc_sync_hollow_event) = ptc_sync_hollow_event { if let Some(ptc_sync_hollow_event) = ptc_sync_hollow_event {
session session
.send_rpc_arg(PTC_SYNC_HOLLOW_EVENT_INFO_ID, &ptc_sync_hollow_event) .push_rpc_arg(PTC_SYNC_HOLLOW_EVENT_INFO_ID, ptc_sync_hollow_event)
.await?; .await?;
} }
@ -37,7 +37,7 @@ pub async fn on_rpc_hollow_move(
}; };
session session
.send_rpc_arg(PTC_POSITION_IN_HOLLOW_CHANGED_ID, &pos) .push_rpc_arg(PTC_POSITION_IN_HOLLOW_CHANGED_ID, pos)
.await?; .await?;
Ok(RpcHollowMoveRet::new( Ok(RpcHollowMoveRet::new(
@ -57,10 +57,10 @@ pub async fn on_rpc_end_battle(
if !hollow_finished { if !hollow_finished {
session session
.send_rpc_arg(PTC_SYNC_HOLLOW_EVENT_INFO_ID, &sync_event) .push_rpc_arg(PTC_SYNC_HOLLOW_EVENT_INFO_ID, sync_event)
.await?; .await?;
} else { } else {
let _ = *session let _ = session
.context .context
.dungeon_manager .dungeon_manager
.hollow_finished() .hollow_finished()
@ -76,7 +76,7 @@ pub async fn on_rpc_end_battle(
}; };
session session
.send_rpc_arg(PTC_DUNGEON_QUEST_FINISHED_ID, &ptc_dungeon_quest_finished) .push_rpc_arg(PTC_DUNGEON_QUEST_FINISHED_ID, ptc_dungeon_quest_finished)
.await?; .await?;
} }
@ -90,9 +90,9 @@ pub async fn on_rpc_end_battle(
.clone(); .clone();
session session
.send_rpc_arg( .push_rpc_arg(
PTC_SYNC_HOLLOW_GRID_MAPS_ID, PTC_SYNC_HOLLOW_GRID_MAPS_ID,
&session.context.hollow_grid_manager.sync_hollow_maps( session.context.hollow_grid_manager.sync_hollow_maps(
player_uid, player_uid,
session.context.dungeon_manager.get_cur_scene_uid(), session.context.dungeon_manager.get_cur_scene_uid(),
), ),
@ -109,14 +109,14 @@ pub async fn on_rpc_end_battle(
}; };
session session
.send_rpc_arg( .push_rpc_arg(
PTC_POSITION_IN_HOLLOW_CHANGED_ID, PTC_POSITION_IN_HOLLOW_CHANGED_ID,
&ptc_position_in_hollow_changed, ptc_position_in_hollow_changed,
) )
.await?; .await?;
session session
.send_rpc_arg(PTC_ENTER_SCENE_ID, &ptc_enter_scene) .push_rpc_arg(PTC_ENTER_SCENE_ID, ptc_enter_scene)
.await?; .await?;
Ok(RpcEndBattleRet::new( Ok(RpcEndBattleRet::new(
@ -156,18 +156,18 @@ pub async fn on_rpc_run_hollow_event_graph(
specials: phashmap![], specials: phashmap![],
}; };
session session
.send_rpc_arg(PTC_SYNC_HOLLOW_EVENT_INFO_ID, &finish_perform) .push_rpc_arg(PTC_SYNC_HOLLOW_EVENT_INFO_ID, finish_perform)
.await?; .await?;
let (ptc_hollow_grid, ptc_sync_hollow_event) = let (ptc_hollow_grid, ptc_sync_hollow_event) =
session.context.hollow_grid_manager.move_to(22, scene_uid); session.context.hollow_grid_manager.move_to(22, scene_uid);
session session
.send_rpc_arg(PTC_HOLLOW_GRID_ID, &ptc_hollow_grid) .push_rpc_arg(PTC_HOLLOW_GRID_ID, ptc_hollow_grid)
.await?; .await?;
if let Some(ptc_sync_hollow_event) = ptc_sync_hollow_event { if let Some(ptc_sync_hollow_event) = ptc_sync_hollow_event {
session session
.send_rpc_arg(PTC_SYNC_HOLLOW_EVENT_INFO_ID, &ptc_sync_hollow_event) .push_rpc_arg(PTC_SYNC_HOLLOW_EVENT_INFO_ID, ptc_sync_hollow_event)
.await?; .await?;
} }
} else { } else {
@ -178,15 +178,15 @@ pub async fn on_rpc_run_hollow_event_graph(
if !hollow_finished { if !hollow_finished {
session session
.send_rpc_arg(PTC_SYNC_HOLLOW_EVENT_INFO_ID, &sync_hollow_event) .push_rpc_arg(PTC_SYNC_HOLLOW_EVENT_INFO_ID, sync_hollow_event)
.await?; .await?;
} }
session session
.send_rpc_arg(PTC_HOLLOW_GRID_ID, &hollow_grid) .push_rpc_arg(PTC_HOLLOW_GRID_ID, hollow_grid)
.await?; .await?;
if hollow_finished { if hollow_finished {
let _ = *session let _ = session
.context .context
.dungeon_manager .dungeon_manager
.hollow_finished() .hollow_finished()
@ -202,7 +202,7 @@ pub async fn on_rpc_run_hollow_event_graph(
}; };
session session
.send_rpc_arg(PTC_DUNGEON_QUEST_FINISHED_ID, &ptc_dungeon_quest_finished) .push_rpc_arg(PTC_DUNGEON_QUEST_FINISHED_ID, ptc_dungeon_quest_finished)
.await?; .await?;
} }
@ -214,7 +214,7 @@ pub async fn on_rpc_run_hollow_event_graph(
.scene_uid .scene_uid
.as_ref() .as_ref()
.unwrap(); .unwrap();
let battle_scene_uid = *session let battle_scene_uid = session
.context .context
.dungeon_manager .dungeon_manager
.create_fight(trigger_battle_id, hollow_uid) .create_fight(trigger_battle_id, hollow_uid)
@ -231,14 +231,14 @@ pub async fn on_rpc_run_hollow_event_graph(
}; };
session session
.send_rpc_arg( .push_rpc_arg(
PTC_POSITION_IN_HOLLOW_CHANGED_ID, PTC_POSITION_IN_HOLLOW_CHANGED_ID,
&ptc_position_in_hollow_changed, ptc_position_in_hollow_changed,
) )
.await?; .await?;
session session
.send_rpc_arg( .push_rpc_arg(
PTC_ENTER_SCENE_ID, PTC_ENTER_SCENE_ID,
session session
.context .context
@ -288,7 +288,7 @@ pub async fn on_rpc_start_hollow_quest(
}; };
session session
.send_rpc_arg(PTC_PROPERTY_CHANGED_ID, &update_properties) .push_rpc_arg(PTC_PROPERTY_CHANGED_ID, update_properties)
.await?; .await?;
} }
@ -298,7 +298,7 @@ pub async fn on_rpc_start_hollow_quest(
.sorted_by_key(|kv| kv.0) .sorted_by_key(|kv| kv.0)
.map(|(_idx, uid)| *uid) .map(|(_idx, uid)| *uid)
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let (dungeon_uid, scene_uid) = *session let (dungeon_uid, scene_uid) = session
.context .context
.dungeon_manager .dungeon_manager
.create_hollow(10001, 10010001, &avatars) .create_hollow(10001, 10010001, &avatars)
@ -336,9 +336,9 @@ pub async fn on_rpc_start_hollow_quest(
session.context.hollow_grid_manager.init_default_map(); session.context.hollow_grid_manager.init_default_map();
session session
.send_rpc_arg( .push_rpc_arg(
PTC_SYNC_HOLLOW_GRID_MAPS_ID, PTC_SYNC_HOLLOW_GRID_MAPS_ID,
&session session
.context .context
.hollow_grid_manager .hollow_grid_manager
.sync_hollow_maps(session.player_uid().raw(), scene_uid), .sync_hollow_maps(session.player_uid().raw(), scene_uid),
@ -355,9 +355,9 @@ pub async fn on_rpc_start_hollow_quest(
}; };
session session
.send_rpc_arg( .push_rpc_arg(
PTC_POSITION_IN_HOLLOW_CHANGED_ID, PTC_POSITION_IN_HOLLOW_CHANGED_ID,
&ptc_position_in_hollow_changed, ptc_position_in_hollow_changed,
) )
.await?; .await?;
@ -380,11 +380,11 @@ pub async fn on_rpc_start_hollow_quest(
}; };
session session
.send_rpc_arg(PTC_SYNC_HOLLOW_EVENT_INFO_ID, &ptc_sync_hollow_event_info) .push_rpc_arg(PTC_SYNC_HOLLOW_EVENT_INFO_ID, ptc_sync_hollow_event_info)
.await?; .await?;
session session
.send_rpc_arg(PTC_ENTER_SCENE_ID, &ptc_enter_scene) .push_rpc_arg(PTC_ENTER_SCENE_ID, ptc_enter_scene)
.await?; .await?;
Ok(RpcStartHollowQuestRet::new()) Ok(RpcStartHollowQuestRet::new())
} }

View file

@ -39,6 +39,7 @@ macro_rules! protocol_handlers {
.instrument(tracing::info_span!(stringify!([<on_$name:snake>]), protocol_id = protocol_id)) .instrument(tracing::info_span!(stringify!([<on_$name:snake>]), protocol_id = protocol_id))
.await?; .await?;
session.flush_rpc_queue().await?;
session.send_rpc_ret(ret).await session.send_rpc_ret(ret).await
} }
)* )*

View file

@ -22,7 +22,7 @@ pub async fn on_rpc_mod_nick_name(
}; };
session session
.send_rpc_arg(PTC_PLAYER_INFO_CHANGED_ID, &player_info_changed) .push_rpc_arg(PTC_PLAYER_INFO_CHANGED_ID, player_info_changed)
.await?; .await?;
Ok(RpcModNickNameRet::new()) Ok(RpcModNickNameRet::new())
} }

View file

@ -56,7 +56,7 @@ pub async fn on_rpc_run_event_graph(
); );
session session
.send_rpc_arg(PTC_SYNC_EVENT_INFO_ID, &ptc_sync_event_info) .push_rpc_arg(PTC_SYNC_EVENT_INFO_ID, ptc_sync_event_info)
.await?; .await?;
Ok(RpcRunEventGraphRet::new()) Ok(RpcRunEventGraphRet::new())
@ -89,7 +89,7 @@ pub async fn on_rpc_finish_event_graph_perform_show(
); );
session session
.send_rpc_arg(PTC_SYNC_EVENT_INFO_ID, &ptc_sync_event_info) .push_rpc_arg(PTC_SYNC_EVENT_INFO_ID, ptc_sync_event_info)
.await?; .await?;
Ok(RpcFinishEventGraphPerformShowRet::new()) Ok(RpcFinishEventGraphPerformShowRet::new())
@ -152,7 +152,7 @@ pub async fn on_rpc_interact_with_unit(
); );
session session
.send_rpc_arg(PTC_SYNC_EVENT_INFO_ID, &ptc_sync_event_info) .push_rpc_arg(PTC_SYNC_EVENT_INFO_ID, ptc_sync_event_info)
.await?; .await?;
} }
@ -206,25 +206,25 @@ pub async fn enter_main_city(session: &NetworkSession) -> Result<()> {
let hall_scene_uid = session.context.dungeon_manager.get_default_scene_uid(); let hall_scene_uid = session.context.dungeon_manager.get_default_scene_uid();
session session
.send_rpc_arg( .push_rpc_arg(
PTC_ENTER_SECTION_ID, PTC_ENTER_SECTION_ID,
session session
.context .context
.dungeon_manager .dungeon_manager
.enter_scene_section(hall_scene_uid, 2) .enter_scene_section(hall_scene_uid, 2)
.unwrap(), .take(),
) )
.await?; .await?;
session session
.send_rpc_arg( .push_rpc_arg(
PTC_SYNC_SCENE_UNIT_ID, PTC_SYNC_SCENE_UNIT_ID,
&session.context.scene_unit_manager.sync(hall_scene_uid, 2), session.context.scene_unit_manager.sync(hall_scene_uid, 2),
) )
.await?; .await?;
session session
.send_rpc_arg( .push_rpc_arg(
PTC_ENTER_SCENE_ID, PTC_ENTER_SCENE_ID,
session session
.context .context
@ -305,24 +305,24 @@ pub async fn on_rpc_enter_world(
if CONFIGURATION.skip_tutorial { if CONFIGURATION.skip_tutorial {
Box::pin(enter_main_city(session)).await?; Box::pin(enter_main_city(session)).await?;
} else { } else {
let fresh_scene_uid = *session.context.dungeon_manager.create_fresh().unwrap(); let fresh_scene_uid = session.context.dungeon_manager.create_fresh().take();
session session
.send_rpc_arg( .push_rpc_arg(
PTC_ENTER_SCENE_ID, PTC_ENTER_SCENE_ID,
session session
.context .context
.dungeon_manager .dungeon_manager
.enter_scene(fresh_scene_uid) .enter_scene(fresh_scene_uid)
.unwrap() .unwrap()
.unwrap(), .take(),
) )
.await?; .await?;
} }
session session
.send_rpc_arg( .push_rpc_arg(
PTC_SYNC_SCENE_TIME_ID, PTC_SYNC_SCENE_TIME_ID,
&PtcSyncSceneTimeArg { PtcSyncSceneTimeArg {
timestamp: 3600 * 8 * 1000, timestamp: 3600 * 8 * 1000,
last_timestamp: 0, last_timestamp: 0,
}, },
@ -341,9 +341,9 @@ pub async fn on_rpc_reenter_world(
tracing::warn!("OnRpcReenterWorld: world re-entrance is not implemented yet, kicking player!"); tracing::warn!("OnRpcReenterWorld: world re-entrance is not implemented yet, kicking player!");
session session
.send_rpc_arg( .push_rpc_arg(
PTC_KICK_PLAYER_ID, PTC_KICK_PLAYER_ID,
&PtcKickPlayerArg { PtcKickPlayerArg {
reason_id: 2, reason_id: 2,
reason_str: String::new(), reason_str: String::new(),
}, },

View file

@ -1,6 +1,7 @@
use anyhow::Result; use anyhow::Result;
use protocol::{AccountInfo, PlayerInfo}; use protocol::{AccountInfo, PlayerInfo};
use qwer::{OctData, ProtocolHeader}; use qwer::{OctData, ProtocolHeader};
use std::collections::VecDeque;
use std::io::Cursor; use std::io::Cursor;
use std::sync::Arc; use std::sync::Arc;
use tokio::io::{AsyncReadExt, AsyncWriteExt}; use tokio::io::{AsyncReadExt, AsyncWriteExt};
@ -33,9 +34,12 @@ impl PlayerUID {
} }
} }
struct QueueItem(pub u16, pub Vec<u8>);
pub struct NetworkSession { pub struct NetworkSession {
client_socket: Arc<Mutex<TcpStream>>, client_socket: Arc<Mutex<TcpStream>>,
cur_rpc_uid: u64, cur_rpc_uid: u64,
outgoing_rpc_queue: Mutex<VecDeque<QueueItem>>,
pub ns_prop_mgr: net_stream::PropertyManager, pub ns_prop_mgr: net_stream::PropertyManager,
pub context: GameContext, pub context: GameContext,
account_uid: OnceCell<AccountUID>, account_uid: OnceCell<AccountUID>,
@ -49,6 +53,7 @@ impl NetworkSession {
Self { Self {
client_socket: Arc::new(Mutex::new(client_socket)), client_socket: Arc::new(Mutex::new(client_socket)),
cur_rpc_uid: 0, cur_rpc_uid: 0,
outgoing_rpc_queue: Mutex::new(VecDeque::new()),
context: GameContext::new(ns_prop_mgr.player_info.clone()), context: GameContext::new(ns_prop_mgr.player_info.clone()),
ns_prop_mgr, ns_prop_mgr,
account_uid: OnceCell::new(), account_uid: OnceCell::new(),
@ -108,13 +113,32 @@ impl NetworkSession {
} }
} }
pub async fn send_rpc_arg(&self, protocol_id: u16, data: &impl OctData) -> Result<()> { pub async fn push_rpc_arg(&self, protocol_id: u16, data: impl OctData) -> Result<()> {
let header: Vec<u8> = ProtocolHeader::default().into();
let mut payload = Vec::new(); let mut payload = Vec::new();
let mut cursor = Cursor::new(&mut payload); let mut cursor = Cursor::new(&mut payload);
data.marshal_to(&mut cursor, 0)?; data.marshal_to(&mut cursor, 0)?;
self.outgoing_rpc_queue
.lock()
.await
.push_back(QueueItem(protocol_id, payload));
Ok(())
}
pub async fn flush_rpc_queue(&self) -> Result<()> {
let mut queue = self.outgoing_rpc_queue.lock().await;
while let Some(QueueItem(protocol_id, payload)) = queue.pop_front() {
self.send_rpc_arg(protocol_id, payload).await?;
}
Ok(())
}
async fn send_rpc_arg(&self, protocol_id: u16, payload: Vec<u8>) -> Result<()> {
let header: Vec<u8> = ProtocolHeader::default().into();
let body: Vec<u8> = RequestBody { let body: Vec<u8> = RequestBody {
protocol_id, protocol_id,
payload, payload,