use rand::RngCore; use save::PlayerSaveData; use crate::{ allocator, logic::{ avatar::LogicClientAvatar, data::{LogicDataTables, LogicNpcData}, math::LogicLong, mode::LogicGameMode, }, network::{message::PiranhaMessage, Messaging}, resources, }; mod handlers; mod protocol_util; mod save; pub struct PlayerSession { messaging: Messaging, pub account_id: Option, pub player_save_data: Option, pub logic_game_mode: Option<&'static mut LogicGameMode>, } impl PlayerSession { pub fn new(messaging: Messaging) -> Self { Self { messaging, account_id: None, player_save_data: None, logic_game_mode: None, } } pub fn send_message(&self, message: *const T) { self.messaging.send(message); } pub fn go_home(&mut self) { self.destruct_game_mode(); let player_save_data = self.player_save_data.as_ref().unwrap(); let logic_client_home = player_save_data.get_logic_client_home(); let logic_client_avatar = player_save_data.get_logic_client_avatar(); let random_seed = rand::rng().next_u32() as i32; let own_home_data_message = protocol_util::build_own_home_data(logic_client_home, logic_client_avatar, random_seed); let logic_game_mode = LogicGameMode::new(false); logic_game_mode.load_home_state(logic_client_home, logic_client_avatar, 0, -1, random_seed); self.logic_game_mode = Some(logic_game_mode); self.send_message(own_home_data_message); } pub fn start_mission(&mut self, npc: &'static LogicNpcData) { const TRAINING_ARENA_ID: i32 = 54000001; self.destruct_game_mode(); resources::prepare_location_data(npc.location); let arena = LogicDataTables::get_data_by_id(TRAINING_ARENA_ID).unwrap(); let player_save_data = self.player_save_data.as_ref().unwrap(); let player_avatar = player_save_data.get_logic_client_avatar(); let player_deck = player_save_data.get_spell_deck(); let npc_deck = player_deck.clone(); let npc_avatar = LogicClientAvatar::new(); npc_avatar.id.set(-1, -1); npc_avatar.account_id.set(-1, -1); npc_avatar.home_id.set(-1, -1); npc_avatar.arena = arena; npc_avatar.level = player_avatar.level; let battle_mode = LogicGameMode::new(true); let battle = battle_mode.battle.get_mut().unwrap(); battle.set_location(npc.location, false, 0); battle.battle_type = 1; battle.npc_data = npc; battle.arena_data = arena; battle.set_spell_decks(player_deck, npc_deck); battle_mode.add_player(player_avatar); battle_mode.add_player(npc_avatar); let sector_state_message = protocol_util::build_sector_state(battle_mode, player_avatar); self.logic_game_mode = Some(battle_mode); self.send_message(sector_state_message); } pub fn destruct_game_mode(&mut self) { if let Some(logic_game_mode) = self.logic_game_mode.take() { logic_game_mode.destruct(); allocator::free(logic_game_mode); } } pub fn work_until_disconnect(&mut self) { while self.messaging.get_connection().is_connected { self.messaging.on_receive(self.messaging.get_connection()); while let Some(message) = self.messaging.next_message() { self.receive_message(message); } } } fn receive_message(&mut self, message: &PiranhaMessage) { handlers::handle_message(self, message); self.messaging.on_wakeup(self.messaging.get_connection()); } }