sendgc #103
							
								
								
									
										2
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							| @ -1001,7 +1001,6 @@ checksum = "739e9d7726dc32173fed2d69d17eef3c54682169e4e20ff1d0a45dcd37063cef" | ||||
| [[package]] | ||||
| name = "libpso" | ||||
| version = "0.1.0" | ||||
| source = "git+http://git.sharnoth.com/jake/libpso#892d2ed220369f0ff7b7530fa734e722c2b21c2c" | ||||
| dependencies = [ | ||||
|  "chrono", | ||||
|  "psopacket", | ||||
| @ -1401,7 +1400,6 @@ dependencies = [ | ||||
| [[package]] | ||||
| name = "psopacket" | ||||
| version = "1.0.0" | ||||
| source = "git+http://git.sharnoth.com/jake/libpso#892d2ed220369f0ff7b7530fa734e722c2b21c2c" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  | ||||
| @ -1,6 +1,7 @@ | ||||
| use serde::{Serialize, Deserialize}; | ||||
| use libpso::character::settings; | ||||
| use libpso::character::guildcard; | ||||
| use libpso::packet::ship::{GuildcardAccept}; | ||||
| 
 | ||||
| pub const USERFLAG_NEWCHAR: u32      = 0x00000001; | ||||
| pub const USERFLAG_DRESSINGROOM: u32 = 0x00000002; | ||||
| @ -9,9 +10,14 @@ pub const USERFLAG_DRESSINGROOM: u32 = 0x00000002; | ||||
| pub struct UserAccountId(pub u32); | ||||
| #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] | ||||
| pub struct UserSettingsId(pub u32); | ||||
| #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] | ||||
| pub struct GuildCardDataId(pub u32); | ||||
| 
 | ||||
| // TODO: use these
 | ||||
|  | ||||
| #[derive(Debug)] | ||||
| pub enum GuildcardError { | ||||
|     GuildcardAlreadyFriend(u32), | ||||
| 
				
					
						jake
						commented  should be  should be `UserAccountId` not `u32` (or whatever proper not-number type is expected) | ||||
|     GuildcardAlreadyBlocked(u32), | ||||
|     GuildcardListFull, | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone, Debug)] | ||||
| pub struct NewUserAccountEntity { | ||||
| @ -125,19 +131,28 @@ impl NewGuildCardDataEntity { | ||||
| } | ||||
| 
 | ||||
| // TODO: implement this properly
 | ||||
| 
				
					
						jake
						commented  TODO: determine if this was implemented properly TODO: determine if this was implemented properly | ||||
| #[derive(Clone)] | ||||
| #[derive(Clone, Debug)] | ||||
| pub struct GuildCardDataEntity { | ||||
|     pub id: GuildCardDataId, | ||||
|     pub user_id: UserAccountId, | ||||
|     pub guildcard: guildcard::GuildCardData, | ||||
|     pub guildcard_data: Box<guildcard::GuildCardData>, | ||||
| 
				
					
						jake
						commented  why is this boxed? why is this boxed? 
				
					
						andy
						commented  
 `GuildCardData` is >50kb cus it contains the friendlist + blocklist. | ||||
| } | ||||
| 
 | ||||
| impl GuildCardDataEntity { | ||||
|     pub fn new(user_id: UserAccountId) -> GuildCardDataEntity { | ||||
|         GuildCardDataEntity { | ||||
|             id: GuildCardDataId(0), | ||||
|             user_id, | ||||
|             guildcard: guildcard::GuildCardData::default(), | ||||
|             guildcard_data: Box::new(guildcard::GuildCardData::default()), | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn add_friend(&mut self, new_friend: &GuildcardAccept) -> Result<(), GuildcardError> { | ||||
|         let next_open_spot = self.guildcard_data.friends | ||||
| 
				
					
						jake
						commented  
 `.iter().position()` might be preferable to `.enumerate().find()`? | ||||
|                                                         .iter() | ||||
|                                                         .enumerate() | ||||
|                                                         .find(|(_i, g)| g.id == 0) | ||||
|                                                         .ok_or(GuildcardError::GuildcardListFull)? | ||||
|                                                         .0; | ||||
|         self.guildcard_data.friends[next_open_spot] = guildcard::GuildCard::from(new_friend); | ||||
|         Ok(()) // TODO: implement a real error
 | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -61,6 +61,10 @@ pub trait EntityGateway: Send + Sync + Clone { | ||||
|         unimplemented!(); | ||||
|     } | ||||
| 
 | ||||
|     async fn set_guild_card(&mut self, _id: UserAccountId, _gc_data: GuildCardDataEntity) -> Result<(), GatewayError> { | ||||
|         unimplemented!(); | ||||
|     } | ||||
| 
 | ||||
|     async fn create_item(&mut self, _item: NewItemEntity) -> Result<ItemEntity, GatewayError> { | ||||
|         unimplemented!(); | ||||
|     } | ||||
|  | ||||
| @ -21,6 +21,7 @@ pub struct InMemoryGateway { | ||||
|     equips: Arc<Mutex<BTreeMap<CharacterEntityId, EquippedEntity>>>, | ||||
|     mag_modifiers: Arc<Mutex<BTreeMap<ItemEntityId, Vec<mag::MagModifier>>>>, | ||||
|     weapon_modifiers: Arc<Mutex<BTreeMap<ItemEntityId, Vec<weapon::WeaponModifier>>>>, | ||||
|     guildcard_entities: Arc<Mutex<BTreeMap<UserAccountId, GuildCardDataEntity>>>, | ||||
| } | ||||
| 
 | ||||
| impl Default for InMemoryGateway { | ||||
| @ -37,6 +38,7 @@ impl Default for InMemoryGateway { | ||||
|             equips: Arc::new(Mutex::new(BTreeMap::new())), | ||||
|             mag_modifiers: Arc::new(Mutex::new(BTreeMap::new())), | ||||
|             weapon_modifiers: Arc::new(Mutex::new(BTreeMap::new())), | ||||
|             guildcard_entities: Arc::new(Mutex::new(BTreeMap::new())), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -101,6 +103,7 @@ impl InMemoryGateway { | ||||
| impl EntityGateway for InMemoryGateway { | ||||
|     async fn create_user(&mut self, user: NewUserAccountEntity) -> Result<UserAccountEntity, GatewayError> { | ||||
|         let mut users = self.users.lock().unwrap(); | ||||
|         let mut guildcards = self.guildcard_entities.lock().unwrap(); | ||||
|         let id = users | ||||
|             .iter() | ||||
|             .fold(0, |sum, (i, _)| std::cmp::max(sum, i.0)) | ||||
| @ -109,7 +112,7 @@ impl EntityGateway for InMemoryGateway { | ||||
|             id: UserAccountId(id), | ||||
|             username: user.username, | ||||
|             password: user.password, | ||||
|             guildcard: user.guildcard, | ||||
|             guildcard: id, | ||||
|             team_id: user.team_id, | ||||
|             banned_until: user.banned_until, | ||||
|             muted_until: user.muted_until, | ||||
| @ -120,7 +123,11 @@ impl EntityGateway for InMemoryGateway { | ||||
|             at_character: false, | ||||
|             at_ship: false, | ||||
|         }; | ||||
| 
 | ||||
|         let guildcard = GuildCardDataEntity::new(UserAccountId(id)); // TODO: NewGuildcardDataEntity ?
 | ||||
|         users.insert(user.id, user.clone()); | ||||
|         guildcards.insert(user.id, guildcard.clone()); | ||||
| 
 | ||||
|         Ok(user) | ||||
|     } | ||||
| 
 | ||||
| @ -213,8 +220,14 @@ impl EntityGateway for InMemoryGateway { | ||||
|         Ok(()) | ||||
|     } | ||||
| 
 | ||||
|     // TODO: ok_or a real error ?
 | ||||
|     async fn get_guild_card_data_by_user(&self, user: &UserAccountEntity) -> Result<GuildCardDataEntity, GatewayError> { | ||||
|         Ok(GuildCardDataEntity::new(user.id)) | ||||
|         let guildcards = self.guildcard_entities.lock().unwrap(); | ||||
|         guildcards | ||||
|             .iter() | ||||
|             .find(|(_, g)| g.user_id == user.id) | ||||
|             .map(|(_, g)| g.clone()) | ||||
|             .ok_or(GatewayError::Error) | ||||
|     } | ||||
| 
 | ||||
|     async fn create_item(&mut self, item: NewItemEntity) -> Result<ItemEntity, GatewayError> { | ||||
| @ -347,4 +360,10 @@ impl EntityGateway for InMemoryGateway { | ||||
|             Err(GatewayError::Error) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     async fn set_guild_card(&mut self, id: UserAccountId, gc_data: GuildCardDataEntity) -> Result<(), GatewayError> { | ||||
|         let mut guildcard = self.guildcard_entities.lock().unwrap(); | ||||
|         guildcard.insert(id, gc_data); | ||||
|         Ok(()) | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -278,9 +278,8 @@ impl EntityGateway for PostgresGateway { | ||||
| 
 | ||||
|     async fn get_guild_card_data_by_user(&self, user: &UserAccountEntity) -> Result<GuildCardDataEntity, GatewayError> { | ||||
|         Ok(GuildCardDataEntity { | ||||
|             id: GuildCardDataId(0), | ||||
|             user_id: user.id, | ||||
|             guildcard: guildcard::GuildCardData::default(), | ||||
|             guildcard_data: Box::new(guildcard::GuildCardData::default()), | ||||
|         }) | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -441,12 +441,10 @@ impl<EG: EntityGateway> CharacterServerState<EG> { | ||||
|     async fn guildcard_data_header(&mut self, id: ClientId) -> Result<Vec<SendCharacterPacket>, anyhow::Error> { | ||||
|         let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?; | ||||
|         let guildcard_data = self.entity_gateway.get_guild_card_data_by_user(client.user.as_ref().unwrap()).await.map_err(|_| CharacterError::CouldNotLoadGuildcard)?; | ||||
| 
 | ||||
|         let bytes = guildcard_data.guildcard.as_bytes(); | ||||
|         let bytes = guildcard_data.guildcard_data.as_bytes(); | ||||
|         let mut crc = crc32::Digest::new(crc32::IEEE); | ||||
|         crc.write(&bytes[..]); | ||||
|         client.guildcard_data_buffer = Some(bytes.to_vec()); | ||||
| 
 | ||||
|         Ok(vec![SendCharacterPacket::GuildcardDataHeader(GuildcardDataHeader::new(bytes.len(), crc.sum32()))]) | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -45,3 +45,17 @@ pub async fn write_infoboard<EG: EntityGateway>(id: ClientId, | ||||
|     entity_gateway.save_character(&client.character).await.unwrap(); | ||||
|     Box::new(None.into_iter()) | ||||
| } | ||||
| 
 | ||||
| // TODO: return Result<Box<...>>  so ship can do await? and catch errors?
 | ||||
| pub async fn accept_guildcard<EG: EntityGateway>(id: ClientId, | ||||
|                                                 accepted_card: &GuildcardAccept, | ||||
|                                                 clients: &mut Clients, | ||||
|                                                 entity_gateway: &mut EG) | ||||
|                                                 -> Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send> { | ||||
|     let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id)).unwrap(); | ||||
| 
 | ||||
|     let mut gc_data = entity_gateway.get_guild_card_data_by_user(&client.user).await.unwrap(); | ||||
|     gc_data.add_friend(accepted_card).unwrap(); | ||||
|     entity_gateway.set_guild_card(client.user.id, gc_data).await.unwrap(); | ||||
|     Box::new(None.into_iter()) // TODO: does the server need to return anything to any client? everything seems to work fine like this...
 | ||||
| } | ||||
| @ -114,6 +114,7 @@ pub enum RecvShipPacket { | ||||
|     RequestShipBlockList(RequestShipBlockList), | ||||
|     ItemsToTrade(ItemsToTrade), | ||||
|     TradeConfirmed(TradeConfirmed), | ||||
|     GuildcardAccept(GuildcardAccept), | ||||
| } | ||||
| 
 | ||||
| impl RecvServerPacket for RecvShipPacket { | ||||
| @ -155,6 +156,7 @@ impl RecvServerPacket for RecvShipPacket { | ||||
|             0xD2 => Ok(RecvShipPacket::TradeConfirmed(TradeConfirmed::from_bytes(data)?)), | ||||
|             0xE7 => Ok(RecvShipPacket::FullCharacterData(Box::new(FullCharacterData::from_bytes(data)?))), | ||||
|             0x1ED => Ok(RecvShipPacket::SaveOptions(SaveOptions::from_bytes(data)?)), | ||||
|             0x4E8 => Ok(RecvShipPacket::GuildcardAccept(GuildcardAccept::from_bytes(data)?)), | ||||
|             _ => Err(PacketParseError::WrongPacketForServerType(u16::from_le_bytes([data[2], data[3]]), data.to_vec())) | ||||
|         } | ||||
|     } | ||||
| @ -743,6 +745,9 @@ impl<EG: EntityGateway> ServerState for ShipServerState<EG> { | ||||
|                 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_manager, &mut self.trades).await? | ||||
|             }, | ||||
|             RecvShipPacket::GuildcardAccept(guildcard_accept) => { | ||||
|                 handler::communication::accept_guildcard(id, guildcard_accept, &mut self.clients, &mut self.entity_gateway).await | ||||
|             }, | ||||
|         }) | ||||
|     } | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	
TODO: remove TODO