diff --git a/src/bin/main.rs b/src/bin/main.rs index 41e9ad4..05305df 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -277,7 +277,7 @@ fn main() { dfp: 0, evp: 0, slots: 4, - wrapping: None, + wrapping: Some(item::WrappingPaper::Green), } ), location: ItemLocation::Inventory { @@ -292,7 +292,7 @@ fn main() { shield: item::shield::ShieldType::Barrier, dfp: 0, evp: 0, - wrapping: None, + wrapping: Some(item::WrappingPaper::Yellow), } ), location: ItemLocation::Inventory { diff --git a/src/entity/gateway/entitygateway.rs b/src/entity/gateway/entitygateway.rs index 74d3f5a..c0d3cba 100644 --- a/src/entity/gateway/entitygateway.rs +++ b/src/entity/gateway/entitygateway.rs @@ -97,6 +97,10 @@ pub trait EntityGateway: Send + Sync + Clone { unimplemented!(); } + async fn add_mag_modifier(&mut self, _item_id: &ItemEntityId, _modifier: mag::MagModifier) -> Result<(), GatewayError> { + unimplemented!(); + } + /* async fn get_items_by_character(&self, _char_id: &CharacterEntityId) -> Result, GatewayError> { diff --git a/src/entity/gateway/inmemory.rs b/src/entity/gateway/inmemory.rs index 17ab155..5167ff1 100644 --- a/src/entity/gateway/inmemory.rs +++ b/src/entity/gateway/inmemory.rs @@ -303,6 +303,14 @@ impl EntityGateway for InMemoryGateway { Ok(()) } + async fn add_mag_modifier(&mut self, item_id: &ItemEntityId, modifier: mag::MagModifier) -> Result<(), GatewayError> { + self.mag_modifiers.lock().unwrap() + .entry(*item_id) + .or_insert(Vec::new()) + .push(modifier); + Ok(()) + } + async fn get_character_inventory(&mut self, char_id: &CharacterEntityId) -> Result { println!("getting inv"); let inventories = self.inventories.lock().unwrap(); diff --git a/src/entity/gateway/postgres/models.rs b/src/entity/gateway/postgres/models.rs index e9533c2..8742dcd 100644 --- a/src/entity/gateway/postgres/models.rs +++ b/src/entity/gateway/postgres/models.rs @@ -362,6 +362,12 @@ impl Into for PgArmor { } } +#[derive(Debug, sqlx::FromRow)] +pub struct PgArmorModifier { + pub armor: i32, + pub modifier: sqlx::types::Json, +} + #[derive(Debug, Serialize, Deserialize)] pub struct PgShield { shield: shield::ShieldType, @@ -392,6 +398,12 @@ impl Into for PgShield { } } +#[derive(Debug, sqlx::FromRow)] +pub struct PgShieldModifier { + pub shield: i32, + pub modifier: sqlx::types::Json, +} + #[derive(Debug, Serialize, Deserialize)] pub struct PgUnit { unit: unit::UnitType, @@ -419,6 +431,12 @@ impl Into for PgUnit { } } +#[derive(Debug, sqlx::FromRow)] +pub struct PgUnitModifier { + pub unit: i32, + pub modifier: sqlx::types::Json, +} + #[derive(Debug, Serialize, Deserialize)] pub struct PgTool { pub tool: tool::ToolType, @@ -665,7 +683,9 @@ pub enum PgMagModifierDetail { FeedMag(i32), BankMag, MagCell(i32), - OwnerChange(CharacterClass, SectionID) + OwnerChange(CharacterClass, SectionID), + WrapPresent, + UnwrapPresent, } impl From for PgMagModifierDetail { @@ -675,6 +695,8 @@ impl From for PgMagModifierDetail { mag::MagModifier::BankMag => PgMagModifierDetail::BankMag, mag::MagModifier::MagCell(cell) => PgMagModifierDetail::MagCell(cell.0 as i32), mag::MagModifier::OwnerChange(class, section_id) => PgMagModifierDetail::OwnerChange(class, section_id), + mag::MagModifier::WrapPresent => PgMagModifierDetail::WrapPresent, + mag::MagModifier::UnwrapPresent => PgMagModifierDetail::UnwrapPresent, } } } @@ -686,6 +708,8 @@ impl Into for PgMagModifierDetail { PgMagModifierDetail::BankMag => mag::MagModifier::BankMag, PgMagModifierDetail::MagCell(cell) => mag::MagModifier::MagCell(ItemEntityId(cell as u32)), PgMagModifierDetail::OwnerChange(class, section_id) => mag::MagModifier::OwnerChange(class, section_id), + PgMagModifierDetail::WrapPresent => mag::MagModifier::WrapPresent, + PgMagModifierDetail::UnwrapPresent => mag::MagModifier::UnwrapPresent, } } } diff --git a/src/entity/gateway/postgres/postgres.rs b/src/entity/gateway/postgres/postgres.rs index f9acf92..9d02c52 100644 --- a/src/entity/gateway/postgres/postgres.rs +++ b/src/entity/gateway/postgres/postgres.rs @@ -91,11 +91,64 @@ impl PostgresGateway { mag::MagModifier::OwnerChange(class, section_id) => { mag.change_owner(class, section_id) }, + mag::MagModifier::WrapPresent => {mag.apply_modifier(&modifier)}, + mag::MagModifier::UnwrapPresent => {mag.apply_modifier(&modifier)}, } }).await; ItemDetail::Mag(mag) }, + ItemDetail::Armor(mut armor) => { + let q = r#"select armor, modifier + from armor_modifier + where armor = $1 + order by created_at"#; + let armor_modifiers = sqlx::query_as::<_, PgArmorModifier>(q) + .bind(id.0 as i32) + .fetch(&self.pool); + + armor_modifiers.for_each(|modifier| { + if let Ok(modifier) = modifier { + armor.apply_modifier(&modifier.modifier); + } + }).await; + + ItemDetail::Armor(armor) + }, + ItemDetail::Shield(mut shield) => { + let q = r#"select shield, modifier + from shield_modifier + where shield = $1 + order by created_at"#; + let shield_modifiers = sqlx::query_as::<_, PgShieldModifier>(q) + .bind(id.0 as i32) + .fetch(&self.pool); + + shield_modifiers.for_each(|modifier| { + if let Ok(modifier) = modifier { + shield.apply_modifier(&modifier.modifier); + } + }).await; + + ItemDetail::Shield(shield) + }, + ItemDetail::Unit(mut unit) => { + let q = r#"select unit, modifier + from unit_modifier + where unit = $1 + order by created_at"#; + let unit_modifiers = sqlx::query_as::<_, PgUnitModifier>(q) + .bind(id.0 as i32) + .fetch(&self.pool); + + unit_modifiers.for_each(|modifier| { + if let Ok(modifier) = modifier { + unit.apply_modifier(&modifier.modifier); + } + }).await; + + ItemDetail::Unit(unit) + }, item @ _ => item }; @@ -416,6 +469,30 @@ impl EntityGateway for PostgresGateway { Ok(()) } + async fn add_armor_modifier(&mut self, item_id: &ItemEntityId, modifier: armor::ArmorModifier) -> Result<(), GatewayError> { + sqlx::query("insert into armor_modifier (armor, modifier) values ($1, $2);") + .bind(item_id.0) + .bind(sqlx::types::Json(modifier)) + .execute(&self.pool).await?; + Ok(()) + } + + async fn add_shield_modifier(&mut self, item_id: &ItemEntityId, modifier: shield::ShieldModifier) -> Result<(), GatewayError> { + sqlx::query("insert into shield_modifier (shield, modifier) values ($1, $2);") + .bind(item_id.0) + .bind(sqlx::types::Json(modifier)) + .execute(&self.pool).await?; + Ok(()) + } + + async fn add_unit_modifier(&mut self, item_id: &ItemEntityId, modifier: unit::UnitModifier) -> Result<(), GatewayError> { + sqlx::query("insert into unit_modifier (unit, modifier) values ($1, $2);") + .bind(item_id.0) + .bind(sqlx::types::Json(modifier)) + .execute(&self.pool).await?; + Ok(()) + } + /* async fn get_items_by_character(&self, char_id: &CharacterEntityId) -> Result, GatewayError> { let q = r#"select * from ( @@ -528,7 +605,6 @@ impl EntityGateway for PostgresGateway { } async fn set_character_inventory(&mut self, char_id: &CharacterEntityId, inventory: &InventoryEntity) -> Result<(), GatewayError> { - println!("postgres.rs::set_character_inventory - received inventory entity: {:?}", inventory); let inventory = inventory.items.iter() .map(|item| { match item { @@ -541,8 +617,6 @@ impl EntityGateway for PostgresGateway { } }) .collect::>(); - println!("postgres.rs::set_character_inventory - collected new inventory: {:?}", inventory); - println!("postgres.rs::set_character_inventory - updating pchar: {:?}", char_id.0); sqlx::query("insert into inventory (pchar, items) values ($1, $2) on conflict (pchar) do update set items = $2") .bind(char_id.0) .bind(sqlx::types::Json(inventory)) diff --git a/src/entity/item/armor.rs b/src/entity/item/armor.rs index 7f7bf8b..5a15dbc 100644 --- a/src/entity/item/armor.rs +++ b/src/entity/item/armor.rs @@ -294,9 +294,7 @@ pub enum ArmorModifier { AddSlot { addslot: ItemEntityId, }, - WrapPresent { - paper: WrappingPaper, - }, + WrapPresent, UnwrapPresent, } @@ -314,6 +312,9 @@ impl Armor { pub fn as_bytes(&self) -> [u8; 16] { let mut result = [0; 16]; result[0..3].copy_from_slice(&self.armor.value()); + if self.wrapping.is_some() { + result[4] += 0x40; + } result[5] = self.slots; result[6] = self.dfp; result[8] = self.evp; @@ -345,7 +346,7 @@ impl Armor { pub fn apply_modifier(&mut self, modifier: &ArmorModifier) { match modifier { - ArmorModifier::WrapPresent{paper} => {self.wrapping = Some(*paper)}, + ArmorModifier::WrapPresent => {self.wrapping = Some(WrappingPaper::White_Pink)}, ArmorModifier::UnwrapPresent => {self.wrapping = None}, _ => {}, } diff --git a/src/entity/item/mag.rs b/src/entity/item/mag.rs index e3a350a..5a7bf8d 100644 --- a/src/entity/item/mag.rs +++ b/src/entity/item/mag.rs @@ -516,7 +516,9 @@ pub enum MagModifier { }, BankMag, // when putting a mag in the bank it truncates the values which has applications when raising degenerate mags MagCell(ItemEntityId), - OwnerChange(CharacterClass, SectionID) + OwnerChange(CharacterClass, SectionID), + WrapPresent, + UnwrapPresent, } #[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize, enum_utils::FromStr)] @@ -1110,6 +1112,14 @@ impl Mag { MagCell::LibertaKit => MagType::Agastya, } } + + pub fn apply_modifier(&mut self, modifier: &MagModifier) { + match modifier { + MagModifier::WrapPresent => {self.wrapping = WrappingPaper::from(self.color % 10)}, // prevents mag color from crashing wrapping papers + MagModifier::UnwrapPresent => {self.wrapping = None}, + _ => {}, // TODO: do mags use any other modifiers? + } + } } diff --git a/src/ship/items/manager.rs b/src/ship/items/manager.rs index b67b048..ba75443 100644 --- a/src/ship/items/manager.rs +++ b/src/ship/items/manager.rs @@ -8,6 +8,9 @@ use crate::entity::item::{Meseta, NewItemEntity, ItemEntity, InventoryItemEntity use crate::entity::item::tool::{Tool, ToolType}; use crate::entity::item::unit; use crate::entity::item::weapon; +use crate::entity::item::armor; +use crate::entity::item::shield; +use crate::entity::item::mag; use crate::ship::map::MapArea; use crate::ship::ship::ItemDropLocation; use crate::ship::drops::{ItemDrop, ItemDropType}; @@ -644,16 +647,34 @@ impl ItemManager { let used_item = used_item_handle.item_mut().ok_or(ItemManagerError::CannotGetMutItem)?; match used_item.item_type() { ItemType::Armor(_) => { - + let actual_used_item = used_item.individual_mut().ok_or(ItemManagerError::CannotGetMutItem)?.armor_mut().ok_or(ItemManagerError::CannotGetMutItem)?; + if actual_used_item.wrapping.is_some() { + actual_used_item.apply_modifier(&armor::ArmorModifier::UnwrapPresent); + entity_gateway.add_armor_modifier(&used_item.entity_ids()[0], armor::ArmorModifier::UnwrapPresent).await?; + } else { + // combining / unsealing? + } }, ItemType::ESWeapon(_) => { }, ItemType::Mag(_) => { - + let actual_used_item = used_item.individual_mut().ok_or(ItemManagerError::CannotGetMutItem)?.mag_mut().ok_or(ItemManagerError::CannotGetMutItem)?; + if actual_used_item.wrapping.is_some() { + actual_used_item.apply_modifier(&mag::MagModifier::UnwrapPresent); + entity_gateway.add_mag_modifier(&used_item.entity_ids()[0], mag::MagModifier::UnwrapPresent).await?; + } else { + // combining / unsealing? + } }, ItemType::Shield(_) => { - + let actual_used_item = used_item.individual_mut().ok_or(ItemManagerError::CannotGetMutItem)?.shield_mut().ok_or(ItemManagerError::CannotGetMutItem)?; + if actual_used_item.wrapping.is_some() { + actual_used_item.apply_modifier(&shield::ShieldModifier::UnwrapPresent); + entity_gateway.add_shield_modifier(&used_item.entity_ids()[0], shield::ShieldModifier::UnwrapPresent).await?; + } else { + // combining / unsealing? + } }, ItemType::TechniqueDisk(_) => {