start on misc interserver things like player counts and ship lists
This commit is contained in:
		
							parent
							
								
									6686aee824
								
							
						
					
					
						commit
						ae7ba9e3fe
					
				| @ -8,7 +8,7 @@ pub struct ServerId(pub usize); | |||||||
| #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] | #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] | ||||||
| pub struct AuthToken(pub String); | pub struct AuthToken(pub String); | ||||||
| 
 | 
 | ||||||
| #[derive(Debug, Serialize, Deserialize)] | #[derive(Debug, Clone, Serialize, Deserialize)] | ||||||
| pub struct Ship { | pub struct Ship { | ||||||
|     pub name: String, |     pub name: String, | ||||||
|     pub ip: Ipv4Addr, |     pub ip: Ipv4Addr, | ||||||
| @ -38,7 +38,8 @@ pub enum ShipMessage { | |||||||
|         message: String, |         message: String, | ||||||
|     }, |     }, | ||||||
|     RequestShipList, |     RequestShipList, | ||||||
| 
 |     AddUser(UserAccountId), | ||||||
|  |     RemoveUser(UserAccountId), | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -204,7 +204,6 @@ pub fn login_listen_mainloop<EG: EntityGateway + 'static>(state: Arc<Mutex<Chara | |||||||
|                 })) |                 })) | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|             login_recv_loop(server_id, socket.clone(), server_state_sender.clone(), client_sender).await; |             login_recv_loop(server_id, socket.clone(), server_state_sender.clone(), client_sender).await; | ||||||
|             interserver_send_loop(server_id, socket.clone(), client_receiver).await; |             interserver_send_loop(server_id, socket.clone(), client_receiver).await; | ||||||
|         } |         } | ||||||
|  | |||||||
| @ -1,10 +1,11 @@ | |||||||
|  | use serde::{Serialize, Deserialize}; | ||||||
| use libpso::character::settings; | use libpso::character::settings; | ||||||
| use libpso::character::guildcard; | use libpso::character::guildcard; | ||||||
| 
 | 
 | ||||||
| pub const USERFLAG_NEWCHAR: u32      = 0x00000001; | pub const USERFLAG_NEWCHAR: u32      = 0x00000001; | ||||||
| pub const USERFLAG_DRESSINGROOM: u32 = 0x00000002; | pub const USERFLAG_DRESSINGROOM: u32 = 0x00000002; | ||||||
| 
 | 
 | ||||||
| #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] | #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] | ||||||
| pub struct UserAccountId(pub u32); | pub struct UserAccountId(pub u32); | ||||||
| #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] | #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] | ||||||
| pub struct UserSettingsId(pub u32); | pub struct UserSettingsId(pub u32); | ||||||
|  | |||||||
| @ -6,6 +6,7 @@ use rand::Rng; | |||||||
| use crc::{crc32, Hasher32}; | use crc::{crc32, Hasher32}; | ||||||
| 
 | 
 | ||||||
| use libpso::packet::login::*; | use libpso::packet::login::*; | ||||||
|  | use libpso::packet::ship::{MenuDetail, SmallLeftDialog}; | ||||||
| use libpso::{PacketParseError, PSOPacket}; | use libpso::{PacketParseError, PSOPacket}; | ||||||
| use libpso::crypto::bb::PSOBBCipher; | use libpso::crypto::bb::PSOBBCipher; | ||||||
| use crate::entity::item; | use crate::entity::item; | ||||||
| @ -18,7 +19,7 @@ use crate::common::leveltable::CharacterLevelTable; | |||||||
| use libpso::{utf8_to_array, utf8_to_utf16_array}; | use libpso::{utf8_to_array, utf8_to_utf16_array}; | ||||||
| 
 | 
 | ||||||
| use crate::entity::gateway::{EntityGateway, GatewayError}; | use crate::entity::gateway::{EntityGateway, GatewayError}; | ||||||
| use crate::entity::account::{UserAccountEntity, NewUserSettingsEntity, USERFLAG_NEWCHAR, USERFLAG_DRESSINGROOM}; | use crate::entity::account::{UserAccountId, UserAccountEntity, NewUserSettingsEntity, USERFLAG_NEWCHAR, USERFLAG_DRESSINGROOM}; | ||||||
| use crate::entity::item::{NewItemEntity, ItemDetail, ItemLocation, InventoryItemEntity, InventoryEntity, BankEntity, BankName, EquippedEntity}; | use crate::entity::item::{NewItemEntity, ItemDetail, ItemLocation, InventoryItemEntity, InventoryEntity, BankEntity, BankName, EquippedEntity}; | ||||||
| use crate::entity::item::weapon::Weapon; | use crate::entity::item::weapon::Weapon; | ||||||
| use crate::entity::item::armor::Armor; | use crate::entity::item::armor::Armor; | ||||||
| @ -57,6 +58,7 @@ pub enum RecvCharacterPacket { | |||||||
|     CharacterPreview(CharacterPreview), |     CharacterPreview(CharacterPreview), | ||||||
|     SetFlag(SetFlag), |     SetFlag(SetFlag), | ||||||
|     MenuSelect(MenuSelect), |     MenuSelect(MenuSelect), | ||||||
|  |     MenuDetail(MenuDetail), | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl RecvServerPacket for RecvCharacterPacket { | impl RecvServerPacket for RecvCharacterPacket { | ||||||
| @ -73,6 +75,7 @@ impl RecvServerPacket for RecvCharacterPacket { | |||||||
|             0xE5 => Ok(RecvCharacterPacket::CharacterPreview(CharacterPreview::from_bytes(data)?)), |             0xE5 => Ok(RecvCharacterPacket::CharacterPreview(CharacterPreview::from_bytes(data)?)), | ||||||
|             0xEC => Ok(RecvCharacterPacket::SetFlag(SetFlag::from_bytes(data)?)), |             0xEC => Ok(RecvCharacterPacket::SetFlag(SetFlag::from_bytes(data)?)), | ||||||
|             0x10 => Ok(RecvCharacterPacket::MenuSelect(MenuSelect::from_bytes(data)?)), |             0x10 => Ok(RecvCharacterPacket::MenuSelect(MenuSelect::from_bytes(data)?)), | ||||||
|  |             0x09 => Ok(RecvCharacterPacket::MenuDetail(MenuDetail::from_bytes(data)?)), | ||||||
|             _ => Err(PacketParseError::WrongPacketForServerType(u16::from_le_bytes([data[2], data[3]]), data.to_vec())) |             _ => Err(PacketParseError::WrongPacketForServerType(u16::from_le_bytes([data[2], data[3]]), data.to_vec())) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @ -94,6 +97,7 @@ pub enum SendCharacterPacket { | |||||||
|     Timestamp(Timestamp), |     Timestamp(Timestamp), | ||||||
|     ShipList(ShipList), |     ShipList(ShipList), | ||||||
|     RedirectClient(RedirectClient), |     RedirectClient(RedirectClient), | ||||||
|  |     SmallLeftDialog(SmallLeftDialog), | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl SendServerPacket for SendCharacterPacket { | impl SendServerPacket for SendCharacterPacket { | ||||||
| @ -112,6 +116,7 @@ impl SendServerPacket for SendCharacterPacket { | |||||||
|             SendCharacterPacket::Timestamp(pkt) => pkt.as_bytes(), |             SendCharacterPacket::Timestamp(pkt) => pkt.as_bytes(), | ||||||
|             SendCharacterPacket::ShipList(pkt) => pkt.as_bytes(), |             SendCharacterPacket::ShipList(pkt) => pkt.as_bytes(), | ||||||
|             SendCharacterPacket::RedirectClient(pkt) => pkt.as_bytes(), |             SendCharacterPacket::RedirectClient(pkt) => pkt.as_bytes(), | ||||||
|  |             SendCharacterPacket::SmallLeftDialog(pkt) => pkt.as_bytes(), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @ -168,6 +173,11 @@ impl ClientState { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #[derive(Clone)] | ||||||
|  | struct ConnectedClient { | ||||||
|  |     ship_id: Option<ServerId>, | ||||||
|  |     expires: Option<chrono::DateTime<chrono::Utc>>, | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| pub struct CharacterServerState<EG: EntityGateway> { | pub struct CharacterServerState<EG: EntityGateway> { | ||||||
|     entity_gateway: EG, |     entity_gateway: EG, | ||||||
| @ -177,6 +187,8 @@ pub struct CharacterServerState<EG: EntityGateway> { | |||||||
|     ships: BTreeMap<ServerId, Ship>, |     ships: BTreeMap<ServerId, Ship>, | ||||||
|     level_table: CharacterLevelTable, |     level_table: CharacterLevelTable, | ||||||
|     auth_token: AuthToken, |     auth_token: AuthToken, | ||||||
|  | 
 | ||||||
|  |     connected_clients: BTreeMap<UserAccountId, ConnectedClient>, | ||||||
|     authenticated_ships: BTreeSet<ServerId>, |     authenticated_ships: BTreeSet<ServerId>, | ||||||
|     ship_sender: BTreeMap<ServerId, Box<dyn Fn(LoginMessage) + Send>>, |     ship_sender: BTreeMap<ServerId, Box<dyn Fn(LoginMessage) + Send>>, | ||||||
| } | } | ||||||
| @ -298,6 +310,7 @@ impl<EG: EntityGateway> CharacterServerState<EG> { | |||||||
|             auth_token: auth_token, |             auth_token: auth_token, | ||||||
|             authenticated_ships: BTreeSet::new(), |             authenticated_ships: BTreeSet::new(), | ||||||
|             ship_sender: BTreeMap::new(), |             ship_sender: BTreeMap::new(), | ||||||
|  |             connected_clients: BTreeMap::new(), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -306,23 +319,35 @@ impl<EG: EntityGateway> CharacterServerState<EG> { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     async fn validate_login(&mut self, id: ClientId, pkt: &Login) -> Result<Vec<SendCharacterPacket>, anyhow::Error> { |     async fn validate_login(&mut self, id: ClientId, pkt: &Login) -> Result<Vec<SendCharacterPacket>, anyhow::Error> { | ||||||
|         let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?; |         match get_login_status(&self.entity_gateway, pkt).await { | ||||||
|         Ok(match get_login_status(&self.entity_gateway, pkt).await.and_then(check_if_already_online) { |             Ok(user) => { | ||||||
|             Ok(mut user) => { |                 if let Some(connected_client) = self.connected_clients.get(&user.id) { | ||||||
|                 user.at_character = true; |                     if let Some(expires) = connected_client.expires { | ||||||
|                 self.entity_gateway.save_user(&user).await?; |                         if expires < chrono::Utc::now() { | ||||||
|  |                             return Ok(vec![SendCharacterPacket::LoginResponse(LoginResponse::by_status(AccountStatus::AlreadyOnline, Session::new()))]); | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
| 
 | 
 | ||||||
|                 let mut response = LoginResponse::by_status(AccountStatus::Ok, Session::new()); |                 let mut response = LoginResponse::by_status(AccountStatus::Ok, Session::new()); | ||||||
|                 response.guildcard = user.guildcard; |                 response.guildcard = user.guildcard; | ||||||
|                 response.team_id = user.team_id.map_or(0, |ti| ti) as u32; |                 response.team_id = user.team_id.map_or(0, |ti| ti) as u32; | ||||||
|  | 
 | ||||||
|  |                 let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?; | ||||||
|  | 
 | ||||||
|  |                 self.connected_clients.insert(user.id.clone(), ConnectedClient { | ||||||
|  |                     ship_id: None, | ||||||
|  |                     expires: Some(chrono::Utc::now() + chrono::Duration::minutes(1)), | ||||||
|  |                 }); | ||||||
|  | 
 | ||||||
|                 client.user = Some(user); |                 client.user = Some(user); | ||||||
|                 client.session = pkt.session; |                 client.session = pkt.session; | ||||||
|                 vec![SendCharacterPacket::LoginResponse(response)] |                 Ok(vec![SendCharacterPacket::LoginResponse(response)]) | ||||||
|             }, |             }, | ||||||
|             Err(err) => { |             Err(err) => { | ||||||
|                 vec![SendCharacterPacket::LoginResponse(LoginResponse::by_status(err, Session::new()))] |                 Ok(vec![SendCharacterPacket::LoginResponse(LoginResponse::by_status(err, Session::new()))]) | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|         }) |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn send_ship_list(&mut self, _id: ClientId, _pkt: &Login) -> Result<Vec<SendCharacterPacket>, anyhow::Error> { |     fn send_ship_list(&mut self, _id: ClientId, _pkt: &Login) -> Result<Vec<SendCharacterPacket>, anyhow::Error> { | ||||||
| @ -493,6 +518,16 @@ impl<EG: EntityGateway> CharacterServerState<EG> { | |||||||
|             .ok_or(CharacterError::InvalidMenuSelection(menuselect.menu, menuselect.item))?; |             .ok_or(CharacterError::InvalidMenuSelection(menuselect.menu, menuselect.item))?; | ||||||
|         Ok(vec![SendCharacterPacket::RedirectClient(RedirectClient::new(u32::from_le_bytes(ship.ip.octets()), ship.port))]) |         Ok(vec![SendCharacterPacket::RedirectClient(RedirectClient::new(u32::from_le_bytes(ship.ip.octets()), ship.port))]) | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     fn ship_detail(&mut self, menudetail: &MenuDetail) -> Result<Vec<SendCharacterPacket>, anyhow::Error> { | ||||||
|  |         let players = self.connected_clients.iter() | ||||||
|  |             .filter(|(_, client)| { | ||||||
|  |                 client.ship_id == Some(ServerId(menudetail.item as usize)) | ||||||
|  |             }) | ||||||
|  |             .count(); | ||||||
|  |         let ship_details = format!("players: {}\nrooms: {}", players, 0); | ||||||
|  |         Ok(vec![SendCharacterPacket::SmallLeftDialog(SmallLeftDialog::new(ship_details))]) | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[async_trait::async_trait] | #[async_trait::async_trait] | ||||||
| @ -557,6 +592,12 @@ impl<EG: EntityGateway> ServerState for CharacterServerState<EG> { | |||||||
|             }, |             }, | ||||||
|             RecvCharacterPacket::MenuSelect(menuselect) => { |             RecvCharacterPacket::MenuSelect(menuselect) => { | ||||||
|                 Box::new(self.select_ship(menuselect)?.into_iter().map(move |pkt| (id, pkt))) |                 Box::new(self.select_ship(menuselect)?.into_iter().map(move |pkt| (id, pkt))) | ||||||
|  |             }, | ||||||
|  |             RecvCharacterPacket::MenuDetail(menudetail) => { | ||||||
|  |                 match menudetail.menu { | ||||||
|  |                     SHIP_MENU_ID => Box::new(self.ship_detail(menudetail)?.into_iter().map(move |pkt| (id, pkt))), | ||||||
|  |                     _ => Box::new(Vec::new().into_iter()) | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|         }) |         }) | ||||||
|     } |     } | ||||||
| @ -588,20 +629,59 @@ impl<EG: EntityGateway> InterserverActor for CharacterServerState<EG> { | |||||||
|                 if self.auth_token == auth_token { |                 if self.auth_token == auth_token { | ||||||
|                     self.authenticated_ships.insert(id); |                     self.authenticated_ships.insert(id); | ||||||
|                 } |                 } | ||||||
|  |                 Ok(Vec::new()) | ||||||
|             }, |             }, | ||||||
|             ShipMessage::NewShip(new_ship) => { |             ShipMessage::NewShip(new_ship) => { | ||||||
|                 if self.authenticated_ships.contains(&id) { |                 if self.authenticated_ships.contains(&id) { | ||||||
|                     self.ships.insert(id, new_ship); |                     self.ships.insert(id, new_ship); | ||||||
|                 } |                 } | ||||||
|  |                 Ok(Vec::new()) | ||||||
|             }, |             }, | ||||||
|             _ => {} |             ShipMessage::AddUser(new_user) => { | ||||||
|  |                 if self.authenticated_ships.contains(&id) { | ||||||
|  |                     self.connected_clients.insert(new_user, ConnectedClient { | ||||||
|  |                         ship_id: Some(id), | ||||||
|  |                         expires: None, | ||||||
|  |                     }); | ||||||
|                 } |                 } | ||||||
|                 Ok(Vec::new()) |                 Ok(Vec::new()) | ||||||
|  |             }, | ||||||
|  |             ShipMessage::RemoveUser(new_user) => { | ||||||
|  |                 if self.authenticated_ships.contains(&id) { | ||||||
|  |                     self.connected_clients.remove(&new_user); | ||||||
|  |                 } | ||||||
|  |                 Ok(Vec::new()) | ||||||
|  |             }, | ||||||
|  |             ShipMessage::RequestShipList => { | ||||||
|  |                 if self.authenticated_ships.contains(&id) { | ||||||
|  |                     Ok(vec![(id, LoginMessage::ShipList { | ||||||
|  |                         ships: self.ships | ||||||
|  |                             .iter() | ||||||
|  |                             .map(|(_, ship)| { | ||||||
|  |                                 ship | ||||||
|  |                             }) | ||||||
|  |                             .cloned() | ||||||
|  |                             .collect() | ||||||
|  |                     })]) | ||||||
|  |                 } | ||||||
|  |                 else { | ||||||
|  |                     Ok(Vec::new()) | ||||||
|  |                 } | ||||||
|  |             }, | ||||||
|  |             ShipMessage::SendMail{..} => { | ||||||
|  |                 Ok(Vec::new()) | ||||||
|  |             }, | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     async fn on_disconnect(&mut self, id: ServerId) -> Vec<(ServerId, Self::SendMessage)> { |     async fn on_disconnect(&mut self, id: ServerId) -> Vec<(ServerId, Self::SendMessage)> { | ||||||
|         self.ships.remove(&id); |         self.ships.remove(&id); | ||||||
|         self.ship_sender.remove(&id); |         self.ship_sender.remove(&id); | ||||||
|  |         self.connected_clients = self.connected_clients.clone().into_iter() | ||||||
|  |             .filter(|(_, client)| { | ||||||
|  |                 client.ship_id != Some(id) | ||||||
|  |             }) | ||||||
|  |             .collect(); | ||||||
|         Vec::new() |         Vec::new() | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -5,19 +5,18 @@ use crate::ship::ship::{SendShipPacket, ShipError, ClientState, Clients}; | |||||||
| use crate::login::login::{get_login_status, check_if_already_online}; | use crate::login::login::{get_login_status, check_if_already_online}; | ||||||
| use crate::entity::gateway::EntityGateway; | use crate::entity::gateway::EntityGateway; | ||||||
| use crate::ship::items::ItemManager; | use crate::ship::items::ItemManager; | ||||||
|  | use crate::common::interserver::ShipMessage; | ||||||
| 
 | 
 | ||||||
| pub async fn validate_login<EG: EntityGateway>(id: ClientId, | pub async fn validate_login<EG: EntityGateway>(id: ClientId, | ||||||
|                                          pkt: &Login, |                                          pkt: &Login, | ||||||
|                                          entity_gateway: &mut EG, |                                          entity_gateway: &mut EG, | ||||||
|                                          clients: &mut Clients, |                                          clients: &mut Clients, | ||||||
|                                          item_manager: &mut ItemManager, |                                          item_manager: &mut ItemManager, | ||||||
|  |                                          shipgate_sender: &Option<Box<dyn Fn(ShipMessage) + Send + Sync>>, | ||||||
|                                          ship_name: &String) |                                          ship_name: &String) | ||||||
|                                          -> Result<Vec<SendShipPacket>, anyhow::Error> { |                                          -> Result<Vec<SendShipPacket>, anyhow::Error> { | ||||||
|     Ok(match get_login_status(entity_gateway, pkt).await.and_then(check_if_already_online) { |     Ok(match get_login_status(entity_gateway, pkt).await { | ||||||
|         Ok(mut user) => { |         Ok(mut user) => { | ||||||
|             user.at_ship= true; |  | ||||||
|             entity_gateway.save_user(&user).await?; |  | ||||||
| 
 |  | ||||||
|             let mut response = LoginResponse::by_status(AccountStatus::Ok, Session::new()); |             let mut response = LoginResponse::by_status(AccountStatus::Ok, Session::new()); | ||||||
|             response.guildcard = user.id.0 as u32; |             response.guildcard = user.id.0 as u32; | ||||||
|             response.team_id = user.team_id.map_or(31, |ti| ti) as u32; |             response.team_id = user.team_id.map_or(31, |ti| ti) as u32; | ||||||
| @ -30,6 +29,10 @@ pub async fn validate_login<EG: EntityGateway>(id: ClientId, | |||||||
|             let settings = entity_gateway.get_user_settings_by_user(&user).await?; |             let settings = entity_gateway.get_user_settings_by_user(&user).await?; | ||||||
| 
 | 
 | ||||||
|             item_manager.load_character(entity_gateway, &character).await?; |             item_manager.load_character(entity_gateway, &character).await?; | ||||||
|  | 
 | ||||||
|  |             if let Some(shipgate_sender) = shipgate_sender.as_ref() { | ||||||
|  |                 shipgate_sender(ShipMessage::AddUser(user.id.clone())); | ||||||
|  |             } | ||||||
|             clients.insert(id, ClientState::new(user, settings, character, pkt.session)); |             clients.insert(id, ClientState::new(user, settings, character, pkt.session)); | ||||||
|             vec![SendShipPacket::LoginResponse(response), SendShipPacket::ShipBlockList(ShipBlockList::new(&&ship_name, 3))] |             vec![SendShipPacket::LoginResponse(response), SendShipPacket::ShipBlockList(ShipBlockList::new(&&ship_name, 3))] | ||||||
|         }, |         }, | ||||||
|  | |||||||
| @ -351,6 +351,7 @@ impl<EG: EntityGateway> ShipServerStateBuilder<EG> { | |||||||
|             port: self.port.unwrap_or(SHIP_PORT), |             port: self.port.unwrap_or(SHIP_PORT), | ||||||
|             shops: Box::new(ItemShops::new()), |             shops: Box::new(ItemShops::new()), | ||||||
|             auth_token: self.auth_token.unwrap_or(AuthToken("".into())), |             auth_token: self.auth_token.unwrap_or(AuthToken("".into())), | ||||||
|  |             ship_list: Vec::new(), | ||||||
|             shipgate_sender: None, |             shipgate_sender: None, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @ -370,7 +371,8 @@ pub struct ShipServerState<EG: EntityGateway> { | |||||||
|     shops: Box<ItemShops>, |     shops: Box<ItemShops>, | ||||||
|     auth_token: AuthToken, |     auth_token: AuthToken, | ||||||
| 
 | 
 | ||||||
|     shipgate_sender: Option<Box<dyn Fn(ShipMessage) + Send>>, |     ship_list: Vec<Ship>, | ||||||
|  |     shipgate_sender: Option<Box<dyn Fn(ShipMessage) + Send + Sync>>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl<EG: EntityGateway> ShipServerState<EG> { | impl<EG: EntityGateway> ShipServerState<EG> { | ||||||
| @ -378,7 +380,7 @@ impl<EG: EntityGateway> ShipServerState<EG> { | |||||||
|         ShipServerStateBuilder::new() |         ShipServerStateBuilder::new() | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn set_sender(&mut self, sender: Box<dyn Fn(ShipMessage) + Send>) { |     pub fn set_sender(&mut self, sender: Box<dyn Fn(ShipMessage) + Send + Sync>) { | ||||||
|         self.shipgate_sender = Some(sender); |         self.shipgate_sender = Some(sender); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -496,7 +498,7 @@ impl<EG: EntityGateway> ServerState for ShipServerState<EG> { | |||||||
|               -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error> { |               -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error> { | ||||||
|         Ok(match pkt { |         Ok(match pkt { | ||||||
|             RecvShipPacket::Login(login) => { |             RecvShipPacket::Login(login) => { | ||||||
|                 Box::new(handler::auth::validate_login(id, login, &mut self.entity_gateway, &mut self.clients, &mut self.item_manager, &self.name).await?.into_iter().map(move |pkt| (id, pkt))) |                 Box::new(handler::auth::validate_login(id, login, &mut self.entity_gateway, &mut self.clients, &mut self.item_manager, &self.shipgate_sender, &self.name).await?.into_iter().map(move |pkt| (id, pkt))) | ||||||
|             }, |             }, | ||||||
|             RecvShipPacket::QuestDetailRequest(questdetailrequest) => { |             RecvShipPacket::QuestDetailRequest(questdetailrequest) => { | ||||||
|                 match questdetailrequest.menu { |                 match questdetailrequest.menu { | ||||||
| @ -601,7 +603,6 @@ impl<EG: EntityGateway> ServerState for ShipServerState<EG> { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     async fn on_disconnect(&mut self, id: ClientId) -> Result<Vec<(ClientId, SendShipPacket)>, anyhow::Error> { |     async fn on_disconnect(&mut self, id: ClientId) -> Result<Vec<(ClientId, SendShipPacket)>, anyhow::Error> { | ||||||
|         // TODO: don't unwrap!
 |  | ||||||
|         let client = self.clients.get(&id).ok_or(ShipError::ClientNotFound(id))?; |         let client = self.clients.get(&id).ok_or(ShipError::ClientNotFound(id))?; | ||||||
|         let area_client = self.client_location.get_local_client(id)?; |         let area_client = self.client_location.get_local_client(id)?; | ||||||
|         let neighbors = self.client_location.get_client_neighbors(id)?; |         let neighbors = self.client_location.get_client_neighbors(id)?; | ||||||
| @ -611,15 +612,19 @@ impl<EG: EntityGateway> ServerState for ShipServerState<EG> { | |||||||
|                 if neighbors.len() == 0 { |                 if neighbors.len() == 0 { | ||||||
|                     self.rooms[room.0] = None; |                     self.rooms[room.0] = None; | ||||||
|                 } |                 } | ||||||
|                 let leader = self.client_location.get_room_leader(room).unwrap(); |                 let leader = self.client_location.get_room_leader(room)?; | ||||||
|                 SendShipPacket::LeaveRoom(LeaveRoom::new(area_client.local_client.id(), leader.local_client.id())) |                 SendShipPacket::LeaveRoom(LeaveRoom::new(area_client.local_client.id(), leader.local_client.id())) | ||||||
|             }, |             }, | ||||||
|             RoomLobby::Lobby(lobby) => { |             RoomLobby::Lobby(lobby) => { | ||||||
|                 let leader = self.client_location.get_lobby_leader(lobby).unwrap(); |                 let leader = self.client_location.get_lobby_leader(lobby)?; | ||||||
|                 SendShipPacket::LeaveLobby(LeaveLobby::new(area_client.local_client.id(), leader.local_client.id())) |                 SendShipPacket::LeaveLobby(LeaveLobby::new(area_client.local_client.id(), leader.local_client.id())) | ||||||
|             } |             } | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|  |         if let Some(shipgate_sender) = self.shipgate_sender.as_ref() { | ||||||
|  |             shipgate_sender(ShipMessage::RemoveUser(client.user.id.clone())); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         self.client_location.remove_client_from_area(id); |         self.client_location.remove_client_from_area(id); | ||||||
|         self.item_manager.remove_character_from_room(&client.character); |         self.item_manager.remove_character_from_room(&client.character); | ||||||
| 
 | 
 | ||||||
| @ -652,8 +657,23 @@ impl<EG: EntityGateway> InterserverActor for ShipServerState<EG> { | |||||||
|             })) ] |             })) ] | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     async fn action(&mut self, _id: ServerId, _msg: Self::RecvMessage) -> Result<Vec<(ServerId, Self::SendMessage)>, Self::Error> { |     async fn action(&mut self, id: ServerId, msg: Self::RecvMessage) -> Result<Vec<(ServerId, Self::SendMessage)>, Self::Error> { | ||||||
|  |         match msg { | ||||||
|  |             LoginMessage::SendMail{..} => { | ||||||
|                 Ok(Vec::new()) |                 Ok(Vec::new()) | ||||||
|  |             }, | ||||||
|  |             LoginMessage::ShipList{ships} => { | ||||||
|  |                 self.ship_list = ships; | ||||||
|  |                 Ok(Vec::new()) | ||||||
|  |             }, | ||||||
|  |             LoginMessage::RequestUsers => { | ||||||
|  |                 Ok(self.clients.iter() | ||||||
|  |                    .map(|(_, client)| { | ||||||
|  |                        (id, ShipMessage::AddUser(client.user.id.clone())) | ||||||
|  |                    }) | ||||||
|  |                    .collect()) | ||||||
|  |             } | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     async fn on_disconnect(&mut self, _id: ServerId) -> Vec<(ServerId, Self::SendMessage)> { |     async fn on_disconnect(&mut self, _id: ServerId) -> Vec<(ServerId, Self::SendMessage)> { | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user