Refactor PlayerSession, in-game lineup editing

This commit is contained in:
xeon 2024-03-29 23:39:42 +03:00
parent dfffe1612e
commit a856f719f0
14 changed files with 231 additions and 86 deletions

View file

@ -1,2 +1,5 @@
mod global_config;
mod player_info;
pub use global_config::INSTANCE as globals;
pub use player_info::PlayerInfo;

View file

@ -0,0 +1,57 @@
use crate::net::PlayerSession;
use super::globals;
use anyhow::Result;
use proto::*;
pub struct PlayerInfo {
pub lineup: LineupInfo,
}
impl PlayerInfo {
pub fn new() -> Self {
Self {
lineup: default_lineup(),
}
}
pub async fn sync_lineup(&self, session: &PlayerSession) -> Result<()> {
session
.send(
CMD_SYNC_LINEUP_NOTIFY,
SyncLineupNotify {
lineup: Some(self.lineup.clone()),
..Default::default()
},
)
.await
}
}
fn default_lineup() -> LineupInfo {
LineupInfo {
plane_id: 10001,
name: String::from("Lineup 1"),
index: 0,
leader_slot: 0,
mp: 5,
mp_max: 5,
avatar_list: globals
.lineup
.iter()
.enumerate()
.map(|(idx, id)| LineupAvatar {
id: *id,
slot: idx as u32,
hp: 10000,
sp: Some(AmountInfo {
cur_amount: 10000,
max_amount: 10000,
}),
satiety: 100,
avatar_type: 3,
})
.collect(),
..Default::default()
}
}

View file

@ -4,7 +4,7 @@ use proto::*;
use crate::{net::PlayerSession, util};
pub async fn on_player_get_token_cs_req(
session: &mut PlayerSession,
session: &PlayerSession,
_body: &PlayerGetTokenCsReq,
) -> Result<()> {
session
@ -21,7 +21,7 @@ pub async fn on_player_get_token_cs_req(
}
pub async fn on_player_login_cs_req(
session: &mut PlayerSession,
session: &PlayerSession,
body: &PlayerLoginCsReq,
) -> Result<()> {
session

View file

@ -8,7 +8,7 @@ static UNLOCKED_AVATARS: [u32; 49] = [
];
pub async fn on_get_avatar_data_cs_req(
session: &mut PlayerSession,
session: &PlayerSession,
body: &GetAvatarDataCsReq,
) -> Result<()> {
session

View file

@ -2,9 +2,11 @@ use super::*;
use crate::game::globals;
pub async fn on_start_cocoon_stage_cs_req(
session: &mut PlayerSession,
session: &PlayerSession,
body: &StartCocoonStageCsReq,
) -> Result<()> {
let player_info = session.player_info();
let rsp = StartCocoonStageScRsp {
retcode: 0,
prop_entity_id: body.prop_entity_id,
@ -14,13 +16,13 @@ pub async fn on_start_cocoon_stage_cs_req(
stage_id: 201012311,
logic_random_seed: 4444,
battle_id: 1,
battle_avatar_list: globals
battle_avatar_list: player_info
.lineup
.avatar_list
.iter()
.enumerate()
.map(|(idx, id)| BattleAvatar {
index: idx as u32,
id: *id,
.map(|avatar| BattleAvatar {
index: avatar.slot,
id: avatar.id,
level: 80,
promotion: 6,
rank: 6,
@ -55,7 +57,7 @@ pub async fn on_start_cocoon_stage_cs_req(
}
pub async fn on_pve_battle_result_cs_req(
session: &mut PlayerSession,
session: &PlayerSession,
body: &PveBattleResultCsReq,
) -> Result<()> {
session

View file

@ -1,86 +1,47 @@
use super::*;
use crate::game::globals;
pub async fn on_get_all_lineup_data_cs_req(
session: &mut PlayerSession,
session: &PlayerSession,
_body: &GetAllLineupDataCsReq,
) -> Result<()> {
let player_info = session.player_info();
session
.send(
CMD_GET_ALL_LINEUP_DATA_SC_RSP,
GetAllLineupDataScRsp {
retcode: 0,
cur_index: 0,
lineup_list: vec![LineupInfo {
plane_id: 10001,
name: String::from("Lineup 1"),
index: 0,
avatar_list: globals
.lineup
.iter()
.enumerate()
.map(|(idx, id)| LineupAvatar {
id: *id,
slot: idx as u32,
hp: 10000,
sp: Some(AmountInfo {
cur_amount: 10000,
max_amount: 10000,
}),
satiety: 100,
avatar_type: 3,
})
.collect(),
..Default::default()
}],
lineup_list: vec![player_info.lineup.clone()],
},
)
.await
}
pub async fn on_get_cur_lineup_data_cs_req(
session: &mut PlayerSession,
session: &PlayerSession,
_body: &GetCurLineupDataCsReq,
) -> Result<()> {
let player_info = session.player_info();
session
.send(
CMD_GET_CUR_LINEUP_DATA_SC_RSP,
GetCurLineupDataScRsp {
retcode: 0,
lineup: Some(LineupInfo {
plane_id: 10001,
name: String::from("Lineup 1"),
index: 0,
leader_slot: 0,
mp: 5,
mp_max: 5,
avatar_list: globals
.lineup
.iter()
.enumerate()
.map(|(idx, id)| LineupAvatar {
id: *id,
slot: idx as u32,
hp: 10000,
sp: Some(AmountInfo {
cur_amount: 10000,
max_amount: 10000,
}),
satiety: 100,
avatar_type: 3,
})
.collect(),
..Default::default()
}),
lineup: Some(player_info.lineup.clone()),
},
)
.await
}
pub async fn on_change_lineup_leader_cs_req(
session: &mut PlayerSession,
session: &PlayerSession,
body: &ChangeLineupLeaderCsReq,
) -> Result<()> {
let mut player_info = session.player_info_mut();
player_info.lineup.leader_slot = body.slot;
session
.send(
CMD_CHANGE_LINEUP_LEADER_SC_RSP,
@ -91,3 +52,101 @@ pub async fn on_change_lineup_leader_cs_req(
)
.await
}
pub async fn on_join_lineup_cs_req(session: &PlayerSession, body: &JoinLineupCsReq) -> Result<()> {
let mut player_info = session.player_info_mut();
if !(0..4).contains(&body.slot) {
return session
.send(
CMD_JOIN_LINEUP_CS_REQ,
JoinLineupScRsp {
retcode: Retcode::RetLineupInvalidMemberPos as u32,
},
)
.await;
}
if player_info
.lineup
.avatar_list
.iter()
.any(|avatar| avatar.slot == body.slot)
{
return session
.send(
CMD_JOIN_LINEUP_CS_REQ,
JoinLineupScRsp {
retcode: Retcode::RetLineupAvatarAlreadyInit as u32,
},
)
.await;
}
player_info
.lineup
.avatar_list
.push(lineup_avatar(body.base_avatar_id, body.slot));
player_info.sync_lineup(session).await?;
session
.send(CMD_JOIN_LINEUP_SC_RSP, JoinLineupScRsp::default())
.await
}
pub async fn on_replace_lineup_cs_req(
session: &PlayerSession,
body: &ReplaceLineupCsReq,
) -> Result<()> {
let mut player_info = session.player_info_mut();
player_info.lineup.avatar_list.clear();
for slot_info in &body.lineup_slots {
player_info
.lineup
.avatar_list
.push(lineup_avatar(slot_info.id, slot_info.slot));
}
player_info.lineup.leader_slot = body.leader_slot;
player_info.sync_lineup(session).await?;
session
.send(CMD_REPLACE_LINEUP_SC_RSP, ReplaceLineupScRsp::default())
.await
}
pub async fn on_quit_lineup_cs_req(session: &PlayerSession, body: &QuitLineupCsReq) -> Result<()> {
let mut player_info = session.player_info_mut();
player_info
.lineup
.avatar_list
.retain(|avatar| avatar.id != body.base_avatar_id);
player_info.sync_lineup(session).await?;
session
.send(
CMD_QUIT_LINEUP_SC_RSP,
QuitLineupScRsp {
plane_id: body.plane_id,
is_mainline: !body.is_virtual,
is_virtual: body.is_virtual,
base_avatar_id: body.base_avatar_id,
retcode: 0,
},
)
.await
}
fn lineup_avatar(id: u32, slot: u32) -> LineupAvatar {
LineupAvatar {
id,
slot,
hp: 10000,
sp: Some(AmountInfo {
cur_amount: 10000,
max_amount: 10000,
}),
satiety: 100,
avatar_type: 3,
}
}

View file

@ -41,7 +41,7 @@ static FINISHED_MAIN_MISSIONS: [u32; 365] = [
];
pub async fn on_get_mission_status_cs_req(
session: &mut PlayerSession,
session: &PlayerSession,
body: &GetMissionStatusCsReq,
) -> Result<()> {
let rsp = GetMissionStatusScRsp {

View file

@ -46,7 +46,7 @@ macro_rules! dummy {
}
}
pub async fn send_dummy_response(&mut self, req_id: u16) -> Result<()> {
pub async fn send_dummy_response(&self, req_id: u16) -> Result<()> {
let cmd_type = match req_id {
$(
x if x == [<Cmd $cmd CsReq>] as u16 => [<Cmd $cmd ScRsp>] as u16,
@ -61,7 +61,7 @@ macro_rules! dummy {
}
.into();
self.client_socket.write_all(&payload).await?;
self.client_socket().await.write_all(&payload).await?;
Ok(())
}

View file

@ -3,7 +3,7 @@ use crate::util;
use super::*;
pub async fn on_get_basic_info_cs_req(
session: &mut PlayerSession,
session: &PlayerSession,
_body: &GetBasicInfoCsReq,
) -> Result<()> {
session
@ -19,7 +19,7 @@ pub async fn on_get_basic_info_cs_req(
}
pub async fn on_get_hero_basic_type_info_cs_req(
session: &mut PlayerSession,
session: &PlayerSession,
_body: &GetHeroBasicTypeInfoCsReq,
) -> Result<()> {
session
@ -40,7 +40,7 @@ pub async fn on_get_hero_basic_type_info_cs_req(
}
pub async fn on_player_heart_beat_cs_req(
session: &mut PlayerSession,
session: &PlayerSession,
body: &PlayerHeartBeatCsReq,
) -> Result<()> {
session

View file

@ -1,7 +1,7 @@
use super::*;
pub async fn on_get_cur_scene_info_cs_req(
session: &mut PlayerSession,
session: &PlayerSession,
_body: &GetCurSceneInfoCsReq,
) -> Result<()> {
session

View file

@ -8,7 +8,7 @@ static TUTORIAL_IDS: [u32; 55] = [
];
pub async fn on_get_tutorial_cs_req(
session: &mut PlayerSession,
session: &PlayerSession,
_body: &GetTutorialCsReq,
) -> Result<()> {
session
@ -29,7 +29,7 @@ pub async fn on_get_tutorial_cs_req(
}
pub async fn on_get_tutorial_guide_cs_req(
session: &mut PlayerSession,
session: &PlayerSession,
_body: &GetTutorialGuideCsReq,
) -> Result<()> {
session
@ -44,7 +44,7 @@ pub async fn on_get_tutorial_guide_cs_req(
}
pub async fn on_unlock_tutorial_guide_cs_req(
session: &mut PlayerSession,
session: &PlayerSession,
body: &UnlockTutorialGuideCsReq,
) -> Result<()> {
session

View file

@ -62,13 +62,13 @@ macro_rules! trait_handler {
pub trait CommandHandler {
$(
paste! {
async fn [<on_$name:snake>](session: &mut PlayerSession, body: &$name) -> Result<()> {
async fn [<on_$name:snake>](session: &PlayerSession, body: &$name) -> Result<()> {
[<on_$name:snake>](session, body).await
}
}
)*
async fn on_message(session: &mut PlayerSession, cmd_type: u16, payload: Vec<u8>) -> Result<()> {
async fn on_message(session: &PlayerSession, cmd_type: u16, payload: Vec<u8>) -> Result<()> {
use ::prost::Message;
if PlayerSession::should_send_dummy_rsp(cmd_type) {
session.send_dummy_response(cmd_type).await?;
@ -641,18 +641,18 @@ trait_handler! {
// ExtraLineupDestroyNotify 763;
// GetLineupAvatarDataCsReq 768;
// SwitchLineupIndexScRsp 795;
// JoinLineupCsReq 702;
JoinLineupCsReq 702;
// GetAllLineupDataScRsp 716;
// SetLineupNameCsReq 742;
// ChangeLineupLeaderScRsp 733;
ChangeLineupLeaderCsReq 706;
// ReplaceLineupCsReq 785;
ReplaceLineupCsReq 785;
// SwapLineupCsReq 786;
// QuitLineupScRsp 743;
// GetLineupAvatarDataScRsp 796;
// ReplaceLineupScRsp 756;
// GetStageLineupCsReq 734;
// QuitLineupCsReq 719;
QuitLineupCsReq 719;
// SetLineupNameScRsp 737;
// SwitchLineupIndexCsReq 759;
GetCurLineupDataCsReq 762;

View file

@ -1,26 +1,38 @@
use anyhow::Result;
use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut};
use prost::Message;
use tokio::{io::AsyncWriteExt, net::TcpStream};
use std::sync::Arc;
use tokio::{
io::AsyncWriteExt,
net::TcpStream,
sync::{Mutex, MutexGuard},
};
use crate::game::PlayerInfo;
use super::{packet::CommandHandler, NetPacket};
pub struct PlayerSession {
pub(crate) client_socket: TcpStream,
client_socket: Arc<Mutex<TcpStream>>,
player_info: Arc<AtomicRefCell<PlayerInfo>>,
}
impl PlayerSession {
pub const fn new(client_socket: TcpStream) -> Self {
Self { client_socket }
pub fn new(client_socket: TcpStream) -> Self {
Self {
client_socket: Arc::new(Mutex::new(client_socket)),
player_info: Arc::new(AtomicRefCell::new(PlayerInfo::new())),
}
}
pub async fn run(&mut self) -> Result<()> {
loop {
let net_packet = NetPacket::read(&mut self.client_socket).await?;
let net_packet = NetPacket::read(&mut *self.client_socket().await).await?;
Self::on_message(self, net_packet.cmd_type, net_packet.body).await?;
}
}
pub async fn send(&mut self, cmd_type: u16, body: impl Message) -> Result<()> {
pub async fn send(&self, cmd_type: u16, body: impl Message) -> Result<()> {
let mut buf = Vec::new();
body.encode(&mut buf)?;
@ -31,9 +43,21 @@ impl PlayerSession {
}
.into();
self.client_socket.write_all(&payload).await?;
self.client_socket().await.write_all(&payload).await?;
Ok(())
}
pub async fn client_socket(&self) -> MutexGuard<'_, TcpStream> {
self.client_socket.lock().await
}
pub fn player_info(&self) -> AtomicRef<PlayerInfo> {
self.player_info.borrow()
}
pub fn player_info_mut(&self) -> AtomicRefMut<PlayerInfo> {
self.player_info.borrow_mut()
}
}
// Auto implemented

View file

@ -9165,7 +9165,7 @@ pub struct VirtualLineupDestroyNotify {
#[derive(serde::Serialize, serde::Deserialize)]
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct Kcllnhmojig {
pub struct LineupSlotInfo {
#[prost(uint32, tag = "11")]
pub slot: u32,
#[prost(enumeration = "AvatarType", tag = "14")]
@ -9182,13 +9182,13 @@ pub struct ReplaceLineupCsReq {
#[prost(uint32, tag = "6")]
pub djdbkfnekpf: u32,
#[prost(uint32, tag = "12")]
pub hpammbapokf: u32,
pub leader_slot: u32,
#[prost(bool, tag = "10")]
pub is_virtual: bool,
#[prost(uint32, tag = "2")]
pub plane_id: u32,
#[prost(message, repeated, tag = "5")]
pub jkifflmenfn: ::prost::alloc::vec::Vec<Kcllnhmojig>,
pub lineup_slots: ::prost::alloc::vec::Vec<LineupSlotInfo>,
#[prost(enumeration = "ExtraLineupType", tag = "9")]
pub extra_lineup_type: i32,
}