This commit is contained in:
		
							parent
							
								
									72d72801e1
								
							
						
					
					
						commit
						9c34baeb26
					
				| @ -9,7 +9,7 @@ use elseware::entity::account::{NewUserAccountEntity, NewUserSettingsEntity}; | ||||
| #[allow(unused_imports)] | ||||
| use elseware::entity::gateway::{EntityGateway, InMemoryGateway, PostgresGateway}; | ||||
| use elseware::entity::character::NewCharacterEntity; | ||||
| use elseware::entity::item::{NewItemEntity, ItemDetail}; | ||||
| use elseware::entity::item::{NewItemEntity, ItemDetail, InventoryItemEntity}; | ||||
| use elseware::common::interserver::AuthToken; | ||||
| 
 | ||||
| use elseware::entity::item; | ||||
| @ -67,13 +67,16 @@ fn main() { | ||||
|             entity_gateway.create_user_settings(NewUserSettingsEntity::new(fake_user.id)).await.unwrap(); | ||||
|             let mut character = NewCharacterEntity::new(fake_user.id); | ||||
|             character.name = format!("Test Char {}", i*2); | ||||
|             entity_gateway.create_character(character).await.unwrap(); | ||||
|             let character = entity_gateway.create_character(character).await.unwrap(); | ||||
|             entity_gateway.set_character_meseta(&character.id, item::Meseta(999999)).await.unwrap(); | ||||
|             entity_gateway.set_bank_meseta(&character.id, item::BankName("".into()), item::Meseta(999999)).await.unwrap(); | ||||
|             let mut character = NewCharacterEntity::new(fake_user.id); | ||||
|             character.slot = 2; | ||||
|             character.name = "ItemRefactor".into(); | ||||
|             character.exp = 80000000; | ||||
|             character.meseta = 999999; | ||||
|             let character = entity_gateway.create_character(character).await.unwrap(); | ||||
|             entity_gateway.set_character_meseta(&character.id, item::Meseta(999999)).await.unwrap(); | ||||
|             entity_gateway.set_bank_meseta(&character.id, item::BankName("".into()), item::Meseta(999999)).await.unwrap(); | ||||
| 
 | ||||
|             for _ in 0..3 { | ||||
|                 entity_gateway.create_item( | ||||
| @ -162,8 +165,8 @@ fn main() { | ||||
|                     item: ItemDetail::Weapon( | ||||
|                         item::weapon::Weapon { | ||||
|                             weapon: item::weapon::WeaponType::DarkFlow, | ||||
|                             grind: 5, | ||||
|                             special: Some(item::weapon::WeaponSpecial::Charge), | ||||
|                             grind: 0, | ||||
|                             special: None, | ||||
|                             attrs: [Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Hit, value: 100}), | ||||
|                                     Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Dark, value: 100}), | ||||
|                                     Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Native, value: 100}),], | ||||
| @ -293,6 +296,20 @@ fn main() { | ||||
|                 } | ||||
|             ).await.unwrap(); | ||||
| 
 | ||||
|             let monomates = futures::future::join_all((0..6).map(|_| { | ||||
|                 let mut entity_gateway = entity_gateway.clone(); | ||||
|                 async move { | ||||
|                     entity_gateway.create_item( | ||||
|                     NewItemEntity { | ||||
|                         item: ItemDetail::Tool ( | ||||
|                             item::tool::Tool { | ||||
|                                 tool: item::tool::ToolType::Monomate, | ||||
|                             } | ||||
|                         ), | ||||
|                     }).await.unwrap() | ||||
|                 } | ||||
|             })).await; | ||||
| 
 | ||||
|             let equipped = item::EquippedEntity { | ||||
|                 weapon: Some(item2_w.id), | ||||
|                 armor: Some(item7_a.id), | ||||
| @ -302,7 +319,7 @@ fn main() { | ||||
|             }; | ||||
|             entity_gateway.set_character_equips(&character.id, &equipped).await.unwrap(); | ||||
| 
 | ||||
|             let inventory = item::InventoryEntity::new(vec![item0, item1, item2_w, item3, item4, item5_m, item6, item7_a, item8_s, item9_u0, item10_u1, item11_u2, item12_u3, item13]); | ||||
|             let inventory = item::InventoryEntity::new(vec![InventoryItemEntity::from(item0), item1.into(), item2_w.into(), item3.into(), item4.into(), item5_m.into(), item6.into(), item7_a.into(), item8_s.into(), item9_u0.into(), item10_u1.into(), item11_u2.into(), item12_u3.into(), item13.into(), monomates.into()]); | ||||
|             entity_gateway.set_character_inventory(&character.id, &inventory).await.unwrap(); | ||||
|             entity_gateway.set_character_bank(&character.id, &item::BankEntity::default(), item::BankName("".into())).await.unwrap(); | ||||
|         } | ||||
|  | ||||
| @ -294,8 +294,6 @@ pub struct NewCharacterEntity { | ||||
|     pub materials: CharacterMaterials, | ||||
| 
 | ||||
|     pub tech_menu: CharacterTechMenu, | ||||
|     pub meseta: u32, | ||||
|     pub bank_meseta: u32, | ||||
|     pub option_flags: u32, | ||||
| } | ||||
| 
 | ||||
| @ -315,8 +313,6 @@ impl NewCharacterEntity { | ||||
|             guildcard: CharacterGuildCard::default(), | ||||
|             materials: CharacterMaterials::default(), | ||||
|             tech_menu: CharacterTechMenu::default(), | ||||
|             meseta: 0, | ||||
|             bank_meseta: 0, | ||||
|             option_flags: 0, | ||||
|         } | ||||
|     } | ||||
| @ -342,8 +338,5 @@ pub struct CharacterEntity { | ||||
|     pub materials: CharacterMaterials, | ||||
| 
 | ||||
|     pub tech_menu: CharacterTechMenu, | ||||
|     pub meseta: u32, | ||||
|     // TODO: this should not be tied to the character
 | ||||
|     pub bank_meseta: u32, | ||||
|     pub option_flags: u32, | ||||
| } | ||||
|  | ||||
| @ -116,7 +116,19 @@ pub trait EntityGateway: Send + Sync + Clone { | ||||
|         unimplemented!(); | ||||
|     } | ||||
| 
 | ||||
|     async fn set_character_meseta(&mut self, _char_id: &CharacterEntityId, amount: usize) -> Result<(), GatewayError> { | ||||
|     async fn get_character_meseta(&mut self, _char_id: &CharacterEntityId) -> Result<Meseta, GatewayError> { | ||||
|         unimplemented!(); | ||||
|     } | ||||
| 
 | ||||
|     async fn set_character_meseta(&mut self, _char_id: &CharacterEntityId, _amount: Meseta) -> Result<(), GatewayError> { | ||||
|         unimplemented!(); | ||||
|     } | ||||
| 
 | ||||
|     async fn get_bank_meseta(&mut self, _char_id: &CharacterEntityId, _bank: BankName) -> Result<Meseta, GatewayError> { | ||||
|         unimplemented!(); | ||||
|     } | ||||
| 
 | ||||
|     async fn set_bank_meseta(&mut self, _char_id: &CharacterEntityId, _bank: BankName, _amount: Meseta) -> Result<(), GatewayError> { | ||||
|         unimplemented!(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -13,6 +13,8 @@ pub struct InMemoryGateway { | ||||
|     users: Arc<Mutex<BTreeMap<UserAccountId, UserAccountEntity>>>, | ||||
|     user_settings: Arc<Mutex<BTreeMap<UserSettingsId, UserSettingsEntity>>>, | ||||
|     characters: Arc<Mutex<BTreeMap<CharacterEntityId, CharacterEntity>>>, | ||||
|     character_meseta: Arc<Mutex<BTreeMap<CharacterEntityId, Meseta>>>, | ||||
|     bank_meseta: Arc<Mutex<BTreeMap<(CharacterEntityId, BankName), Meseta>>>, | ||||
|     items: Arc<Mutex<BTreeMap<ItemEntityId, ItemEntity>>>, | ||||
|     inventories: Arc<Mutex<BTreeMap<CharacterEntityId, InventoryEntity>>>, | ||||
|     banks: Arc<Mutex<BTreeMap<CharacterEntityId, BankEntity>>>, | ||||
| @ -27,6 +29,8 @@ impl Default for InMemoryGateway { | ||||
|             users: Arc::new(Mutex::new(BTreeMap::new())), | ||||
|             user_settings: Arc::new(Mutex::new(BTreeMap::new())), | ||||
|             characters: Arc::new(Mutex::new(BTreeMap::new())), | ||||
|             character_meseta: Arc::new(Mutex::new(BTreeMap::new())), | ||||
|             bank_meseta: Arc::new(Mutex::new(BTreeMap::new())), | ||||
|             items: Arc::new(Mutex::new(BTreeMap::new())), | ||||
|             inventories: Arc::new(Mutex::new(BTreeMap::new())), | ||||
|             banks: Arc::new(Mutex::new(BTreeMap::new())), | ||||
| @ -197,8 +201,6 @@ impl EntityGateway for InMemoryGateway { | ||||
|             guildcard: character.guildcard, | ||||
|             materials: character.materials, | ||||
|             tech_menu: character.tech_menu, | ||||
|             meseta: character.meseta, | ||||
|             bank_meseta: character.bank_meseta, | ||||
|             option_flags: character.option_flags, | ||||
|         }; | ||||
|         characters.insert(new_character.id, new_character.clone()); | ||||
| @ -314,11 +316,35 @@ impl EntityGateway for InMemoryGateway { | ||||
|         Ok(()) | ||||
|     } | ||||
| 
 | ||||
|     async fn set_character_meseta(&mut self, char_id: &CharacterEntityId, amount: usize) -> Result<(), GatewayError> { | ||||
|         let mut characters = self.characters.lock().unwrap(); | ||||
|         if let Some(char) = characters.get_mut(&char_id) { | ||||
|             char.meseta = amount as u32; | ||||
|         } | ||||
|     async fn set_character_meseta(&mut self, char_id: &CharacterEntityId, meseta: Meseta) -> Result<(), GatewayError> { | ||||
|         let mut character_meseta = self.character_meseta.lock().unwrap(); | ||||
|         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(); | ||||
|         if let Some(meseta) = character_meseta.get_mut(&char_id) { | ||||
|             Ok(*meseta) | ||||
|         } | ||||
|         else { | ||||
|             Err(GatewayError::Error) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     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(); | ||||
|         bank_meseta.insert((*char_id, bank), 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(); | ||||
|         if let Some(meseta) = bank_meseta.get_mut(&(*char_id, bank)) { | ||||
|             Ok(*meseta) | ||||
|         } | ||||
|         else { | ||||
|             Err(GatewayError::Error) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
							
								
								
									
										15
									
								
								src/entity/gateway/postgres/migrations/V0004__meseta.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								src/entity/gateway/postgres/migrations/V0004__meseta.sql
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | ||||
| create table character_meseta ( | ||||
|   pchar integer references character (id) not null unique, | ||||
|   meseta integer not null, | ||||
| ); | ||||
| 
 | ||||
| create table bank_meseta ( | ||||
|   pchar integer references character (id) not null, | ||||
|   bank varchar(128) not null, | ||||
|   meseta integer not null, | ||||
|   unique (pchar, bank) | ||||
| ); | ||||
| 
 | ||||
| 
 | ||||
| alter table player_character | ||||
|   drop column meseta, bank_meseta; | ||||
| @ -216,8 +216,6 @@ pub struct PgCharacter { | ||||
|     tp: i16, | ||||
| 
 | ||||
|     tech_menu: Vec<u8>, | ||||
|     meseta: i32, | ||||
|     bank_meseta: i32, | ||||
| } | ||||
| 
 | ||||
| impl From<PgCharacter> for CharacterEntity { | ||||
| @ -267,8 +265,6 @@ impl From<PgCharacter> for CharacterEntity { | ||||
|             tech_menu: CharacterTechMenu { | ||||
|                 tech_menu: vec_to_array(other.tech_menu) | ||||
|             }, | ||||
|             meseta: other.meseta as u32, | ||||
|             bank_meseta: other.bank_meseta as u32, | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -182,7 +182,7 @@ impl EntityGateway for PostgresGateway { | ||||
|     async fn create_character(&mut self, char: NewCharacterEntity) -> Result<CharacterEntity, GatewayError> { | ||||
|         let q = r#"insert into player_character
 | ||||
|                   (user_account, slot, name, exp, class, section_id, costume, skin, face, head, hair, hair_r, hair_g, hair_b, prop_x, prop_y, techs, | ||||
|                    config, infoboard, guildcard, power, mind, def, evade, luck, hp, tp, tech_menu, meseta, bank_meseta, option_flags) | ||||
|                    config, infoboard, guildcard, power, mind, def, evade, luck, hp, tp, tech_menu, option_flags) | ||||
|                   values | ||||
|                   ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28, $29, $30, $31) | ||||
|                   returning *;"#;
 | ||||
| @ -215,8 +215,6 @@ impl EntityGateway for PostgresGateway { | ||||
|             .bind(char.materials.hp as i16) | ||||
|             .bind(char.materials.tp as i16) | ||||
|             .bind(char.tech_menu.tech_menu.to_vec()) | ||||
|             .bind(char.meseta as i32) | ||||
|             .bind(char.bank_meseta as i32) | ||||
|             .bind(char.option_flags as i32) | ||||
|             .fetch_one(&self.pool).await?; | ||||
| 
 | ||||
| @ -241,7 +239,7 @@ impl EntityGateway for PostgresGateway { | ||||
|         let q = r#"update player_character set
 | ||||
|                    user_account=$1, slot=$2, name=$3, exp=$4, class=$5, section_id=$6, costume=$7, skin=$8, face=$9, head=$10, hair=$11, hair_r=$12, | ||||
|                    hair_g=$13, hair_b=$14, prop_x=$15, prop_y=$16, techs=$17, config=$18, infoboard=$19, guildcard=$20, power=$21, mind=$22, def=$23, | ||||
|                    evade=$24, luck=$25, hp=$26, tp=$27, tech_menu=$28, meseta=$29, bank_meseta=$30, option_flags=$31 | ||||
|                    evade=$24, luck=$25, hp=$26, tp=$27, tech_menu=$28, option_flags=$29 | ||||
|                    where id=$32;"#;
 | ||||
|         sqlx::query(q) | ||||
|             .bind(char.user_id.0) | ||||
| @ -272,8 +270,6 @@ impl EntityGateway for PostgresGateway { | ||||
|             .bind(char.materials.hp as i16) | ||||
|             .bind(char.materials.tp as i16) | ||||
|             .bind(char.tech_menu.tech_menu.to_vec()) | ||||
|             .bind(char.meseta as i32) | ||||
|             .bind(char.bank_meseta as i32) | ||||
|             .bind(char.option_flags as i32) | ||||
|             .bind(char.id.0 as i32) | ||||
|             .execute(&self.pool).await?; | ||||
| @ -551,12 +547,43 @@ impl EntityGateway for PostgresGateway { | ||||
|         Ok(()) | ||||
|     } | ||||
| 
 | ||||
|     async fn set_character_meseta(&mut self, char_id: &CharacterEntityId, amount: usize) -> Result<(), GatewayError> { | ||||
|         sqlx::query(r#"update player_character set meseta=$2 where id = $1"#) | ||||
|     async fn set_character_meseta(&mut self, char_id: &CharacterEntityId, meseta: Meseta) -> Result<(), GatewayError> { | ||||
|         sqlx::query("insert into character_meseta values ($1, $2) on conflict (pchar) do update set items = $2") | ||||
|             .bind(char_id.0) | ||||
|             .bind(amount as i32) | ||||
|             .bind(meseta.0 as i32) | ||||
|             .execute(&self.pool) | ||||
|             .await?; | ||||
|         Ok(()) | ||||
|     } | ||||
| 
 | ||||
|     async fn get_character_meseta(&mut self, char_id: &CharacterEntityId) -> Result<Meseta, GatewayError> { | ||||
|         #[derive(sqlx::FromRow)] | ||||
|         struct PgMeseta(i32); | ||||
|         let meseta = sqlx::query_as::<_, PgMeseta>(r#"select meseta from character_meseta where id = $1"#) | ||||
|             .bind(char_id.0) | ||||
|             .fetch_one(&self.pool) | ||||
|             .await?; | ||||
|         Ok(Meseta(meseta.0 as u32)) | ||||
|     } | ||||
| 
 | ||||
|     async fn set_bank_meseta(&mut self, char_id: &CharacterEntityId, bank: BankName, meseta: Meseta) -> Result<(), GatewayError> { | ||||
|         sqlx::query("insert into bank_meseta values ($1, $2, $3) on conflict (pchar, bank) do update set items = $2") | ||||
|             .bind(char_id.0) | ||||
|             .bind(meseta.0 as i32) | ||||
|             .bind(bank.0) | ||||
|             .execute(&self.pool) | ||||
|             .await?; | ||||
|         Ok(()) | ||||
|     } | ||||
| 
 | ||||
|     async fn get_bank_meseta(&mut self, char_id: &CharacterEntityId, bank: BankName) -> Result<Meseta, GatewayError> { | ||||
|         #[derive(sqlx::FromRow)] | ||||
|         struct PgMeseta(i32); | ||||
|         let meseta = sqlx::query_as::<_, PgMeseta>(r#"select meseta from character_meseta where id = $1 and bank = $2"#) | ||||
|             .bind(char_id.0) | ||||
|             .bind(bank.0) | ||||
|             .fetch_one(&self.pool) | ||||
|             .await?; | ||||
|         Ok(Meseta(meseta.0 as u32)) | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -60,7 +60,7 @@ pub enum ItemNote { | ||||
|     }, | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, Clone, PartialEq)] | ||||
| #[derive(Debug, Copy, Clone, PartialEq)] | ||||
| pub struct Meseta(pub u32); | ||||
| 
 | ||||
| impl Meseta { | ||||
|  | ||||
| @ -20,7 +20,7 @@ use libpso::{utf8_to_array, utf8_to_utf16_array}; | ||||
| 
 | ||||
| use crate::entity::gateway::{EntityGateway, GatewayError}; | ||||
| use crate::entity::account::{UserAccountId, UserAccountEntity, NewUserSettingsEntity, USERFLAG_NEWCHAR, USERFLAG_DRESSINGROOM}; | ||||
| use crate::entity::item::{NewItemEntity, ItemDetail, ItemNote, InventoryItemEntity, InventoryEntity, BankEntity, BankName, EquippedEntity}; | ||||
| use crate::entity::item::{NewItemEntity, ItemDetail, ItemNote, InventoryItemEntity, InventoryEntity, BankEntity, BankName, EquippedEntity, Meseta}; | ||||
| use crate::entity::item::weapon::Weapon; | ||||
| use crate::entity::item::armor::Armor; | ||||
| use crate::entity::item::tech::Technique; | ||||
| @ -201,8 +201,8 @@ async fn new_character<EG: EntityGateway>(entity_gateway: &mut EG, user: &UserAc | ||||
|         _ => {} | ||||
|     } | ||||
| 
 | ||||
|     character.meseta = 300; | ||||
|     let character = entity_gateway.create_character(character).await?; | ||||
|     entity_gateway.set_character_meseta(&character.id, Meseta(300)).await?; | ||||
| 
 | ||||
|     let new_weapon = match character.char_class { | ||||
|         CharacterClass::HUmar | CharacterClass::HUnewearl | CharacterClass::HUcast | CharacterClass::HUcaseal => item::weapon::WeaponType::Saber, | ||||
|  | ||||
| @ -2,11 +2,13 @@ use libpso::character::character; | ||||
| use crate::common::leveltable::CharacterStats; | ||||
| use crate::entity::character::CharacterEntity; | ||||
| use crate::ship::items::{CharacterInventory, CharacterBank}; | ||||
| use crate::entity::item::Meseta; | ||||
| 
 | ||||
| pub struct CharacterBytesBuilder<'a> { | ||||
|     character: Option<&'a CharacterEntity>, | ||||
|     stats: Option<&'a CharacterStats>, | ||||
|     level: Option<u32>, | ||||
|     meseta: Option<Meseta>, | ||||
| } | ||||
| 
 | ||||
| impl<'a> Default for CharacterBytesBuilder<'a> { | ||||
| @ -15,6 +17,7 @@ impl<'a> Default for CharacterBytesBuilder<'a> { | ||||
|             character: None, | ||||
|             stats: None, | ||||
|             level: None, | ||||
|             meseta: None, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -42,10 +45,18 @@ impl<'a> CharacterBytesBuilder<'a> { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn meseta(self, meseta: Meseta) -> CharacterBytesBuilder<'a> { | ||||
|         CharacterBytesBuilder { | ||||
|             meseta: Some(meseta), | ||||
|             ..self | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn build(self) -> character::Character { | ||||
|         let character = self.character.unwrap(); | ||||
|         let stats = self.stats.unwrap(); | ||||
|         let level = self.level.unwrap(); | ||||
|         let meseta = self.meseta.unwrap(); | ||||
|         character::Character { | ||||
|             name: libpso::utf8_to_utf16_array!(character.name, 16), | ||||
|             hp: stats.hp, | ||||
| @ -70,7 +81,7 @@ impl<'a> CharacterBytesBuilder<'a> { | ||||
|             prop_y: character.appearance.prop_y, | ||||
|             config: character.config.as_bytes(), | ||||
|             techniques: character.techs.as_bytes(), | ||||
|             meseta: character.meseta, | ||||
|             meseta: meseta.0 as u32, | ||||
|             exp: character.exp, | ||||
|             ..character::Character::default() | ||||
|         } | ||||
| @ -82,6 +93,7 @@ pub struct FullCharacterBytesBuilder<'a> { | ||||
|     character: Option<&'a CharacterEntity>, | ||||
|     stats: Option<&'a CharacterStats>, | ||||
|     level: Option<u32>, | ||||
|     meseta: Option<Meseta>, | ||||
|     inventory: Option<&'a CharacterInventory>, | ||||
|     bank: Option<&'a CharacterBank>, | ||||
|     key_config: Option<&'a [u8; 0x16C]>, | ||||
| @ -97,6 +109,7 @@ impl<'a> Default for FullCharacterBytesBuilder<'a> { | ||||
|             character: None, | ||||
|             stats: None, | ||||
|             level: None, | ||||
|             meseta: None, | ||||
|             inventory: None, | ||||
|             bank: None, | ||||
|             key_config: None, | ||||
| @ -131,6 +144,13 @@ impl<'a> FullCharacterBytesBuilder<'a> { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn meseta(self, meseta: Meseta) -> FullCharacterBytesBuilder<'a> { | ||||
|         FullCharacterBytesBuilder { | ||||
|             meseta: Some(meseta), | ||||
|             ..self | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn inventory(self, inventory: &'a CharacterInventory) -> FullCharacterBytesBuilder<'a> { | ||||
|         FullCharacterBytesBuilder { | ||||
|             inventory: Some(inventory), | ||||
| @ -184,6 +204,7 @@ impl<'a> FullCharacterBytesBuilder<'a> { | ||||
|         let character = self.character.unwrap(); | ||||
|         let stats = self.stats.unwrap(); | ||||
|         let level = self.level.unwrap(); | ||||
|         let meseta = self.meseta.unwrap(); | ||||
|         let inventory = self.inventory.unwrap(); | ||||
|         let bank = self.bank.unwrap(); | ||||
|         let key_config = self.key_config.unwrap(); | ||||
| @ -204,6 +225,7 @@ impl<'a> FullCharacterBytesBuilder<'a> { | ||||
|                 .character(character) | ||||
|                 .stats(stats) | ||||
|                 .level(level - 1) | ||||
|                 .meseta(meseta) | ||||
|                 .build(), | ||||
|             inventory: character::Inventory { | ||||
|                 item_count: inventory.count() as u8, | ||||
|  | ||||
| @ -106,6 +106,8 @@ pub struct ItemManager { | ||||
|     pub(super) id_counter: u32, | ||||
| 
 | ||||
|     pub(self) character_inventory: HashMap<CharacterEntityId, CharacterInventory>, | ||||
|     pub(self) character_meseta: HashMap<CharacterEntityId, Meseta>, | ||||
|     pub(self) bank_meseta: HashMap<CharacterEntityId, Meseta>, | ||||
|     //character_bank: HashMap<CharacterEntityId, BTreeMap<BankName, CharacterBank>>,
 | ||||
|     pub(self) character_bank: HashMap<CharacterEntityId, CharacterBank>, | ||||
|     pub(self) character_floor: HashMap<CharacterEntityId, RoomFloorItems>, | ||||
| @ -120,6 +122,8 @@ impl Default for ItemManager { | ||||
|         ItemManager { | ||||
|             id_counter: 0, | ||||
|             character_inventory: HashMap::new(), | ||||
|             character_meseta: HashMap::new(), | ||||
|             bank_meseta: HashMap::new(), | ||||
|             character_bank: HashMap::new(), | ||||
|             character_floor: HashMap::new(), | ||||
|             character_room: HashMap::new(), | ||||
| @ -194,8 +198,13 @@ impl ItemManager { | ||||
|             .collect::<Result<Vec<_>, _>>()?; | ||||
|         let character_bank = CharacterBank::new(bank_items); | ||||
| 
 | ||||
|         let character_meseta = entity_gateway.get_character_meseta(&character.id).await?; | ||||
|         let bank_meseta = entity_gateway.get_bank_meseta(&character.id, BankName("".into())).await?; | ||||
| 
 | ||||
|         self.character_inventory.insert(character.id, character_inventory); | ||||
|         self.character_bank.insert(character.id, character_bank); | ||||
|         self.character_meseta.insert(character.id, character_meseta); | ||||
|         self.bank_meseta.insert(character.id, bank_meseta); | ||||
|         Ok(()) | ||||
|     } | ||||
| 
 | ||||
| @ -237,6 +246,35 @@ impl ItemManager { | ||||
|            //.ok_or(ItemManagerError::InvalidBankName(BankName("".to_string())))?)
 | ||||
|     } | ||||
| 
 | ||||
|     pub fn get_character_meseta(&self, character_id: &CharacterEntityId) -> Result<&Meseta, ItemManagerError> { | ||||
|         Ok(self.character_meseta.get(&character_id) | ||||
|            .ok_or(ItemManagerError::NoCharacter(*character_id))?) | ||||
|     } | ||||
| 
 | ||||
|     pub fn get_character_meseta_mut<'a>(&'a mut self, character_id: &CharacterEntityId) -> Result<&'a mut Meseta, ItemManagerError> { | ||||
|         Ok(self.character_meseta.get_mut(&character_id) | ||||
|            .ok_or(ItemManagerError::NoCharacter(*character_id))?) | ||||
|     } | ||||
| 
 | ||||
|     pub fn get_bank_meseta(&self, character_id: &CharacterEntityId) -> Result<&Meseta, ItemManagerError> { | ||||
|         Ok(self.bank_meseta.get(&character_id) | ||||
|            .ok_or(ItemManagerError::NoCharacter(*character_id))?) | ||||
|     } | ||||
| 
 | ||||
|     pub fn get_bank_meseta_mut<'a>(&'a mut self, character_id: &CharacterEntityId) -> Result<&'a mut Meseta, ItemManagerError> { | ||||
|         Ok(self.bank_meseta.get_mut(&character_id) | ||||
|            .ok_or(ItemManagerError::NoCharacter(*character_id))?) | ||||
|     } | ||||
| 
 | ||||
|     pub fn get_character_and_bank_meseta_mut<'a>(&'a mut self, character_id: &CharacterEntityId) -> Result<(&'a mut Meseta, &'a mut Meseta), ItemManagerError> { | ||||
|         Ok(( | ||||
|             self.character_meseta.get_mut(&character_id) | ||||
|                 .ok_or(ItemManagerError::NoCharacter(*character_id))?, | ||||
|             self.bank_meseta.get_mut(&character_id) | ||||
|                 .ok_or(ItemManagerError::NoCharacter(*character_id))? | ||||
|         )) | ||||
|     } | ||||
| 
 | ||||
|     /*pub fn get_character_bank_mut(&mut self, character: &CharacterEntity) -> Result<&CharacterBank, ItemManagerError> {
 | ||||
|         Ok(self.character_bank | ||||
|            .get_mut(&character.id) | ||||
| @ -336,11 +374,12 @@ impl ItemManager { | ||||
|                         } | ||||
|                     }, | ||||
|                     FloorItem::Meseta(meseta_floor_item) => { | ||||
|                         if character.meseta >= 999999 { | ||||
|                         let character_meseta = it.manager.character_meseta.get(&character.id).ok_or(ItemManagerError::NoCharacter(character.id))?; | ||||
|                         if character_meseta.0 >= 999999 { | ||||
|                             return Err(ItemManagerError::CouldNotAddToInventory(*item_id).into()); | ||||
|                         } | ||||
|                         it.action(Box::new(AddMesetaFloorItemToInventory { | ||||
|                             character: (**character).clone(), | ||||
|                             character_id: character.id, | ||||
|                             item: meseta_floor_item.clone() | ||||
|                         })); | ||||
| 
 | ||||
| @ -493,11 +532,12 @@ impl ItemManager { | ||||
|                                                                         -> Result<FloorItem, anyhow::Error> { | ||||
|         let room_id = self.character_room.get(&character.id).ok_or(ItemManagerError::NoCharacter(character.id))?; | ||||
|         let shared_floor = self.room_floor.get_mut(room_id).ok_or(ItemManagerError::NoCharacter(character.id))?; | ||||
|         if character.meseta < amount { | ||||
|         let character_meseta = self.character_meseta.get_mut(&character.id).ok_or(ItemManagerError::NoCharacter(character.id))?; | ||||
|         if character_meseta.0 < amount { | ||||
|             return Err(ItemManagerError::CouldNotDropMeseta.into()) | ||||
|         } | ||||
|         character.meseta -= amount; | ||||
|         entity_gateway.save_character(character).await?; | ||||
|         character_meseta.0 -= amount; | ||||
|         entity_gateway.set_character_meseta(&character.id, *character_meseta).await?; | ||||
| 
 | ||||
|         let item_id = self.room_item_id_counter.borrow_mut().get_mut(room_id).ok_or(ItemManagerError::NoCharacter(character.id))?(); | ||||
|         let floor_item = FloorItem::Meseta(MesetaFloorItem { | ||||
| @ -1183,16 +1223,16 @@ impl<EG: EntityGateway> ItemAction<EG> for AddStackedFloorItemToInventory { | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| struct AddMesetaFloorItemToInventory{ | ||||
|     character: CharacterEntity, | ||||
|     character_id: CharacterEntityId, | ||||
|     item: MesetaFloorItem, | ||||
| } | ||||
| 
 | ||||
| #[async_trait::async_trait] | ||||
| impl<EG: EntityGateway> ItemAction<EG> for AddMesetaFloorItemToInventory { | ||||
|     async fn commit(&self, _item_manager: &mut ItemManager, entity_gateway: &mut EG) -> Result<(), TransactionCommitError> { | ||||
|         let mut nchar = self.character.clone(); | ||||
|         nchar.meseta = std::cmp::min(self.character.meseta + self.item.meseta.0, 999999); | ||||
|         entity_gateway.save_character(&nchar).await?; | ||||
|     async fn commit(&self, item_manager: &mut ItemManager, entity_gateway: &mut EG) -> Result<(), TransactionCommitError> { | ||||
|         let character_meseta = item_manager.character_meseta.get_mut(&self.character_id).ok_or(ItemManagerError::NoCharacter(self.character_id))?; | ||||
|         character_meseta.0 = std::cmp::min(character_meseta.0 + self.item.meseta.0, 999999); | ||||
|         entity_gateway.set_character_meseta(&self.character_id, *character_meseta).await?; | ||||
|         Ok(()) | ||||
|     } | ||||
| } | ||||
| @ -1254,7 +1294,17 @@ struct TradeMeseta { | ||||
| 
 | ||||
| #[async_trait::async_trait] | ||||
| impl<EG: EntityGateway> ItemAction<EG> for TradeMeseta { | ||||
|     async fn commit(&self, _item_manager: &mut ItemManager, entity_gateway: &mut EG) -> Result<(), TransactionCommitError> { | ||||
|     async fn commit(&self, item_manager: &mut ItemManager, entity_gateway: &mut EG) -> Result<(), TransactionCommitError> { | ||||
|         { | ||||
|             let src_meseta = item_manager.get_character_meseta_mut(&self.src_character_id)?; | ||||
|             src_meseta.0 -= self.amount as u32; | ||||
|             entity_gateway.set_character_meseta(&self.src_character_id, *src_meseta).await?; | ||||
|         } | ||||
|         { | ||||
|             let dest_meseta = item_manager.get_character_meseta_mut(&self.dest_character_id)?; | ||||
|             dest_meseta.0 += self.amount as u32; | ||||
|             entity_gateway.set_character_meseta(&self.dest_character_id, *dest_meseta).await?; | ||||
|         } | ||||
|         Ok(()) | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -26,10 +26,12 @@ pub fn player_header(tag: u32, client: &ClientState, area_client: &AreaClient) - | ||||
| pub fn player_info(tag: u32, client: &ClientState, area_client: &AreaClient, item_manager: &ItemManager, level_table: &CharacterLevelTable) -> PlayerInfo { | ||||
|     let (level, stats) = level_table.get_stats_from_exp(client.character.char_class, client.character.exp); | ||||
|     let inventory = item_manager.get_character_inventory(&client.character).unwrap(); | ||||
|     let meseta = item_manager.get_character_meseta(&client.character.id).unwrap(); | ||||
|     let character = CharacterBytesBuilder::default() | ||||
|         .character(&client.character) | ||||
|         .stats(&stats) | ||||
|         .level(level - 1) | ||||
|         .meseta(*meseta) | ||||
|         .build(); | ||||
|     PlayerInfo { | ||||
|         header: player_header(tag, client, area_client), | ||||
|  | ||||
| @ -232,8 +232,8 @@ pub async fn send_bank_list(id: ClientId, | ||||
| { | ||||
|     let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id))?; | ||||
|     let bank_items = item_manager.get_character_bank(&client.character)?; | ||||
| 
 | ||||
|     let bank_items_pkt = builder::message::bank_item_list(bank_items, client.character.bank_meseta); | ||||
|     let bank_meseta = item_manager.get_bank_meseta(&client.character.id)?; | ||||
|     let bank_items_pkt = builder::message::bank_item_list(bank_items, bank_meseta.0); | ||||
|     Ok(Box::new(vec![(id, SendShipPacket::BankItemList(bank_items_pkt))].into_iter())) | ||||
| } | ||||
| 
 | ||||
| @ -252,11 +252,16 @@ where | ||||
|     let other_clients_in_area = client_location.get_all_clients_by_client(id).map_err(|err| -> ClientLocationError { err.into() })?; | ||||
|     let bank_action_pkts = match bank_interaction.action { | ||||
|         BANK_ACTION_DEPOSIT => { | ||||
|             let character_meseta = item_manager.get_character_meseta(&client.character.id)?; | ||||
|             let bank_meseta = item_manager.get_bank_meseta(&client.character.id)?; | ||||
|             if bank_interaction.item_id == 0xFFFFFFFF { | ||||
|                 if client.character.meseta >= bank_interaction.meseta_amount && (bank_interaction.meseta_amount + client.character.bank_meseta) <= BANK_MESETA_CAPACITY { | ||||
|                     client.character.meseta -= bank_interaction.meseta_amount; | ||||
|                     client.character.bank_meseta += bank_interaction.meseta_amount; | ||||
|                     entity_gateway.save_character(&client.character).await?; | ||||
|                 if character_meseta.0 >= bank_interaction.meseta_amount && (bank_interaction.meseta_amount + bank_meseta.0) <= BANK_MESETA_CAPACITY { | ||||
|                     let (character_meseta, bank_meseta) = item_manager.get_character_and_bank_meseta_mut(&client.character.id)?; | ||||
|                     character_meseta.0 -= bank_interaction.meseta_amount; | ||||
|                     bank_meseta.0 += bank_interaction.meseta_amount; | ||||
|                     entity_gateway.set_character_meseta(&client.character.id, *character_meseta).await?; | ||||
|                     // TODO: BankName
 | ||||
|                     entity_gateway.set_bank_meseta(&client.character.id, item::BankName("".into()), *bank_meseta).await?; | ||||
|                 } | ||||
|                 Vec::new() | ||||
|             } | ||||
| @ -267,11 +272,16 @@ where | ||||
|             } | ||||
|         }, | ||||
|         BANK_ACTION_WITHDRAW => { | ||||
|             let character_meseta = item_manager.get_character_meseta(&client.character.id)?; | ||||
|             let bank_meseta = item_manager.get_bank_meseta(&client.character.id)?; | ||||
|             if bank_interaction.item_id == 0xFFFFFFFF { | ||||
|                 if client.character.meseta + bank_interaction.meseta_amount <= INVENTORY_MESETA_CAPACITY { | ||||
|                     client.character.meseta += bank_interaction.meseta_amount; | ||||
|                     client.character.bank_meseta -= bank_interaction.meseta_amount; | ||||
|                     entity_gateway.save_character(&client.character).await?; | ||||
|                 if (bank_meseta.0 >= bank_interaction.meseta_amount) && (character_meseta.0 + bank_interaction.meseta_amount <= INVENTORY_MESETA_CAPACITY) { | ||||
|                     let (character_meseta, bank_meseta) = item_manager.get_character_and_bank_meseta_mut(&client.character.id)?; | ||||
|                     character_meseta.0 += bank_interaction.meseta_amount; | ||||
|                     bank_meseta.0 -= bank_interaction.meseta_amount; | ||||
|                     entity_gateway.set_character_meseta(&client.character.id, *character_meseta).await?; | ||||
|                     // TODO: BankName
 | ||||
|                     entity_gateway.set_bank_meseta(&client.character.id, item::BankName("".into()), *bank_meseta).await?; | ||||
|                 } | ||||
|                 Vec::new() | ||||
|             } | ||||
| @ -370,12 +380,13 @@ where | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     if client.character.meseta < item.price() as u32 { | ||||
|     let character_meseta = item_manager.get_character_meseta_mut(&client.character.id)?; | ||||
|     if character_meseta.0 < item.price() as u32 { | ||||
|         return Err(ShipError::ShopError.into()) | ||||
|     } | ||||
| 
 | ||||
|     client.character.meseta -= item.price() as u32; | ||||
|     entity_gateway.save_character(&client.character).await?; | ||||
|     character_meseta.0 -= item.price() as u32; | ||||
|     entity_gateway.set_character_meseta(&client.character.id, *character_meseta).await?; | ||||
| 
 | ||||
|     let inventory_item = item_manager.player_buys_item(entity_gateway, &client.character, item, ClientItemId(buy_item.item_id), buy_item.amount as usize).await?; | ||||
|     let create = builder::message::create_withdrawn_inventory_item(area_client, inventory_item)?; | ||||
| @ -447,8 +458,9 @@ where | ||||
|         grind: grind_mod, | ||||
|     }); | ||||
| 
 | ||||
|     client.character.meseta -= 100; | ||||
|     entity_gateway.save_character(&client.character).await?; | ||||
|     let character_meseta = item_manager.get_character_meseta_mut(&client.character.id)?; | ||||
|     character_meseta.0 -= 100; | ||||
|     entity_gateway.set_character_meseta(&client.character.id, *character_meseta).await?; | ||||
| 
 | ||||
|     let preview_pkt = builder::message::tek_preview(ClientItemId(tek_request.item_id), &weapon)?; | ||||
| 
 | ||||
|  | ||||
| @ -22,12 +22,14 @@ pub fn block_selected(id: ClientId, | ||||
|     let (level, stats) = level_table.get_stats_from_exp(client.character.char_class, client.character.exp); | ||||
| 
 | ||||
|     let inventory = item_manager.get_character_inventory(&client.character).unwrap(); | ||||
|     let meseta = item_manager.get_character_meseta(&client.character.id).unwrap(); | ||||
|     let bank = item_manager.get_character_bank(&client.character).unwrap(); | ||||
| 
 | ||||
|     let fc = FullCharacterBytesBuilder::default() | ||||
|         .character(&client.character) | ||||
|         .stats(&stats) | ||||
|         .level(level) | ||||
|         .meseta(*meseta) | ||||
|         .inventory(inventory) | ||||
|         .bank(bank) | ||||
|         .key_config(&client.settings.settings.key_config) | ||||
|  | ||||
| @ -194,7 +194,7 @@ pub fn update_player_position(id: ClientId, | ||||
|             .ok_or_else(|| ShipError::InvalidRoom(room_id.0 as u32))? | ||||
|             .as_ref() | ||||
|             .ok_or_else(|| ShipError::InvalidRoom(room_id.0 as u32))?; | ||||
|         
 | ||||
| 
 | ||||
|         match &message.msg { | ||||
|             GameMessage::PlayerChangedMap(p) => { | ||||
|                 client.x = p.x; | ||||
| @ -258,18 +258,22 @@ pub fn update_player_position(id: ClientId, | ||||
| pub async fn charge_attack<EG>(id: ClientId, | ||||
|                         charge: &ChargeAttack, | ||||
|                         clients: &mut Clients, | ||||
|                         entity_gateway: &mut EG) | ||||
|                         entity_gateway: &mut EG, | ||||
|                         item_manager: &mut ItemManager) | ||||
|                         -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error> | ||||
| where | ||||
|     EG: EntityGateway | ||||
| { | ||||
|     let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?; | ||||
|     if client.character.meseta >= charge.meseta { | ||||
|         client.character.meseta -= charge.meseta; | ||||
|         entity_gateway.save_character(&client.character).await?; | ||||
|     let meseta = item_manager.get_character_meseta_mut(&client.character.id)?; | ||||
| 
 | ||||
|     if meseta.0 >= charge.meseta { | ||||
|         meseta.0 -= charge.meseta; | ||||
|         entity_gateway.set_character_meseta(&client.character.id, *meseta).await?; | ||||
|         // TODO: this should probably echo the packet
 | ||||
|         Ok(Box::new(None.into_iter())) | ||||
|     } else { | ||||
|         Err(ShipError::NotEnoughMeseta(id, client.character.meseta).into()) | ||||
|         Err(ShipError::NotEnoughMeseta(id, meseta.0).into()) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @ -293,18 +297,21 @@ where | ||||
| pub async fn player_used_medical_center<EG>(id: ClientId, | ||||
|                                             _pumc: &PlayerUsedMedicalCenter, // not needed?
 | ||||
|                                             entity_gateway: &mut EG, | ||||
|                                             clients: &mut Clients) | ||||
|                                             clients: &mut Clients, | ||||
|                                             item_manager: &mut ItemManager) | ||||
|                                             -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error> | ||||
| where | ||||
|     EG: EntityGateway | ||||
| { | ||||
|     let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?; | ||||
|     if client.character.meseta >= 10 { | ||||
|         client.character.meseta -= 10; | ||||
|         entity_gateway.save_character(&client.character).await?; | ||||
|     let meseta = item_manager.get_character_meseta_mut(&client.character.id)?; | ||||
|     if meseta.0 >= 10 { | ||||
|         meseta.0 -= 10; | ||||
|         entity_gateway.set_character_meseta(&client.character.id, *meseta).await?; | ||||
|         // TODO: this should probably echo the packet
 | ||||
|         Ok(Box::new(None.into_iter())) | ||||
|     } else { | ||||
|         Err(ShipError::NotEnoughMeseta(id, client.character.meseta).into()) | ||||
|         Err(ShipError::NotEnoughMeseta(id, meseta.0).into()) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -488,14 +488,14 @@ impl<EG: EntityGateway> ShipServerState<EG> { | ||||
|                 handler::message::update_player_position(id, msg, &mut self.clients, &block.client_location, &block.rooms)? | ||||
|             }, | ||||
|             GameMessage::ChargeAttack(charge_attack) => { | ||||
|                 handler::message::charge_attack(id, charge_attack, &mut self.clients, &mut self.entity_gateway).await? | ||||
|                 handler::message::charge_attack(id, charge_attack, &mut self.clients, &mut self.entity_gateway, &mut self.item_manager).await? | ||||
|             }, | ||||
|             GameMessage::PlayerUseItem(player_use_item) => { | ||||
|                 let block = self.blocks.with_client(id, &self.clients)?; | ||||
|                 handler::message::use_item(id, player_use_item, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut self.item_manager).await? | ||||
|             }, | ||||
|             GameMessage::PlayerUsedMedicalCenter(player_used_medical_center) => { | ||||
|                 handler::message::player_used_medical_center(id, player_used_medical_center, &mut self.entity_gateway, &mut self.clients).await? | ||||
|                 handler::message::player_used_medical_center(id, player_used_medical_center, &mut self.entity_gateway, &mut self.clients, &mut self.item_manager).await? | ||||
|             }, | ||||
|             GameMessage::PlayerFeedMag(player_feed_mag) => { | ||||
|                 let block = self.blocks.with_client(id, &self.clients)?; | ||||
|  | ||||
| @ -4,6 +4,7 @@ use elseware::common::serverstate::{ClientId, ServerState}; | ||||
| use elseware::entity::gateway::EntityGateway; | ||||
| use elseware::entity::account::{UserAccountEntity, NewUserAccountEntity, NewUserSettingsEntity}; | ||||
| use elseware::entity::character::{CharacterEntity, NewCharacterEntity}; | ||||
| use elseware::entity::item::{Meseta, BankName}; | ||||
| use elseware::ship::ship::{ShipServerState, RecvShipPacket}; | ||||
| use elseware::ship::room::Difficulty; | ||||
| 
 | ||||
| @ -27,6 +28,8 @@ pub async fn new_user_character<EG: EntityGateway>(entity_gateway: &mut EG, user | ||||
|     let _settings = entity_gateway.create_user_settings(new_settings).await.unwrap(); | ||||
|     let new_character = NewCharacterEntity::new(user.id); | ||||
|     let character = entity_gateway.create_character(new_character).await.unwrap(); | ||||
|     entity_gateway.set_character_meseta(&character.id, Meseta(0)).await.unwrap(); | ||||
|     entity_gateway.set_bank_meseta(&character.id, BankName("".into()), Meseta(0)).await.unwrap(); | ||||
| 
 | ||||
|     (user, character) | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user