use std::convert::TryInto; use libpso::packet::ship::*; use networking::serverstate::ClientId; use maps::Holiday; use client::{ClientState, Clients}; use location::{ClientLocation, RoomId, AreaClient, ClientLocationError}; use room::RoomState; use items::state::ItemState; use crate::{player_header, player_info}; use futures::stream::StreamExt; pub async fn join_room(id: ClientId, clients: &Clients, client_location: &ClientLocation, room_id: RoomId, room: &RoomState, event: Holiday) -> Result { let all_clients = client_location.get_clients_in_room(room_id).await.map_err(|err| -> ClientLocationError { err.into() })?; #[allow(clippy::manual_try_fold)] // I don't think its even possible to make this work here let players = futures::stream::iter(all_clients.iter()) .enumerate() .fold::, _, _>(Ok([PlayerHeader::default(); 4]), |acc, (i, c)| async move { let header_area_client = client_location.get_local_client(id).await.map_err(|err| -> ClientLocationError {err.into() })?; clients.with(c.client, |client| Box::pin(async move { acc.map(|mut a| { a[i] = player_header(0x10000, client, &header_area_client); a }) })).await? }).await?; let area_client = client_location.get_local_client(id).await.map_err(|err| -> ClientLocationError { err.into() })?; let leader = client_location.get_room_leader(room_id).await.map_err(|err| -> ClientLocationError { err.into() })?; Ok(JoinRoom { flag: all_clients.len() as u32, maps: room.maps.map_headers(), players, client: area_client.local_client.id(), leader: leader.local_client.id(), one: 1, difficulty: room.mode.difficulty().into(), battle: room.mode.battle() as u8, event: event.into(), section: room.section_id.into(), challenge: room.mode.challenge() as u8, random_seed: room.random_seed, episode: room.mode.episode().into(), one2: 1, single_player: room.mode.player_mode().value(), unknown: 0, }) } pub async fn add_to_room(_id: ClientId, client: &ClientState, area_client: &AreaClient, leader: &AreaClient, item_state: &ItemState, event: Holiday) -> Result { let inventory = item_state.get_character_inventory(&client.character).await?; Ok(AddToRoom { flag: 1, client: area_client.local_client.id(), leader: leader.local_client.id(), one: 0, // TODO: ???????? lobby: 0xFF, block: 0, event: event.into(), padding: 0, playerinfo: player_info(0x10000, client, area_client, &inventory).await, }) } pub fn build_rare_monster_list(rare_monster_vec: Vec) -> RareMonsterList { RareMonsterList { ids: rare_monster_vec.try_into().unwrap_or([0xFFFFu16; 16]), } }