diff --git a/src/entity/account.rs b/src/entity/account.rs index 3406f52..7c0274c 100644 --- a/src/entity/account.rs +++ b/src/entity/account.rs @@ -19,12 +19,14 @@ pub struct UserAccount { pub flags: u32, // TODO: is this used for anything other than character creation? } +#[derive(Clone, Debug, Default)] pub struct UserSettings { pub id: u32, pub user_id: u32, pub settings: settings::UserSettings, } +#[derive(Clone, Default)] pub struct GuildCardData { pub id: u32, pub user_id: u32, diff --git a/src/entity/character.rs b/src/entity/character.rs index d682eba..42c16f0 100644 --- a/src/entity/character.rs +++ b/src/entity/character.rs @@ -1,8 +1,9 @@ use libpso::character::character; -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, Default)] pub struct Character { pub id: u32, pub user_id: u32, + pub slot: u32, pub character: character::Character, -} +} \ No newline at end of file diff --git a/src/entity/gateway/entitygateway.rs b/src/entity/gateway/entitygateway.rs index 9299cb4..8ec4f75 100644 --- a/src/entity/gateway/entitygateway.rs +++ b/src/entity/gateway/entitygateway.rs @@ -26,7 +26,11 @@ pub trait EntityGateway { unimplemented!(); } - fn set_character_by_user(&mut self, _user: &UserAccount, _slot: u32, _char: Character) { + fn new_character_by_user(&mut self, _user: &UserAccount) -> Character { + unimplemented!(); + } + + fn set_character(&mut self, _char: &Character) { unimplemented!(); } diff --git a/src/entity/gateway/inmemory.rs b/src/entity/gateway/inmemory.rs new file mode 100644 index 0000000..ad01aca --- /dev/null +++ b/src/entity/gateway/inmemory.rs @@ -0,0 +1,103 @@ +use std::collections::HashMap; + +use crate::entity::account::*; +use crate::entity::character::*; +use crate::entity::gateway::EntityGateway; + +use libpso::character::settings; + +use std::sync::{Arc, Mutex}; + +pub struct InMemoryGateway { + users: Arc>>, + user_settings: Arc>>, + //guildcard: Arc>>, + characters: Arc>>, +} + +impl InMemoryGateway { + pub fn new() -> InMemoryGateway { + InMemoryGateway { + users: Arc::new(Mutex::new(HashMap::new())), + user_settings: Arc::new(Mutex::new(HashMap::new())), + //guildcard: Arc::new(Mutex::new(HashMap::new())), + characters: Arc::new(Mutex::new(HashMap::new())), + } + } +} + +impl EntityGateway for InMemoryGateway { + fn get_user_by_id(&self, id: u32) -> Option { + let users = self.users.lock().unwrap(); + users.get(&id).map(|k| k.clone()) + } + + fn get_user_by_name(&self, username: String) -> Option { + let users = self.users.lock().unwrap(); + users + .iter() + .find(|(_, k)| k.username == username) + .map(|(_, k)| k.clone()) + } + + fn set_user(&mut self, user: &UserAccount) { + let mut users = self.users.lock().unwrap(); + users.insert(user.id, user.clone()); + } + + fn get_user_settings_by_user(&self, user: &UserAccount) -> Option { + let user_settings = self.user_settings.lock().unwrap(); + user_settings + .iter() + .find(|(_, k)| k.id == user.id) + .map(|(_, k)| k.clone()) + } + + fn create_user_settings_by_user(&self, user: &UserAccount) -> UserSettings { + let mut user_settings = self.user_settings.lock().unwrap(); + let id = user_settings + .iter() + .fold(0, |sum, (i, _)| std::cmp::max(sum, *i)) + + 1; + let new_settings = UserSettings { + id: id, + user_id: user.id, + settings: settings::UserSettings::default(), + }; + user_settings.insert(id, new_settings.clone()); + new_settings + } + + fn get_characters_by_user(&self, user: &UserAccount) -> [Option; 4] { + 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())); + chars + } + + fn new_character_by_user(&mut self, user: &UserAccount) -> Character { + let mut characters = self.characters.lock().unwrap(); + let id = characters + .iter() + .fold(0, |sum, (i, _)| std::cmp::max(sum, *i)) + + 1; + + let mut c = Character::default(); + c.id = id; + c.user_id = user.id; + characters.insert(id, c.clone()); + c + } + + fn set_character(&mut self, char: &Character) { + let mut characters = self.characters.lock().unwrap(); + characters.insert(char.id, char.clone()); + } + + fn get_guild_card_data_by_user(&self, _user: &UserAccount) -> GuildCardData { + GuildCardData::default() + } +} diff --git a/src/entity/gateway/mod.rs b/src/entity/gateway/mod.rs index 480cac3..214bdfd 100644 --- a/src/entity/gateway/mod.rs +++ b/src/entity/gateway/mod.rs @@ -1,3 +1,5 @@ pub mod entitygateway; +pub mod inmemory; pub use entitygateway::EntityGateway; +pub use inmemory::InMemoryGateway; diff --git a/src/login/character.rs b/src/login/character.rs index 1fb607d..d717542 100644 --- a/src/login/character.rs +++ b/src/login/character.rs @@ -383,12 +383,16 @@ impl ServerState for CharacterServerState { let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?; let mut user = client.user.as_mut().unwrap(); if user.flags == USERFLAG_NEWCHAR { + let mut char = self.entity_gateway.new_character_by_user(&user); + char.slot = preview.slot; + char.character = preview.character.as_character(); let char = Character { id: 9, + slot: preview.slot, user_id: user.id, character: preview.character.as_character() }; - self.entity_gateway.set_character_by_user(&user, preview.slot, char); + self.entity_gateway.set_character(&char); } if user.flags == USERFLAG_DRESSINGROOM { // TODO: dressing room stuff diff --git a/src/login/main.rs b/src/login/main.rs index 47708c6..a1c8561 100644 --- a/src/login/main.rs +++ b/src/login/main.rs @@ -49,6 +49,7 @@ impl LoginStubData { characters: [Some(Character { id: 1, + slot: 0, user_id: 1, character: c, }), @@ -78,8 +79,8 @@ impl EntityGateway for LoginStubData { self.characters } - fn set_character_by_user(&mut self, _user: &UserAccount, slot: u32, char: Character) { - self.characters[slot as usize] = Some(char); + fn set_character(&mut self, char: &Character) { + self.characters[char.slot as usize] = Some(char.clone()); } fn get_guild_card_data_by_user(&self, user: &UserAccount) -> GuildCardData {