diff --git a/src/ship/packet/builder/lobby.rs b/src/ship/packet/builder/lobby.rs new file mode 100644 index 0000000..56aaf66 --- /dev/null +++ b/src/ship/packet/builder/lobby.rs @@ -0,0 +1,92 @@ +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, AreaClient}; +use crate::entity::character::CharacterEntity; +use crate::ship::items::{ActiveInventory}; +use libpso::character::character::{Inventory, InventoryItem}; +use libpso::utf8_to_utf16_array; + +fn player_header(tag: u32, client: &ClientState, area_client: &AreaClient) -> PlayerHeader { + PlayerHeader { + tag: tag, + guildcard: client.user.id.0, + _unknown1: [0; 5], + client_id: area_client.local_client.id() as u32, + name: libpso::utf8_to_utf16_array!(client.character.name, 16), + _unknown2: 2, + } +} + +fn player_info(tag: u32, client: &ClientState, area_client: &AreaClient, level_table: &CharacterLevelTable) -> PlayerInfo { + let (level, stats) = level_table.get_stats_from_exp(client.character.char_class, client.character.exp); + let character = CharacterBytesBuilder::new() + .character(&client.character) + .stats(&stats) + .level(level - 1) + .build(); + PlayerInfo { + header: player_header(tag, client, area_client), + inventory: Inventory { + item_count: client.inventory.count() as u8, + hp_mats_used: 0, // TODO: materials + tp_mats_used: 0, // TODO: materials + language: 0, // TODO: account language + items: client.inventory.as_client_inventory_items(), + }, + character: character, + } +} + +pub fn join_lobby(id: ClientId, + lobby: LobbyId, + client_location: &ClientLocation, + clients: &HashMap, + level_table: &CharacterLevelTable) + -> Result { + let lobby_clients = client_location.get_clients_in_lobby(lobby).map_err(|err| ShipError::ClientError(format!("{:?}", err)))?; + let playerinfo = lobby_clients.iter() + .map(|area_client| { + let client = clients.get(&area_client.client).ok_or(ShipError::ClientNotFound(area_client.client)).unwrap(); + player_info(0x100, &client, area_client, level_table) + }); + + let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id)).unwrap(); + 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)))?; + Ok(JoinLobby { + client: area_client.local_client.id(), + leader: leader.local_client.id(), + one: 1, + lobby: lobby.id(), + block: client.block as u16, + event: 0, + padding: 0, + playerinfo: playerinfo.collect(), + }) +} + +pub fn add_to_lobby(id: ClientId, + lobby: LobbyId, + client_location: &ClientLocation, + clients: &HashMap, + level_table: &CharacterLevelTable) + -> Result { + let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id)).unwrap(); + 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)))?; + Ok(AddToLobby { + flag: 1, + client: area_client.local_client.id(), + leader: leader.local_client.id(), + one: 1, + lobby: lobby.id(), + block: client.block as u16, + event: 0, + padding: 0, + playerinfo: player_info(0x100, &client, &area_client, level_table), + }) +} diff --git a/src/ship/packet/builder/mod.rs b/src/ship/packet/builder/mod.rs index e69de29..36bd53c 100644 --- a/src/ship/packet/builder/mod.rs +++ b/src/ship/packet/builder/mod.rs @@ -0,0 +1 @@ +pub mod lobby; diff --git a/src/ship/packet/handler/lobby.rs b/src/ship/packet/handler/lobby.rs index 9b48e12..dcc627d 100644 --- a/src/ship/packet/handler/lobby.rs +++ b/src/ship/packet/handler/lobby.rs @@ -5,6 +5,7 @@ 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 crate::ship::packet; use libpso::character::character; // this function needs a better home @@ -44,84 +45,8 @@ pub fn send_player_to_lobby(id: ClientId, 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 join_lobby = packet::builder::lobby::join_lobby(id, lobby, client_location, clients, level_table)?; + let addto = packet::builder::lobby::add_to_lobby(id, lobby, client_location, clients, level_table)?; let neighbors = client_location.get_client_neighbors(id).unwrap(); Ok(vec![(id, SendShipPacket::JoinLobby(join_lobby))]