diff --git a/src/entity/account.rs b/src/entity/account.rs index cc77d92..032d80b 100644 --- a/src/entity/account.rs +++ b/src/entity/account.rs @@ -6,9 +6,17 @@ use libpso::character::guildcard; pub const USERFLAG_NEWCHAR: u32 = 0x00000001; pub const USERFLAG_DRESSINGROOM: u32 = 0x00000002; +// TOOD: these should not derive default +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, Default)] +pub struct UserAccountId(pub u32); +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, Default)] +pub struct UserSettingsId(pub u32); +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, Default)] +pub struct GuildCardDataId(pub u32); + #[derive(Clone, Debug)] -pub struct UserAccount { - pub id: u32, +pub struct UserAccountEntity { + pub id: UserAccountId, pub username: String, pub password: String, pub guildcard: u32, @@ -20,15 +28,15 @@ pub struct UserAccount { } #[derive(Clone, Debug, Default)] -pub struct UserSettings { - pub id: u32, - pub user_id: u32, +pub struct UserSettingsEntity { + pub id: UserSettingsId, + pub user_id: UserAccountId, pub settings: settings::UserSettings, } #[derive(Clone, Default)] -pub struct GuildCardData { - pub id: u32, - pub user_id: u32, +pub struct GuildCardDataEntity { + pub id: GuildCardDataId, + pub user_id: UserAccountId, pub guildcard: guildcard::GuildCardData, } diff --git a/src/entity/character.rs b/src/entity/character.rs index fe856e7..3e49631 100644 --- a/src/entity/character.rs +++ b/src/entity/character.rs @@ -3,6 +3,7 @@ use std::collections::HashMap; use libpso::packet::ship::{UpdateConfig, WriteInfoboard}; use crate::entity::item::tech::Technique; +use crate::entity::account::UserAccountId; #[derive(Copy, Clone, Hash, PartialEq, Eq)] pub enum CharacterClass { @@ -234,7 +235,7 @@ pub struct CharacterEntityId(pub u32); #[derive(Clone)] pub struct CharacterEntity { pub id: CharacterEntityId, - pub user_id: u32, + pub user_id: UserAccountId, pub slot: u32, pub name: String, @@ -254,7 +255,7 @@ impl std::default::Default for CharacterEntity { fn default() -> CharacterEntity { CharacterEntity { id: CharacterEntityId(0), - user_id: 0, + user_id: UserAccountId(0), slot: 0, name: "".into(), exp: 0, diff --git a/src/entity/gateway/entitygateway.rs b/src/entity/gateway/entitygateway.rs index ebbe509..eb15535 100644 --- a/src/entity/gateway/entitygateway.rs +++ b/src/entity/gateway/entitygateway.rs @@ -5,27 +5,27 @@ use crate::entity::item::*; use libpso::item; pub trait EntityGateway { - fn get_user_by_id(&self, _id: u32) -> Option { + fn get_user_by_id(&self, _id: UserAccountId) -> Option { unimplemented!(); } - fn get_user_by_name(&self, _username: String) -> Option { + fn get_user_by_name(&self, _username: String) -> Option { unimplemented!(); } - fn set_user(&mut self, _user: &UserAccount) { + fn set_user(&mut self, _user: &UserAccountEntity) { unimplemented!(); } - fn get_user_settings_by_user(&self, _user: &UserAccount) -> Option { + fn get_user_settings_by_user(&self, _user: &UserAccountEntity) -> Option { unimplemented!(); } - fn create_user_settings_by_user(&self, _user: &UserAccount) -> UserSettings { + fn create_user_settings_by_user(&self, _user: &UserAccountEntity) -> UserSettingsEntity { unimplemented!(); } - fn get_characters_by_user(&self, _user: &UserAccount) -> [Option; 4] { + fn get_characters_by_user(&self, _user: &UserAccountEntity) -> [Option; 4] { unimplemented!(); } @@ -33,11 +33,11 @@ pub trait EntityGateway { unimplemented!(); } - fn new_character_by_user(&mut self, _user: &UserAccount) -> CharacterEntity { + fn new_character_by_user(&mut self, _user: &UserAccountEntity) -> CharacterEntity { unimplemented!(); } - fn get_guild_card_data_by_user(&self, _user: &UserAccount) -> GuildCardData { + fn get_guild_card_data_by_user(&self, _user: &UserAccountEntity) -> GuildCardDataEntity { unimplemented!(); } diff --git a/src/entity/gateway/inmemory.rs b/src/entity/gateway/inmemory.rs index 1c93af8..5e04f99 100644 --- a/src/entity/gateway/inmemory.rs +++ b/src/entity/gateway/inmemory.rs @@ -13,8 +13,8 @@ use std::sync::{Arc, Mutex}; #[derive(Clone)] pub struct InMemoryGateway { - users: Arc>>, - user_settings: Arc>>, + users: Arc>>, + user_settings: Arc>>, characters: Arc>>, items: Arc>>, } @@ -31,12 +31,12 @@ impl InMemoryGateway { } impl EntityGateway for InMemoryGateway { - fn get_user_by_id(&self, id: u32) -> Option { + fn get_user_by_id(&self, id: UserAccountId) -> Option { let users = self.users.lock().unwrap(); users.get(&id).map(|k| k.clone()) } - fn get_user_by_name(&self, username: String) -> Option { + fn get_user_by_name(&self, username: String) -> Option { let users = self.users.lock().unwrap(); users .iter() @@ -44,35 +44,35 @@ impl EntityGateway for InMemoryGateway { .map(|(_, k)| k.clone()) } - fn set_user(&mut self, user: &UserAccount) { + fn set_user(&mut self, user: &UserAccountEntity) { let mut users = self.users.lock().unwrap(); users.insert(user.id, user.clone()); } - fn get_user_settings_by_user(&self, user: &UserAccount) -> Option { + fn get_user_settings_by_user(&self, user: &UserAccountEntity) -> Option { let user_settings = self.user_settings.lock().unwrap(); user_settings .iter() - .find(|(_, k)| k.id == user.id) + .find(|(_, k)| k.user_id == user.id) .map(|(_, k)| k.clone()) } - fn create_user_settings_by_user(&self, user: &UserAccount) -> UserSettings { + fn create_user_settings_by_user(&self, user: &UserAccountEntity) -> UserSettingsEntity { let mut user_settings = self.user_settings.lock().unwrap(); let id = user_settings .iter() - .fold(0, |sum, (i, _)| std::cmp::max(sum, *i)) + .fold(0, |sum, (i, _)| std::cmp::max(sum, i.0)) + 1; - let new_settings = UserSettings { - id: id, + let new_settings = UserSettingsEntity { + id: UserSettingsId(id), user_id: user.id, settings: settings::UserSettings::default(), }; - user_settings.insert(id, new_settings.clone()); + user_settings.insert(new_settings.id, new_settings.clone()); new_settings } - fn get_characters_by_user(&self, user: &UserAccount) -> [Option; 4] { + fn get_characters_by_user(&self, user: &UserAccountEntity) -> [Option; 4] { let characters = self.characters.lock().unwrap(); let mut chars = [None; 4]; characters @@ -82,7 +82,7 @@ impl EntityGateway for InMemoryGateway { chars } - fn new_character_by_user(&mut self, user: &UserAccount) -> CharacterEntity { + fn new_character_by_user(&mut self, user: &UserAccountEntity) -> CharacterEntity { let mut characters = self.characters.lock().unwrap(); let id = characters .iter() @@ -101,8 +101,8 @@ impl EntityGateway for InMemoryGateway { characters.insert(char.id, char.clone()); } - fn get_guild_card_data_by_user(&self, _user: &UserAccount) -> GuildCardData { - GuildCardData::default() + fn get_guild_card_data_by_user(&self, _user: &UserAccountEntity) -> GuildCardDataEntity { + GuildCardDataEntity::default() } fn new_item(&mut self, item: ItemDetail, location: ItemLocation) -> ItemEntity { diff --git a/src/login/character.rs b/src/login/character.rs index 4b9cf24..71934f8 100644 --- a/src/login/character.rs +++ b/src/login/character.rs @@ -16,7 +16,7 @@ use crate::common::leveltable::CharacterLevelTable; use libpso::{utf8_to_array, utf8_to_utf16_array}; use crate::entity::gateway::EntityGateway; -use crate::entity::account::{UserAccount, USERFLAG_NEWCHAR, USERFLAG_DRESSINGROOM}; +use crate::entity::account::{UserAccountEntity, USERFLAG_NEWCHAR, USERFLAG_DRESSINGROOM}; use crate::entity::item::{ItemDetail, ItemLocation}; use crate::entity::item::weapon::Weapon; use crate::entity::item::armor::Armor; @@ -142,7 +142,7 @@ fn generate_param_data(path: &str) -> (ParamDataHeader, Vec) { #[derive(Clone)] struct ClientState { param_index: usize, - user: Option, + user: Option, characters: Option<[Option; 4]>, guildcard_data_buffer: Option>, session: Session, @@ -189,7 +189,7 @@ pub struct CharacterServerState { } -fn new_character(entity_gateway: &mut EG, user: &UserAccount, preview: &CharacterPreview) { +fn new_character(entity_gateway: &mut EG, user: &UserAccountEntity, preview: &CharacterPreview) { let mut char = entity_gateway.new_character_by_user(&user); new_character_from_preview(&mut char, preview); match char.char_class { @@ -647,7 +647,7 @@ mod test { } impl EntityGateway for TestData { - fn get_user_settings_by_user(&self, _user: &UserAccount) -> Option { + fn get_user_settings_by_user(&self, _user: &UserAccountEntity) -> Option { Some(UserSettings { id: 0, user_id: 0, @@ -658,7 +658,7 @@ mod test { let mut server = CharacterServerState::new(TestData {}); let mut clientstate = ClientState::new(); - clientstate.user = Some(UserAccount { + clientstate.user = Some(UserAccountEntity { id: 1, username: "testuser".to_owned(), password: bcrypt::hash("mypassword", 5).unwrap(), @@ -700,7 +700,7 @@ mod test { fn test_character_create() { let TestData = InMemoryGateway::new(); let mut fake_user = ClientState::new(); - fake_user.user = Some(UserAccount { + fake_user.user = Some(UserAccountEntity { id: 3, username: "hi3".to_string(), password: bcrypt::hash("qwer", 5).unwrap(), diff --git a/src/login/login.rs b/src/login/login.rs index e0feec7..6237dfe 100644 --- a/src/login/login.rs +++ b/src/login/login.rs @@ -14,7 +14,7 @@ use crate::common::cipherkeys::{ELSEWHERE_PRIVATE_KEY, ELSEWHERE_PARRAY}; use crate::common::serverstate::{SendServerPacket, RecvServerPacket, ServerState, OnConnect, ClientId}; use crate::entity::gateway::EntityGateway; -use crate::entity::account::UserAccount; +use crate::entity::account::UserAccountEntity; pub const LOGIN_PORT: u16 = 12000; @@ -56,7 +56,7 @@ impl SendServerPacket for SendLoginPacket { } -pub fn get_login_status(entity_gateway: &impl EntityGateway, pkt: &Login) -> Result { +pub fn get_login_status(entity_gateway: &impl EntityGateway, pkt: &Login) -> Result { let username = array_to_utf8(pkt.username).map_err(|_err| AccountStatus::Error)?; let password = array_to_utf8(pkt.password).map_err(|_err| AccountStatus::Error)?; let user = entity_gateway.get_user_by_name(username).ok_or(AccountStatus::InvalidUser)?; @@ -172,9 +172,9 @@ mod test { } impl EntityGateway for TestData { - fn get_user_by_name(&self, name: String) -> Option { + fn get_user_by_name(&self, name: String) -> Option { assert!(name == "testuser"); - Some(UserAccount { + Some(UserAccountEntity { id: 1, username: "testuser".to_owned(), password: bcrypt::hash("mypassword", 5).unwrap(), @@ -220,7 +220,7 @@ mod test { } impl EntityGateway for TestData { - fn get_user_by_name(&self, _name: String) -> Option { + fn get_user_by_name(&self, _name: String) -> Option { None } } @@ -252,9 +252,9 @@ mod test { } impl EntityGateway for TestData { - fn get_user_by_name(&self, name: String) -> Option { + fn get_user_by_name(&self, name: String) -> Option { assert!(name == "testuser"); - Some(UserAccount { + Some(UserAccountEntity { id: 1, username: "testuser".to_owned(), password: bcrypt::hash("notpassword", 5).unwrap(), @@ -295,9 +295,9 @@ mod test { } impl EntityGateway for TestData { - fn get_user_by_name(&self, name: String) -> Option { + fn get_user_by_name(&self, name: String) -> Option { assert!(name == "testuser"); - Some(UserAccount { + Some(UserAccountEntity { id: 1, username: "testuser".to_owned(), password: bcrypt::hash("mypassword", 5).unwrap(), diff --git a/src/main.rs b/src/main.rs index e1dabfd..4035914 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,7 +18,7 @@ use patch::patch::{PatchServerState, generate_patch_tree, load_config, load_motd use login::login::LoginServerState; use login::character::CharacterServerState; use ship::ship::ShipServerState; -use entity::account::UserAccount; +use entity::account::{UserAccountEntity, UserAccountId}; use entity::gateway::{EntityGateway, InMemoryGateway}; use entity::item::ItemLocation; @@ -58,8 +58,8 @@ fn main() { setup_logger(); let mut entity_gateway = InMemoryGateway::new(); - let fake_user = UserAccount { - id: 1, + let fake_user = UserAccountEntity { + id: UserAccountId(1), username: "hi".to_string(), password: bcrypt::hash("qwer", 5).unwrap(), guildcard: 1u32, @@ -98,8 +98,8 @@ fn main() { ); - let fake_user2 = UserAccount { - id: 2, + let fake_user2 = UserAccountEntity { + id: UserAccountId(2), username: "hi2".to_string(), password: bcrypt::hash("qwer", 5).unwrap(), guildcard: 2u32, @@ -119,8 +119,8 @@ fn main() { character.name = "Test Char 4".into(); entity_gateway.set_character(&character); - let fake_user3 = UserAccount { - id: 3, + let fake_user3 = UserAccountEntity { + id: UserAccountId(3), username: "hi3".to_string(), password: bcrypt::hash("qwer", 5).unwrap(), guildcard: 3u32, @@ -140,8 +140,8 @@ fn main() { character.name = "Test Char 6".into(); entity_gateway.set_character(&character); - let fake_user4 = UserAccount { - id: 4, + let fake_user4 = UserAccountEntity { + id: UserAccountId(4), username: "hi4".to_string(), password: bcrypt::hash("qwer", 5).unwrap(), guildcard: 4u32, diff --git a/src/ship/ship.rs b/src/ship/ship.rs index 5dbb472..3ce13f8 100644 --- a/src/ship/ship.rs +++ b/src/ship/ship.rs @@ -17,7 +17,7 @@ use crate::common::serverstate::{SendServerPacket, RecvServerPacket, ServerState use crate::common::leveltable::CharacterLevelTable; use crate::entity::gateway::EntityGateway; -use crate::entity::account::{UserAccount, UserSettings, USERFLAG_NEWCHAR, USERFLAG_DRESSINGROOM}; +use crate::entity::account::{UserAccountEntity, UserSettingsEntity, USERFLAG_NEWCHAR, USERFLAG_DRESSINGROOM}; use crate::entity::character::CharacterEntity; use crate::entity::item::{ItemLocation, ItemEntity}; use crate::login::login::get_login_status; @@ -119,8 +119,8 @@ impl SendServerPacket for SendShipPacket { } struct ClientState { - user: UserAccount, - settings: UserSettings, + user: UserAccountEntity, + settings: UserSettingsEntity, character: CharacterEntity, session: Session, //guildcard: GuildCard, @@ -130,7 +130,7 @@ struct ClientState { } impl ClientState { - fn new(user: UserAccount, settings: UserSettings, character: CharacterEntity, inventory: items::ActiveInventory, /*bank: Bank,*/ session: Session) -> ClientState { + fn new(user: UserAccountEntity, settings: UserSettingsEntity, character: CharacterEntity, inventory: items::ActiveInventory, /*bank: Bank,*/ session: Session) -> ClientState { ClientState { user: user, settings: settings, @@ -171,7 +171,7 @@ impl ShipServerState { Ok(match get_login_status(&self.entity_gateway, pkt) { Ok(user) => { let mut response = LoginResponse::by_status(AccountStatus::Ok, Session::new()); - response.guildcard = user.id as u32; + response.guildcard = user.id.0 as u32; response.team_id = user.team_id.map_or(31, |ti| ti) as u32; let characters = self.entity_gateway.get_characters_by_user(&user); let character = characters @@ -233,7 +233,7 @@ impl ShipServerState { PlayerInfo { header: PlayerHeader { tag: 0x100, - guildcard: client.user.id, + guildcard: client.user.id.0, _unknown1: [0; 5], client_id: room_client.index as u32, name: c.name, @@ -289,7 +289,7 @@ impl ShipServerState { playerinfo: PlayerInfo { header: PlayerHeader { tag: 0x100, - guildcard: client.user.id, + guildcard: client.user.id.0, _unknown1: [0; 5], client_id: client_id as u32, name: c.name, @@ -336,7 +336,7 @@ impl ShipServerState { msg: GameMessage::GuildcardRecv(GuildcardRecv { client: guildcard_send.client, target: guildcard_send.target, - guildcard: client.user.id, + guildcard: client.user.id.0, name: utf8_to_utf16_array!(client.character.name, 0x18), team: [0; 0x10], // TODO: teams not yet implemented desc: utf8_to_utf16_array!(client.character.guildcard.description, 0x58), @@ -365,7 +365,7 @@ impl ShipServerState { fn player_chat(&mut self, id: ClientId, msg: &PlayerChat) -> Result + Send>, ShipError> { let client = self.clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?; - let cmsg = PlayerChat::new(client.user.id, msg.message.clone()); + let cmsg = PlayerChat::new(client.user.id.0, msg.message.clone()); Ok(Box::new(self.client_location.get_area_by_user(id).clients().iter() .map(move |client| { @@ -392,7 +392,7 @@ impl ShipServerState { let client = self.clients.get_mut(&id).unwrap();//.ok_or(ShipError::ClientNotFound(id)).unwrap(); let players = [PlayerHeader { tag: 0x00010000, - guildcard: client.user.id, + guildcard: client.user.id.0, _unknown1: [0; 5], client_id: 0, name: libpso::utf8_to_utf16_array!(client.character.name, 16),