Merge pull request 'clone entitygateway more' (#117) from clone_gateway_more into master
	
		
			
	
		
	
	
		
	
		
			All checks were successful
		
		
	
	
		
			
				
	
				continuous-integration/drone/push Build is passing
				
			
		
		
	
	
				
					
				
			
		
			All checks were successful
		
		
	
	continuous-integration/drone/push Build is passing
				
			Reviewed-on: #117
This commit is contained in:
		
						commit
						bbc1919309
					
				| @ -180,7 +180,7 @@ where | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| pub fn login_listen_mainloop<EG: EntityGateway + 'static>(state: Arc<Mutex<CharacterServerState<EG>>>, port: u16) ->  Pin<Box<dyn Future<Output = ()>>> { | ||||
| pub fn login_listen_mainloop<EG: EntityGateway + Clone + 'static>(state: Arc<Mutex<CharacterServerState<EG>>>, port: u16) ->  Pin<Box<dyn Future<Output = ()>>> { | ||||
|     Box::pin(async_std::task::spawn(async move { | ||||
|         let listener = async_std::net::TcpListener::bind(&std::net::SocketAddr::from((std::net::Ipv4Addr::new(0,0,0,0), port))).await.unwrap(); | ||||
|         let mut id = 0; | ||||
| @ -210,7 +210,7 @@ pub fn login_listen_mainloop<EG: EntityGateway + 'static>(state: Arc<Mutex<Chara | ||||
|     })) | ||||
| } | ||||
| 
 | ||||
| pub fn ship_connect_mainloop<EG: EntityGateway + 'static>(state: Arc<Mutex<ShipServerState<EG>>>, ip: std::net::Ipv4Addr, port: u16) ->  Pin<Box<dyn Future<Output = ()>>> { | ||||
| pub fn ship_connect_mainloop<EG: EntityGateway + Clone + 'static>(state: Arc<Mutex<ShipServerState<EG>>>, ip: std::net::Ipv4Addr, port: u16) ->  Pin<Box<dyn Future<Output = ()>>> { | ||||
|     Box::pin(async_std::task::spawn(async move { | ||||
|         let mut id = 0; | ||||
|         let (server_state_sender, server_state_receiver) = async_std::channel::bounded(1024); | ||||
|  | ||||
| @ -23,13 +23,13 @@ pub fn patch_mainloop(patch_state: PatchServerState, patch_port: u16) -> Pin<Box | ||||
|     Box::pin(client_mainloop) | ||||
| } | ||||
| 
 | ||||
| pub fn login_mainloop<EG: EntityGateway + 'static>(login_state: LoginServerState<EG>, login_port: u16) -> Pin<Box<dyn Future<Output = ()>>> { | ||||
| pub fn login_mainloop<EG: EntityGateway + Clone + 'static>(login_state: LoginServerState<EG>, login_port: u16) -> Pin<Box<dyn Future<Output = ()>>> { | ||||
|     let login_state = Arc::new(Mutex::new(login_state)); | ||||
|     let client_mainloop = client_accept_mainloop(login_state, login_port); | ||||
|     Box::pin(client_mainloop) | ||||
| } | ||||
| 
 | ||||
| pub fn character_mainloop<EG: EntityGateway + 'static>(character_state: CharacterServerState<EG>, character_port: u16, comm_port: u16) -> Pin<Box<dyn Future<Output = ()>>> { | ||||
| pub fn character_mainloop<EG: EntityGateway + Clone + 'static>(character_state: CharacterServerState<EG>, character_port: u16, comm_port: u16) -> Pin<Box<dyn Future<Output = ()>>> { | ||||
|     let character_state = Arc::new(Mutex::new(character_state)); | ||||
|     let client_mainloop = client_accept_mainloop(character_state.clone(), character_port); | ||||
|     let ship_communication_mainloop = login_listen_mainloop(character_state, comm_port); | ||||
| @ -37,7 +37,7 @@ pub fn character_mainloop<EG: EntityGateway + 'static>(character_state: Characte | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| pub fn ship_mainloop<EG: EntityGateway + 'static>(ship_state: ShipServerState<EG>, ship_port: u16, comm_ip: std::net::Ipv4Addr, comm_port: u16) -> Pin<Box<dyn Future<Output = ()>>> { | ||||
| pub fn ship_mainloop<EG: EntityGateway + Clone + 'static>(ship_state: ShipServerState<EG>, ship_port: u16, comm_ip: std::net::Ipv4Addr, comm_port: u16) -> Pin<Box<dyn Future<Output = ()>>> { | ||||
|     let ship_state = Arc::new(Mutex::new(ship_state)); | ||||
|     let client_mainloop = client_accept_mainloop(ship_state.clone(), ship_port); | ||||
|     let login_communication_mainloop = ship_connect_mainloop(ship_state, comm_ip, comm_port); | ||||
|  | ||||
| @ -7,57 +7,199 @@ use crate::entity::character::*; | ||||
| use crate::entity::gateway::{EntityGateway, EntityGatewayTransaction, GatewayError}; | ||||
| use crate::entity::item::*; | ||||
| 
 | ||||
| use std::sync::{Arc, Mutex}; | ||||
| use async_std::sync::{Arc, Mutex}; | ||||
| 
 | ||||
| // TODO: implement multiple banks
 | ||||
| 
 | ||||
| pub struct InMemoryGatewayTransaction<'a> { | ||||
|     working_gateway: InMemoryGateway, | ||||
|     original_gateway: &'a mut InMemoryGateway, | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| fn copy_if_needed<K, V>(working_table: &mut BTreeMap<K, V>, original_table: &BTreeMap<K, V>, key: K) -> Option<()> | ||||
| where | ||||
|     K: Ord + Copy, | ||||
|     V: Clone, | ||||
| { | ||||
|     if let std::collections::btree_map::Entry::Vacant(e) = working_table.entry(key) { | ||||
|         e.insert(original_table.get(&key)?.clone()); | ||||
|     } | ||||
| 
 | ||||
|     Some(()) | ||||
| } | ||||
| 
 | ||||
| // functions here have been skipped as they are not used in transactions, add as needed
 | ||||
| #[async_trait::async_trait] | ||||
| impl<'a> EntityGateway for InMemoryGatewayTransaction<'a> { | ||||
|     async fn create_user(&mut self, user: NewUserAccountEntity) -> Result<UserAccountEntity, GatewayError> { | ||||
|         self.working_gateway.create_user(user).await | ||||
|     } | ||||
| 
 | ||||
|     async fn get_user_by_id(&mut self, id: UserAccountId) -> Result<UserAccountEntity, GatewayError> { | ||||
|         match self.working_gateway.get_user_by_id(id).await { | ||||
|             Ok(user) => Ok(user), | ||||
|             Err(_) => { | ||||
|                 self.original_gateway.get_user_by_id(id).await | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     async fn get_user_by_name(&mut self, username: String) -> Result<UserAccountEntity, GatewayError> { | ||||
|         match self.working_gateway.get_user_by_name(username.clone()).await { | ||||
|             Ok(user) => Ok(user), | ||||
|             Err(_) => { | ||||
|                 self.original_gateway.get_user_by_name(username).await | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     async fn save_user(&mut self, user: &UserAccountEntity) -> Result<(), GatewayError>  { | ||||
|         self.working_gateway.save_user(user).await | ||||
|     } | ||||
| 
 | ||||
|     async fn create_user_settings(&mut self, settings: NewUserSettingsEntity) -> Result<UserSettingsEntity, GatewayError> { | ||||
|         self.working_gateway.create_user_settings(settings).await | ||||
|     } | ||||
| 
 | ||||
|     async fn get_user_settings_by_user(&mut self, user: &UserAccountEntity) -> Result<UserSettingsEntity, GatewayError> { | ||||
|         match self.working_gateway.get_user_settings_by_user(user).await { | ||||
|             Ok(user) => Ok(user), | ||||
|             Err(_) => { | ||||
|                 self.original_gateway.get_user_settings_by_user(user).await | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     async fn save_character(&mut self, char: &CharacterEntity) -> Result<(), GatewayError>  { | ||||
|         copy_if_needed(&mut *self.working_gateway.characters.lock().await, | ||||
|                        &*self.original_gateway.characters.lock().await, | ||||
|                        char.id | ||||
|         ); | ||||
|         self.working_gateway.save_character(char).await | ||||
|     } | ||||
| 
 | ||||
|     async fn create_item(&mut self, item: NewItemEntity) -> Result<ItemEntity, GatewayError> { | ||||
|         self.working_gateway.create_item(item).await | ||||
|     } | ||||
| 
 | ||||
|     async fn add_item_note(&mut self, item_id: &ItemEntityId, item_note: ItemNote) -> Result<(), GatewayError> { | ||||
|         self.working_gateway.add_item_note(item_id, item_note).await | ||||
|     } | ||||
| 
 | ||||
|     async fn feed_mag(&mut self, mag_item_id: &ItemEntityId, tool_item_id: &ItemEntityId) -> Result<(), GatewayError> { | ||||
|         self.working_gateway.feed_mag(mag_item_id, tool_item_id).await | ||||
|     } | ||||
| 
 | ||||
|     async fn change_mag_owner(&mut self, mag_item_id: &ItemEntityId, character: &CharacterEntity) -> Result<(), GatewayError> { | ||||
|         self.working_gateway.change_mag_owner(mag_item_id, character).await | ||||
|     } | ||||
| 
 | ||||
|     async fn use_mag_cell(&mut self, mag_item_id: &ItemEntityId, mag_cell_id: &ItemEntityId) -> Result<(), GatewayError> { | ||||
|         self.working_gateway.use_mag_cell(mag_item_id, mag_cell_id).await | ||||
|     } | ||||
| 
 | ||||
|     async fn add_weapon_modifier(&mut self, item_id: &ItemEntityId, modifier: weapon::WeaponModifier) -> Result<(), GatewayError> { | ||||
|         self.working_gateway.add_weapon_modifier(item_id, modifier).await | ||||
|     } | ||||
| 
 | ||||
|     async fn get_character_inventory(&mut self, char_id: &CharacterEntityId) -> Result<InventoryEntity, GatewayError> { | ||||
|         match self.working_gateway.get_character_inventory(char_id).await { | ||||
|             Ok(inventory) => Ok(inventory), | ||||
|             Err(_) => { | ||||
|                 self.original_gateway.get_character_inventory(char_id).await | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     async fn get_character_bank(&mut self, char_id: &CharacterEntityId, bank_name: &BankName) -> Result<BankEntity, GatewayError> { | ||||
|         match self.working_gateway.get_character_bank(char_id, bank_name).await { | ||||
|             Ok(bank) => Ok(bank), | ||||
|             Err(_) => { | ||||
|                 self.original_gateway.get_character_bank(char_id, bank_name).await | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     async fn set_character_inventory(&mut self, char_id: &CharacterEntityId, inventory: &InventoryEntity) -> Result<(), GatewayError> { | ||||
|         self.working_gateway.set_character_inventory(char_id, inventory).await | ||||
|     } | ||||
| 
 | ||||
|     async fn set_character_bank(&mut self, char_id: &CharacterEntityId, bank: &BankEntity, bank_name: &BankName) -> Result<(), GatewayError> { | ||||
|         self.working_gateway.set_character_bank(char_id, bank, bank_name).await | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     async fn get_character_equips(&mut self, char_id: &CharacterEntityId) -> Result<EquippedEntity, GatewayError> { | ||||
|         match self.working_gateway.get_character_equips(char_id).await { | ||||
|             Ok(equips) => Ok(equips), | ||||
|             Err(_) => { | ||||
|                 self.original_gateway.get_character_equips(char_id).await | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     async fn set_character_equips(&mut self, char_id: &CharacterEntityId, equipped: &EquippedEntity) -> Result<(), GatewayError> { | ||||
|         self.working_gateway.set_character_equips(char_id, equipped).await | ||||
|     } | ||||
| 
 | ||||
|     async fn set_character_meseta(&mut self, char_id: &CharacterEntityId, meseta: Meseta) -> Result<(), GatewayError> { | ||||
|         self.working_gateway.set_character_meseta(char_id, meseta).await | ||||
|     } | ||||
| 
 | ||||
|     async fn get_character_meseta(&mut self, char_id: &CharacterEntityId) -> Result<Meseta, GatewayError> { | ||||
|         match self.working_gateway.get_character_meseta(char_id).await { | ||||
|             Ok(meseta) => Ok(meseta), | ||||
|             Err(_) => { | ||||
|                 self.original_gateway.get_character_meseta(char_id).await | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     async fn set_bank_meseta(&mut self, char_id: &CharacterEntityId, bank: &BankName, meseta: Meseta) -> Result<(), GatewayError> { | ||||
|         self.working_gateway.set_bank_meseta(char_id, bank, meseta).await | ||||
|     } | ||||
| 
 | ||||
|     async fn get_bank_meseta(&mut self, char_id: &CharacterEntityId, bank: &BankName) -> Result<Meseta, GatewayError> { | ||||
|         match self.working_gateway.get_bank_meseta(char_id, bank).await { | ||||
|             Ok(meseta) => Ok(meseta), | ||||
|             Err(_) => { | ||||
|                 self.original_gateway.get_bank_meseta(char_id, bank).await | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     async fn create_trade(&mut self, char_id1: &CharacterEntityId, char_id2: &CharacterEntityId) -> Result<TradeEntity, GatewayError> { | ||||
|         self.working_gateway.create_trade(char_id1, char_id2).await | ||||
|     } | ||||
| 
 | ||||
|     async fn set_character_playtime(&mut self, char_id: &CharacterEntityId, playtime: u32) -> Result<(), GatewayError> { | ||||
|         copy_if_needed(&mut *self.working_gateway.characters.lock().await, | ||||
|                        &*self.original_gateway.characters.lock().await, | ||||
|                        *char_id | ||||
|         ); | ||||
|         self.working_gateway.set_character_playtime(char_id, playtime).await | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[async_trait::async_trait] | ||||
| impl<'a> EntityGatewayTransaction for InMemoryGatewayTransaction<'a> { | ||||
|     fn gateway(&mut self) -> &mut dyn EntityGateway { | ||||
|         &mut self.working_gateway | ||||
|         self | ||||
|     } | ||||
| 
 | ||||
|     async fn commit(mut self: Box<Self>) -> Result<(), GatewayError> { | ||||
|         self.original_gateway.users.lock().unwrap().clear(); | ||||
|         self.original_gateway.users.lock().unwrap().extend(self.working_gateway.users.lock().unwrap().clone()); | ||||
| 
 | ||||
|         self.original_gateway.user_settings.lock().unwrap().clear(); | ||||
|         self.original_gateway.user_settings.lock().unwrap().extend(self.working_gateway.user_settings.lock().unwrap().clone()); | ||||
| 
 | ||||
|         self.original_gateway.characters.lock().unwrap().clear(); | ||||
|         self.original_gateway.characters.lock().unwrap().extend(self.working_gateway.characters.lock().unwrap().clone()); | ||||
| 
 | ||||
|         self.original_gateway.character_meseta.lock().unwrap().clear(); | ||||
|         self.original_gateway.character_meseta.lock().unwrap().extend(self.working_gateway.character_meseta.lock().unwrap().clone()); | ||||
| 
 | ||||
|         self.original_gateway.bank_meseta.lock().unwrap().clear(); | ||||
|         self.original_gateway.bank_meseta.lock().unwrap().extend(self.working_gateway.bank_meseta.lock().unwrap().clone()); | ||||
| 
 | ||||
|         self.original_gateway.items.lock().unwrap().clear(); | ||||
|         self.original_gateway.items.lock().unwrap().extend(self.working_gateway.items.lock().unwrap().clone()); | ||||
| 
 | ||||
|         self.original_gateway.inventories.lock().unwrap().clear(); | ||||
|         self.original_gateway.inventories.lock().unwrap().extend(self.working_gateway.inventories.lock().unwrap().clone()); | ||||
| 
 | ||||
|         self.original_gateway.banks.lock().unwrap().clear(); | ||||
|         self.original_gateway.banks.lock().unwrap().extend(self.working_gateway.banks.lock().unwrap().clone()); | ||||
| 
 | ||||
|         self.original_gateway.equips.lock().unwrap().clear(); | ||||
|         self.original_gateway.equips.lock().unwrap().extend(self.working_gateway.equips.lock().unwrap().clone()); | ||||
| 
 | ||||
|         self.original_gateway.mag_modifiers.lock().unwrap().clear(); | ||||
|         self.original_gateway.mag_modifiers.lock().unwrap().extend(self.working_gateway.mag_modifiers.lock().unwrap().clone()); | ||||
| 
 | ||||
|         self.original_gateway.weapon_modifiers.lock().unwrap().clear(); | ||||
|         self.original_gateway.weapon_modifiers.lock().unwrap().extend(self.working_gateway.weapon_modifiers.lock().unwrap().clone()); | ||||
| 
 | ||||
|         self.original_gateway.trades.lock().unwrap().clear(); | ||||
|         self.original_gateway.trades.lock().unwrap().extend(self.working_gateway.trades.lock().unwrap().clone()); | ||||
|         self.original_gateway.users.lock().await.extend(self.working_gateway.users.lock().await.clone()); | ||||
|         self.original_gateway.user_settings.lock().await.extend(self.working_gateway.user_settings.lock().await.clone()); | ||||
|         self.original_gateway.characters.lock().await.extend(self.working_gateway.characters.lock().await.clone()); | ||||
|         self.original_gateway.character_meseta.lock().await.extend(self.working_gateway.character_meseta.lock().await.clone()); | ||||
|         self.original_gateway.bank_meseta.lock().await.extend(self.working_gateway.bank_meseta.lock().await.clone()); | ||||
|         self.original_gateway.items.lock().await.extend(self.working_gateway.items.lock().await.clone()); | ||||
|         self.original_gateway.inventories.lock().await.extend(self.working_gateway.inventories.lock().await.clone()); | ||||
|         self.original_gateway.banks.lock().await.extend(self.working_gateway.banks.lock().await.clone()); | ||||
|         self.original_gateway.equips.lock().await.extend(self.working_gateway.equips.lock().await.clone()); | ||||
|         self.original_gateway.mag_modifiers.lock().await.extend(self.working_gateway.mag_modifiers.lock().await.clone()); | ||||
|         self.original_gateway.weapon_modifiers.lock().await.extend(self.working_gateway.weapon_modifiers.lock().await.clone()); | ||||
|         self.original_gateway.trades.lock().await.extend(self.working_gateway.trades.lock().await.clone()); | ||||
| 
 | ||||
|         Ok(()) | ||||
|     } | ||||
| @ -98,60 +240,60 @@ impl Default for InMemoryGateway { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl InMemoryGateway { | ||||
|     fn apply_modifiers(&self, inventory: InventoryEntity ) -> InventoryEntity { | ||||
|         let items = self.items.lock().unwrap(); | ||||
|         let inventory_items = inventory.items.into_iter() | ||||
|             .map(|item| { | ||||
|                 item.map_individual(|mut item| { | ||||
|                     item.item = match item.item { | ||||
|                         ItemDetail::Weapon(mut weapon) => { | ||||
|                             if let Some(weapon_modifiers) = self.weapon_modifiers.lock().unwrap().get(&item.id) { | ||||
|                                 for weapon_modifier in weapon_modifiers.iter() { | ||||
|                                     weapon.apply_modifier(weapon_modifier); | ||||
| fn apply_modifiers(items: &BTreeMap<ItemEntityId, ItemEntity>, | ||||
|                    weapon_modifiers: &BTreeMap<ItemEntityId, Vec<weapon::WeaponModifier>>, | ||||
|                    mag_modifiers: &BTreeMap<ItemEntityId, Vec<mag::MagModifier>>, | ||||
|                    inventory: InventoryEntity ) -> InventoryEntity { | ||||
|     let inventory_items = inventory.items.into_iter() | ||||
|         .map(|item| { | ||||
|             item.map_individual(|mut item| { | ||||
|                 item.item = match item.item { | ||||
|                     ItemDetail::Weapon(mut weapon) => { | ||||
|                         if let Some(weapon_modifiers) = weapon_modifiers.get(&item.id) { | ||||
|                             for weapon_modifier in weapon_modifiers.iter() { | ||||
|                                 weapon.apply_modifier(weapon_modifier); | ||||
|                             } | ||||
|                         } | ||||
|                         ItemDetail::Weapon(weapon) | ||||
|                     }, | ||||
|                     ItemDetail::Mag(mag) => { | ||||
|                         let mut mag = mag::Mag::baby_mag(mag.color as u16); | ||||
|                         if let Some(mag_modifiers) = mag_modifiers.get(&item.id) { | ||||
|                             for mag_modifier in mag_modifiers.iter() { | ||||
|                                 match mag_modifier { | ||||
|                                     mag::MagModifier::FeedMag {food} => { | ||||
|                                         if let Some(mag_feed) = items.get(food) { | ||||
|                                             if let ItemDetail::Tool(mag_feed) = mag_feed.item { | ||||
|                                                 mag.feed(mag_feed.tool) | ||||
|                                             } | ||||
|                                         } | ||||
|                                     }, | ||||
|                                     mag::MagModifier::OwnerChange(class, section_id) => { | ||||
|                                         mag.change_owner(*class, *section_id) | ||||
|                                     }, | ||||
|                                     mag::MagModifier::MagCell(mag_cell_id) => { | ||||
|                                         if let Some(mag_cell) = items.get(mag_cell_id) { | ||||
|                                             if let ItemDetail::Tool(mag_cell) = mag_cell.item { | ||||
|                                                 mag.apply_mag_cell(mag_cell.tool.try_into().unwrap()).unwrap() | ||||
|                                             } | ||||
|                                         } | ||||
|                                     }, | ||||
|                                     _ => {} | ||||
|                                 } | ||||
|                             } | ||||
|                             ItemDetail::Weapon(weapon) | ||||
|                         }, | ||||
|                         ItemDetail::Mag(mag) => { | ||||
|                             let mut mag = mag::Mag::baby_mag(mag.color as u16); | ||||
|                             if let Some(mag_modifiers) = self.mag_modifiers.lock().unwrap().get(&item.id) { | ||||
|                                 for mag_modifier in mag_modifiers.iter() { | ||||
|                                     match mag_modifier { | ||||
|                                         mag::MagModifier::FeedMag {food} => { | ||||
|                                             if let Some(mag_feed) = items.get(food) { | ||||
|                                                 if let ItemDetail::Tool(mag_feed) = mag_feed.item { | ||||
|                                                     mag.feed(mag_feed.tool) | ||||
|                                                 } | ||||
|                                             } | ||||
|                                         }, | ||||
|                                         mag::MagModifier::OwnerChange(class, section_id) => { | ||||
|                                             mag.change_owner(*class, *section_id) | ||||
|                                         }, | ||||
|                                         mag::MagModifier::MagCell(mag_cell_id) => { | ||||
|                                             if let Some(mag_cell) = items.get(mag_cell_id) { | ||||
|                                                 if let ItemDetail::Tool(mag_cell) = mag_cell.item { | ||||
|                                                     mag.apply_mag_cell(mag_cell.tool.try_into().unwrap()).unwrap() | ||||
|                                                 } | ||||
|                                             } | ||||
|                                         }, | ||||
|                                         _ => {} | ||||
|                                     } | ||||
|                                 } | ||||
|                             } | ||||
|                             ItemDetail::Mag(mag) | ||||
|                         } | ||||
|                         _ => { | ||||
|                             item.item | ||||
|                         } | ||||
|                     }; | ||||
|                         ItemDetail::Mag(mag) | ||||
|                     } | ||||
|                     _ => { | ||||
|                         item.item | ||||
|                     } | ||||
|                 }; | ||||
| 
 | ||||
|                     item | ||||
|                 }) | ||||
|                 item | ||||
|             }) | ||||
|             .collect(); | ||||
|         InventoryEntity::new(inventory_items) | ||||
|     } | ||||
|         }) | ||||
|         .collect(); | ||||
|     InventoryEntity::new(inventory_items) | ||||
| } | ||||
| 
 | ||||
| #[async_trait::async_trait] | ||||
| @ -159,18 +301,18 @@ impl EntityGateway for InMemoryGateway { | ||||
|     async fn transaction<'a>(&'a mut self) -> Result<Box<dyn EntityGatewayTransaction + 'a>, GatewayError> | ||||
|     { | ||||
|         let working_gateway = { | ||||
|             let users = self.users.lock().unwrap().clone(); | ||||
|             let user_settings = self.user_settings.lock().unwrap().clone(); | ||||
|             let characters = self.characters.lock().unwrap().clone(); | ||||
|             let character_meseta = self.character_meseta.lock().unwrap().clone(); | ||||
|             let bank_meseta = self.bank_meseta.lock().unwrap().clone(); | ||||
|             let items = self.items.lock().unwrap().clone(); | ||||
|             let inventories = self.inventories.lock().unwrap().clone(); | ||||
|             let banks = self.banks.lock().unwrap().clone(); | ||||
|             let equips = self.equips.lock().unwrap().clone(); | ||||
|             let mag_modifiers = self.mag_modifiers.lock().unwrap().clone(); | ||||
|             let weapon_modifiers = self.weapon_modifiers.lock().unwrap().clone(); | ||||
|             let trades = self.trades.lock().unwrap().clone(); | ||||
|             let users = self.users.lock().await.clone(); | ||||
|             let user_settings = self.user_settings.lock().await.clone(); | ||||
|             let characters = self.characters.lock().await.clone(); | ||||
|             let character_meseta = self.character_meseta.lock().await.clone(); | ||||
|             let bank_meseta = self.bank_meseta.lock().await.clone(); | ||||
|             let items = self.items.lock().await.clone(); | ||||
|             let inventories = self.inventories.lock().await.clone(); | ||||
|             let banks = self.banks.lock().await.clone(); | ||||
|             let equips = self.equips.lock().await.clone(); | ||||
|             let mag_modifiers = self.mag_modifiers.lock().await.clone(); | ||||
|             let weapon_modifiers = self.weapon_modifiers.lock().await.clone(); | ||||
|             let trades = self.trades.lock().await.clone(); | ||||
| 
 | ||||
|             InMemoryGateway { | ||||
|                 users: Arc::new(Mutex::new(users)), | ||||
| @ -202,18 +344,18 @@ impl EntityGateway for InMemoryGateway { | ||||
|         R: Send, | ||||
|         E: From<GatewayError>, | ||||
|     { | ||||
|         let users = self.users.lock().unwrap().clone(); | ||||
|         let user_settings = self.user_settings.lock().unwrap().clone(); | ||||
|         let characters = self.characters.lock().unwrap().clone(); | ||||
|         let character_meseta = self.character_meseta.lock().unwrap().clone(); | ||||
|         let bank_meseta = self.bank_meseta.lock().unwrap().clone(); | ||||
|         let items = self.items.lock().unwrap().clone(); | ||||
|         let inventories = self.inventories.lock().unwrap().clone(); | ||||
|         let banks = self.banks.lock().unwrap().clone(); | ||||
|         let equips = self.equips.lock().unwrap().clone(); | ||||
|         let mag_modifiers = self.mag_modifiers.lock().unwrap().clone(); | ||||
|         let weapon_modifiers = self.weapon_modifiers.lock().unwrap().clone(); | ||||
|         let trades = self.trades.lock().unwrap().clone(); | ||||
|         let users = self.users.lock().await.clone(); | ||||
|         let user_settings = self.user_settings.lock().await.clone(); | ||||
|         let characters = self.characters.lock().await.clone(); | ||||
|         let character_meseta = self.character_meseta.lock().await.clone(); | ||||
|         let bank_meseta = self.bank_meseta.lock().await.clone(); | ||||
|         let items = self.items.lock().await.clone(); | ||||
|         let inventories = self.inventories.lock().await.clone(); | ||||
|         let banks = self.banks.lock().await.clone(); | ||||
|         let equips = self.equips.lock().await.clone(); | ||||
|         let mag_modifiers = self.mag_modifiers.lock().await.clone(); | ||||
|         let weapon_modifiers = self.weapon_modifiers.lock().await.clone(); | ||||
|         let trades = self.trades.lock().await.clone(); | ||||
| 
 | ||||
|         let working_gateway = InMemoryGateway { | ||||
|             users: Arc::new(Mutex::new(users)), | ||||
| @ -242,7 +384,7 @@ impl EntityGateway for InMemoryGateway { | ||||
|     } | ||||
| 
 | ||||
|     async fn create_user(&mut self, user: NewUserAccountEntity) -> Result<UserAccountEntity, GatewayError> { | ||||
|         let mut users = self.users.lock().unwrap(); | ||||
|         let mut users = self.users.lock().await; | ||||
|         let id = users | ||||
|             .iter() | ||||
|             .fold(0, |sum, (i, _)| std::cmp::max(sum, i.0)) | ||||
| @ -267,12 +409,12 @@ impl EntityGateway for InMemoryGateway { | ||||
|     } | ||||
| 
 | ||||
|     async fn get_user_by_id(&mut self, id: UserAccountId) -> Result<UserAccountEntity, GatewayError> { | ||||
|         let users = self.users.lock().unwrap(); | ||||
|         let users = self.users.lock().await; | ||||
|         users.get(&id).cloned().ok_or(GatewayError::Error) | ||||
|     } | ||||
| 
 | ||||
|     async fn get_user_by_name(&mut self, username: String) -> Result<UserAccountEntity, GatewayError> { | ||||
|         let users = self.users.lock().unwrap(); | ||||
|         let users = self.users.lock().await; | ||||
|         users | ||||
|             .iter() | ||||
|             .find(|(_, k)| k.username == username) | ||||
| @ -281,13 +423,13 @@ impl EntityGateway for InMemoryGateway { | ||||
|     } | ||||
| 
 | ||||
|     async fn save_user(&mut self, user: &UserAccountEntity) -> Result<(), GatewayError>  { | ||||
|         let mut users = self.users.lock().unwrap(); | ||||
|         let mut users = self.users.lock().await; | ||||
|         users.insert(user.id, user.clone()); | ||||
|         Ok(()) | ||||
|     } | ||||
| 
 | ||||
|     async fn create_user_settings(&mut self, settings: NewUserSettingsEntity) -> Result<UserSettingsEntity, GatewayError> { | ||||
|         let mut user_settings = self.user_settings.lock().unwrap(); | ||||
|         let mut user_settings = self.user_settings.lock().await; | ||||
|         let id = user_settings | ||||
|             .iter() | ||||
|             .fold(0, |sum, (i, _)| std::cmp::max(sum, i.0)) | ||||
| @ -302,7 +444,7 @@ impl EntityGateway for InMemoryGateway { | ||||
|     } | ||||
| 
 | ||||
|     async fn get_user_settings_by_user(&mut self, user: &UserAccountEntity) -> Result<UserSettingsEntity, GatewayError> { | ||||
|         let user_settings = self.user_settings.lock().unwrap(); | ||||
|         let user_settings = self.user_settings.lock().await; | ||||
|         user_settings | ||||
|             .iter() | ||||
|             .find(|(_, k)| k.user_id == user.id) | ||||
| @ -311,7 +453,7 @@ impl EntityGateway for InMemoryGateway { | ||||
|     } | ||||
| 
 | ||||
|     async fn get_characters_by_user(&mut self, user: &UserAccountEntity) -> Result<[Option<CharacterEntity>; 4], GatewayError> { | ||||
|         let characters = self.characters.lock().unwrap(); | ||||
|         let characters = self.characters.lock().await; | ||||
|         const NONE: Option<CharacterEntity> = None; | ||||
|         let mut chars = [NONE; 4]; | ||||
|         characters | ||||
| @ -322,7 +464,7 @@ impl EntityGateway for InMemoryGateway { | ||||
|     } | ||||
| 
 | ||||
|     async fn create_character(&mut self, character: NewCharacterEntity) -> Result<CharacterEntity, GatewayError> { | ||||
|         let mut characters = self.characters.lock().unwrap(); | ||||
|         let mut characters = self.characters.lock().await; | ||||
|         let id = characters | ||||
|             .iter() | ||||
|             .fold(0, |sum, (i, _)| std::cmp::max(sum, i.0)) | ||||
| @ -353,7 +495,7 @@ impl EntityGateway for InMemoryGateway { | ||||
|     } | ||||
| 
 | ||||
|     async fn save_character(&mut self, char: &CharacterEntity) -> Result<(), GatewayError>  { | ||||
|         let mut characters = self.characters.lock().unwrap(); | ||||
|         let mut characters = self.characters.lock().await; | ||||
|         characters.insert(char.id, char.clone()); | ||||
|         Ok(()) | ||||
|     } | ||||
| @ -363,7 +505,7 @@ impl EntityGateway for InMemoryGateway { | ||||
|     } | ||||
| 
 | ||||
|     async fn create_item(&mut self, item: NewItemEntity) -> Result<ItemEntity, GatewayError> { | ||||
|         let mut items = self.items.lock().unwrap(); | ||||
|         let mut items = self.items.lock().await; | ||||
|         let id = items | ||||
|             .iter() | ||||
|             .fold(0, |sum, (i, _)| std::cmp::max(sum, i.0)) | ||||
| @ -381,7 +523,7 @@ impl EntityGateway for InMemoryGateway { | ||||
|     } | ||||
| 
 | ||||
|     async fn feed_mag(&mut self, mag_item_id: &ItemEntityId, tool_item_id: &ItemEntityId) -> Result<(), GatewayError> { | ||||
|         self.mag_modifiers.lock().unwrap() | ||||
|         self.mag_modifiers.lock().await | ||||
|             .entry(*mag_item_id) | ||||
|             .or_insert_with(Vec::new) | ||||
|             .push(mag::MagModifier::FeedMag { | ||||
| @ -391,7 +533,7 @@ impl EntityGateway for InMemoryGateway { | ||||
|     } | ||||
| 
 | ||||
|     async fn change_mag_owner(&mut self, mag_item_id: &ItemEntityId, character: &CharacterEntity) -> Result<(), GatewayError> { | ||||
|         self.mag_modifiers.lock().unwrap() | ||||
|         self.mag_modifiers.lock().await | ||||
|             .entry(*mag_item_id) | ||||
|             .or_insert_with(Vec::new) | ||||
|             .push(mag::MagModifier::OwnerChange(character.char_class, character.section_id)); | ||||
| @ -399,7 +541,7 @@ impl EntityGateway for InMemoryGateway { | ||||
|     } | ||||
| 
 | ||||
|     async fn use_mag_cell(&mut self, mag_item_id: &ItemEntityId, mag_cell_id: &ItemEntityId) -> Result<(), GatewayError> { | ||||
|         self.mag_modifiers.lock().unwrap() | ||||
|         self.mag_modifiers.lock().await | ||||
|             .entry(*mag_item_id) | ||||
|             .or_insert_with(Vec::new) | ||||
|             .push(mag::MagModifier::MagCell(*mag_cell_id)); | ||||
| @ -407,7 +549,7 @@ impl EntityGateway for InMemoryGateway { | ||||
|     } | ||||
| 
 | ||||
|     async fn add_weapon_modifier(&mut self, item_id: &ItemEntityId, modifier: weapon::WeaponModifier) -> Result<(), GatewayError> { | ||||
|         self.weapon_modifiers.lock().unwrap() | ||||
|         self.weapon_modifiers.lock().await | ||||
|             .entry(*item_id) | ||||
|             .or_insert_with(Vec::new) | ||||
|             .push(modifier); | ||||
| @ -415,17 +557,20 @@ impl EntityGateway for InMemoryGateway { | ||||
|     } | ||||
| 
 | ||||
|     async fn get_character_inventory(&mut self, char_id: &CharacterEntityId) -> Result<InventoryEntity, GatewayError> { | ||||
|         let inventories = self.inventories.lock().unwrap(); | ||||
|         let inventories = self.inventories.lock().await; | ||||
|         let items = self.items.lock().await; | ||||
|         let weapon_modifiers = self.weapon_modifiers.lock().await; | ||||
|         let mag_modifiers = self.mag_modifiers.lock().await; | ||||
|         Ok(inventories | ||||
|            .iter() | ||||
|            .find(|(id, _)| **id == *char_id) | ||||
|            .map(|(_, inv)| inv.clone()) | ||||
|            .map(|inv| self.apply_modifiers(inv)) | ||||
|            .map(|inv| apply_modifiers(&items, &weapon_modifiers, &mag_modifiers, inv)) | ||||
|            .unwrap_or_default()) | ||||
|     } | ||||
| 
 | ||||
|     async fn get_character_bank(&mut self, char_id: &CharacterEntityId, _bank_name: &BankName) -> Result<BankEntity, GatewayError> { | ||||
|         let banks = self.banks.lock().unwrap(); | ||||
|         let banks = self.banks.lock().await; | ||||
|         Ok(banks | ||||
|            .iter() | ||||
|            .find(|(id, _)| **id == *char_id) | ||||
| @ -434,20 +579,20 @@ impl EntityGateway for InMemoryGateway { | ||||
|     } | ||||
| 
 | ||||
|     async fn set_character_inventory(&mut self, char_id: &CharacterEntityId, inventory: &InventoryEntity) -> Result<(), GatewayError> { | ||||
|         let mut inventories = self.inventories.lock().unwrap(); | ||||
|         let mut inventories = self.inventories.lock().await; | ||||
|         inventories.insert(*char_id, inventory.clone()); | ||||
|         Ok(()) | ||||
|     } | ||||
| 
 | ||||
|     // TOOD: impl bank name
 | ||||
|     async fn set_character_bank(&mut self, char_id: &CharacterEntityId, bank: &BankEntity, _bank_name: &BankName) -> Result<(), GatewayError> { | ||||
|         let mut banks = self.banks.lock().unwrap(); | ||||
|         let mut banks = self.banks.lock().await; | ||||
|         banks.insert(*char_id, bank.clone()); | ||||
|         Ok(()) | ||||
|     } | ||||
| 
 | ||||
|     async fn get_character_equips(&mut self, char_id: &CharacterEntityId) -> Result<EquippedEntity, GatewayError> { | ||||
|         let equips = self.equips.lock().unwrap(); | ||||
|         let equips = self.equips.lock().await; | ||||
|         Ok(equips | ||||
|             .iter() | ||||
|             .find(|(id, _)| **id == *char_id) | ||||
| @ -456,19 +601,19 @@ impl EntityGateway for InMemoryGateway { | ||||
|     } | ||||
| 
 | ||||
|     async fn set_character_equips(&mut self, char_id: &CharacterEntityId, equipped: &EquippedEntity) -> Result<(), GatewayError> { | ||||
|         let mut equips = self.equips.lock().unwrap(); | ||||
|         let mut equips = self.equips.lock().await; | ||||
|         equips.insert(*char_id, equipped.clone()); | ||||
|         Ok(()) | ||||
|     } | ||||
| 
 | ||||
|     async fn set_character_meseta(&mut self, char_id: &CharacterEntityId, meseta: Meseta) -> Result<(), GatewayError> { | ||||
|         let mut character_meseta = self.character_meseta.lock().unwrap(); | ||||
|         let mut character_meseta = self.character_meseta.lock().await; | ||||
|         character_meseta.insert(*char_id, meseta); | ||||
|         Ok(()) | ||||
|     } | ||||
| 
 | ||||
|     async fn get_character_meseta(&mut self, char_id: &CharacterEntityId) -> Result<Meseta, GatewayError> { | ||||
|         let mut character_meseta = self.character_meseta.lock().unwrap(); | ||||
|         let mut character_meseta = self.character_meseta.lock().await; | ||||
|         if let Some(meseta) = character_meseta.get_mut(char_id) { | ||||
|             Ok(*meseta) | ||||
|         } | ||||
| @ -478,13 +623,13 @@ impl EntityGateway for InMemoryGateway { | ||||
|     } | ||||
| 
 | ||||
|     async fn set_bank_meseta(&mut self, char_id: &CharacterEntityId, bank: &BankName, meseta: Meseta) -> Result<(), GatewayError> { | ||||
|         let mut bank_meseta = self.bank_meseta.lock().unwrap(); | ||||
|         let mut bank_meseta = self.bank_meseta.lock().await; | ||||
|         bank_meseta.insert((*char_id, bank.clone()), meseta); | ||||
|         Ok(()) | ||||
|     } | ||||
| 
 | ||||
|     async fn get_bank_meseta(&mut self, char_id: &CharacterEntityId, bank: &BankName) -> Result<Meseta, GatewayError> { | ||||
|         let mut bank_meseta = self.bank_meseta.lock().unwrap(); | ||||
|         let mut bank_meseta = self.bank_meseta.lock().await; | ||||
|         if let Some(meseta) = bank_meseta.get_mut(&(*char_id, bank.clone())) { | ||||
|             Ok(*meseta) | ||||
|         } | ||||
| @ -494,7 +639,7 @@ impl EntityGateway for InMemoryGateway { | ||||
|     } | ||||
| 
 | ||||
|     async fn create_trade(&mut self, char_id1: &CharacterEntityId, char_id2: &CharacterEntityId) -> Result<TradeEntity, GatewayError> { | ||||
|         let mut trades = self.trades.lock().unwrap(); | ||||
|         let mut trades = self.trades.lock().await; | ||||
|         let id = trades.len() as u32; | ||||
|         let new_trade = TradeEntity { | ||||
|             id: TradeId(id), | ||||
| @ -506,7 +651,7 @@ impl EntityGateway for InMemoryGateway { | ||||
|     } | ||||
| 
 | ||||
|     async fn set_character_playtime(&mut self, char_id: &CharacterEntityId, playtime: u32) -> Result<(), GatewayError> { | ||||
|         let mut characters = self.characters.lock().unwrap(); | ||||
|         let mut characters = self.characters.lock().await; | ||||
|         if let Some(character) = characters.get_mut(char_id) { | ||||
|             character.playtime = playtime; | ||||
|             Ok(()) | ||||
|  | ||||
| @ -10,14 +10,14 @@ use crate::common::interserver::ShipMessage; | ||||
| #[allow(clippy::too_many_arguments)] | ||||
| pub async fn validate_login<EG: EntityGateway>(id: ClientId, | ||||
|                                                pkt: &Login, | ||||
|                                                entity_gateway: &mut EG, | ||||
|                                                mut entity_gateway: EG, | ||||
|                                                clients: &mut Clients, | ||||
|                                                item_state: &mut ItemState, | ||||
|                                                shipgate_sender: &Option<Box<dyn Fn(ShipMessage) + Send + Sync>>, | ||||
|                                                ship_name: &str, | ||||
|                                                num_blocks: usize) | ||||
|                                          -> Result<Vec<SendShipPacket>, anyhow::Error> { | ||||
|     Ok(match get_login_status(entity_gateway, pkt).await { | ||||
|     Ok(match get_login_status(&mut entity_gateway, pkt).await { | ||||
|         Ok(user) => { | ||||
|             let mut response = LoginResponse::by_status(AccountStatus::Ok, Session::new()); | ||||
|             response.guildcard = user.id.0 as u32; | ||||
| @ -30,7 +30,7 @@ pub async fn validate_login<EG: EntityGateway>(id: ClientId, | ||||
|                 .clone(); | ||||
|             let settings = entity_gateway.get_user_settings_by_user(&user).await?; | ||||
| 
 | ||||
|             item_state.load_character(entity_gateway, &character).await?; | ||||
|             item_state.load_character(&mut entity_gateway, &character).await?; | ||||
| 
 | ||||
|             if let Some(shipgate_sender) = shipgate_sender.as_ref() { | ||||
|                 shipgate_sender(ShipMessage::AddUser(user.id)); | ||||
|  | ||||
| @ -38,7 +38,7 @@ pub fn request_infoboard(id: ClientId, | ||||
| pub async fn write_infoboard<EG: EntityGateway>(id: ClientId, | ||||
|                                           new_infoboard: &WriteInfoboard, | ||||
|                                           clients: &mut Clients, | ||||
|                                           entity_gateway: &mut EG) | ||||
|                                           mut entity_gateway: EG) | ||||
|                        -> Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send> { | ||||
|     let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id)).unwrap(); | ||||
|     client.character.info_board.update_infoboard(new_infoboard); | ||||
|  | ||||
| @ -70,7 +70,7 @@ pub fn guildcard_send(id: ClientId, | ||||
| 
 | ||||
| pub async fn request_item<EG>(id: ClientId, | ||||
|                               request_item: &RequestItem, | ||||
|                               entity_gateway: &mut EG, | ||||
|                               mut entity_gateway: EG, | ||||
|                               client_location: &ClientLocation, | ||||
|                               clients: &mut Clients, | ||||
|                               rooms: &mut Rooms, | ||||
| @ -109,7 +109,7 @@ where | ||||
|             item: item_drop, | ||||
|         }; | ||||
|         let client = clients.get_mut(&area_client.client).ok_or(ShipError::ClientNotFound(area_client.client))?; | ||||
|         let floor_item = enemy_drops_item(item_state, entity_gateway, client.character.id, item_drop).await?; | ||||
|         let floor_item = enemy_drops_item(item_state, &mut entity_gateway, client.character.id, item_drop).await?; | ||||
|         let item_drop_msg = builder::message::item_drop(request_item.client, request_item.target, &floor_item)?; | ||||
| 
 | ||||
|         item_drop_packets.push((area_client.client, SendShipPacket::Message(Message::new(GameMessage::ItemDrop(item_drop_msg))))); | ||||
| @ -120,7 +120,7 @@ where | ||||
| 
 | ||||
| pub async fn pickup_item<EG>(id: ClientId, | ||||
|                              pickup_item: &PickupItem, | ||||
|                              entity_gateway: &mut EG, | ||||
|                              mut entity_gateway: EG, | ||||
|                              client_location: &ClientLocation, | ||||
|                              clients: &mut Clients, | ||||
|                              item_state: &mut ItemState) | ||||
| @ -133,30 +133,15 @@ where | ||||
|     let room_id = client_location.get_room(id).map_err(|err| -> ClientLocationError { err.into() })?; | ||||
|     let clients_in_area = client_location.get_clients_in_room(room_id).map_err(|err| -> ClientLocationError { err.into() })?; | ||||
| 
 | ||||
|     // TODO: should not need to fetch the item here to construct this packet
 | ||||
|     //let (item, floor_type) = item_manager.get_floor_item_by_id(&client.character, ClientItemId(pickup_item.item_id))?;
 | ||||
|     /* | ||||
|     let (item, floor_type) = item_state.get_floor_item(&client.character, &ClientItemId(pickup_item.item_id))?; | ||||
|     let remove_item = builder::message::remove_item_from_floor(area_client, item)?; | ||||
|     let create_item = match item { | ||||
|         FloorItem::Individual(individual_floor_item) => Some(builder::message::create_individual_item(area_client, item.item_id(), &individual_floor_item.item)?), | ||||
|         FloorItem::Stacked(stacked_floor_item) => Some(builder::message::create_stacked_item(area_client, item.item_id(), &stacked_floor_item.tool, stacked_floor_item.count())?), | ||||
|         FloorItem::Meseta(_) => None, | ||||
|         //_ => Some(builder::message::create_item(area_client, &item)?),
 | ||||
|     }; | ||||
|      */ | ||||
| 
 | ||||
|     let (item, floor_type) = item_state.get_floor_item(&client.character.id, &ClientItemId(pickup_item.item_id))?; | ||||
|     let remove_item = builder::message::remove_item_from_floor(area_client, item)?; | ||||
|     let create_item = match &item.item { | ||||
|         FloorItemDetail::Individual(individual_floor_item) => Some(builder::message::create_individual_item(area_client, item.item_id, individual_floor_item)?), | ||||
|         FloorItemDetail::Stacked(stacked_floor_item) => Some(builder::message::create_stacked_item(area_client, item.item_id, &stacked_floor_item.tool, stacked_floor_item.count())?), | ||||
|         FloorItemDetail::Meseta(_) => None, | ||||
|         //_ => Some(builder::message::create_item(area_client, &item)?),
 | ||||
|     }; | ||||
| 
 | ||||
|     //match item_manager.character_picks_up_item(entity_gateway, &mut client.character, ClientItemId(pickup_item.item_id)).await {
 | ||||
|     match pick_up_item(item_state, entity_gateway, &client.character, &ClientItemId(pickup_item.item_id)).await { | ||||
|     match pick_up_item(item_state, &mut entity_gateway, &client.character, &ClientItemId(pickup_item.item_id)).await { | ||||
|         Ok(trigger_create_item) => { | ||||
|             let remove_packets: Box<dyn Iterator<Item=(ClientId, SendShipPacket)> + Send> = match floor_type { | ||||
|                 FloorType::Local => { | ||||
| @ -189,7 +174,7 @@ where | ||||
| 
 | ||||
| pub async fn request_box_item<EG>(id: ClientId, | ||||
|     box_drop_request: &BoxDropRequest, | ||||
|     entity_gateway: &mut EG, | ||||
|     mut entity_gateway: EG, | ||||
|     client_location: &ClientLocation, | ||||
|     clients: &mut Clients, | ||||
|     rooms: &mut Rooms, | ||||
| @ -228,7 +213,7 @@ EG: EntityGateway | ||||
|             item: item_drop, | ||||
|         }; | ||||
|         let client = clients.get_mut(&area_client.client).ok_or(ShipError::ClientNotFound(area_client.client))?; | ||||
|         let floor_item = enemy_drops_item(item_state, entity_gateway, client.character.id, item_drop).await?; | ||||
|         let floor_item = enemy_drops_item(item_state, &mut entity_gateway, client.character.id, item_drop).await?; | ||||
|         let item_drop_msg = builder::message::item_drop(box_drop_request.client, box_drop_request.target, &floor_item)?; | ||||
|         item_drop_packets.push((area_client.client, SendShipPacket::Message(Message::new(GameMessage::ItemDrop(item_drop_msg))))) | ||||
|     } | ||||
| @ -251,7 +236,7 @@ pub async fn send_bank_list(id: ClientId, | ||||
| 
 | ||||
| pub async fn bank_interaction<EG>(id: ClientId, | ||||
|                                   bank_interaction: &BankInteraction, | ||||
|                                   entity_gateway: &mut EG, | ||||
|                                   mut entity_gateway: EG, | ||||
|                                   client_location: &ClientLocation, | ||||
|                                   clients: &mut Clients, | ||||
|                                   item_state: &mut ItemState) | ||||
| @ -265,22 +250,22 @@ where | ||||
|     let bank_action_pkts = match bank_interaction.action { | ||||
|         BANK_ACTION_DEPOSIT => { | ||||
|             if bank_interaction.item_id == 0xFFFFFFFF { | ||||
|                 deposit_meseta(item_state, entity_gateway, &client.character, bank_interaction.meseta_amount).await?; | ||||
|                 deposit_meseta(item_state, &mut entity_gateway, &client.character, bank_interaction.meseta_amount).await?; | ||||
|                 Vec::new() | ||||
|             } | ||||
|             else { | ||||
|                 deposit_item(item_state, entity_gateway, &client.character, &ClientItemId(bank_interaction.item_id), bank_interaction.item_amount as u32).await?; | ||||
|                 deposit_item(item_state, &mut entity_gateway, &client.character, &ClientItemId(bank_interaction.item_id), bank_interaction.item_amount as u32).await?; | ||||
|                 let player_no_longer_has_item = builder::message::player_no_longer_has_item(area_client, ClientItemId(bank_interaction.item_id), bank_interaction.item_amount as u32); | ||||
|                 vec![SendShipPacket::Message(Message::new(GameMessage::PlayerNoLongerHasItem(player_no_longer_has_item)))] | ||||
|             } | ||||
|         }, | ||||
|         BANK_ACTION_WITHDRAW => { | ||||
|             if bank_interaction.item_id == 0xFFFFFFFF { | ||||
|                 withdraw_meseta(item_state, entity_gateway, &client.character, bank_interaction.meseta_amount).await?; | ||||
|                 withdraw_meseta(item_state, &mut entity_gateway, &client.character, bank_interaction.meseta_amount).await?; | ||||
|                 Vec::new() | ||||
|             } | ||||
|             else { | ||||
|                 let item_added_to_inventory = withdraw_item(item_state, entity_gateway, &client.character, &ClientItemId(bank_interaction.item_id), bank_interaction.item_amount as u32).await?; | ||||
|                 let item_added_to_inventory = withdraw_item(item_state, &mut entity_gateway, &client.character, &ClientItemId(bank_interaction.item_id), bank_interaction.item_amount as u32).await?; | ||||
|                 let item_created = builder::message::create_withdrawn_inventory_item2(area_client, &item_added_to_inventory)?; | ||||
|                 vec![SendShipPacket::Message(Message::new(GameMessage::CreateItem(item_created)))] | ||||
|             } | ||||
| @ -342,7 +327,7 @@ pub async fn shop_request(id: ClientId, | ||||
| 
 | ||||
| pub async fn buy_item<EG>(id: ClientId, | ||||
|                           buy_item: &BuyItem, | ||||
|                           entity_gateway: &mut EG, | ||||
|                           mut entity_gateway: EG, | ||||
|                           client_location: &ClientLocation, | ||||
|                           clients: &mut Clients, | ||||
|                           item_state: &mut ItemState) | ||||
| @ -372,7 +357,7 @@ where | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     let inventory_item = buy_shop_item(item_state, entity_gateway, &client.character, item, ClientItemId(buy_item.item_id), buy_item.amount as u32).await?; | ||||
|     let inventory_item = buy_shop_item(item_state, &mut entity_gateway, &client.character, item, ClientItemId(buy_item.item_id), buy_item.amount as u32).await?; | ||||
|     let create = builder::message::create_withdrawn_inventory_item(area_client, &inventory_item)?; | ||||
| 
 | ||||
|     if remove { | ||||
| @ -407,7 +392,7 @@ const TEK_PERCENT_MODIFIER: [item::weapon::TekPercentModifier; 5] = [item::weapo | ||||
| 
 | ||||
| pub async fn request_tek_item<EG>(id: ClientId, | ||||
|                                   tek_request: &TekRequest, | ||||
|                                   entity_gateway: &mut EG, | ||||
|                                   mut entity_gateway: EG, | ||||
|                                   clients: &mut Clients, | ||||
|                                   item_state: &mut ItemState) | ||||
|                                   -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error> | ||||
| @ -441,7 +426,7 @@ where | ||||
|         grind: grind_mod, | ||||
|     }); | ||||
| 
 | ||||
|     take_meseta(item_state, entity_gateway, &client.character.id, item::Meseta(100)).await?; | ||||
|     take_meseta(item_state, &mut entity_gateway, &client.character.id, item::Meseta(100)).await?; | ||||
| 
 | ||||
|     let preview_pkt = builder::message::tek_preview(ClientItemId(tek_request.item_id), &weapon)?; | ||||
| 
 | ||||
| @ -450,7 +435,7 @@ where | ||||
| 
 | ||||
| pub async fn accept_tek_item<EG>(id: ClientId, | ||||
|                                  tek_accept: &TekAccept, | ||||
|                                  entity_gateway: &mut EG, | ||||
|                                  mut entity_gateway: EG, | ||||
|                                  client_location: &ClientLocation, | ||||
|                                  clients: &mut Clients, | ||||
|                                  item_state: &mut ItemState) | ||||
| @ -471,7 +456,7 @@ where | ||||
|             percent: percent_mod, | ||||
|             grind: grind_mod, | ||||
|         }; | ||||
|         let weapon = apply_modifier(item_state, entity_gateway, &client.character, item_id, item::ItemModifier::WeaponModifier(modifier)).await?; | ||||
|         let weapon = apply_modifier(item_state, &mut entity_gateway, &client.character, item_id, item::ItemModifier::WeaponModifier(modifier)).await?; | ||||
| 
 | ||||
|         let create_item_pkt = builder::message::create_individual_item(area_client, item_id, &weapon)?; | ||||
| 
 | ||||
|  | ||||
| @ -72,7 +72,7 @@ pub async fn change_lobby<EG: EntityGateway>(id: ClientId, | ||||
|                                              item_state: &mut ItemState, | ||||
|                                              level_table: &CharacterLevelTable, | ||||
|                                              ship_rooms: &mut Rooms, | ||||
|                                              entity_gateway: &mut EG) | ||||
|                                              mut entity_gateway: EG) | ||||
|                                              -> Result<Vec<(ClientId, SendShipPacket)>, anyhow::Error> { | ||||
|     let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id))?; | ||||
|     let prev_area = client_location.get_area(id).map_err(|err| -> ClientLocationError {err.into()})?; | ||||
| @ -103,7 +103,7 @@ pub async fn change_lobby<EG: EntityGateway>(id: ClientId, | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     item_state.load_character(entity_gateway, &client.character).await?; | ||||
|     item_state.load_character(&mut entity_gateway, &client.character).await?; | ||||
|     let join_lobby = packet::builder::lobby::join_lobby(id, lobby, client_location, clients, item_state, level_table)?; | ||||
|     let addto = packet::builder::lobby::add_to_lobby(id, lobby, client_location, clients, item_state, level_table)?; | ||||
|     let neighbors = client_location.get_client_neighbors(id).unwrap(); | ||||
|  | ||||
| @ -13,7 +13,7 @@ use crate::ship::items::tasks::{drop_item, drop_partial_item, drop_meseta, equip | ||||
| 
 | ||||
| pub async fn request_exp<EG: EntityGateway>(id: ClientId, | ||||
|                                             request_exp: &RequestExp, | ||||
|                                             entity_gateway: &mut EG, | ||||
|                                             mut entity_gateway: EG, | ||||
|                                             client_location: &ClientLocation, | ||||
|                                             clients: &mut Clients, | ||||
|                                             rooms: &mut Rooms, | ||||
| @ -67,7 +67,7 @@ pub async fn request_exp<EG: EntityGateway>(id: ClientId, | ||||
| 
 | ||||
| pub async fn player_drop_item<EG>(id: ClientId, | ||||
|                                   player_drop_item: &PlayerDropItem, | ||||
|                                   entity_gateway: &mut EG, | ||||
|                                   mut entity_gateway: EG, | ||||
|                                   client_location: &ClientLocation, | ||||
|                                   clients: &mut Clients, | ||||
|                                   rooms: &mut Rooms, | ||||
| @ -83,7 +83,7 @@ where | ||||
|         .as_mut() | ||||
|         .ok_or(ShipError::InvalidRoom(room_id.0 as u32))?; | ||||
|     let area = room.map_areas.get_area_map(player_drop_item.map_area)?; | ||||
|     drop_item(item_state, entity_gateway, &client.character, &ClientItemId(player_drop_item.item_id), *area, (player_drop_item.x, player_drop_item.y, player_drop_item.z)).await?; | ||||
|     drop_item(item_state, &mut entity_gateway, &client.character, &ClientItemId(player_drop_item.item_id), *area, (player_drop_item.x, player_drop_item.y, player_drop_item.z)).await?; | ||||
|     let clients_in_area = client_location.get_clients_in_room(room_id).map_err(|err| -> ClientLocationError { err.into() })?; | ||||
|     let pdi = player_drop_item.clone(); | ||||
|     Ok(Box::new(clients_in_area.into_iter() | ||||
| @ -118,7 +118,7 @@ pub fn drop_coordinates(id: ClientId, | ||||
| 
 | ||||
| pub async fn no_longer_has_item<EG>(id: ClientId, | ||||
|                                     no_longer_has_item: &PlayerNoLongerHasItem, | ||||
|                                     entity_gateway: &mut EG, | ||||
|                                     mut entity_gateway: EG, | ||||
|                                     client_location: &ClientLocation, | ||||
|                                     clients: &mut Clients, | ||||
|                                     item_state: &mut ItemState) | ||||
| @ -135,7 +135,7 @@ where | ||||
|         } | ||||
| 
 | ||||
|         if no_longer_has_item.item_id == 0xFFFFFFFF { | ||||
|             let dropped_meseta = drop_meseta(item_state, entity_gateway, &client.character, drop_location.map_area, (drop_location.x, drop_location.z), no_longer_has_item.amount).await?; | ||||
|             let dropped_meseta = drop_meseta(item_state, &mut entity_gateway, &client.character, drop_location.map_area, (drop_location.x, drop_location.z), no_longer_has_item.amount).await?; | ||||
| 
 | ||||
|             let dropped_meseta_pkt = builder::message::drop_split_meseta_stack(area_client, &dropped_meseta)?; | ||||
|             let no_longer_has_meseta_pkt = builder::message::player_no_longer_has_meseta(area_client, no_longer_has_item.amount as u32); | ||||
| @ -159,7 +159,7 @@ where | ||||
|             )) | ||||
|         } | ||||
|         else { | ||||
|             let dropped_item = drop_partial_item(item_state, entity_gateway, &client.character, &drop_location.item_id, drop_location.map_area, (drop_location.x, drop_location.z), no_longer_has_item.amount).await?; | ||||
|             let dropped_item = drop_partial_item(item_state, &mut entity_gateway, &client.character, &drop_location.item_id, drop_location.map_area, (drop_location.x, drop_location.z), no_longer_has_item.amount).await?; | ||||
| 
 | ||||
|             let dropped_item_pkt = builder::message::drop_split_stack(area_client, &dropped_item)?; | ||||
|             client.item_drop_location = None; | ||||
| @ -259,7 +259,7 @@ pub fn update_player_position(id: ClientId, | ||||
| 
 | ||||
| pub async fn charge_attack<EG>(id: ClientId, | ||||
|                                charge: &ChargeAttack, | ||||
|                                entity_gateway: &mut EG, | ||||
|                                mut entity_gateway: EG, | ||||
|                                client_location: &ClientLocation, | ||||
|                                clients: &mut Clients, | ||||
|                                item_state: &mut ItemState) | ||||
| @ -270,7 +270,7 @@ where | ||||
|     let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?; | ||||
| 
 | ||||
|     // TODO: should probably validate this to be a legit number, I'd just hardcode 200 but vjaya
 | ||||
|     take_meseta(item_state, entity_gateway, &client.character.id, Meseta(charge.meseta)).await?; | ||||
|     take_meseta(item_state, &mut entity_gateway, &client.character.id, Meseta(charge.meseta)).await?; | ||||
| 
 | ||||
|     let charge = charge.clone(); | ||||
|     Ok(Box::new(client_location.get_client_neighbors(id).unwrap().into_iter() | ||||
| @ -281,7 +281,7 @@ where | ||||
| 
 | ||||
| pub async fn player_uses_item<EG>(id: ClientId, | ||||
|                           player_use_tool: &PlayerUseItem, | ||||
|                           entity_gateway: &mut EG, | ||||
|                           mut entity_gateway: EG, | ||||
|                           _client_location: &ClientLocation, | ||||
|                           clients: &mut Clients, | ||||
|                           item_state: &mut ItemState) | ||||
| @ -290,13 +290,13 @@ where | ||||
|     EG: EntityGateway | ||||
| { | ||||
|     let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?; | ||||
|     use_item(item_state, entity_gateway, &mut client.character, &ClientItemId(player_use_tool.item_id), 1).await?; | ||||
|     use_item(item_state, &mut entity_gateway, &mut client.character, &ClientItemId(player_use_tool.item_id), 1).await?; | ||||
|     Ok(Box::new(None.into_iter())) // TODO: should probably tell other players we used an item
 | ||||
| } | ||||
| 
 | ||||
| pub async fn player_used_medical_center<EG>(id: ClientId, | ||||
|                                             pumc: &PlayerUsedMedicalCenter, | ||||
|                                             entity_gateway: &mut EG, | ||||
|                                             mut entity_gateway: EG, | ||||
|                                             client_location: &ClientLocation, | ||||
|                                             clients: &mut Clients, | ||||
|                                             item_state: &mut ItemState) | ||||
| @ -306,7 +306,7 @@ where | ||||
| { | ||||
|     let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?; | ||||
| 
 | ||||
|     take_meseta(item_state, entity_gateway, &client.character.id, Meseta(10)).await?; | ||||
|     take_meseta(item_state, &mut entity_gateway, &client.character.id, Meseta(10)).await?; | ||||
| 
 | ||||
|     let pumc = pumc.clone(); | ||||
|     Ok(Box::new(client_location.get_client_neighbors(id).unwrap().into_iter() | ||||
| @ -318,7 +318,7 @@ where | ||||
| 
 | ||||
| pub async fn player_feed_mag<EG>(id: ClientId, | ||||
|                                  mag_feed: &PlayerFeedMag, | ||||
|                                  entity_gateway: &mut EG, | ||||
|                                  mut entity_gateway: EG, | ||||
|                                  client_location: &ClientLocation, | ||||
|                                  clients: &Clients, | ||||
|                                  item_state: &mut ItemState) | ||||
| @ -327,7 +327,7 @@ where | ||||
|     EG: EntityGateway | ||||
| { | ||||
|     let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id))?; | ||||
|     feed_mag(item_state, entity_gateway, &client.character, &ClientItemId(mag_feed.mag_id), &ClientItemId(mag_feed.item_id)).await?; | ||||
|     feed_mag(item_state, &mut entity_gateway, &client.character, &ClientItemId(mag_feed.mag_id), &ClientItemId(mag_feed.item_id)).await?; | ||||
| 
 | ||||
|     let mag_feed = mag_feed.clone(); | ||||
|     Ok(Box::new(client_location.get_client_neighbors(id).unwrap().into_iter() | ||||
| @ -338,7 +338,7 @@ where | ||||
| 
 | ||||
| pub async fn player_equips_item<EG>(id: ClientId, | ||||
|                                     pkt: &PlayerEquipItem, | ||||
|                                     entity_gateway: &mut EG, | ||||
|                                     mut entity_gateway: EG, | ||||
|                                     clients: &Clients, | ||||
|                                     item_state: &mut ItemState) | ||||
|                                     -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error> | ||||
| @ -352,13 +352,13 @@ where | ||||
|     else { | ||||
|         0 | ||||
|     }; | ||||
|     equip_item(item_state, entity_gateway, &client.character, &ClientItemId(pkt.item_id), equip_slot).await?; | ||||
|     equip_item(item_state, &mut entity_gateway, &client.character, &ClientItemId(pkt.item_id), equip_slot).await?; | ||||
|     Ok(Box::new(None.into_iter())) // TODO: tell other players you equipped an item
 | ||||
| } | ||||
| 
 | ||||
| pub async fn player_unequips_item<EG>(id: ClientId, | ||||
|                                     pkt: &PlayerUnequipItem, | ||||
|                                     entity_gateway: &mut EG, | ||||
|                                     mut entity_gateway: EG, | ||||
|                                     clients: &Clients, | ||||
|                                     item_state: &mut ItemState) | ||||
|                                     -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error> | ||||
| @ -366,13 +366,13 @@ where | ||||
|     EG: EntityGateway | ||||
| { | ||||
|     let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id))?; | ||||
|     unequip_item(item_state, entity_gateway, &client.character, &ClientItemId(pkt.item_id)).await?; | ||||
|     unequip_item(item_state, &mut entity_gateway, &client.character, &ClientItemId(pkt.item_id)).await?; | ||||
|     Ok(Box::new(None.into_iter())) // TODO: tell other players if you unequip an item
 | ||||
| } | ||||
| 
 | ||||
| pub async fn player_sorts_items<EG>(id: ClientId, | ||||
|                                     pkt: &SortItems, | ||||
|                                     entity_gateway: &mut EG, | ||||
|                                     mut entity_gateway: EG, | ||||
|                                     clients: &Clients, | ||||
|                                     item_state: &mut ItemState) | ||||
|                                     -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error> | ||||
| @ -391,13 +391,13 @@ where | ||||
|             } | ||||
|         }) | ||||
|         .collect(); | ||||
|     sort_inventory(item_state, entity_gateway, &client.character, item_ids).await?; | ||||
|     sort_inventory(item_state, &mut entity_gateway, &client.character, item_ids).await?; | ||||
|     Ok(Box::new(None.into_iter())) // TODO: clients probably care about each others item orders
 | ||||
| } | ||||
| 
 | ||||
| pub async fn player_sells_item<EG> (id: ClientId, | ||||
|                                     sold_item: &PlayerSoldItem, | ||||
|                                     entity_gateway: &mut EG, | ||||
|                                     mut entity_gateway: EG, | ||||
|                                     clients: &mut Clients, | ||||
|                                     item_state: &mut ItemState) | ||||
|                                     -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error> | ||||
| @ -405,7 +405,7 @@ where | ||||
|     EG: EntityGateway | ||||
| { | ||||
|     let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?; | ||||
|     sell_item(item_state, entity_gateway, &client.character, ClientItemId(sold_item.item_id), sold_item.amount as u32).await?; | ||||
|     sell_item(item_state, &mut entity_gateway, &client.character, ClientItemId(sold_item.item_id), sold_item.amount as u32).await?; | ||||
|     // TODO: send the packet to other clients
 | ||||
|     Ok(Box::new(None.into_iter())) | ||||
| } | ||||
|  | ||||
| @ -6,7 +6,7 @@ use crate::entity::gateway::EntityGateway; | ||||
| pub async fn update_config<EG: EntityGateway>(id: ClientId, | ||||
|                                         update_config: &UpdateConfig, | ||||
|                                         clients: &mut Clients, | ||||
|                                         entity_gateway: &mut EG) | ||||
|                                         mut entity_gateway: EG) | ||||
|                                         -> Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send> { | ||||
|     let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id)).unwrap(); | ||||
|     client.character.config.update(update_config); | ||||
| @ -17,7 +17,7 @@ pub async fn update_config<EG: EntityGateway>(id: ClientId, | ||||
| pub async fn save_options<EG: EntityGateway>(id: ClientId, | ||||
|                                             save_options: &SaveOptions, | ||||
|                                             clients: &mut Clients, | ||||
|                                             entity_gateway: &mut EG) | ||||
|                                             mut entity_gateway: EG) | ||||
|                                             -> Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send> { | ||||
|     // TODO: don't unwrap?
 | ||||
|     let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id)).unwrap(); | ||||
| @ -29,7 +29,7 @@ pub async fn save_options<EG: EntityGateway>(id: ClientId, | ||||
| pub async fn keyboard_config<EG: EntityGateway>(id: ClientId, | ||||
|                                                 keyboard_config: &KeyboardConfig, | ||||
|                                                 clients: &mut Clients, | ||||
|                                                 entity_gateway: &mut EG) | ||||
|                                                 mut entity_gateway: EG) | ||||
|                                                 -> Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send> { | ||||
|     let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id)).unwrap(); | ||||
|     client.character.keyboard_config.update(keyboard_config); | ||||
| @ -40,10 +40,10 @@ pub async fn keyboard_config<EG: EntityGateway>(id: ClientId, | ||||
| pub async fn gamepad_config<EG: EntityGateway>(id: ClientId, | ||||
|                                                 gamepad_config: &GamepadConfig, | ||||
|                                                 clients: &mut Clients, | ||||
|                                                 entity_gateway: &mut EG) | ||||
|                                                 mut entity_gateway: EG) | ||||
|                                                 -> Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send> { | ||||
|     let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id)).unwrap(); | ||||
|     client.character.gamepad_config.update(gamepad_config); | ||||
|     entity_gateway.save_character(&client.character).await.unwrap(); | ||||
|     Box::new(None.into_iter()) | ||||
| } | ||||
| } | ||||
|  | ||||
| @ -429,7 +429,7 @@ pub async fn items_to_trade(id: ClientId, | ||||
| } | ||||
| 
 | ||||
| pub async fn trade_confirmed<EG>(id: ClientId, | ||||
|                                  entity_gateway: &mut EG, | ||||
|                                  mut entity_gateway: EG, | ||||
|                                  client_location: &ClientLocation, | ||||
|                                  clients: &mut Clients, | ||||
|                                  item_state: &mut ItemState, | ||||
| @ -493,7 +493,7 @@ where | ||||
|                         }); | ||||
| 
 | ||||
|                     let (this_new_items, other_new_items) = trade_items(item_state, | ||||
|                                                                         entity_gateway, | ||||
|                                                                         &mut entity_gateway, | ||||
|                                                                         (&this_local_client, &this_client.character, &this.items, Meseta(this.meseta as u32)), | ||||
|                                                                         (&other_local_client, &other_client.character, &other.items, Meseta(other.meseta as u32))).await?; | ||||
| 
 | ||||
|  | ||||
| @ -373,7 +373,7 @@ impl Default for ItemShops { | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| pub struct ShipServerStateBuilder<EG: EntityGateway> { | ||||
| pub struct ShipServerStateBuilder<EG: EntityGateway + Clone> { | ||||
|     entity_gateway: Option<EG>, | ||||
|     name: Option<String>, | ||||
|     ip: Option<Ipv4Addr>, | ||||
| @ -382,7 +382,7 @@ pub struct ShipServerStateBuilder<EG: EntityGateway> { | ||||
|     num_blocks: usize, | ||||
| } | ||||
| 
 | ||||
| impl<EG: EntityGateway> Default for ShipServerStateBuilder<EG> { | ||||
| impl<EG: EntityGateway + Clone> Default for ShipServerStateBuilder<EG> { | ||||
|     fn default() -> ShipServerStateBuilder<EG> { | ||||
|         ShipServerStateBuilder { | ||||
|             entity_gateway: None, | ||||
| @ -395,7 +395,7 @@ impl<EG: EntityGateway> Default for ShipServerStateBuilder<EG> { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<EG: EntityGateway> ShipServerStateBuilder<EG> { | ||||
| impl<EG: EntityGateway + Clone> ShipServerStateBuilder<EG> { | ||||
|     #[must_use] | ||||
|     pub fn gateway(mut self, entity_gateway: EG) -> ShipServerStateBuilder<EG> { | ||||
|         self.entity_gateway = Some(entity_gateway); | ||||
| @ -478,7 +478,7 @@ impl Blocks { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| pub struct ShipServerState<EG: EntityGateway> { | ||||
| pub struct ShipServerState<EG: EntityGateway + Clone> { | ||||
|     entity_gateway: EG, | ||||
|     pub clients: Clients, | ||||
|     level_table: CharacterLevelTable, | ||||
| @ -496,7 +496,7 @@ pub struct ShipServerState<EG: EntityGateway> { | ||||
|     trades: TradeState, | ||||
| } | ||||
| 
 | ||||
| impl<EG: EntityGateway> ShipServerState<EG> { | ||||
| impl<EG: EntityGateway + Clone> ShipServerState<EG> { | ||||
|     pub fn builder() -> ShipServerStateBuilder<EG> { | ||||
|         ShipServerStateBuilder::default() | ||||
|     } | ||||
| @ -509,11 +509,11 @@ impl<EG: EntityGateway> ShipServerState<EG> { | ||||
|         Ok(match &msg.msg { | ||||
|             GameMessage::RequestExp(request_exp) => { | ||||
|                 let block = self.blocks.with_client(id, &self.clients)?; | ||||
|                 handler::message::request_exp(id, request_exp, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut block.rooms, &self.level_table).await? | ||||
|                 handler::message::request_exp(id, request_exp, self.entity_gateway.clone(), &block.client_location, &mut self.clients, &mut block.rooms, &self.level_table).await? | ||||
|             }, | ||||
|             GameMessage::PlayerDropItem(player_drop_item) => { | ||||
|                 let block = self.blocks.with_client(id, &self.clients)?; | ||||
|                 handler::message::player_drop_item(id, player_drop_item, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut block.rooms, &mut self.item_state).await? | ||||
|                 handler::message::player_drop_item(id, player_drop_item, self.entity_gateway.clone(), &block.client_location, &mut self.clients, &mut block.rooms, &mut self.item_state).await? | ||||
|             }, | ||||
|             GameMessage::DropCoordinates(drop_coordinates) => { | ||||
|                 let block = self.blocks.with_client(id, &self.clients)?; | ||||
| @ -521,7 +521,7 @@ impl<EG: EntityGateway> ShipServerState<EG> { | ||||
|             }, | ||||
|             GameMessage::PlayerNoLongerHasItem(no_longer_has_item) => { | ||||
|                 let block = self.blocks.with_client(id, &self.clients)?; | ||||
|                 handler::message::no_longer_has_item(id, no_longer_has_item, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut self.item_state).await? | ||||
|                 handler::message::no_longer_has_item(id, no_longer_has_item, self.entity_gateway.clone(), &block.client_location, &mut self.clients, &mut self.item_state).await? | ||||
|             }, | ||||
|             GameMessage::PlayerChangedMap(_) | GameMessage::PlayerChangedMap2(_) | GameMessage::TellOtherPlayerMyLocation(_) | 
 | ||||
|             GameMessage::PlayerWarpingToFloor(_) | GameMessage::PlayerTeleported(_) | GameMessage::PlayerStopped(_) | 
 | ||||
| @ -532,31 +532,31 @@ impl<EG: EntityGateway> ShipServerState<EG> { | ||||
|             }, | ||||
|             GameMessage::ChargeAttack(charge_attack) => { | ||||
|                 let block = self.blocks.with_client(id, &self.clients)?; | ||||
|                 handler::message::charge_attack(id, charge_attack, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut self.item_state).await? | ||||
|                 handler::message::charge_attack(id, charge_attack, self.entity_gateway.clone(), &block.client_location, &mut self.clients, &mut self.item_state).await? | ||||
|             }, | ||||
|             GameMessage::PlayerUseItem(player_use_item) => { | ||||
|                 let block = self.blocks.with_client(id, &self.clients)?; | ||||
|                 handler::message::player_uses_item(id, player_use_item, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut self.item_state).await? | ||||
|                 handler::message::player_uses_item(id, player_use_item, self.entity_gateway.clone(), &block.client_location, &mut self.clients, &mut self.item_state).await? | ||||
|             }, | ||||
|             GameMessage::PlayerUsedMedicalCenter(player_used_medical_center) => { | ||||
|                 let block = self.blocks.with_client(id, &self.clients)?; | ||||
|                 handler::message::player_used_medical_center(id, player_used_medical_center, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut self.item_state).await? | ||||
|                 handler::message::player_used_medical_center(id, player_used_medical_center, self.entity_gateway.clone(), &block.client_location, &mut self.clients, &mut self.item_state).await? | ||||
|             }, | ||||
|             GameMessage::PlayerFeedMag(player_feed_mag) => { | ||||
|                 let block = self.blocks.with_client(id, &self.clients)?; | ||||
|                 handler::message::player_feed_mag(id, player_feed_mag, &mut self.entity_gateway, &block.client_location, &self.clients, &mut self.item_state).await? | ||||
|                 handler::message::player_feed_mag(id, player_feed_mag, self.entity_gateway.clone(), &block.client_location, &self.clients, &mut self.item_state).await? | ||||
|             }, | ||||
|             GameMessage::PlayerEquipItem(player_equip_item) => { | ||||
|                 handler::message::player_equips_item(id, player_equip_item, &mut self.entity_gateway, &self.clients, &mut self.item_state).await? | ||||
|                 handler::message::player_equips_item(id, player_equip_item, self.entity_gateway.clone(), &self.clients, &mut self.item_state).await? | ||||
|             }, | ||||
|             GameMessage::PlayerUnequipItem(player_unequip_item) => { | ||||
|                 handler::message::player_unequips_item(id, player_unequip_item, &mut self.entity_gateway, &self.clients, &mut self.item_state).await? | ||||
|                 handler::message::player_unequips_item(id, player_unequip_item, self.entity_gateway.clone(), &self.clients, &mut self.item_state).await? | ||||
|             }, | ||||
|             GameMessage::SortItems(sort_items) => { | ||||
|                 handler::message::player_sorts_items(id, sort_items, &mut self.entity_gateway, &self.clients, &mut self.item_state).await? | ||||
|                 handler::message::player_sorts_items(id, sort_items, self.entity_gateway.clone(), &self.clients, &mut self.item_state).await? | ||||
|             }, | ||||
|             GameMessage::PlayerSoldItem(player_sold_item) => { | ||||
|                 handler::message::player_sells_item(id, player_sold_item, &mut self.entity_gateway, &mut self.clients, &mut self.item_state).await? | ||||
|                 handler::message::player_sells_item(id, player_sold_item, self.entity_gateway.clone(), &mut self.clients, &mut self.item_state).await? | ||||
|             }, | ||||
|             _ => { | ||||
|                 let cmsg = msg.clone(); | ||||
| @ -577,31 +577,31 @@ impl<EG: EntityGateway> ShipServerState<EG> { | ||||
|                 handler::direct_message::guildcard_send(id, guildcard_send, target, &block.client_location, &self.clients) | ||||
|             }, | ||||
|             GameMessage::RequestItem(request_item) => { | ||||
|                 handler::direct_message::request_item(id, request_item, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut block.rooms, &mut self.item_state).await? | ||||
|                 handler::direct_message::request_item(id, request_item, self.entity_gateway.clone(), &block.client_location, &mut self.clients, &mut block.rooms, &mut self.item_state).await? | ||||
|             }, | ||||
|             GameMessage::PickupItem(pickup_item) => { | ||||
|                 handler::direct_message::pickup_item(id, pickup_item, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut self.item_state).await? | ||||
|                 handler::direct_message::pickup_item(id, pickup_item, self.entity_gateway.clone(), &block.client_location, &mut self.clients, &mut self.item_state).await? | ||||
|             }, | ||||
|             GameMessage::BoxDropRequest(box_drop_request) => { | ||||
|                 handler::direct_message::request_box_item(id, box_drop_request, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut block.rooms, &mut self.item_state).await? | ||||
|                 handler::direct_message::request_box_item(id, box_drop_request, self.entity_gateway.clone(), &block.client_location, &mut self.clients, &mut block.rooms, &mut self.item_state).await? | ||||
|             }, | ||||
|             GameMessage::BankRequest(_bank_request) => { | ||||
|                 handler::direct_message::send_bank_list(id, &self.clients, &mut self.item_state).await? | ||||
|             }, | ||||
|             GameMessage::BankInteraction(bank_interaction) => { | ||||
|                 handler::direct_message::bank_interaction(id, bank_interaction, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut self.item_state).await? | ||||
|                 handler::direct_message::bank_interaction(id, bank_interaction, self.entity_gateway.clone(), &block.client_location, &mut self.clients, &mut self.item_state).await? | ||||
|             }, | ||||
|             GameMessage::ShopRequest(shop_request) => { | ||||
|                 handler::direct_message::shop_request(id, shop_request, &block.client_location, &mut self.clients, &block.rooms, &self.level_table, &mut self.shops).await? | ||||
|             }, | ||||
|             GameMessage::BuyItem(buy_item) => { | ||||
|                 handler::direct_message::buy_item(id, buy_item, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut self.item_state).await? | ||||
|                 handler::direct_message::buy_item(id, buy_item, self.entity_gateway.clone(), &block.client_location, &mut self.clients, &mut self.item_state).await? | ||||
|             }, | ||||
|             GameMessage::TekRequest(tek_request) => { | ||||
|                 handler::direct_message::request_tek_item(id, tek_request, &mut self.entity_gateway, &mut self.clients, &mut self.item_state).await? | ||||
|                 handler::direct_message::request_tek_item(id, tek_request, self.entity_gateway.clone(), &mut self.clients, &mut self.item_state).await? | ||||
|             }, | ||||
|             GameMessage::TekAccept(tek_accept) => { | ||||
|                 handler::direct_message::accept_tek_item(id, tek_accept, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut self.item_state).await? | ||||
|                 handler::direct_message::accept_tek_item(id, tek_accept, self.entity_gateway.clone(), &block.client_location, &mut self.clients, &mut self.item_state).await? | ||||
|             }, | ||||
|             GameMessage::TradeRequest(trade_request) => { | ||||
|                 handler::trade::trade_request(id, trade_request, target, &block.client_location, &mut self.clients, &mut self.item_state, &mut self.trades).await? | ||||
| @ -619,7 +619,7 @@ impl<EG: EntityGateway> ShipServerState<EG> { | ||||
| } | ||||
| 
 | ||||
| #[async_trait::async_trait] | ||||
| impl<EG: EntityGateway> ServerState for ShipServerState<EG> { | ||||
| impl<EG: EntityGateway + Clone> ServerState for ShipServerState<EG> { | ||||
|     type SendPacket = SendShipPacket; | ||||
|     type RecvPacket = RecvShipPacket; | ||||
|     type PacketError = anyhow::Error; | ||||
| @ -647,7 +647,7 @@ impl<EG: EntityGateway> ServerState for ShipServerState<EG> { | ||||
| 
 | ||||
|         Ok(match pkt { | ||||
|             RecvShipPacket::Login(login) => { | ||||
|                 Box::new(handler::auth::validate_login(id, login, &mut self.entity_gateway, &mut self.clients, &mut self.item_state, &self.shipgate_sender, &self.name, self.blocks.0.len()) | ||||
|                 Box::new(handler::auth::validate_login(id, login, self.entity_gateway.clone(), &mut self.clients, &mut self.item_state, &self.shipgate_sender, &self.name, self.blocks.0.len()) | ||||
|                          .await?.into_iter().map(move |pkt| (id, pkt))) | ||||
|             }, | ||||
|             RecvShipPacket::QuestDetailRequest(questdetailrequest) => { | ||||
| @ -721,14 +721,14 @@ impl<EG: EntityGateway> ServerState for ShipServerState<EG> { | ||||
|                 handler::room::room_name_request(id, &block.client_location, &block.rooms) | ||||
|             }, | ||||
|             RecvShipPacket::UpdateConfig(pkt) => { | ||||
|                 handler::settings::update_config(id, pkt, &mut self.clients, &mut self.entity_gateway).await | ||||
|                 handler::settings::update_config(id, pkt, &mut self.clients, self.entity_gateway.clone()).await | ||||
|             }, | ||||
|             RecvShipPacket::ViewInfoboardRequest(_pkt) => { | ||||
|                 let block = self.blocks.with_client(id, &self.clients)?; | ||||
|                 handler::communication::request_infoboard(id, &block.client_location, &self.clients) | ||||
|             }, | ||||
|             RecvShipPacket::WriteInfoboard(pkt) => { | ||||
|                 handler::communication::write_infoboard(id, pkt, &mut self.clients, &mut self.entity_gateway).await | ||||
|                 handler::communication::write_infoboard(id, pkt, &mut self.clients, self.entity_gateway.clone()).await | ||||
|             }, | ||||
|             RecvShipPacket::RoomListRequest(_req) => { | ||||
|                 let block = self.blocks.with_client(id, &self.clients)?; | ||||
| @ -752,7 +752,7 @@ impl<EG: EntityGateway> ServerState for ShipServerState<EG> { | ||||
|             }, | ||||
|             RecvShipPacket::LobbySelect(pkt) => { | ||||
|                 let block = self.blocks.with_client(id, &self.clients)?; | ||||
|                 Box::new(handler::lobby::change_lobby(id, pkt.lobby, &mut block.client_location, &self.clients, &mut self.item_state, &self.level_table, &mut block.rooms, &mut self.entity_gateway).await?.into_iter()) | ||||
|                 Box::new(handler::lobby::change_lobby(id, pkt.lobby, &mut block.client_location, &self.clients, &mut self.item_state, &self.level_table, &mut block.rooms, self.entity_gateway.clone()).await?.into_iter()) | ||||
|             }, | ||||
|             RecvShipPacket::RequestQuestList(rql) => { | ||||
|                 let block = self.blocks.with_client(id, &self.clients)?; | ||||
| @ -774,7 +774,7 @@ impl<EG: EntityGateway> ServerState for ShipServerState<EG> { | ||||
|                 Box::new(None.into_iter()) | ||||
|             }, | ||||
|             RecvShipPacket::SaveOptions(save_options) => { | ||||
|                 handler::settings::save_options(id, save_options, &mut self.clients, &mut self.entity_gateway).await | ||||
|                 handler::settings::save_options(id, save_options, &mut self.clients, self.entity_gateway.clone()).await | ||||
|             }, | ||||
|             RecvShipPacket::RequestShipList(_) => { | ||||
|                 handler::ship::ship_list(id, &self.ship_list) | ||||
| @ -788,13 +788,13 @@ impl<EG: EntityGateway> ServerState for ShipServerState<EG> { | ||||
|             }, | ||||
|             RecvShipPacket::TradeConfirmed(_) => { | ||||
|                 let block = self.blocks.with_client(id, &self.clients)?; | ||||
|                 handler::trade::trade_confirmed(id, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut self.item_state, &mut self.trades).await? | ||||
|                 handler::trade::trade_confirmed(id, self.entity_gateway.clone(), &block.client_location, &mut self.clients, &mut self.item_state, &mut self.trades).await? | ||||
|             }, | ||||
|             RecvShipPacket::KeyboardConfig(keyboard_config) => { | ||||
|                 handler::settings::keyboard_config(id, keyboard_config, &mut self.clients, &mut self.entity_gateway).await | ||||
|                 handler::settings::keyboard_config(id, keyboard_config, &mut self.clients, self.entity_gateway.clone()).await | ||||
|             }, | ||||
|             RecvShipPacket::GamepadConfig(gamepad_config) => { | ||||
|                 handler::settings::gamepad_config(id, gamepad_config, &mut self.clients, &mut self.entity_gateway).await | ||||
|                 handler::settings::gamepad_config(id, gamepad_config, &mut self.clients, self.entity_gateway.clone()).await | ||||
|             }, | ||||
|         }) | ||||
|     } | ||||
| @ -839,7 +839,7 @@ impl<EG: EntityGateway> ServerState for ShipServerState<EG> { | ||||
| 
 | ||||
| 
 | ||||
| #[async_trait::async_trait] | ||||
| impl<EG: EntityGateway> InterserverActor for ShipServerState<EG> { | ||||
| impl<EG: EntityGateway + Clone> InterserverActor for ShipServerState<EG> { | ||||
|     type SendMessage = ShipMessage; | ||||
|     type RecvMessage = LoginMessage; | ||||
|     type Error = (); | ||||
|  | ||||
| @ -13,7 +13,7 @@ use libpso::packet::login::{Login, Session}; | ||||
| use libpso::{utf8_to_array, utf8_to_utf16_array}; | ||||
| 
 | ||||
| 
 | ||||
| pub async fn new_user_character<EG: EntityGateway>(entity_gateway: &mut EG, username: &str, password: &str, kb_conf_preset: usize) -> (UserAccountEntity, CharacterEntity) { | ||||
| pub async fn new_user_character<EG: EntityGateway + Clone>(entity_gateway: &mut EG, username: &str, password: &str, kb_conf_preset: usize) -> (UserAccountEntity, CharacterEntity) { | ||||
|     let new_user = NewUserAccountEntity { | ||||
|         email: format!("{}@pso.com", username), | ||||
|         username: username.into(), | ||||
| @ -34,7 +34,7 @@ pub async fn new_user_character<EG: EntityGateway>(entity_gateway: &mut EG, user | ||||
|     (user, character) | ||||
| } | ||||
| 
 | ||||
| pub async fn log_in_char<EG: EntityGateway>(ship: &mut ShipServerState<EG>, id: ClientId, username: &str, password: &str) { | ||||
| pub async fn log_in_char<EG: EntityGateway + Clone>(ship: &mut ShipServerState<EG>, id: ClientId, username: &str, password: &str) { | ||||
|     let username = username.to_string(); | ||||
|     let password = password.to_string(); | ||||
|     ship.handle(id, &RecvShipPacket::Login(Login { | ||||
| @ -52,24 +52,24 @@ pub async fn log_in_char<EG: EntityGateway>(ship: &mut ShipServerState<EG>, id: | ||||
|     })).await.unwrap().for_each(drop); | ||||
| } | ||||
| 
 | ||||
| pub async fn join_lobby<EG: EntityGateway>(ship: &mut ShipServerState<EG>, id: ClientId) { | ||||
| pub async fn join_lobby<EG: EntityGateway + Clone>(ship: &mut ShipServerState<EG>, id: ClientId) { | ||||
|     ship.handle(id, &RecvShipPacket::CharData(CharData { | ||||
|         _unknown: [0; 0x828] | ||||
|     })).await.unwrap().for_each(drop); | ||||
| } | ||||
| 
 | ||||
| pub async fn create_room<EG: EntityGateway>(ship: &mut ShipServerState<EG>, id: ClientId, name: &str, password: &str) { | ||||
| pub async fn create_room<EG: EntityGateway + Clone>(ship: &mut ShipServerState<EG>, id: ClientId, name: &str, password: &str) { | ||||
|     create_room_with_difficulty(ship, id, name, password, Difficulty::Normal).await; | ||||
| } | ||||
| 
 | ||||
| pub async fn leave_room<EG: EntityGateway>(ship: &mut ShipServerState<EG>, id: ClientId) { | ||||
| pub async fn leave_room<EG: EntityGateway + Clone>(ship: &mut ShipServerState<EG>, id: ClientId) { | ||||
|     ship.handle(id, &RecvShipPacket::LobbySelect(LobbySelect { | ||||
|         menu: 3, | ||||
|         lobby: 0, | ||||
|     })).await.unwrap().for_each(drop); | ||||
| } | ||||
| 
 | ||||
| pub async fn create_room_with_difficulty<EG: EntityGateway>(ship: &mut ShipServerState<EG>, id: ClientId, name: &str, password: &str, difficulty: Difficulty) { | ||||
| pub async fn create_room_with_difficulty<EG: EntityGateway + Clone>(ship: &mut ShipServerState<EG>, id: ClientId, name: &str, password: &str, difficulty: Difficulty) { | ||||
|     ship.handle(id, &RecvShipPacket::CreateRoom(CreateRoom { | ||||
|         unknown: [0; 2], | ||||
|         name: utf8_to_utf16_array!(name, 16), | ||||
| @ -84,7 +84,7 @@ pub async fn create_room_with_difficulty<EG: EntityGateway>(ship: &mut ShipServe | ||||
|     ship.handle(id, &RecvShipPacket::DoneBursting(DoneBursting {})).await.unwrap().for_each(drop); | ||||
| } | ||||
| 
 | ||||
| pub async fn join_room<EG: EntityGateway>(ship: &mut ShipServerState<EG>, id: ClientId, room_id: u32) { | ||||
| pub async fn join_room<EG: EntityGateway + Clone>(ship: &mut ShipServerState<EG>, id: ClientId, room_id: u32) { | ||||
|     ship.handle(id, &RecvShipPacket::MenuSelect(MenuSelect { | ||||
|         menu: ROOM_MENU_ID, | ||||
|         item: room_id, | ||||
|  | ||||
| @ -15,7 +15,7 @@ use libpso::packet::messages::*; | ||||
| mod common; | ||||
| use common::*; | ||||
| 
 | ||||
| async fn initialize_trade<EG: EntityGateway>(ship: &mut ShipServerState<EG>, client1: ClientId, client2: ClientId) { | ||||
| async fn initialize_trade<EG: EntityGateway + Clone>(ship: &mut ShipServerState<EG>, client1: ClientId, client2: ClientId) { | ||||
|     ship.handle(client1, &RecvShipPacket::DirectMessage(DirectMessage::new(client2.0 as u32 -1, GameMessage::TradeRequest(TradeRequest { | ||||
|         client: client1.0 as u8 -1, | ||||
|         target: 0, | ||||
| @ -29,7 +29,7 @@ async fn initialize_trade<EG: EntityGateway>(ship: &mut ShipServerState<EG>, cli | ||||
|     })))).await.unwrap().for_each(drop); | ||||
| } | ||||
| 
 | ||||
| async fn confirm_trade<EG: EntityGateway>(ship: &mut ShipServerState<EG>, client1: ClientId, client2: ClientId) { | ||||
| async fn confirm_trade<EG: EntityGateway + Clone>(ship: &mut ShipServerState<EG>, client1: ClientId, client2: ClientId) { | ||||
|     ship.handle(client1, &RecvShipPacket::DirectMessage(DirectMessage::new(client2.0 as u32 -1, GameMessage::TradeRequest(TradeRequest { | ||||
|         client: client1.0 as u8 -1, | ||||
|         target: 0, | ||||
| @ -43,7 +43,7 @@ async fn confirm_trade<EG: EntityGateway>(ship: &mut ShipServerState<EG>, client | ||||
|     })))).await.unwrap().for_each(drop); | ||||
| } | ||||
| 
 | ||||
| async fn finalconfirm_trade<EG: EntityGateway>(ship: &mut ShipServerState<EG>, client1: ClientId, client2: ClientId) { | ||||
| async fn finalconfirm_trade<EG: EntityGateway + Clone>(ship: &mut ShipServerState<EG>, client1: ClientId, client2: ClientId) { | ||||
|     ship.handle(client1, &RecvShipPacket::DirectMessage(DirectMessage::new(client2.0 as u32 -1, GameMessage::TradeRequest(TradeRequest { | ||||
|         client: client1.0 as u8 -1, | ||||
|         target: 0, | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user