diff --git a/src/ship/packet/handler/ship.rs b/src/ship/packet/handler/ship.rs index b393e61..a63ebdf 100644 --- a/src/ship/packet/handler/ship.rs +++ b/src/ship/packet/handler/ship.rs @@ -1,3 +1,4 @@ +use async_std::sync::{Arc, RwLock}; use libpso::packet::ship::*; use libpso::packet::login::RedirectClient; use crate::common::serverstate::ClientId; @@ -5,17 +6,27 @@ use crate::common::interserver::Ship; use crate::ship::ship::{SendShipPacket, ShipError}; use crate::ship::packet::builder; -pub fn ship_list(id: ClientId, ship_list: &[Ship]) -> Vec<(ClientId, SendShipPacket)> { - vec![(id, SendShipPacket::ShipList(builder::ship::ship_list(ship_list)))] +pub async fn ship_list(id: ClientId, ship_list: &Arc>>) -> Vec<(ClientId, SendShipPacket)> { + let ship_list = ship_list + .read() + .await + .clone(); + vec![(id, SendShipPacket::ShipList(builder::ship::ship_list(&ship_list)))] } pub fn block_list(id: ClientId, shipname: &str, num_blocks: usize) -> Vec<(ClientId, SendShipPacket)> { vec![(id, SendShipPacket::ShipBlockList(ShipBlockList::new(shipname, num_blocks)))] } -pub fn selected_ship(id: ClientId, menuselect: MenuSelect, ship_list: &[Ship]) - -> Result, ShipError> { - let ship = ship_list.get(menuselect.item as usize).ok_or_else(|| ShipError::InvalidShip(menuselect.item as usize))?; - let ip = u32::from_ne_bytes(ship.ip.octets()); - Ok(vec![(id, SendShipPacket::RedirectClient(RedirectClient::new(ip, ship.port)))]) +pub async fn selected_ship(id: ClientId, menuselect: MenuSelect, ship_list: &Arc>>) + -> Result, ShipError> { + let (ip, port) = ship_list + .read() + .await + .get(menuselect.item as usize) + .map(|ship| { + (u32::from_ne_bytes(ship.ip.octets()), ship.port) + }) + .ok_or_else(|| ShipError::InvalidShip(menuselect.item as usize))?; + Ok(vec![(id, SendShipPacket::RedirectClient(RedirectClient::new(ip, port)))]) } diff --git a/src/ship/ship.rs b/src/ship/ship.rs index d183ebf..71469fe 100644 --- a/src/ship/ship.rs +++ b/src/ship/ship.rs @@ -3,7 +3,7 @@ use std::net::Ipv4Addr; use std::collections::HashMap; use async_std::channel; -use async_std::sync::{Arc, Mutex}; +use async_std::sync::{Arc, Mutex, RwLock}; use rand::Rng; use thiserror::Error; @@ -449,7 +449,7 @@ impl ShipServerStateBuilder { event: self.event.unwrap_or(ShipEvent::None), auth_token: self.auth_token.unwrap_or_else(|| AuthToken("".into())), - ship_list: Vec::new(), + ship_list: Arc::new(RwLock::new(Vec::new())), shipgate_sender: None, trades: Default::default(), } @@ -492,7 +492,7 @@ pub struct ShipServerState { port: u16, auth_token: AuthToken, - ship_list: Vec, + ship_list: Arc>>, shipgate_sender: Option>, trades: TradeState, } @@ -666,7 +666,7 @@ impl ServerState for ShipServerState { match menuselect.menu { SHIP_MENU_ID => { let leave_lobby = handler::lobby::remove_from_lobby(id, &mut block.client_location).await.into_iter().into_iter().flatten(); - let select_ship = handler::ship::selected_ship(id, menuselect, &self.ship_list)?; + let select_ship = handler::ship::selected_ship(id, menuselect, &self.ship_list).await?; leave_lobby.chain(select_ship).collect() } BLOCK_MENU_ID => { @@ -784,7 +784,7 @@ impl ServerState for ShipServerState { handler::settings::save_options(id, save_options, &self.clients, &mut self.entity_gateway).await? }, RecvShipPacket::RequestShipList(_) => { - handler::ship::ship_list(id, &self.ship_list) + handler::ship::ship_list(id, &self.ship_list).await }, RecvShipPacket::RequestShipBlockList(_) => { handler::ship::block_list(id, &self.name, self.blocks.0.len()) @@ -865,8 +865,12 @@ impl InterserverActor for ShipServerState { LoginMessage::SendMail{..} => { Ok(Vec::new()) }, - LoginMessage::ShipList{ships} => { - self.ship_list = ships; + LoginMessage::ShipList{mut ships} => { + let mut ship_list = self.ship_list + .write() + .await; + ship_list.clear(); + ship_list.append(&mut ships); Ok(Vec::new()) }, LoginMessage::RequestUsers => {