trigger-rs/crates/battle-server/src/server_message_handler.rs
2025-02-21 14:03:43 +03:00

166 lines
4.7 KiB
Rust

use tokio::sync::Mutex;
use tracing::{debug, error, warn};
use trigger_protocol::EnterSceneScNotify;
use trigger_sv::{
message::{
BindClientSessionMessage, BindClientSessionOkMessage, ChangeGameStateMessage,
ForwardClientProtocolMessage, GameStateCallback, GameStateCallbackMessage, Header,
UnbindClientSessionMessage, WithOpcode,
},
net::ServerType,
};
use crate::{logic::GameState, session::BattleSession, AppState};
pub async fn handle_message(state: &'static AppState, packet: trigger_sv::message::NetworkPacket) {
match packet.opcode {
BindClientSessionMessage::OPCODE => {
if let Some(message) = packet.get_message() {
on_bind_client_session(state, packet.header, message).await;
}
}
UnbindClientSessionMessage::OPCODE => {
if let Some(message) = packet.get_message() {
on_unbind_client_session(state, packet.header, message).await;
}
}
ChangeGameStateMessage::OPCODE => {
if let Some(message) = packet.get_message() {
on_change_game_state(state, packet.header, message).await;
}
}
ForwardClientProtocolMessage::OPCODE => {
if let Some(message) = packet.get_message() {
on_forward_client_message(state, packet.header, message).await;
}
}
opcode => warn!("unhandled server message, opcode: {opcode}"),
}
}
async fn on_change_game_state(
state: &'static AppState,
_header: Header,
message: ChangeGameStateMessage,
) {
let Some(session) = state.sessions.get(&message.session_id) else {
return;
};
let mut session = session.lock().await;
debug!(
"changing game state for player with uid {}, request: {:?}",
session.player_uid, message
);
let Some(game_state) = GameState::new(&state.filecfg, &message.data) else {
error!("unsupported game state data received: {:?}", message.data);
return;
};
debug!(
"created fight scene for player with uid {}: quest_id: {}, play_type: {:?}",
session.player_uid,
game_state.dungeon.quest_id,
game_state.scene.get_play_type()
);
let enter_scene_notify = EnterSceneScNotify {
scene_info: Some(game_state.scene.get_protocol_scene_info()),
dungeon_info: Some(game_state.dungeon.get_protocol_dungeon_info()),
};
session.game_state = Some(game_state);
state
.network_mgr
.send_to(
ServerType::GameServer,
0,
GameStateCallbackMessage {
session_id: session.id,
protocol_units: vec![enter_scene_notify.into()],
scene_save_data: None,
callback: GameStateCallback::Loaded,
},
)
.await;
}
async fn on_forward_client_message(
state: &'static AppState,
_header: Header,
message: ForwardClientProtocolMessage,
) {
let Some(session) = state.sessions.get(&message.session_id) else {
return;
};
let mut session = session.lock().await;
for callback in crate::session::message::handle_client_message(
&mut session,
message.request_id,
message.message,
) {
state
.network_mgr
.send_to(
ServerType::GameServer,
0,
GameStateCallbackMessage {
session_id: session.id,
protocol_units: Vec::new(),
scene_save_data: None,
callback,
},
)
.await;
}
}
async fn on_unbind_client_session(
state: &'static AppState,
_header: Header,
message: UnbindClientSessionMessage,
) {
if let Some((_, session)) = state.sessions.remove(&message.session_id) {
let session = session.lock().await;
debug!(
"unregistered session with id {} (player_uid: {})",
session.id, session.player_uid
);
}
}
async fn on_bind_client_session(
state: &'static AppState,
header: Header,
message: BindClientSessionMessage,
) {
state.sessions.insert(
message.session_id,
Mutex::new(BattleSession {
id: message.session_id,
player_uid: message.player_uid,
game_state: None,
}),
);
debug!(
"registered new session, id: {}, player_uid: {}",
message.session_id, message.player_uid
);
state
.network_mgr
.send_to(
header.sender_type.try_into().unwrap(),
header.sender_id,
BindClientSessionOkMessage {
session_id: message.session_id,
},
)
.await;
}