Browse Source

modifiers are for the boys

presents
andy 3 years ago
parent
commit
ba0b827c24
  1. 5
      src/bin/main.rs
  2. 12
      src/entity/gateway/entitygateway.rs
  3. 30
      src/entity/gateway/inmemory.rs
  4. 6
      src/entity/gateway/postgres/models.rs
  5. 4
      src/entity/gateway/postgres/postgres.rs
  6. 24
      src/entity/item/armor.rs
  7. 15
      src/entity/item/shield.rs
  8. 13
      src/entity/item/unit.rs
  9. 17
      src/entity/item/weapon.rs
  10. 1
      src/login/character.rs
  11. 5
      src/ship/drops/generic_armor.rs
  12. 1
      src/ship/drops/rare_drop_table.rs
  13. 25
      src/ship/items/inventory.rs
  14. 19
      src/ship/items/manager.rs
  15. 1
      src/ship/shops/armor.rs

5
src/bin/main.rs

@ -74,7 +74,7 @@ fn main() {
character.meseta = 999999;
let character = entity_gateway.create_character(character).await.unwrap();
for _ in 0..3 {
for _ in 0..3usize {
entity_gateway.create_item(
item::NewItemEntity {
item: item::ItemDetail::Weapon(
@ -94,7 +94,7 @@ fn main() {
}).await.unwrap();
}
for _ in 0..8 {
for _ in 0..8usize {
entity_gateway.create_item(
NewItemEntity {
item: ItemDetail::Tool (
@ -277,6 +277,7 @@ fn main() {
dfp: 0,
evp: 0,
slots: 4,
wrapping: None,
}
),
location: ItemLocation::Inventory {

12
src/entity/gateway/entitygateway.rs

@ -85,6 +85,18 @@ pub trait EntityGateway: Send + Sync + Clone {
unimplemented!();
}
async fn add_armor_modifier(&mut self, _item_id: &ItemEntityId, _modifier: armor::ArmorModifier) -> Result<(), GatewayError> {
unimplemented!();
}
async fn add_shield_modifier(&mut self, _item_id: &ItemEntityId, _modifier: shield::ShieldModifier) -> Result<(), GatewayError> {
unimplemented!();
}
async fn add_unit_modifier(&mut self, _item_id: &ItemEntityId, _modifier: unit::UnitModifier) -> Result<(), GatewayError> {
unimplemented!();
}
/*
async fn get_items_by_character(&self, _char_id: &CharacterEntityId) -> Result<Vec<ItemEntity>, GatewayError> {

30
src/entity/gateway/inmemory.rs

@ -19,6 +19,9 @@ 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>>>>,
armor_modifiers: Arc<Mutex<BTreeMap<ItemEntityId, Vec<armor::ArmorModifier>>>>,
shield_modifiers: Arc<Mutex<BTreeMap<ItemEntityId, Vec<shield::ShieldModifier>>>>,
unit_modifiers: Arc<Mutex<BTreeMap<ItemEntityId, Vec<unit::UnitModifier>>>>,
}
impl InMemoryGateway {
@ -33,6 +36,9 @@ impl InMemoryGateway {
equips: Arc::new(Mutex::new(BTreeMap::new())),
mag_modifiers: Arc::new(Mutex::new(BTreeMap::new())),
weapon_modifiers: Arc::new(Mutex::new(BTreeMap::new())),
armor_modifiers: Arc::new(Mutex::new(BTreeMap::new())),
shield_modifiers: Arc::new(Mutex::new(BTreeMap::new())),
unit_modifiers: Arc::new(Mutex::new(BTreeMap::new())),
}
}
}
@ -273,6 +279,30 @@ impl EntityGateway for InMemoryGateway {
Ok(())
}
async fn add_armor_modifier(&mut self, item_id: &ItemEntityId, modifier: armor::ArmorModifier) -> Result<(), GatewayError> {
self.armor_modifiers.lock().unwrap()
.entry(*item_id)
.or_insert(Vec::new())
.push(modifier);
Ok(())
}
async fn add_shield_modifier(&mut self, item_id: &ItemEntityId, modifier: shield::ShieldModifier) -> Result<(), GatewayError> {
self.shield_modifiers.lock().unwrap()
.entry(*item_id)
.or_insert(Vec::new())
.push(modifier);
Ok(())
}
async fn add_unit_modifier(&mut self, item_id: &ItemEntityId, modifier: unit::UnitModifier) -> Result<(), GatewayError> {
self.unit_modifiers.lock().unwrap()
.entry(*item_id)
.or_insert(Vec::new())
.push(modifier);
Ok(())
}
async fn get_character_inventory(&mut self, char_id: &CharacterEntityId) -> Result<InventoryEntity, GatewayError> {
println!("getting inv");
let inventories = self.inventories.lock().unwrap();

6
src/entity/gateway/postgres/models.rs

@ -335,7 +335,7 @@ pub struct PgArmor {
dfp: u8,
evp: u8,
slots: u8,
// wrapping: Option<WrappingPaper>, // TODO: check if this clobbers slots
wrapping: Option<WrappingPaper>, // TODO: check if this clobbers slots
}
impl From<armor::Armor> for PgArmor {
@ -345,7 +345,7 @@ impl From<armor::Armor> for PgArmor {
dfp: other.dfp,
evp: other.evp,
slots: other.slots,
// wrapping: other.wrapping,
wrapping: other.wrapping,
}
}
}
@ -357,7 +357,7 @@ impl Into<armor::Armor> for PgArmor {
dfp: self.dfp,
evp: self.evp,
slots: self.slots,
// wrapping: self.wrapping,
wrapping: self.wrapping,
}
}
}

4
src/entity/gateway/postgres/postgres.rs

@ -528,6 +528,7 @@ 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 {
@ -540,7 +541,8 @@ impl EntityGateway for PostgresGateway {
}
})
.collect::<Vec<_>>();
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))

24
src/entity/item/armor.rs

@ -293,7 +293,11 @@ impl ArmorType {
pub enum ArmorModifier {
AddSlot {
addslot: ItemEntityId,
}
},
WrapPresent {
paper: WrappingPaper,
},
UnwrapPresent,
}
@ -303,7 +307,7 @@ pub struct Armor {
pub dfp: u8,
pub evp: u8,
pub slots: u8,
// pub wrapping: Option<WrappingPaper>, // clobbers slots
pub wrapping: Option<WrappingPaper>,
}
impl Armor {
@ -318,16 +322,32 @@ impl Armor {
pub fn from_bytes(data: [u8; 16]) -> Result<Armor, ItemParseError> {
let a = ArmorType::parse_type([data[0], data[1], data[2]]);
let w = {
if data[4] & 0x40 == 0x40 {
WrappingPaper::from(0) // always use default wrapping paper to preserve slot info
} else {
None
}
};
if a.is_ok() {
Ok(Armor {
armor: a.unwrap(),
dfp: data[6],
evp: data[8],
slots: data[5],
wrapping: w,
})
}
else {
Err(ItemParseError::InvalidArmorBytes) // TODO: error handling if wrong bytes are given
}
}
pub fn apply_modifier(&mut self, modifier: &ArmorModifier) {
match modifier {
ArmorModifier::WrapPresent{paper} => {self.wrapping = Some(*paper)},
ArmorModifier::UnwrapPresent => {self.wrapping = None},
_ => {},
}
}
}

15
src/entity/item/shield.rs

@ -519,6 +519,13 @@ impl ShieldType {
}
}
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
pub enum ShieldModifier {
WrapPresent {
paper: WrappingPaper,
},
UnwrapPresent,
}
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
pub struct Shield {
@ -562,4 +569,12 @@ impl Shield {
Err(ItemParseError::InvalidShieldBytes) // TODO: error handling if wrong bytes are given
}
}
pub fn apply_modifier(&mut self, modifier: &ShieldModifier) {
match modifier {
ShieldModifier::WrapPresent{paper} => {self.wrapping = Some(*paper)},
ShieldModifier::UnwrapPresent => {self.wrapping = None},
_ => {},
}
}
}

13
src/entity/item/unit.rs

@ -330,6 +330,10 @@ pub enum UnitModifier {
Plus,
Minus,
MinusMinus,
WrapPresent {
paper: WrappingPaper,
},
UnwrapPresent,
}
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
@ -361,6 +365,7 @@ impl Unit {
result[6] = 0xFE;
result[7] = 0xFF;
},
_ => {}, // handling wrapping here is weird?
}
}
@ -401,4 +406,12 @@ impl Unit {
Err(ItemParseError::InvalidUnitBytes) // TODO: error handling if wrong bytes are given
}
}
pub fn apply_modifier(&mut self, modifier: &UnitModifier) {
match modifier {
UnitModifier::WrapPresent{paper} => {self.wrapping = Some(*paper)},
UnitModifier::UnwrapPresent => {self.wrapping = None},
_ => {},
}
}
}

17
src/entity/item/weapon.rs

@ -1452,6 +1452,10 @@ pub enum WeaponModifier {
percent: TekPercentModifier,
grind: i32,
},
WrapPresent {
paper: WrappingPaper,
},
UnwrapPresent,
}
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
@ -1518,6 +1522,8 @@ impl Weapon {
self.grind = std::cmp::max(self.grind as i32 + grind, 0) as u8;
self.tekked = true;
},
WeaponModifier::WrapPresent{paper} => {self.wrapping = Some(*paper)},
WeaponModifier::UnwrapPresent => {self.wrapping = None},
_ => {}
}
}
@ -1558,7 +1564,6 @@ impl Weapon {
if w.is_ok() {
let mut s = None;
let mut t = true;
let mut p = None; // wrapping paper
let g = data[3];
if data[4] & 0x80 == 0x80 {
@ -1566,9 +1571,13 @@ impl Weapon {
t = false;
}
if data[4] & 0x40 == 0x40 {
p = WrappingPaper::from(data[5]);
}
let p = {
if data[4] & 0x40 == 0x40 {
WrappingPaper::from(data[5])
} else {
None
}
};
let mut a = [
None,

1
src/login/character.rs

@ -234,6 +234,7 @@ async fn new_character<EG: EntityGateway>(entity_gateway: &mut EG, user: &UserAc
dfp: 0,
evp: 0,
slots: 0,
wrapping: None,
}),
location: ItemLocation::Inventory {
character_id: character.id,

5
src/ship/drops/generic_armor.rs

@ -107,6 +107,7 @@ impl GenericArmorTable {
dfp: dfp_modifier as u8,
evp: evp_modifier as u8,
slots: slots as u8,
wrapping: None,
}))
}
}
@ -126,24 +127,28 @@ mod test {
dfp: 0,
evp: 0,
slots: 1,
wrapping: None,
})));
assert!(gat.get_drop(&MapArea::Caves3, &mut rng) == Some(ItemDropType::Armor(Armor {
armor: ArmorType::AbsorbArmor,
dfp: 1,
evp: 1,
slots: 1,
wrapping: None,
})));
assert!(gat.get_drop(&MapArea::Forest2, &mut rng) == Some(ItemDropType::Armor(Armor {
armor: ArmorType::HyperFrame,
dfp: 0,
evp: 0,
slots: 0,
wrapping: None,
})));
assert!(gat.get_drop(&MapArea::DarkFalz, &mut rng) == Some(ItemDropType::Armor(Armor {
armor: ArmorType::ImperialArmor,
dfp: 2,
evp: 1,
slots: 0,
wrapping: None,
})));
}
}

1
src/ship/drops/rare_drop_table.rs

@ -114,6 +114,7 @@ impl RareDropTable {
dfp: self.armor_stats.dfp_modifier(&armor, rng) as u8,
evp: self.armor_stats.evp_modifier(&armor, rng) as u8,
slots: self.armor_stats.slots(map_area, rng) as u8,
wrapping: None,
})
},
RareDropItem::Shield(shield) => {

25
src/ship/items/inventory.rs

@ -6,6 +6,9 @@ use crate::entity::item::{ItemEntityId, ItemDetail, ItemEntity, ItemType, ItemLo
use crate::entity::item::tool::Tool;
use crate::entity::item::mag::Mag;
use crate::entity::item::weapon::Weapon;
use crate::entity::item::armor::Armor; // TODO: cleanup uses
use crate::entity::item::shield::Shield;
use crate::entity::item::unit::Unit;
use crate::ship::items::{ClientItemId, BankItem, BankItemHandle};
use crate::ship::items::floor::{IndividualFloorItem, StackedFloorItem};
@ -55,6 +58,28 @@ impl IndividualInventoryItem {
_ => None
}
}
pub fn armor_mut(&mut self) -> Option<&mut Armor> {
match self.item {
ItemDetail::Armor(ref mut armor) => Some(armor),
_ => None
}
}
pub fn shield_mut(&mut self) -> Option<&mut Shield> {
match self.item {
ItemDetail::Shield(ref mut shield) => Some(shield),
_ => None
}
}
pub fn unit_mut(&mut self) -> Option<&mut Unit> {
match self.item {
ItemDetail::Unit(ref mut unit) => Some(unit),
_ => None
}
}
}
#[derive(Debug, Clone)]

19
src/ship/items/manager.rs

@ -639,9 +639,7 @@ impl ItemManager {
entity_gateway: &mut EG,
character: &mut CharacterEntity,
client_item_id: ClientItemId) -> Result<(), anyhow::Error> {
// println!("manager::use_item(): ClientItemId: {:?}", client_item_id);
let inventory = self.character_inventory.get_mut(&character.id).ok_or(ItemManagerError::NoCharacter(character.id))?;
let mut used_item_handle = inventory.get_item_handle_by_id(client_item_id).ok_or(ItemManagerError::ItemIdNotInInventory(client_item_id))?;
let used_item = used_item_handle.item_mut().ok_or(ItemManagerError::CannotGetMutItem)?;
match used_item.item_type() {
@ -765,13 +763,25 @@ impl ItemManager {
}
},
ItemType::Unit(_) => {
let actual_used_item = used_item.individual_mut().ok_or(ItemManagerError::CannotGetMutItem)?.unit_mut().ok_or(ItemManagerError::CannotGetMutItem)?;
if actual_used_item.wrapping.is_some() {
actual_used_item.apply_modifier(&unit::UnitModifier::UnwrapPresent);
entity_gateway.add_unit_modifier(&used_item.entity_ids()[0], unit::UnitModifier::UnwrapPresent).await?;
} else {
// combining / unsealing?
}
},
ItemType::Weapon(_) => {
let actual_used_item = used_item.individual_mut().ok_or(ItemManagerError::CannotGetMutItem)?.weapon_mut().ok_or(ItemManagerError::CannotGetMutItem)?;
actual_used_item.unwrap_present();
if actual_used_item.wrapping.is_some() {
actual_used_item.apply_modifier(&weapon::WeaponModifier::UnwrapPresent);
entity_gateway.add_weapon_modifier(&used_item.entity_ids()[0], weapon::WeaponModifier::UnwrapPresent).await?;
} else {
// combining / unsealing?
}
},
}
entity_gateway.set_character_inventory(&character.id, &inventory.as_inventory_entity(&character.id)).await?;
Ok(())
}
@ -953,7 +963,6 @@ impl ItemManager {
pub fn get_inventory_item_by_id(&mut self, character: &CharacterEntity, item_id: ClientItemId) -> Result<&InventoryItem, anyhow::Error> {
let inventory = self.character_inventory.get_mut(&character.id).ok_or(ItemManagerError::NoCharacter(character.id))?;
println!("item_manager.get_inventory_item_by_id() inventory: {:?}", inventory);
Ok(inventory.get_item_by_id(item_id).ok_or(ItemManagerError::ItemIdNotInInventory(item_id))?)
}
}

1
src/ship/shops/armor.rs

@ -71,6 +71,7 @@ impl ShopItem for ArmorShopItem {
dfp: 0,
evp: 0,
slots: *slot as u8,
wrapping: None,
})
},
ArmorShopItem::Barrier(barrier) => {

Loading…
Cancel
Save