Some checks failed
continuous-integration/drone/push Build is failing
fun while it lasted ItemLocation ceased to be the canonical place to store an item's location. replaced with ItemNote which basically covers the actual use case but without the enforcing of a location.
326 lines
13 KiB
Rust
326 lines
13 KiB
Rust
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>>>,
|
|
mag_modifiers: Arc<Mutex<BTreeMap<ItemEntityId, Vec<mag::MagModifier>>>>,
|
|
weapon_modifiers: Arc<Mutex<BTreeMap<ItemEntityId, Vec<weapon::WeaponModifier>>>>,
|
|
}
|
|
|
|
impl Default for InMemoryGateway {
|
|
fn default() -> 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())),
|
|
mag_modifiers: Arc::new(Mutex::new(BTreeMap::new())),
|
|
weapon_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::Mag(mag) => {
|
|
let mut mag = 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} => {
|
|
if let Some(mag_feed) = items.get(food) {
|
|
if let ItemDetail::Tool(mag_feed) = mag_feed.item {
|
|
mag.feed(mag_feed.tool)
|
|
}
|
|
}
|
|
},
|
|
mag::MagModifier::OwnerChange(class, section_id) => {
|
|
mag.change_owner(*class, *section_id)
|
|
},
|
|
mag::MagModifier::MagCell(mag_cell_id) => {
|
|
if let Some(mag_cell) = items.get(mag_cell_id) {
|
|
if let ItemDetail::Tool(mag_cell) = mag_cell.item {
|
|
mag.apply_mag_cell(mag_cell.tool.try_into().unwrap())
|
|
}
|
|
}
|
|
},
|
|
_ => {}
|
|
}
|
|
}
|
|
}
|
|
ItemDetail::Mag(mag)
|
|
}
|
|
_ => {
|
|
item.item
|
|
}
|
|
};
|
|
|
|
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).cloned().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();
|
|
const NONE: Option<CharacterEntity> = None;
|
|
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),
|
|
item: item.item,
|
|
};
|
|
items.insert(ItemEntityId(id), new_item.clone());
|
|
Ok(new_item)
|
|
}
|
|
|
|
async fn add_item_note(&mut self, item_id: &ItemEntityId, item_note: ItemNote) -> Result<(), GatewayError> {
|
|
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_with(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_with(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_with(Vec::new)
|
|
.push(mag::MagModifier::MagCell(*mag_cell_id));
|
|
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_with(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_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_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(())
|
|
}
|
|
|
|
// TOOD: 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_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(())
|
|
}
|
|
|
|
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;
|
|
}
|
|
Ok(())
|
|
}
|
|
}
|