You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

441 lines
19 KiB

use std::collections::BTreeMap;
use std::convert::TryInto;
use crate::entity::account::*;
use crate::entity::character::*;
use crate::entity::gateway::{EntityGateway, GatewayError};
use crate::entity::item::*;
use std::sync::{Arc, Mutex};
#[derive(Clone)]
pub struct InMemoryGateway {
users: Arc<Mutex<BTreeMap<UserAccountId, UserAccountEntity>>>,
user_settings: Arc<Mutex<BTreeMap<UserSettingsId, UserSettingsEntity>>>,
characters: Arc<Mutex<BTreeMap<CharacterEntityId, CharacterEntity>>>,
items: Arc<Mutex<BTreeMap<ItemEntityId, ItemEntity>>>,
inventories: Arc<Mutex<BTreeMap<CharacterEntityId, InventoryEntity>>>,
banks: Arc<Mutex<BTreeMap<CharacterEntityId, BankEntity>>>,
equips: Arc<Mutex<BTreeMap<CharacterEntityId, EquippedEntity>>>,
weapon_modifiers: Arc<Mutex<BTreeMap<ItemEntityId, Vec<weapon::WeaponModifier>>>>,
esweapon_modifiers: Arc<Mutex<BTreeMap<ItemEntityId, Vec<esweapon::ESWeaponModifier>>>>,
armor_modifiers: Arc<Mutex<BTreeMap<ItemEntityId, Vec<armor::ArmorModifier>>>>,
unit_modifiers: Arc<Mutex<BTreeMap<ItemEntityId, Vec<unit::UnitModifier>>>>,
shield_modifiers: Arc<Mutex<BTreeMap<ItemEntityId, Vec<shield::ShieldModifier>>>>,
mag_modifiers: Arc<Mutex<BTreeMap<ItemEntityId, Vec<mag::MagModifier>>>>,
tech_modifiers: Arc<Mutex<BTreeMap<ItemEntityId, Vec<tech::TechModifier>>>>,
tool_modifiers: Arc<Mutex<BTreeMap<ItemEntityId, Vec<tool::ToolModifier>>>>,
}
impl InMemoryGateway {
pub fn new() -> InMemoryGateway {
InMemoryGateway {
users: Arc::new(Mutex::new(BTreeMap::new())),
user_settings: Arc::new(Mutex::new(BTreeMap::new())),
characters: 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())),
equips: Arc::new(Mutex::new(BTreeMap::new())),
weapon_modifiers: Arc::new(Mutex::new(BTreeMap::new())),
esweapon_modifiers: Arc::new(Mutex::new(BTreeMap::new())),
armor_modifiers: Arc::new(Mutex::new(BTreeMap::new())),
unit_modifiers: Arc::new(Mutex::new(BTreeMap::new())),
shield_modifiers: Arc::new(Mutex::new(BTreeMap::new())),
mag_modifiers: Arc::new(Mutex::new(BTreeMap::new())),
tech_modifiers: Arc::new(Mutex::new(BTreeMap::new())),
tool_modifiers: Arc::new(Mutex::new(BTreeMap::new())),
}
}
}
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);
}
}
ItemDetail::Weapon(weapon)
},
ItemDetail::ESWeapon(mut esweapon) => {
if let Some(esweapon_modifiers) = self.esweapon_modifiers.lock().unwrap().get(&item.id) {
for esweapon_modifier in esweapon_modifiers.iter() {
esweapon.apply_modifier(&esweapon_modifier);
}
}
ItemDetail::ESWeapon(esweapon)
},
ItemDetail::Armor(mut armor) => {
if let Some(armor_modifiers) = self.armor_modifiers.lock().unwrap().get(&item.id) {
for armor_modifier in armor_modifiers.iter() {
armor.apply_modifier(&armor_modifier);
}
}
ItemDetail::Armor(armor)
},
ItemDetail::Unit(mut unit) => {
if let Some(unit_modifiers) = self.unit_modifiers.lock().unwrap().get(&item.id) {
for unit_modifier in unit_modifiers.iter() {
unit.apply_modifier(&unit_modifier);
}
}
ItemDetail::Unit(unit)
},
ItemDetail::Shield(mut shield) => {
if let Some(shield_modifiers) = self.shield_modifiers.lock().unwrap().get(&item.id) {
for shield_modifier in shield_modifiers.iter() {
shield.apply_modifier(&shield_modifier);
}
}
ItemDetail::Shield(shield)
},
ItemDetail::Mag(mag) => {
let mut mag = {
if mag.wrapping.is_some() {
mag::Mag::wrapped_baby_mag(mag.color as u16)
} else {
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} => {
items.get(&food).map(|mag_feed| {
match mag_feed.item {
ItemDetail::Tool(mag_feed) => mag.feed(mag_feed.tool),
_ => {}
}
});
},
mag::MagModifier::OwnerChange(class, section_id) => {
mag.change_owner(*class, *section_id)
},
mag::MagModifier::MagCell(mag_cell_id) => {
items.get(&mag_cell_id).map(|mag_cell| {
match mag_cell.item {
ItemDetail::Tool(mag_cell) => mag.apply_mag_cell(mag_cell.tool.try_into().unwrap()),
_ => {}
}
});
},
_ => {}
}
}
}
ItemDetail::Mag(mag)
},
ItemDetail::TechniqueDisk(mut tech) => {
if let Some(tech_modifiers) = self.tech_modifiers.lock().unwrap().get(&item.id) {
for tech_modifier in tech_modifiers.iter() {
tech.apply_modifier(&tech_modifier);
}
}
ItemDetail::TechniqueDisk(tech)
},
ItemDetail::Tool(mut tool) => {
if let Some(tool_modifiers) = self.tool_modifiers.lock().unwrap().get(&item.id) {
for tool_modifier in tool_modifiers.iter() {
tool.apply_modifier(&tool_modifier);
}
}
ItemDetail::Tool(tool)
},
};
item
})
})
.collect();
InventoryEntity::new(inventory_items)
}
}
#[async_trait::async_trait]
impl EntityGateway for InMemoryGateway {
async fn create_user(&mut self, user: NewUserAccountEntity) -> Result<UserAccountEntity, GatewayError> {
let mut users = self.users.lock().unwrap();
let id = users
.iter()
.fold(0, |sum, (i, _)| std::cmp::max(sum, i.0))
+ 1;
let user = UserAccountEntity {
id: UserAccountId(id),
username: user.username,
password: user.password,
guildcard: user.guildcard,
team_id: user.team_id,
banned_until: user.banned_until,
muted_until: user.muted_until,
created_at: chrono::Utc::now(),
flags: user.flags,
activated: user.activated,
at_login: false,
at_character: false,
at_ship: false,
};
users.insert(user.id, user.clone());
Ok(user)
}
async fn get_user_by_id(&self, id: UserAccountId) -> Result<UserAccountEntity, GatewayError> {
let users = self.users.lock().unwrap();
users.get(&id).map(|k| k.clone()).ok_or(GatewayError::Error)
}
async fn get_user_by_name(&self, username: String) -> Result<UserAccountEntity, GatewayError> {
let users = self.users.lock().unwrap();
users
.iter()
.find(|(_, k)| k.username == username)
.map(|(_, k)| k.clone())
.ok_or(GatewayError::Error)
}
async fn save_user(&mut self, user: &UserAccountEntity) -> Result<(), GatewayError> {
let mut users = self.users.lock().unwrap();
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 id = user_settings
.iter()
.fold(0, |sum, (i, _)| std::cmp::max(sum, i.0))
+ 1;
let new_settings = UserSettingsEntity {
id: UserSettingsId(id),
user_id: settings.user_id,
settings: settings.settings,
};
user_settings.insert(new_settings.id, new_settings.clone());
Ok(new_settings)
}
async fn get_user_settings_by_user(&self, user: &UserAccountEntity) -> Result<UserSettingsEntity, GatewayError> {
let user_settings = self.user_settings.lock().unwrap();
user_settings
.iter()
.find(|(_, k)| k.user_id == user.id)
.map(|(_, k)| k.clone())
.ok_or(GatewayError::Error)
}
async fn get_characters_by_user(&self, user: &UserAccountEntity) -> Result<[Option<CharacterEntity>; 4], GatewayError> {
let characters = self.characters.lock().unwrap();
let mut chars = [None; 4];
characters
.iter()
.filter(|(_, c)| c.user_id == user.id)
.for_each(|(_, c)| chars[c.slot as usize] = Some(c.clone()));
Ok(chars)
}
async fn create_character(&mut self, character: NewCharacterEntity) -> Result<CharacterEntity, GatewayError> {
let mut characters = self.characters.lock().unwrap();
let id = characters
.iter()
.fold(0, |sum, (i, _)| std::cmp::max(sum, i.0))
+ 1;
let new_character = CharacterEntity {
id: CharacterEntityId(id),
user_id: character.user_id,
slot: character.slot,
name: character.name,
exp: character.exp,
char_class: character.char_class,
section_id: character.section_id,
appearance: character.appearance,
techs: character.techs,
config: character.config,
info_board: character.info_board,
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());
Ok(new_character)
}
async fn save_character(&mut self, char: &CharacterEntity) -> Result<(), GatewayError> {
let mut characters = self.characters.lock().unwrap();
characters.insert(char.id, char.clone());
Ok(())
}
async fn get_guild_card_data_by_user(&self, user: &UserAccountEntity) -> Result<GuildCardDataEntity, GatewayError> {
Ok(GuildCardDataEntity::new(user.id))
}
async fn create_item(&mut self, item: NewItemEntity) -> Result<ItemEntity, GatewayError> {
let mut items = self.items.lock().unwrap();
let id = items
.iter()
.fold(0, |sum, (i, _)| std::cmp::max(sum, i.0))
+ 1;
let new_item = ItemEntity {
id: ItemEntityId(id),
location: item.location,
item: item.item,
};
items.insert(ItemEntityId(id), new_item.clone());
Ok(new_item)
}
async fn change_item_location(&mut self, item_id: &ItemEntityId, item_location: ItemLocation) -> Result<(), GatewayError> {
self.items.lock().unwrap().get_mut(&item_id)
.map(|item_entity| {
item_entity.location = item_location
});
Ok(())
}
async fn feed_mag(&mut self, mag_item_id: &ItemEntityId, tool_item_id: &ItemEntityId) -> Result<(), GatewayError> {
self.mag_modifiers.lock().unwrap()
.entry(*mag_item_id)
.or_insert(Vec::new())
.push(mag::MagModifier::FeedMag {
food: *tool_item_id
});
Ok(())
}
async fn change_mag_owner(&mut self, mag_item_id: &ItemEntityId, character: &CharacterEntity) -> Result<(), GatewayError> {
self.mag_modifiers.lock().unwrap()
.entry(*mag_item_id)
.or_insert(Vec::new())
.push(mag::MagModifier::OwnerChange(character.char_class, character.section_id));
Ok(())
}
async fn use_mag_cell(&mut self, mag_item_id: &ItemEntityId, mag_cell_id: &ItemEntityId) -> Result<(), GatewayError> {
self.mag_modifiers.lock().unwrap()
.entry(*mag_item_id)
.or_insert(Vec::new())
.push(mag::MagModifier::MagCell(mag_cell_id.clone()));
Ok(())
}
async fn add_weapon_modifier(&mut self, item_id: &ItemEntityId, modifier: weapon::WeaponModifier) -> Result<(), GatewayError> {
self.weapon_modifiers.lock().unwrap()
.entry(*item_id)
.or_insert(Vec::new())
.push(modifier);
Ok(())
}
async fn add_esweapon_modifier(&mut self, item_id: &ItemEntityId, modifier: esweapon::ESWeaponModifier) -> Result<(), GatewayError> {
self.esweapon_modifiers.lock().unwrap()
.entry(*item_id)
.or_insert(Vec::new())
.push(modifier);
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_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 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_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 add_tech_modifier(&mut self, item_id: &ItemEntityId, modifier: tech::TechModifier) -> Result<(), GatewayError> {
self.tech_modifiers.lock().unwrap()
.entry(*item_id)
.or_insert(Vec::new())
.push(modifier);
Ok(())
}
async fn add_tool_modifier(&mut self, item_id: &ItemEntityId, modifier: tool::ToolModifier) -> Result<(), GatewayError> {
self.tool_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();
Ok(inventories
.iter()
.find(|(id, _)| **id == *char_id)
.map(|(_, inv)| inv.clone())
.map(|inv| self.apply_modifiers(inv))
.unwrap_or(InventoryEntity::default()))
}
async fn get_character_bank(&mut self, char_id: &CharacterEntityId, _bank_name: BankName) -> Result<BankEntity, GatewayError> {
let banks = self.banks.lock().unwrap();
Ok(banks
.iter()
.find(|(id, _)| **id == *char_id)
.map(|(_, b)| b.clone())
.unwrap_or(BankEntity::default()))
}
async fn set_character_inventory(&mut self, char_id: &CharacterEntityId, inventory: &InventoryEntity) -> Result<(), GatewayError> {
let mut inventories = self.inventories.lock().unwrap();
inventories.insert(*char_id, inventory.clone());
Ok(())
}
// TODO: 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();
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();
Ok(equips
.iter()
.find(|(id, _)| **id == *char_id)
.map(|(_, inv)| inv.clone())
.unwrap_or(EquippedEntity::default()))
}
async fn set_character_equips(&mut self, char_id: &CharacterEntityId, equipped: &EquippedEntity) -> Result<(), GatewayError> {
let mut equips = self.equips.lock().unwrap();
equips.insert(*char_id, equipped.clone());
Ok(())
}
}