add client.rs
This commit is contained in:
		
							parent
							
								
									4dc814d244
								
							
						
					
					
						commit
						6f0fa05e3b
					
				
							
								
								
									
										172
									
								
								src/ship/client.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										172
									
								
								src/ship/client.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,172 @@ | |||||||
|  | use std::collections::HashMap; | ||||||
|  | use async_std::sync::{Arc, RwLock, RwLockReadGuard}; | ||||||
|  | 
 | ||||||
|  | use futures::future::BoxFuture; | ||||||
|  | 
 | ||||||
|  | use libpso::packet::ship::*; | ||||||
|  | use libpso::packet::login::Session; | ||||||
|  | 
 | ||||||
|  | use crate::common::serverstate::ClientId; | ||||||
|  | use crate::entity::account::{UserAccountEntity, UserSettingsEntity}; | ||||||
|  | use crate::entity::character::CharacterEntity; | ||||||
|  | use crate::entity::item; | ||||||
|  | 
 | ||||||
|  | use crate::ship::ship::ShipError; | ||||||
|  | use crate::ship::items; | ||||||
|  | use crate::ship::map::MapArea; | ||||||
|  | use crate::ship::shops::{WeaponShopItem, ToolShopItem, ArmorShopItem}; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | #[derive(Clone, Default)] | ||||||
|  | pub struct Clients(Arc<RwLock<HashMap<ClientId, RwLock<ClientState>>>>); | ||||||
|  | 
 | ||||||
|  | impl Clients { | ||||||
|  |     pub async fn add(&mut self, client_id: ClientId, client_state: ClientState) { | ||||||
|  |         self.0 | ||||||
|  |             .write() | ||||||
|  |             .await | ||||||
|  |             .insert(client_id, RwLock::new(client_state)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub async fn remove(&mut self, client_id: &ClientId) -> Option<ClientState> { | ||||||
|  |         Some(self.0 | ||||||
|  |             .write() | ||||||
|  |             .await | ||||||
|  |             .remove(client_id)? | ||||||
|  |             .into_inner()) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub async fn with<'a, T, F>(&'a self, client_id: ClientId, func: F) -> Result<T, ShipError> | ||||||
|  |     where | ||||||
|  |         T: Send, | ||||||
|  |         F: for<'b> FnOnce(&'b ClientState) -> BoxFuture<'b, T> + Send + 'a, | ||||||
|  |     { | ||||||
|  |         let clients = self.0 | ||||||
|  |             .read() | ||||||
|  |             .await; | ||||||
|  |         let client = clients | ||||||
|  |             .get(&client_id) | ||||||
|  |             .ok_or_else(|| ShipError::ClientNotFound(client_id))? | ||||||
|  |             .read() | ||||||
|  |             .await; | ||||||
|  | 
 | ||||||
|  |         Ok(func(&client).await) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub async fn with_many<'a, T, F, const N: usize>(&'a self, client_ids: [ClientId; N], func: F) -> Result<T, ShipError> | ||||||
|  |     where | ||||||
|  |         T: Send, | ||||||
|  |         F: for<'b> FnOnce([RwLockReadGuard<'b, ClientState>; N]) -> BoxFuture<'b, T> + Send + 'a, | ||||||
|  |     { | ||||||
|  |         let clients = self.0 | ||||||
|  |             .read() | ||||||
|  |             .await; | ||||||
|  |         
 | ||||||
|  |         let mut client_states: [std::mem::MaybeUninit<RwLockReadGuard<ClientState>>; N] = unsafe { | ||||||
|  |             std::mem::MaybeUninit::uninit().assume_init() | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         for (cindex, client_id) in client_ids.iter().enumerate() { | ||||||
|  |             let c = clients | ||||||
|  |                 .get(client_id) | ||||||
|  |                 .ok_or_else(|| ShipError::ClientNotFound(*client_id))? | ||||||
|  |                 .read() | ||||||
|  |                 .await; | ||||||
|  |             client_states[cindex].write(c); | ||||||
|  |         } | ||||||
|  |         
 | ||||||
|  |         let client_states = unsafe { | ||||||
|  |             // TODO: this should just be a normal transmute but due to compiler limitations it
 | ||||||
|  |             // does not yet work with const generics
 | ||||||
|  |             // https://github.com/rust-lang/rust/issues/61956
 | ||||||
|  |             std::mem::transmute_copy::<_, [RwLockReadGuard<ClientState>; N]>(&client_states) | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         Ok(func(client_states).await) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub async fn with_mut<'a, T, F>(&'a self, client_id: ClientId, func: F) -> Result<T, ShipError> | ||||||
|  |     where | ||||||
|  |         T: Send, | ||||||
|  |         F: for<'b> FnOnce(&'b mut ClientState) -> BoxFuture<'b, T> + Send + 'a, | ||||||
|  |     { | ||||||
|  |         let clients = self.0 | ||||||
|  |             .read() | ||||||
|  |             .await; | ||||||
|  |         let mut client = clients | ||||||
|  |             .get(&client_id) | ||||||
|  |             .ok_or_else(|| ShipError::ClientNotFound(client_id))? | ||||||
|  |             .write() | ||||||
|  |             .await; | ||||||
|  | 
 | ||||||
|  |         Ok(func(&mut client).await) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | #[derive(Debug, Clone, Copy)] | ||||||
|  | pub struct ItemDropLocation { | ||||||
|  |     pub map_area: MapArea, | ||||||
|  |     pub x: f32, | ||||||
|  |     pub z: f32, | ||||||
|  |     pub item_id: items::ClientItemId, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | pub struct LoadingQuest { | ||||||
|  |     pub header_bin: Option<QuestHeader>, | ||||||
|  |     pub header_dat: Option<QuestHeader>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | pub struct ClientState { | ||||||
|  |     pub user: UserAccountEntity, | ||||||
|  |     pub settings: UserSettingsEntity, | ||||||
|  |     pub character: CharacterEntity, | ||||||
|  |     _session: Session, | ||||||
|  |     //guildcard: GuildCard,
 | ||||||
|  |     pub block: usize, | ||||||
|  |     pub item_drop_location: Option<ItemDropLocation>, | ||||||
|  |     pub done_loading_quest: bool, | ||||||
|  |     pub area: Option<MapArea>, | ||||||
|  |     pub x: f32, | ||||||
|  |     pub y: f32, | ||||||
|  |     pub z: f32, | ||||||
|  |     pub weapon_shop: Vec<WeaponShopItem>, | ||||||
|  |     pub tool_shop: Vec<ToolShopItem>, | ||||||
|  |     pub armor_shop: Vec<ArmorShopItem>, | ||||||
|  |     pub tek: Option<(items::ClientItemId, item::weapon::TekSpecialModifier, item::weapon::TekPercentModifier, i32)>, | ||||||
|  |     pub character_playtime: chrono::Duration, | ||||||
|  |     pub log_on_time: chrono::DateTime<chrono::Utc>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl ClientState { | ||||||
|  |     pub fn new(user: UserAccountEntity, settings: UserSettingsEntity, character: CharacterEntity, session: Session) -> ClientState { | ||||||
|  |         let character_playtime = chrono::Duration::seconds(character.playtime as i64); | ||||||
|  |         ClientState { | ||||||
|  |             user, | ||||||
|  |             settings, | ||||||
|  |             character, | ||||||
|  |             _session: session, | ||||||
|  |             block: 0, | ||||||
|  |             item_drop_location: None, | ||||||
|  |             done_loading_quest: false, | ||||||
|  |             area: None, | ||||||
|  |             x: 0.0, | ||||||
|  |             y: 0.0, | ||||||
|  |             z: 0.0, | ||||||
|  |             weapon_shop: Vec::new(), | ||||||
|  |             tool_shop: Vec::new(), | ||||||
|  |             armor_shop: Vec::new(), | ||||||
|  |             tek: None, | ||||||
|  |             character_playtime, | ||||||
|  |             log_on_time: chrono::Utc::now(), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn update_playtime(&mut self) { | ||||||
|  |         let additional_playtime = chrono::Utc::now() - self.log_on_time; | ||||||
|  |         self.character.playtime = (self.character_playtime + additional_playtime).num_seconds() as u32; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user