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, Clients}; 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: &Clients, 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: &Clients, 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), }) }