diff --git a/src/ship/mod.rs b/src/ship/mod.rs index 4b6b4d0..c0b74b2 100644 --- a/src/ship/mod.rs +++ b/src/ship/mod.rs @@ -7,3 +7,4 @@ pub mod item_stats; pub mod map; pub mod monster; pub mod drops; +pub mod packet; diff --git a/src/ship/packet/builder/mod.rs b/src/ship/packet/builder/mod.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/ship/packet/handler/lobby.rs b/src/ship/packet/handler/lobby.rs new file mode 100644 index 0000000..9efe3bd --- /dev/null +++ b/src/ship/packet/handler/lobby.rs @@ -0,0 +1,101 @@ +use std::collections::HashMap; +use libpso::packet::ship::*; +use crate::common::serverstate::ClientId; +use crate::common::leveltable::CharacterLevelTable; +use crate::ship::ship::{SendShipPacket, ShipError, ClientState}; +use crate::ship::character::{CharacterBytesBuilder, FullCharacterBytesBuilder}; +use crate::ship::location::{ClientLocation, LobbyId, RoomId, RoomLobby, MAX_ROOMS}; +use libpso::character::character; + + +pub fn send_player_to_lobby(id: ClientId, + _pkt: &CharData, + client_location: &mut ClientLocation, + clients: &HashMap, + level_table: &CharacterLevelTable) -> Result, ShipError> { + let lobby = client_location.add_client_to_next_available_lobby(id, LobbyId(0)).map_err(|_| ShipError::TooManyClients)?; + let lobby_clients = client_location.get_clients_in_lobby(lobby).map_err(|err| ShipError::ClientError(format!("{:?}", err)))?; + let playerinfo = lobby_clients.iter() + .map(|room_client| { + let client = clients.get(&room_client.client).ok_or(ShipError::ClientNotFound(id)).unwrap(); + let (level, stats) = level_table.get_stats_from_exp(client.character.char_class, client.character.exp); + let c = CharacterBytesBuilder::new() + .character(&client.character) + .stats(&stats) + .level(level - 1) + .build(); + PlayerInfo { + header: PlayerHeader { + tag: 0x100, + guildcard: client.user.id.0, + _unknown1: [0; 5], + client_id: room_client.local_client.id() as u32, + name: c.name, + _unknown2: 2, + }, + inventory: character::Inventory { + item_count: 0, + hp_mats_used: 0, + tp_mats_used: 0, + language: 0, + items: [character::InventoryItem::default(); 30], + }, + character: c, + } + }); + let area_client = client_location.get_local_client(id).map_err(|err| ShipError::ClientError(format!("{:?}", err)))?; + let leader = client_location.get_lobby_leader(lobby).map_err(|err| ShipError::ClientError(format!("{:?}", err)))?; + + let join_lobby = JoinLobby { + client: area_client.local_client.id(), + leader: leader.local_client.id(), + one: 1, + lobby: lobby.id(), + block: 1, + event: 0, + padding: 0, + playerinfo: playerinfo.collect(), + }; + + let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id))?; + let (level, stats) = level_table.get_stats_from_exp(client.character.char_class, client.character.exp); + let c = CharacterBytesBuilder::new() + .character(&client.character) + .stats(&stats) + .level(level - 1) + .build(); + let addto = AddToLobby { + flag: 1, + client: area_client.local_client.id(), + leader: leader.local_client.id(), + one: 1, + lobby: lobby.id(), + block: 1, + event: 0, + padding: 0, + playerinfo: PlayerInfo { + header: PlayerHeader { + tag: 0x100, + guildcard: client.user.id.0, + _unknown1: [0; 5], + client_id: area_client.local_client.id() as u32, + name: c.name, + _unknown2: 2, + }, + inventory: character::Inventory { + item_count: 0, + hp_mats_used: 0, + tp_mats_used: 0, + language: 0, + items: [character::InventoryItem::default(); 30], + }, + character: c, + }, + }; + + let neighbors = client_location.get_client_neighbors(id).unwrap(); + Ok(vec![(id, SendShipPacket::JoinLobby(join_lobby))] + .into_iter() + .chain(neighbors.into_iter() + .map(|c| (c.client, SendShipPacket::AddToLobby(addto.clone())))).collect()) +} diff --git a/src/ship/packet/handler/mod.rs b/src/ship/packet/handler/mod.rs new file mode 100644 index 0000000..36bd53c --- /dev/null +++ b/src/ship/packet/handler/mod.rs @@ -0,0 +1 @@ +pub mod lobby; diff --git a/src/ship/packet/mod.rs b/src/ship/packet/mod.rs new file mode 100644 index 0000000..5b46ce1 --- /dev/null +++ b/src/ship/packet/mod.rs @@ -0,0 +1,2 @@ +pub mod builder; +pub mod handler; diff --git a/src/ship/ship.rs b/src/ship/ship.rs index 483e61c..709805f 100644 --- a/src/ship/ship.rs +++ b/src/ship/ship.rs @@ -25,6 +25,7 @@ use crate::ship::location::{ClientLocation, LobbyId, RoomId, RoomLobby, MAX_ROOM use crate::ship::character::{CharacterBytesBuilder, FullCharacterBytesBuilder}; use crate::ship::items; use crate::ship::room; +use crate::ship::packet::handler; pub const SHIP_PORT: u16 = 23423; @@ -133,10 +134,10 @@ impl SendServerPacket for SendShipPacket { } } -struct ClientState { - user: UserAccountEntity, +pub struct ClientState { + pub user: UserAccountEntity, settings: UserSettingsEntity, - character: CharacterEntity, + pub character: CharacterEntity, session: Session, //guildcard: GuildCard, inventory: items::ActiveInventory, @@ -337,93 +338,6 @@ impl ShipServerState { } } - fn send_player_to_lobby(&mut self, id: ClientId, _pkt: &CharData) -> Result, ShipError> { - let lobby = self.client_location.add_client_to_next_available_lobby(id, LobbyId(0)).map_err(|_| ShipError::TooManyClients)?; - let clients = self.client_location.get_clients_in_lobby(lobby).map_err(|err| ShipError::ClientError(format!("{:?}", err)))?; - let playerinfo = clients.iter() - .map(|room_client| { - let client = self.clients.get(&room_client.client).ok_or(ShipError::ClientNotFound(id)).unwrap(); - let (level, stats) = self.level_table.get_stats_from_exp(client.character.char_class, client.character.exp); - let c = CharacterBytesBuilder::new() - .character(&client.character) - .stats(&stats) - .level(level - 1) - .build(); - PlayerInfo { - header: PlayerHeader { - tag: 0x100, - guildcard: client.user.id.0, - _unknown1: [0; 5], - client_id: room_client.local_client.id() as u32, - name: c.name, - _unknown2: 2, - }, - inventory: character::Inventory { - item_count: 0, - hp_mats_used: 0, - tp_mats_used: 0, - language: 0, - items: [character::InventoryItem::default(); 30], - }, - character: c, - } - }); - let area_client = self.client_location.get_local_client(id).map_err(|err| ShipError::ClientError(format!("{:?}", err)))?; - let leader = self.client_location.get_lobby_leader(lobby).map_err(|err| ShipError::ClientError(format!("{:?}", err)))?; - - let join_lobby = JoinLobby { - client: area_client.local_client.id(), - leader: leader.local_client.id(), - one: 1, - lobby: lobby.id(), - block: 1, - event: 0, - padding: 0, - playerinfo: playerinfo.collect(), - }; - - let client = self.clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?; - let (level, stats) = self.level_table.get_stats_from_exp(client.character.char_class, client.character.exp); - let c = CharacterBytesBuilder::new() - .character(&client.character) - .stats(&stats) - .level(level - 1) - .build(); - let addto = AddToLobby { - flag: 1, - client: area_client.local_client.id(), - leader: leader.local_client.id(), - one: 1, - lobby: lobby.id(), - block: 1, - event: 0, - padding: 0, - playerinfo: PlayerInfo { - header: PlayerHeader { - tag: 0x100, - guildcard: client.user.id.0, - _unknown1: [0; 5], - client_id: area_client.local_client.id() as u32, - name: c.name, - _unknown2: 2, - }, - inventory: character::Inventory { - item_count: 0, - hp_mats_used: 0, - tp_mats_used: 0, - language: 0, - items: [character::InventoryItem::default(); 30], - }, - character: c, - }, - }; - - let neighbors = self.client_location.get_client_neighbors(id).unwrap(); - Ok(vec![(id, SendShipPacket::JoinLobby(join_lobby))] - .into_iter() - .chain(neighbors.into_iter() - .map(|c| (c.client, SendShipPacket::AddToLobby(addto.clone())))).collect()) - } fn done_bursting(&mut self, id: ClientId) -> Box + Send> { let area = self.client_location.get_area(id).unwrap(); @@ -694,7 +608,7 @@ impl ServerState for ShipServerState { } }, RecvShipPacket::CharData(chardata) => { - Box::new(self.send_player_to_lobby(id, chardata)?.into_iter()) + Box::new(handler::lobby::send_player_to_lobby(id, chardata, &mut self.client_location, &self.clients, &self.level_table)?.into_iter()) }, RecvShipPacket::Message(msg) => { self.message(id, msg)