From 7a831c35c42501c86d08ae7af3b559b9cae021ee Mon Sep 17 00:00:00 2001 From: jake Date: Thu, 22 Oct 2020 13:16:24 -0600 Subject: [PATCH 01/27] add separate binaries for the server types --- src/bin/login.rs | 25 +++++++++++++++++++++++++ src/bin/patch.rs | 16 ++++++++++++++++ src/bin/ship.rs | 30 ++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+) create mode 100644 src/bin/login.rs create mode 100644 src/bin/patch.rs create mode 100644 src/bin/ship.rs diff --git a/src/bin/login.rs b/src/bin/login.rs new file mode 100644 index 0000000..42c3324 --- /dev/null +++ b/src/bin/login.rs @@ -0,0 +1,25 @@ +use log::{info}; +use elseware::entity::gateway::postgres::PostgresGateway; +use elseware::login::login::LoginServerState; +use elseware::login::character::CharacterServerState; +use elseware::common::mainloop::{login_mainloop, character_mainloop}; + +async fn main() { + let db_host = std::env::var("DB_HOST").unwrap(); + let db_username = std::env::var("DB_USERNAME").unwrap(); + let db_password = std::env::var("DB_PASSWORD").unwrap(); + let db_dbname = std::env::var("DB_DBNAME").unwrap(); + let entity_gateway = PostgresGateway::new(&db_host, &db_dbname, &db_username, &db_password); + + let thread_entity_gateway = entity_gateway.clone(); + let login_state = LoginServerState::new(thread_entity_gateway); + let login_loop = login_mainloop(login_state, elseware::login::login::LOGIN_PORT); + + let char_state = CharacterServerState::new(entity_gateway); + let character_loop = character_mainloop(char_state, elseware::login::character::CHARACTER_PORT, elseware::login::login::COMMUNICATION_PORT); + + info!("[auth/character] starting server"); + async_std::task::block_on(async move { + futures::future::join_all(vec![login_loop, character_loop]).await + }); +} diff --git a/src/bin/patch.rs b/src/bin/patch.rs new file mode 100644 index 0000000..17bceda --- /dev/null +++ b/src/bin/patch.rs @@ -0,0 +1,16 @@ +use elseware::patch::patch::{PatchServerState, generate_patch_tree, load_config, load_motd}; +use log::{info}; +use elseware::common::mainloop::patch_mainloop; + +fn main() { + info!("[patch] starting server"); + let patch_config = load_config(); + let patch_motd = load_motd(); + let (patch_file_tree, patch_file_lookup) = generate_patch_tree(patch_config.path.as_str()); + let patch_state = PatchServerState::new(patch_file_tree, patch_file_lookup, patch_motd); + let patch_loop = patch_mainloop(patch_state, patch_config.port); + + async_std::task::block_on(async move { + patch_loop.await + }); +} diff --git a/src/bin/ship.rs b/src/bin/ship.rs new file mode 100644 index 0000000..fd1d367 --- /dev/null +++ b/src/bin/ship.rs @@ -0,0 +1,30 @@ +use log::{info}; +use elseware::entity::gateway::postgres::PostgresGateway; +use elseware::ship::ship::ShipServerState; +use elseware::ship::ship::ShipServerStateBuilder; +use elseware::common::mainloop::ship_mainloop; + +async fn main() { + let db_host = std::env::var("DB_HOST").unwrap(); + let db_username = std::env::var("DB_USERNAME").unwrap(); + let db_password = std::env::var("DB_PASSWORD").unwrap(); + let db_dbname = std::env::var("DB_DBNAME").unwrap(); + let entity_gateway = PostgresGateway::new(&db_host, &db_dbname, &db_username, &db_password); + + let ship_name = std::env::var("SHIP_NAME").unwrap().parse().unwrap(); + let ip = std::env::var("SELF_IP").unwrap().parse().unwrap(); + let ship_state = ShipServerStateBuilder::new() + .name(ship_name) + .ip(ip) + .port(elseware::ship::ship::SHIP_PORT) + .gateway(entity_gateway) + .build(); + + let shipgate_ip = std::env::var("SHIPGATE_IP").unwrap().parse().unwrap(); + let ship_loop = ship_mainloop(ship_state, elseware::ship::ship::SHIP_PORT, shipgate_ip, elseware::login::login::COMMUNICATION_PORT); + + info!("[auth/character] starting server"); + async_std::task::block_on(async move { + ship_loop.await + }); +} From 29422eac51a560590092e4c0dbf28abb9afc3162 Mon Sep 17 00:00:00 2001 From: jake Date: Sat, 24 Oct 2020 00:16:42 -0600 Subject: [PATCH 02/27] I am dubm --- src/bin/login.rs | 2 +- src/bin/ship.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bin/login.rs b/src/bin/login.rs index 42c3324..fe40d94 100644 --- a/src/bin/login.rs +++ b/src/bin/login.rs @@ -4,7 +4,7 @@ use elseware::login::login::LoginServerState; use elseware::login::character::CharacterServerState; use elseware::common::mainloop::{login_mainloop, character_mainloop}; -async fn main() { +fn main() { let db_host = std::env::var("DB_HOST").unwrap(); let db_username = std::env::var("DB_USERNAME").unwrap(); let db_password = std::env::var("DB_PASSWORD").unwrap(); diff --git a/src/bin/ship.rs b/src/bin/ship.rs index fd1d367..78cfa5a 100644 --- a/src/bin/ship.rs +++ b/src/bin/ship.rs @@ -4,7 +4,7 @@ use elseware::ship::ship::ShipServerState; use elseware::ship::ship::ShipServerStateBuilder; use elseware::common::mainloop::ship_mainloop; -async fn main() { +fn main() { let db_host = std::env::var("DB_HOST").unwrap(); let db_username = std::env::var("DB_USERNAME").unwrap(); let db_password = std::env::var("DB_PASSWORD").unwrap(); From 466195193ded165ca54fc9059b3e2c44795c52c7 Mon Sep 17 00:00:00 2001 From: jake Date: Sat, 24 Oct 2020 00:17:25 -0600 Subject: [PATCH 03/27] load patch config from env vars --- src/bin/patch.rs | 4 ++-- src/patch/patch.rs | 21 ++++++++++++++++----- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/bin/patch.rs b/src/bin/patch.rs index 17bceda..a12df4e 100644 --- a/src/bin/patch.rs +++ b/src/bin/patch.rs @@ -1,10 +1,10 @@ -use elseware::patch::patch::{PatchServerState, generate_patch_tree, load_config, load_motd}; +use elseware::patch::patch::{PatchServerState, generate_patch_tree, load_config_env, load_motd}; use log::{info}; use elseware::common::mainloop::patch_mainloop; fn main() { info!("[patch] starting server"); - let patch_config = load_config(); + let patch_config = load_config_env(); let patch_motd = load_motd(); let (patch_file_tree, patch_file_lookup) = generate_patch_tree(patch_config.path.as_str()); let patch_state = PatchServerState::new(patch_file_tree, patch_file_lookup, patch_motd); diff --git a/src/patch/patch.rs b/src/patch/patch.rs index 6c18876..b96616e 100644 --- a/src/patch/patch.rs +++ b/src/patch/patch.rs @@ -381,7 +381,7 @@ impl Iterator for SendFileIterator { #[derive(Debug, Deserialize)] pub struct PatchConfig { pub path: String, - pub ip: String, + pub ip: String, // TODO: this does nothing pub port: u16, } @@ -403,11 +403,22 @@ pub fn load_config() -> PatchConfig { config } -pub fn load_motd() -> String { - let mut motd: String = "Welcome to Elseware!".to_string(); +pub fn load_config_env() -> PatchConfig { + let patch_path = std::env::var("PATCHFILE_DIR").unwrap(); + let patch_port = std::env::var("PATCH_PORT").unwrap().parse().unwrap(); + + PatchConfig { + path: patch_path, + ip: "127.0.0.1".into(), + port: patch_port, + } +} +pub fn load_motd() -> String { if let Ok(m) = fs::read_to_string("patch.motd") { - motd = m.clone(); + m + } + else { + "Welcome to Elseware!".to_string() } - motd } From 69374ea424469a5ff9fc06566ca1dfdad2801cb7 Mon Sep 17 00:00:00 2001 From: jake Date: Sat, 24 Oct 2020 00:18:07 -0600 Subject: [PATCH 04/27] use sqlx for migrations --- src/entity/gateway/postgres/postgres.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/entity/gateway/postgres/postgres.rs b/src/entity/gateway/postgres/postgres.rs index c26650f..2a32d0d 100644 --- a/src/entity/gateway/postgres/postgres.rs +++ b/src/entity/gateway/postgres/postgres.rs @@ -31,8 +31,11 @@ pub struct PostgresGateway { impl PostgresGateway { pub fn new(host: &str, dbname: &str, username: &str, password: &str) -> PostgresGateway { - // the postgres dep can be removed once refinery supports sqlx - let mut conn = Client::connect(&format!("host='{}' dbname='{}' user='{}' password='{}'", host, dbname, username, password), NoTls).unwrap(); + let mut conn = refinery::config::Config::new(refinery::config::ConfigDbType::Postgres) + .set_db_host(&host) + .set_db_user(&username) + .set_db_pass(&password) + .set_db_name(&dbname); embedded::migrations::runner().run(&mut conn).unwrap(); let pool = async_std::task::block_on(async move { From 2351b31125c04adf964bf560a01458363f1dc692 Mon Sep 17 00:00:00 2001 From: jake Date: Sat, 24 Oct 2020 17:45:59 -0600 Subject: [PATCH 05/27] entitygateway uses results for its functions now --- src/entity/gateway/entitygateway.rs | 49 ++++---- src/entity/gateway/inmemory.rs | 64 ++++++----- src/entity/gateway/mod.rs | 2 +- src/entity/gateway/postgres/postgres.rs | 143 +++++++++++++----------- src/login/character.rs | 14 ++- src/login/login.rs | 2 +- src/ship/items/manager.rs | 33 +++--- src/ship/ship.rs | 3 +- 8 files changed, 175 insertions(+), 135 deletions(-) diff --git a/src/entity/gateway/entitygateway.rs b/src/entity/gateway/entitygateway.rs index 71c23fd..7a28563 100644 --- a/src/entity/gateway/entitygateway.rs +++ b/src/entity/gateway/entitygateway.rs @@ -1,80 +1,91 @@ +use thiserror::Error; + use crate::entity::account::*; use crate::entity::character::*; use crate::entity::item::*; -// TODO: all these Options should be Results + +// TODO: better granularity? +//#[derive(Error, Debug)] +#[derive(Error, Debug)] +#[error("")] +pub enum GatewayError { + Error, + PgError(#[from] sqlx::Error) +} + #[async_trait::async_trait] pub trait EntityGateway: Send + Sync + Clone { - async fn create_user(&mut self, _user: NewUserAccountEntity) -> Option { + async fn create_user(&mut self, _user: NewUserAccountEntity) -> Result { unimplemented!() } - async fn get_user_by_id(&self, _id: UserAccountId) -> Option { + async fn get_user_by_id(&self, _id: UserAccountId) -> Result { unimplemented!(); } - async fn get_user_by_name(&self, _username: String) -> Option { + async fn get_user_by_name(&self, _username: String) -> Result { unimplemented!(); } - async fn save_user(&mut self, _user: &UserAccountEntity) { + async fn save_user(&mut self, _user: &UserAccountEntity) -> Result<(), GatewayError> { unimplemented!(); } - async fn create_user_settings(&mut self, _settings: NewUserSettingsEntity) -> Option { + async fn create_user_settings(&mut self, _settings: NewUserSettingsEntity) -> Result { unimplemented!(); } - async fn get_user_settings_by_user(&self, _user: &UserAccountEntity) -> Option { + async fn get_user_settings_by_user(&self, _user: &UserAccountEntity) -> Result { unimplemented!(); } - async fn save_user_settings(&mut self, _settings: &UserSettingsEntity) { + async fn save_user_settings(&mut self, _settings: &UserSettingsEntity) -> Result<(), GatewayError> { unimplemented!(); } - async fn create_character(&mut self, _char: NewCharacterEntity) -> Option { + async fn create_character(&mut self, _char: NewCharacterEntity) -> Result { unimplemented!(); } // TODO: just make this a vec sorted by slot order? - async fn get_characters_by_user(&self, _user: &UserAccountEntity) -> [Option; 4] { + async fn get_characters_by_user(&self, _user: &UserAccountEntity) -> Result<[Option; 4], GatewayError> { unimplemented!(); } - async fn save_character(&mut self, _char: &CharacterEntity) { + async fn save_character(&mut self, _char: &CharacterEntity) -> Result<(), GatewayError> { unimplemented!(); } - async fn get_guild_card_data_by_user(&self, _user: &UserAccountEntity) -> GuildCardDataEntity { + async fn get_guild_card_data_by_user(&self, _user: &UserAccountEntity) -> Result { unimplemented!(); } - async fn create_item(&mut self, _item: NewItemEntity) -> Option { + async fn create_item(&mut self, _item: NewItemEntity) -> Result { unimplemented!(); } - async fn save_item(&mut self, _item: &ItemEntity) { + async fn save_item(&mut self, _item: &ItemEntity) -> Result<(), GatewayError> { unimplemented!(); } - async fn change_item_location(&mut self, _item_id: &ItemEntityId, _item_location: ItemLocation) { + async fn change_item_location(&mut self, _item_id: &ItemEntityId, _item_location: ItemLocation) -> Result<(), GatewayError> { unimplemented!(); } - async fn feed_mag(&mut self, _mag_item_id: &ItemEntityId, _tool_item_id: &ItemEntityId) { + async fn feed_mag(&mut self, _mag_item_id: &ItemEntityId, _tool_item_id: &ItemEntityId) -> Result<(), GatewayError> { unimplemented!(); } - async fn change_mag_owner(&mut self, _mag_item_id: &ItemEntityId, _character: &CharacterEntity) { + async fn change_mag_owner(&mut self, _mag_item_id: &ItemEntityId, _character: &CharacterEntity) -> Result<(), GatewayError> { unimplemented!(); } - async fn use_mag_cell(&mut self, _mag_item_id: &ItemEntityId, _mag_cell_id: &ItemEntityId) { + async fn use_mag_cell(&mut self, _mag_item_id: &ItemEntityId, _mag_cell_id: &ItemEntityId) -> Result<(), GatewayError> { unimplemented!(); } - async fn get_items_by_character(&self, _char: &CharacterEntity) -> Vec { + async fn get_items_by_character(&self, _char: &CharacterEntity) -> Result, GatewayError> { unimplemented!(); } } diff --git a/src/entity/gateway/inmemory.rs b/src/entity/gateway/inmemory.rs index 2801eb1..01ec302 100644 --- a/src/entity/gateway/inmemory.rs +++ b/src/entity/gateway/inmemory.rs @@ -3,7 +3,7 @@ use std::convert::TryInto; use crate::entity::account::*; use crate::entity::character::*; -use crate::entity::gateway::EntityGateway; +use crate::entity::gateway::{EntityGateway, GatewayError}; use crate::entity::item::*; use std::sync::{Arc, Mutex}; @@ -31,7 +31,7 @@ impl InMemoryGateway { #[async_trait::async_trait] impl EntityGateway for InMemoryGateway { - async fn create_user(&mut self, user: NewUserAccountEntity) -> Option { + async fn create_user(&mut self, user: NewUserAccountEntity) -> Result { let mut users = self.users.lock().unwrap(); let id = users .iter() @@ -47,30 +47,33 @@ impl EntityGateway for InMemoryGateway { muted_until: user.muted_until, created_at: user.created_at, flags: user.flags, + activated: true, }; users.insert(user.id, user.clone()); - Some(user) + Ok(user) } - async fn get_user_by_id(&self, id: UserAccountId) -> Option { + async fn get_user_by_id(&self, id: UserAccountId) -> Result { let users = self.users.lock().unwrap(); - users.get(&id).map(|k| k.clone()) + users.get(&id).map(|k| k.clone()).ok_or(GatewayError::Error) } - async fn get_user_by_name(&self, username: String) -> Option { + async fn get_user_by_name(&self, username: String) -> Result { 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) { + 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) -> Option { + async fn create_user_settings(&mut self, settings: NewUserSettingsEntity) -> Result { let mut user_settings = self.user_settings.lock().unwrap(); let id = user_settings .iter() @@ -82,28 +85,29 @@ impl EntityGateway for InMemoryGateway { settings: settings.settings, }; user_settings.insert(new_settings.id, new_settings.clone()); - Some(new_settings) + Ok(new_settings) } - async fn get_user_settings_by_user(&self, user: &UserAccountEntity) -> Option { + async fn get_user_settings_by_user(&self, user: &UserAccountEntity) -> Result { 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) -> [Option; 4] { + async fn get_characters_by_user(&self, user: &UserAccountEntity) -> Result<[Option; 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())); - chars + Ok(chars) } - async fn create_character(&mut self, character: NewCharacterEntity) -> Option { + async fn create_character(&mut self, character: NewCharacterEntity) -> Result { let mut characters = self.characters.lock().unwrap(); let id = characters .iter() @@ -130,19 +134,20 @@ impl EntityGateway for InMemoryGateway { option_flags: character.option_flags, }; characters.insert(new_character.id, new_character.clone()); - Some(new_character) + Ok(new_character) } - async fn save_character(&mut self, char: &CharacterEntity) { + 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) -> GuildCardDataEntity { - GuildCardDataEntity::new(user.id) + async fn get_guild_card_data_by_user(&self, user: &UserAccountEntity) -> Result { + Ok(GuildCardDataEntity::new(user.id)) } - async fn create_item(&mut self, item: NewItemEntity) -> Option { + async fn create_item(&mut self, item: NewItemEntity) -> Result { let mut items = self.items.lock().unwrap(); let id = items .iter() @@ -154,47 +159,52 @@ impl EntityGateway for InMemoryGateway { item: item.item, }; items.insert(ItemEntityId(id), new_item.clone()); - Some(new_item) + Ok(new_item) } - async fn save_item(&mut self, item: &ItemEntity) { + async fn save_item(&mut self, item: &ItemEntity) -> Result<(), GatewayError> { let mut items = self.items.lock().unwrap(); items.insert(item.id, item.clone()); + Ok(()) } - async fn change_item_location(&mut self, item_id: &ItemEntityId, item_location: ItemLocation) { + 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) { + 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) { + 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) { + 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 get_items_by_character(&self, character: &CharacterEntity) -> Vec { + async fn get_items_by_character(&self, character: &CharacterEntity) -> Result, GatewayError> { let items = self.items.lock().unwrap(); - items + Ok(items .iter() .filter(|(_, k)| { match k.location { @@ -241,6 +251,6 @@ impl EntityGateway for InMemoryGateway { }; item }) - .collect() + .collect()) } } diff --git a/src/entity/gateway/mod.rs b/src/entity/gateway/mod.rs index 528dcea..d819ef5 100644 --- a/src/entity/gateway/mod.rs +++ b/src/entity/gateway/mod.rs @@ -2,6 +2,6 @@ pub mod entitygateway; pub mod inmemory; pub mod postgres; -pub use entitygateway::EntityGateway; +pub use entitygateway::{EntityGateway, GatewayError}; pub use inmemory::InMemoryGateway; pub use self::postgres::PostgresGateway; diff --git a/src/entity/gateway/postgres/postgres.rs b/src/entity/gateway/postgres/postgres.rs index 2a32d0d..a9f2f2a 100644 --- a/src/entity/gateway/postgres/postgres.rs +++ b/src/entity/gateway/postgres/postgres.rs @@ -9,7 +9,7 @@ use libpso::character::{settings, guildcard}; use libpso::util::vec_to_array; use crate::entity::account::*; use crate::entity::character::*; -use crate::entity::gateway::EntityGateway; +use crate::entity::gateway::{EntityGateway, GatewayError}; use crate::entity::item::*; use super::models::*; @@ -99,30 +99,30 @@ impl PostgresGateway { #[async_trait::async_trait] impl EntityGateway for PostgresGateway { - async fn create_user(&mut self, user: NewUserAccountEntity) -> Option { + async fn create_user(&mut self, user: NewUserAccountEntity) -> Result { let new_user = sqlx::query_as::<_, PgUserAccount>("insert into user_accounts (email, username, password) values ($1, $2, $3) returning *;") .bind(user.email) .bind(user.username) .bind(user.password) - .fetch_one(&self.pool).await.unwrap(); - Some(new_user.into()) + .fetch_one(&self.pool).await?; + Ok(new_user.into()) } - async fn get_user_by_id(&self, id: UserAccountId) -> Option { + async fn get_user_by_id(&self, id: UserAccountId) -> Result { let user = sqlx::query_as::<_, PgUserAccount>("select * from user_accounts where id = $1") .bind(id.0) - .fetch_one(&self.pool).await.unwrap(); - Some(user.into()) + .fetch_one(&self.pool).await?; + Ok(user.into()) } - async fn get_user_by_name(&self, username: String) -> Option { + async fn get_user_by_name(&self, username: String) -> Result { let user = sqlx::query_as::<_, PgUserAccount>("select * from user_accounts where username = $1") .bind(username) - .fetch_one(&self.pool).await.unwrap(); - Some(user.into()) + .fetch_one(&self.pool).await?; + Ok(user.into()) } - async fn save_user(&mut self, user: &UserAccountEntity) { + async fn save_user(&mut self, user: &UserAccountEntity) -> Result<(), GatewayError> { sqlx::query("UPDATE user_accounts set name=$1, password=$2, banned=$3, muted=$4, flags=$5 where id=$6") .bind(&user.username) .bind(&user.password) @@ -130,10 +130,11 @@ impl EntityGateway for PostgresGateway { .bind(&user.muted_until) .bind(&user.flags) .bind(&user.id.0) - .fetch_one(&self.pool).await.unwrap(); + .fetch_one(&self.pool).await?; + Ok(()) } - async fn create_user_settings(&mut self, settings: NewUserSettingsEntity) -> Option { + async fn create_user_settings(&mut self, settings: NewUserSettingsEntity) -> Result { let new_settings = sqlx::query_as::<_, PgUserSettings>("insert into user_settings (user_account, blocked_users, key_config, joystick_config, option_flags, shortcuts, symbol_chats, team_name) values ($1, $2, $3, $4, $5, $6, $7, $8) returning *;") .bind(settings.user_id.0) @@ -144,18 +145,18 @@ impl EntityGateway for PostgresGateway { .bind(settings.settings.shortcuts.to_vec()) .bind(settings.settings.symbol_chats.to_vec()) .bind(settings.settings.team_name.to_vec().into_iter().map(|i| i.to_le_bytes().to_vec()).flatten().collect::>()) - .fetch_one(&self.pool).await.unwrap(); - Some(new_settings.into()) + .fetch_one(&self.pool).await?; + Ok(new_settings.into()) } - async fn get_user_settings_by_user(&self, user: &UserAccountEntity) -> Option { + async fn get_user_settings_by_user(&self, user: &UserAccountEntity) -> Result { let settings = sqlx::query_as::<_, PgUserSettings>("select * from user_settings where id = $1") .bind(user.id.0) - .fetch_one(&self.pool).await.unwrap(); - Some(settings.into()) + .fetch_one(&self.pool).await?; + Ok(settings.into()) } - async fn save_user_settings(&mut self, settings: &UserSettingsEntity) { + async fn save_user_settings(&mut self, settings: &UserSettingsEntity) -> Result<(), GatewayError> { sqlx::query("update user_settings set blocked_users=$1, key_config=$2, joystick_config=$3, option_flags=$4, shortcuts=$5, symbol_chats=$6, team_name=$7 where id=$8") .bind(settings.settings.blocked_users.to_vec().into_iter().map(|i| i.to_le_bytes().to_vec()).flatten().collect::>()) .bind(&settings.settings.key_config.to_vec()) @@ -165,10 +166,11 @@ impl EntityGateway for PostgresGateway { .bind(&settings.settings.symbol_chats.to_vec()) .bind(settings.settings.team_name.to_vec().into_iter().map(|i| i.to_le_bytes().to_vec()).flatten().collect::>()) .bind(&settings.id.0) - .fetch_one(&self.pool).await.unwrap(); + .fetch_one(&self.pool).await?; + Ok(()) } - async fn create_character(&mut self, char: NewCharacterEntity) -> Option { + async fn create_character(&mut self, char: NewCharacterEntity) -> Result { let q = r#"insert into player_character (user_account, slot, name, exp, class, section_id, costume, skin, face, head, hair, hair_r, hair_g, hair_b, prop_x, prop_y, techs, config, infoboard, guildcard, power, mind, def, evade, luck, hp, tp, tech_menu, meseta, bank_meseta, option_flags) @@ -208,28 +210,28 @@ impl EntityGateway for PostgresGateway { .bind(char.meseta as i32) .bind(char.bank_meseta as i32) .bind(char.option_flags as i32) - .fetch_one(&self.pool).await.unwrap(); + .fetch_one(&self.pool).await?; sqlx::query("insert into inventory_slots (pchar) values ($1)") .bind(character.id) - .execute(&self.pool).await.unwrap(); - Some(character.into()) + .execute(&self.pool).await?; + Ok(character.into()) } - async fn get_characters_by_user(&self, user: &UserAccountEntity) -> [Option; 4] { + async fn get_characters_by_user(&self, user: &UserAccountEntity) -> Result<[Option; 4], GatewayError> { let mut stream = sqlx::query_as::<_, PgCharacter>("select * from player_character where user_account = $1 and slot < 4 order by slot") .bind(user.id.0) .fetch(&self.pool); let mut result = [None; 4]; - while let Some(character) = stream.try_next().await.unwrap() { + while let Some(character) = stream.try_next().await? { let index = character.slot as usize; result[index] = Some(character.into()) } - result + Ok(result) } - async fn save_character(&mut self, char: &CharacterEntity) { + async fn save_character(&mut self, char: &CharacterEntity) -> Result<(), GatewayError> { let q = r#"update player_character set user_account=$1, slot=$2, name=$3, exp=$4, class=$5, section_id=$6, costume=$7, skin=$8, face=$9, head=$10, hair=$11, hair_r=$12, hair_g=$13, hair_b=$14, prop_x=$15, prop_y=$16, techs=$17, config=$18, infoboard=$19, guildcard=$20, power=$21, mind=$22, def=$23, @@ -267,31 +269,33 @@ impl EntityGateway for PostgresGateway { .bind(char.meseta as i32) .bind(char.bank_meseta as i32) .bind(char.id.0 as i32) - .execute(&self.pool).await.unwrap(); + .execute(&self.pool).await?; + Ok(()) } - async fn get_guild_card_data_by_user(&self, user: &UserAccountEntity) -> GuildCardDataEntity { - GuildCardDataEntity { + async fn get_guild_card_data_by_user(&self, user: &UserAccountEntity) -> Result { + Ok(GuildCardDataEntity { id: GuildCardDataId(0), user_id: user.id, guildcard: guildcard::GuildCardData::default(), - } + }) } - async fn create_item(&mut self, item: NewItemEntity) -> Option { + async fn create_item(&mut self, item: NewItemEntity) -> Result { + let mut tx = self.pool.begin().await?; let new_item = sqlx::query_as::<_, PgItem>("insert into item (item) values ($1) returning *;") .bind(sqlx::types::Json(PgItemDetail::from(item.item))) - .fetch_one(&self.pool).await.unwrap(); + .fetch_one(&mut tx).await?; let location = if let ItemLocation::Inventory{character_id, slot, ..} = &item.location { sqlx::query("insert into item_location (item, location) values ($1, $2)") .bind(new_item.id) .bind(sqlx::types::Json(PgItemLocationDetail::from(item.location.clone()))) - .execute(&self.pool).await.unwrap(); + .execute(&mut tx).await?; sqlx::query("update inventory_slots set items[$2] = $1 where pchar = $3") .bind(new_item.id) .bind(*slot as i32) .bind(character_id.0 as i32) - .execute(&self.pool).await.unwrap(); + .execute(&mut tx).await?; sqlx::query_as::<_, PgItemLocation>(r#"select item_location.item, jsonb_set(item_location.location, '{Inventory,slot}', (array_position(inventory_slots.items, item.id))::text::jsonb) as location, @@ -303,70 +307,77 @@ impl EntityGateway for PostgresGateway { order by item_location.created_at limit 1"#) .bind(new_item.id) - .fetch_one(&self.pool).await.unwrap() + .fetch_one(&mut tx).await? } else { sqlx::query_as::<_, PgItemLocation>("insert into item_location (item, location) values ($1, $2) returning *") .bind(new_item.id) .bind(sqlx::types::Json(PgItemLocationDetail::from(item.location))) - .fetch_one(&self.pool).await.unwrap() + .fetch_one(&mut tx).await? }; - Some(ItemEntity { + tx.commit().await?; + Ok(ItemEntity { id: ItemEntityId(new_item.id as u32), item: new_item.item.0.into(), location: location.location.0.into(), }) } - async fn change_item_location(&mut self, item_id: &ItemEntityId, item_location: ItemLocation) { + async fn change_item_location(&mut self, item_id: &ItemEntityId, item_location: ItemLocation) -> Result<(), GatewayError> { + let mut tx = self.pool.begin().await?; if let ItemLocation::Inventory{character_id, slot, ..} = &item_location { sqlx::query("update inventory_slots set items[array_position(items, $1)] = null where pchar = $2 and items[array_position(items, $1)] is not null") .bind(item_id.0 as i32) .bind(character_id.0 as i32) - .execute(&self.pool).await.unwrap(); + .execute(&mut tx).await?; sqlx::query("update inventory_slots set items[$2] = $1 where pchar = $3") .bind(item_id.0 as i32) .bind(*slot as i32) .bind(character_id.0 as i32) - .execute(&self.pool).await.unwrap(); + .execute(&mut tx).await?; sqlx::query(r#"insert into item_location (item, location) select $1, $2 where (select jsonb_object_keys(location) from item_location where item=$1 order by created_at desc limit 1) != 'Inventory'"#) .bind(item_id.0) .bind(sqlx::types::Json(PgItemLocationDetail::from(item_location))) - .execute(&self.pool).await.unwrap(); + .execute(&mut tx).await?; } else { sqlx::query("insert into item_location (item, location) values ($1, $2)") .bind(item_id.0) .bind(sqlx::types::Json(PgItemLocationDetail::from(item_location))) - .execute(&self.pool).await.unwrap(); + .execute(&mut tx).await?; } + tx.commit().await?; + Ok(()) } - async fn feed_mag(&mut self, mag_item_id: &ItemEntityId, tool_item_id: &ItemEntityId) { + async fn feed_mag(&mut self, mag_item_id: &ItemEntityId, tool_item_id: &ItemEntityId) -> Result<(), GatewayError> { sqlx::query("insert into mag_modifier (mag, modifier) values ($1, $2);") .bind(mag_item_id.0) .bind(sqlx::types::Json(PgMagModifierDetail::from(mag::MagModifier::FeedMag{food: *tool_item_id}))) - .execute(&self.pool).await.unwrap(); + .execute(&self.pool).await?; + Ok(()) } - async fn change_mag_owner(&mut self, mag_item_id: &ItemEntityId, character: &CharacterEntity) { + async fn change_mag_owner(&mut self, mag_item_id: &ItemEntityId, character: &CharacterEntity) -> Result<(), GatewayError> { sqlx::query("insert into mag_modifier (mag, modifier) values ($1, $2);") .bind(mag_item_id.0) .bind(sqlx::types::Json(PgMagModifierDetail::from(mag::MagModifier::OwnerChange(character.char_class, character.section_id)))) - .execute(&self.pool).await.unwrap(); + .execute(&self.pool).await?; + Ok(()) } - async fn use_mag_cell(&mut self, mag_item_id: &ItemEntityId, mag_cell_id: &ItemEntityId) { + async fn use_mag_cell(&mut self, mag_item_id: &ItemEntityId, mag_cell_id: &ItemEntityId) -> Result<(), GatewayError> { sqlx::query("insert into mag_modifier (mag, modifier) values ($1, $2);") .bind(mag_item_id.0) .bind(sqlx::types::Json(PgMagModifierDetail::from(mag::MagModifier::MagCell(*mag_cell_id)))) - .execute(&self.pool).await.unwrap(); + .execute(&self.pool).await?; + Ok(()) } - async fn get_items_by_character(&self, char: &CharacterEntity) -> Vec { + async fn get_items_by_character(&self, char: &CharacterEntity) -> Result, GatewayError> { let q = r#"select * from ( select distinct on (item_location.item) item.id, @@ -388,20 +399,20 @@ impl EntityGateway for PostgresGateway { let items = sqlx::query_as::<_, PgItemWithLocation>(q) .bind(char.id.0) .fetch(&self.pool); - join_all(items - .filter_map(|item: Result| { - let item = item.ok()?; - Some(ItemEntity { - id: ItemEntityId(item.id as u32), - item: item.item.0.into(), - location: item.location.0.into() - }) - }) - .map(|item: ItemEntity| { - self.apply_item_modifications(item) - }) - .collect::>() - .await - ).await + Ok(join_all(items + .filter_map(|item: Result| { + let item = item.ok()?; + Some(ItemEntity { + id: ItemEntityId(item.id as u32), + item: item.item.0.into(), + location: item.location.0.into() + }) + }) + .map(|item: ItemEntity| { + self.apply_item_modifications(item) + }) + .collect::>() + .await + ).await) } } diff --git a/src/login/character.rs b/src/login/character.rs index a06a513..99b6ebf 100644 --- a/src/login/character.rs +++ b/src/login/character.rs @@ -36,6 +36,9 @@ const SHIP_MENU_ID: u32 = 1; pub enum CharacterError { InvalidMenuSelection(u32, u32), ClientNotFound(ClientId), + CouldNotLoadSettings, + CouldNotLoadCharacters, + CouldNotLoadGuildcard, } #[derive(Debug)] @@ -310,12 +313,11 @@ impl CharacterServerState { let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?; let user = client.user.as_ref().unwrap(); - // TODO: this should error (data should be added on account creation, why did I copy this silly sylv logic?) let settings = match self.entity_gateway.get_user_settings_by_user(&user).await { - Some(settings) => settings, - None => { + Ok(settings) => settings, + Err(_) => { let user_settings = NewUserSettingsEntity::new(user.id); - self.entity_gateway.create_user_settings(user_settings).await.unwrap() + self.entity_gateway.create_user_settings(user_settings).await.map_err(|_| CharacterError::CouldNotLoadSettings)? } }; @@ -329,7 +331,7 @@ impl CharacterServerState { async fn char_select(&mut self, id: ClientId, select: &CharSelect) -> Result, CharacterError> { let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?; if client.characters.is_none() { - client.characters = Some(self.entity_gateway.get_characters_by_user(client.user.as_ref().unwrap()).await); + client.characters = Some(self.entity_gateway.get_characters_by_user(client.user.as_ref().unwrap()).await.map_err(|_| CharacterError::CouldNotLoadCharacters)?); } if select.reason == 0 { @@ -374,7 +376,7 @@ impl CharacterServerState { async fn guildcard_data_header(&mut self, id: ClientId) -> Result, CharacterError> { let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?; - let guildcard_data = self.entity_gateway.get_guild_card_data_by_user(client.user.as_ref().unwrap()).await; + let guildcard_data = self.entity_gateway.get_guild_card_data_by_user(client.user.as_ref().unwrap()).await.map_err(|_| CharacterError::CouldNotLoadGuildcard)?; let bytes = guildcard_data.guildcard.as_bytes(); let mut crc = crc32::Digest::new(crc32::IEEE); diff --git a/src/login/login.rs b/src/login/login.rs index d105b64..a3efb2d 100644 --- a/src/login/login.rs +++ b/src/login/login.rs @@ -60,7 +60,7 @@ impl SendServerPacket for SendLoginPacket { pub async 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).await.ok_or(AccountStatus::InvalidUser)?; + let user = entity_gateway.get_user_by_name(username).await.map_err(|_| AccountStatus::InvalidUser)?; let verified = bcrypt::verify(password, user.password.as_str()).map_err(|_err| AccountStatus::Error)?; match verified { true => if user.banned_until.map(|banned| banned > chrono::Utc::now()).unwrap_or(false) { diff --git a/src/ship/items/manager.rs b/src/ship/items/manager.rs index cd777fb..8e7ebc8 100644 --- a/src/ship/items/manager.rs +++ b/src/ship/items/manager.rs @@ -48,10 +48,12 @@ pub enum ItemManagerError { CannotGetIndividualItem, InvalidSlot(u8, u8), // slots available, slot attempted NoArmorEquipped, + ItemIdNotInInventory(ClientItemId), + GatewayError(#[from] crate::entity::gateway::GatewayError) } -async fn update_inventory_slots(entity_gateway: &mut EG, character: &CharacterEntity, inventory: &CharacterInventory) { +async fn update_inventory_slots(entity_gateway: &mut EG, character: &CharacterEntity, inventory: &CharacterInventory) -> Result<(), ItemManagerError> { for (slot, item) in inventory.iter().enumerate() { match item { InventoryItem::Individual(individual_inventory_item) => { @@ -62,7 +64,7 @@ async fn update_inventory_slots(entity_gateway: &mut EG, char slot: slot, equipped: individual_inventory_item.equipped, } - ).await + ).await? }, InventoryItem::Stacked(stacked_inventory_item) => { for entity_id in stacked_inventory_item.entity_ids.iter() { @@ -72,10 +74,12 @@ async fn update_inventory_slots(entity_gateway: &mut EG, char character_id: character.id, slot: slot, equipped: false, - }).await; - }} + }).await? + } + } } } + Ok(()) } @@ -111,8 +115,8 @@ impl ItemManager { } // TODO: Result - pub async fn load_character(&mut self, entity_gateway: &mut EG, character: &CharacterEntity) { - let items = entity_gateway.get_items_by_character(&character).await; + pub async fn load_character(&mut self, entity_gateway: &mut EG, character: &CharacterEntity) -> Result<(), ItemManagerError> { + let items = entity_gateway.get_items_by_character(&character).await?; let inventory_items = items.clone().into_iter() .filter_map(|item| { match item.location { @@ -204,6 +208,7 @@ impl ItemManager { let inventory = CharacterInventory::new(inventory_items.into_iter().map(|(_k, v)| v).take(30).collect()); self.character_inventory.insert(character.id, inventory); self.character_bank.insert(character.id, bank_items.remove(&BankName("".to_string())).unwrap_or(CharacterBank::new(Vec::new()))); + Ok(()) } pub fn add_character_to_room(&mut self, room_id: RoomId, character: &CharacterEntity, area_client: AreaClient) { @@ -392,7 +397,7 @@ impl ItemManager { y: item_drop.y, z: item_drop.z, } - }).await.ok_or(ItemManagerError::EntityGatewayError)?; + }).await?; FloorItem::Individual(IndividualFloorItem { entity_id: entity.id, item_id: item_id, @@ -413,7 +418,7 @@ impl ItemManager { y: item_drop.y, z: item_drop.z, } - }).await.ok_or(ItemManagerError::EntityGatewayError)?; + }).await?; FloorItem::Stacked(StackedFloorItem { entity_ids: vec![entity.id], item_id: item_id, @@ -483,7 +488,7 @@ impl ItemManager { }, } - update_inventory_slots(entity_gateway, character, &inventory).await; + update_inventory_slots(entity_gateway, character, &inventory).await?; Ok(()) } @@ -813,7 +818,7 @@ impl ItemManager { item_entities.push(entity_gateway.create_item(NewItemEntity { location: ItemLocation::Shop, item: ItemDetail::Tool(tool), - }).await.ok_or(ItemManagerError::EntityGatewayError)?); + }).await?); } let floor_item = StackedFloorItem { entity_ids: item_entities.into_iter().map(|i| i.id).collect(), @@ -843,7 +848,7 @@ impl ItemManager { let item_entity = entity_gateway.create_item(NewItemEntity { location: ItemLocation::Shop, item: ItemDetail::Tool(tool), - }).await.ok_or(ItemManagerError::EntityGatewayError)?; + }).await?; let floor_item = IndividualFloorItem { entity_id: item_entity.id, item_id: item_id, @@ -861,7 +866,7 @@ impl ItemManager { character_id: character.id, slot: slot.0, equipped: false, - }).await;//.ok_or(ItemManagerError::EntityGatewayError)?; + }).await?; picked_up_item.item_id }; inventory.get_item_by_id(item_id).ok_or(ItemManagerError::ItemIdNotInInventory(item_id))? @@ -871,7 +876,7 @@ impl ItemManager { let item_entity = entity_gateway.create_item(NewItemEntity { location: ItemLocation::Shop, item: item_detail.clone(), - }).await.ok_or(ItemManagerError::EntityGatewayError)?; + }).await?; let floor_item = IndividualFloorItem { entity_id: item_entity.id, item_id: item_id, @@ -889,7 +894,7 @@ impl ItemManager { character_id: character.id, slot: slot.0, equipped: false, - }).await;//.ok_or(ItemManagerError::EntityGatewayError)?; + }).await?; picked_up_item.item_id }; inventory.get_item_by_id(item_id).ok_or(ItemManagerError::ItemIdNotInInventory(item_id))? diff --git a/src/ship/ship.rs b/src/ship/ship.rs index dc6b6b2..7f1e3b2 100644 --- a/src/ship/ship.rs +++ b/src/ship/ship.rs @@ -18,7 +18,7 @@ use crate::common::serverstate::{SendServerPacket, RecvServerPacket, ServerState use crate::common::leveltable::CharacterLevelTable; use crate::common::interserver::{AuthToken, Ship, ServerId, InterserverActor, LoginMessage, ShipMessage}; -use crate::entity::gateway::EntityGateway; +use crate::entity::gateway::{EntityGateway, GatewayError}; use crate::entity::account::{UserAccountEntity, UserSettingsEntity}; use crate::entity::character::{CharacterEntity, SectionID}; @@ -62,6 +62,7 @@ pub enum ShipError { IoError(#[from] std::io::Error), NotEnoughMeseta(ClientId, u32), ShopError, + GatewayError(#[from] GatewayError), } #[derive(Debug)] From 0db9a73849233763078914f5de51344dceb6be08 Mon Sep 17 00:00:00 2001 From: jake Date: Sat, 24 Oct 2020 17:46:38 -0600 Subject: [PATCH 06/27] check if an account is activated before allowing a login --- src/entity/account.rs | 1 + src/entity/gateway/postgres/models.rs | 3 ++- src/ship/packet/handler/auth.rs | 32 +++++++++++++++------------ 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/src/entity/account.rs b/src/entity/account.rs index d62f75e..7f45350 100644 --- a/src/entity/account.rs +++ b/src/entity/account.rs @@ -39,6 +39,7 @@ pub struct UserAccountEntity { pub muted_until: Option>, pub created_at: chrono::DateTime, pub flags: u32, // TODO: is this used for anything other than character creation? + pub activated: bool, } #[derive(Clone, Debug)] diff --git a/src/entity/gateway/postgres/models.rs b/src/entity/gateway/postgres/models.rs index ea8fc21..a987ba2 100644 --- a/src/entity/gateway/postgres/models.rs +++ b/src/entity/gateway/postgres/models.rs @@ -25,6 +25,7 @@ pub struct PgUserAccount { muted: Option>, created_at: chrono::DateTime, flags: i32, + activated: bool, } impl Into for PgUserAccount { @@ -37,9 +38,9 @@ impl Into for PgUserAccount { muted_until: self.muted, created_at: self.created_at, flags: self.flags as u32, - // TOOD guildcard: self.id as u32 + 1, team_id: None, + activated: self.activated } } } diff --git a/src/ship/packet/handler/auth.rs b/src/ship/packet/handler/auth.rs index a0cb15e..7cd5c20 100644 --- a/src/ship/packet/handler/auth.rs +++ b/src/ship/packet/handler/auth.rs @@ -15,21 +15,25 @@ pub async fn validate_login(id: ClientId, -> Result, ShipError> { Ok(match get_login_status(entity_gateway, pkt).await { Ok(user) => { - let mut response = LoginResponse::by_status(AccountStatus::Ok, Session::new()); - response.guildcard = user.id.0 as u32; - response.team_id = user.team_id.map_or(31, |ti| ti) as u32; - let characters = entity_gateway.get_characters_by_user(&user).await; - let character = characters - .get(pkt.session.character_slot as usize) - .ok_or(ShipError::InvalidSlot(id, pkt.session.character_slot as u32))?.as_ref() - .ok_or(ShipError::NoCharacterInSlot(id, pkt.session.character_slot as u32))? - .clone(); - let settings = entity_gateway.get_user_settings_by_user(&user).await - .ok_or(ShipError::ClientNotFound(id))?; + if user.activated { + let mut response = LoginResponse::by_status(AccountStatus::Ok, Session::new()); + response.guildcard = user.id.0 as u32; + response.team_id = user.team_id.map_or(31, |ti| ti) as u32; + let characters = entity_gateway.get_characters_by_user(&user).await?; + let character = characters + .get(pkt.session.character_slot as usize) + .ok_or(ShipError::InvalidSlot(id, pkt.session.character_slot as u32))?.as_ref() + .ok_or(ShipError::NoCharacterInSlot(id, pkt.session.character_slot as u32))? + .clone(); + let settings = entity_gateway.get_user_settings_by_user(&user).await?; - item_manager.load_character(entity_gateway, &character).await; - clients.insert(id, ClientState::new(user, settings, character, pkt.session)); - vec![SendShipPacket::LoginResponse(response), SendShipPacket::ShipBlockList(ShipBlockList::new(&&ship_name, 3))] + item_manager.load_character(entity_gateway, &character).await; + clients.insert(id, ClientState::new(user, settings, character, pkt.session)); + vec![SendShipPacket::LoginResponse(response), SendShipPacket::ShipBlockList(ShipBlockList::new(&&ship_name, 3))] + } + else { + vec![SendShipPacket::LoginResponse(LoginResponse::by_status(AccountStatus::Locked, Session::new()))] + } }, Err(err) => { vec![SendShipPacket::LoginResponse(LoginResponse::by_status(err, Session::new()))] From 19e30f34e6b51910268b0541b4dcace6132e54be Mon Sep 17 00:00:00 2001 From: jake Date: Sun, 25 Oct 2020 20:19:05 -0600 Subject: [PATCH 07/27] remote postgres dep and fix save_user function --- Cargo.toml | 1 - src/entity/gateway/postgres/models.rs | 3 --- src/entity/gateway/postgres/postgres.rs | 7 ++----- 3 files changed, 2 insertions(+), 9 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4720390..52c528e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,7 +30,6 @@ ages-prs = "0.1" async-trait = "0.1.31" lazy_static = "1.4.0" barrel = { version = "0.6.5", features = ["pg"] } -postgres = "0.17.5" refinery = { version = "0.3.0", features = ["postgres"] } sqlx = { version = "0.4.0-beta.1", features = ["postgres", "json", "chrono"] } diff --git a/src/entity/gateway/postgres/models.rs b/src/entity/gateway/postgres/models.rs index a987ba2..f60a9cf 100644 --- a/src/entity/gateway/postgres/models.rs +++ b/src/entity/gateway/postgres/models.rs @@ -13,9 +13,6 @@ use crate::ship::map::MapArea; use sqlx::postgres::PgPoolOptions; use sqlx::Row; use sqlx::Execute; -use postgres::{Client, NoTls}; - - #[derive(Debug, sqlx::FromRow)] pub struct PgUserAccount { id: i32, diff --git a/src/entity/gateway/postgres/postgres.rs b/src/entity/gateway/postgres/postgres.rs index a9f2f2a..17877df 100644 --- a/src/entity/gateway/postgres/postgres.rs +++ b/src/entity/gateway/postgres/postgres.rs @@ -14,9 +14,6 @@ use crate::entity::item::*; use super::models::*; use sqlx::postgres::PgPoolOptions; -use sqlx::Row; -use sqlx::Execute; -use postgres::{Client, NoTls}; mod embedded { use refinery::embed_migrations; @@ -123,14 +120,14 @@ impl EntityGateway for PostgresGateway { } async fn save_user(&mut self, user: &UserAccountEntity) -> Result<(), GatewayError> { - sqlx::query("UPDATE user_accounts set name=$1, password=$2, banned=$3, muted=$4, flags=$5 where id=$6") + sqlx::query("UPDATE user_accounts set username=$1, password=$2, banned=$3, muted=$4, flags=$5 where id=$6") .bind(&user.username) .bind(&user.password) .bind(&user.banned_until) .bind(&user.muted_until) .bind(&user.flags) .bind(&user.id.0) - .fetch_one(&self.pool).await?; + .execute(&self.pool).await?; Ok(()) } From 1ac85b9a5c74b33799aa95c2be1de89aa6874147 Mon Sep 17 00:00:00 2001 From: jake Date: Sun, 25 Oct 2020 20:20:27 -0600 Subject: [PATCH 08/27] tell loginserv the ip of charserv --- src/bin/login.rs | 3 ++- src/bin/main.rs | 4 ++-- src/login/login.rs | 8 +++++--- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/bin/login.rs b/src/bin/login.rs index fe40d94..0ed44e0 100644 --- a/src/bin/login.rs +++ b/src/bin/login.rs @@ -9,10 +9,11 @@ fn main() { let db_username = std::env::var("DB_USERNAME").unwrap(); let db_password = std::env::var("DB_PASSWORD").unwrap(); let db_dbname = std::env::var("DB_DBNAME").unwrap(); + let charserv_ip = std::env::var("CHARSERV_IP").unwrap().parse().unwrap(); let entity_gateway = PostgresGateway::new(&db_host, &db_dbname, &db_username, &db_password); let thread_entity_gateway = entity_gateway.clone(); - let login_state = LoginServerState::new(thread_entity_gateway); + let login_state = LoginServerState::new(thread_entity_gateway, charserv_ip); let login_loop = login_mainloop(login_state, elseware::login::login::LOGIN_PORT); let char_state = CharacterServerState::new(entity_gateway); diff --git a/src/bin/main.rs b/src/bin/main.rs index 9146fa2..a23ff54 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -54,7 +54,7 @@ fn main() { for i in 0..5 { let fake_user = NewUserAccountEntity { email: format!("fake{}@email.com", i), - username: if i == 0 { "hi".to_string() } else { format!("hi{}", i+1) }, + username: if i == 0 { "hiz".to_string() } else { format!("hi{}", i+1) }, password: bcrypt::hash("qwer", 5).unwrap(), guildcard: i + 1, team_id: None, @@ -315,7 +315,7 @@ fn main() { let thread_entity_gateway = entity_gateway.clone(); info!("[auth] starting server"); - let login_state = LoginServerState::new(thread_entity_gateway); + let login_state = LoginServerState::new(thread_entity_gateway, "127.0.0.1".parse().unwrap()); let login_loop = login_mainloop(login_state, elseware::login::login::LOGIN_PORT); let thread_entity_gateway = entity_gateway.clone(); diff --git a/src/login/login.rs b/src/login/login.rs index a3efb2d..af17189 100644 --- a/src/login/login.rs +++ b/src/login/login.rs @@ -75,13 +75,15 @@ pub async fn get_login_status(entity_gateway: &impl EntityGateway, pkt: &Login) pub struct LoginServerState { + character_server_ip: net::Ipv4Addr, entity_gateway: EG, } impl LoginServerState { - pub fn new(entity_gateway: EG) -> LoginServerState { + pub fn new(entity_gateway: EG, character_server_ip: net::Ipv4Addr) -> LoginServerState { LoginServerState { entity_gateway: entity_gateway, + character_server_ip: character_server_ip.into(), } } @@ -89,8 +91,8 @@ impl LoginServerState { match get_login_status(&self.entity_gateway, pkt).await { Ok(_user) => { let response = SendLoginPacket::LoginResponse(LoginResponse::by_status(AccountStatus::Ok, pkt.session)); - let ip = net::Ipv4Addr::new(127,0,0,1); - let ip = u32::from_ne_bytes(ip.octets()); + //let ip = net::Ipv4Addr::new(127,0,0,1); + let ip = u32::from_ne_bytes(self.character_server_ip.octets()); vec![response, SendLoginPacket::RedirectClient(RedirectClient::new(ip, crate::login::character::CHARACTER_PORT))] }, From e3e5bff3003d4cc3e957461690b405ba54ac1e81 Mon Sep 17 00:00:00 2001 From: jake Date: Sun, 25 Oct 2020 23:38:17 -0600 Subject: [PATCH 09/27] fix tests --- tests/test_bank.rs | 124 +++++++++++++++++++------------------- tests/test_character.rs | 4 +- tests/test_item_pickup.rs | 72 +++++++++++----------- tests/test_item_use.rs | 22 +++---- tests/test_mags.rs | 20 +++--- tests/test_shops.rs | 52 ++++++++-------- 6 files changed, 147 insertions(+), 147 deletions(-) diff --git a/tests/test_bank.rs b/tests/test_bank.rs index f0328bb..5ae4085 100644 --- a/tests/test_bank.rs +++ b/tests/test_bank.rs @@ -33,7 +33,7 @@ async fn test_bank_items_sent_in_character_login() { character_id: char1.id, name: item::BankName("".to_string()) } - }).await; + }).await.unwrap(); let mut ship = ShipServerState::builder() .gateway(entity_gateway.clone()) @@ -72,7 +72,7 @@ async fn test_request_bank_items() { character_id: char1.id, name: item::BankName("".to_string()) } - }).await; + }).await.unwrap(); } let mut ship = ShipServerState::builder() @@ -117,7 +117,7 @@ async fn test_request_stacked_bank_items() { character_id: char1.id, name: item::BankName("".to_string()) } - }).await; + }).await.unwrap(); } let mut ship = ShipServerState::builder() @@ -165,7 +165,7 @@ async fn test_request_bank_items_sorted() { character_id: char1.id, name: item::BankName("".to_string()) } - }).await; + }).await.unwrap(); entity_gateway.create_item( item::NewItemEntity { item: item::ItemDetail::Tool ( @@ -177,7 +177,7 @@ async fn test_request_bank_items_sorted() { character_id: char1.id, name: item::BankName("".to_string()) } - }).await; + }).await.unwrap(); entity_gateway.create_item( item::NewItemEntity { item: item::ItemDetail::Weapon( @@ -194,7 +194,7 @@ async fn test_request_bank_items_sorted() { character_id: char1.id, name: item::BankName("".to_string()) } - }).await; + }).await.unwrap(); let mut ship = ShipServerState::builder() .gateway(entity_gateway.clone()) @@ -243,7 +243,7 @@ async fn test_deposit_individual_item() { slot: 0, equipped: false, } - }).await; + }).await.unwrap(); entity_gateway.create_item( item::NewItemEntity { item: item::ItemDetail::Weapon( @@ -261,7 +261,7 @@ async fn test_deposit_individual_item() { slot: 1, equipped: false, } - }).await; + }).await.unwrap(); let mut ship = ShipServerState::builder() .gateway(entity_gateway.clone()) @@ -295,7 +295,7 @@ async fn test_deposit_individual_item() { && player_no_longer_has_item.amount == 0 )); - let items = entity_gateway.get_items_by_character(&char1).await; + let items = entity_gateway.get_items_by_character(&char1).await.unwrap(); let bank_item_ids = items.iter() .filter_map(|item| { if let item::ItemLocation::Bank {..} = item.location { @@ -329,7 +329,7 @@ async fn test_deposit_stacked_item() { slot: 0, equipped: false, } - }).await; + }).await.unwrap(); } let mut ship = ShipServerState::builder() @@ -364,7 +364,7 @@ async fn test_deposit_stacked_item() { && player_no_longer_has_item.amount == 3 )); - let items = entity_gateway.get_items_by_character(&char1).await; + let items = entity_gateway.get_items_by_character(&char1).await.unwrap(); let bank_item_ids = items.iter() .filter_map(|item| { if let item::ItemLocation::Bank {..} = item.location { @@ -398,7 +398,7 @@ async fn test_deposit_partial_stacked_item() { slot: 0, equipped: false, } - }).await; + }).await.unwrap(); } let mut ship = ShipServerState::builder() @@ -433,7 +433,7 @@ async fn test_deposit_partial_stacked_item() { && player_no_longer_has_item.amount == 2 )); - let items = entity_gateway.get_items_by_character(&char1).await; + let items = entity_gateway.get_items_by_character(&char1).await.unwrap(); let bank_item_ids = items.iter() .filter_map(|item| { if let item::ItemLocation::Bank {..} = item.location { @@ -480,7 +480,7 @@ async fn test_deposit_stacked_item_with_stack_already_in_bank() { slot: 0, equipped: false, } - }).await; + }).await.unwrap(); entity_gateway.create_item( item::NewItemEntity { @@ -493,7 +493,7 @@ async fn test_deposit_stacked_item_with_stack_already_in_bank() { character_id: char1.id, name: item::BankName("".into()), } - }).await; + }).await.unwrap(); } let mut ship = ShipServerState::builder() @@ -528,7 +528,7 @@ async fn test_deposit_stacked_item_with_stack_already_in_bank() { && player_no_longer_has_item.amount == 2 )); - let items = entity_gateway.get_items_by_character(&char1).await; + let items = entity_gateway.get_items_by_character(&char1).await.unwrap(); let bank_item_ids = items.iter() .filter_map(|item| { if let item::ItemLocation::Bank {..} = item.location { @@ -561,7 +561,7 @@ async fn test_deposit_stacked_item_with_full_stack_in_bank() { slot: 0, equipped: false, } - }).await; + }).await.unwrap(); } for _ in 0..10 { @@ -576,7 +576,7 @@ async fn test_deposit_stacked_item_with_full_stack_in_bank() { character_id: char1.id, name: item::BankName("".into()), } - }).await; + }).await.unwrap(); } let mut ship = ShipServerState::builder() @@ -604,7 +604,7 @@ async fn test_deposit_stacked_item_with_full_stack_in_bank() { assert!(packets.is_err()); - let items = entity_gateway.get_items_by_character(&char1).await; + let items = entity_gateway.get_items_by_character(&char1).await.unwrap(); let bank_item_ids = items.iter() .filter_map(|item| { if let item::ItemLocation::Bank {..} = item.location { @@ -653,7 +653,7 @@ async fn test_deposit_individual_item_in_full_bank() { slot: 0, equipped: false, } - }).await; + }).await.unwrap(); for _ in 0..200 { entity_gateway.create_item( @@ -672,7 +672,7 @@ async fn test_deposit_individual_item_in_full_bank() { character_id: char1.id, name: item::BankName("".to_string()) } - }).await; + }).await.unwrap(); } let mut ship = ShipServerState::builder() @@ -700,7 +700,7 @@ async fn test_deposit_individual_item_in_full_bank() { assert!(packets.is_err()); - let items = entity_gateway.get_items_by_character(&char1).await; + let items = entity_gateway.get_items_by_character(&char1).await.unwrap(); let bank_item_ids = items.iter() .filter_map(|item| { if let item::ItemLocation::Bank {..} = item.location { @@ -745,7 +745,7 @@ async fn test_deposit_stacked_item_in_full_bank() { slot: 0, equipped: false, } - }).await; + }).await.unwrap(); } for _ in 0..200 { @@ -765,7 +765,7 @@ async fn test_deposit_stacked_item_in_full_bank() { character_id: char1.id, name: item::BankName("".to_string()) } - }).await; + }).await.unwrap(); } let mut ship = ShipServerState::builder() @@ -793,7 +793,7 @@ async fn test_deposit_stacked_item_in_full_bank() { assert!(packets.is_err()); - let items = entity_gateway.get_items_by_character(&char1).await; + let items = entity_gateway.get_items_by_character(&char1).await.unwrap(); let bank_item_ids = items.iter() .filter_map(|item| { if let item::ItemLocation::Bank {..} = item.location { @@ -838,7 +838,7 @@ async fn test_deposit_stacked_item_in_full_bank_with_partial_stack() { slot: 0, equipped: false, } - }).await; + }).await.unwrap(); } for _ in 0..199 { @@ -858,7 +858,7 @@ async fn test_deposit_stacked_item_in_full_bank_with_partial_stack() { character_id: char1.id, name: item::BankName("".to_string()) } - }).await; + }).await.unwrap(); } for _ in 0..2 { @@ -873,7 +873,7 @@ async fn test_deposit_stacked_item_in_full_bank_with_partial_stack() { character_id: char1.id, name: item::BankName("".to_string()) } - }).await; + }).await.unwrap(); } let mut ship = ShipServerState::builder() @@ -899,7 +899,7 @@ async fn test_deposit_stacked_item_in_full_bank_with_partial_stack() { unknown: 0, })))).await.unwrap().for_each(drop); - let items = entity_gateway.get_items_by_character(&char1).await; + let items = entity_gateway.get_items_by_character(&char1).await.unwrap(); let bank_item_ids = items.iter() .filter_map(|item| { if let item::ItemLocation::Bank {..} = item.location { @@ -931,7 +931,7 @@ async fn test_deposit_meseta() { let (user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await; char1.meseta = 300; - entity_gateway.save_character(&char1).await; + entity_gateway.save_character(&char1).await.unwrap(); let mut ship = ShipServerState::builder() .gateway(entity_gateway.clone()) @@ -956,7 +956,7 @@ async fn test_deposit_meseta() { unknown: 0, })))).await.unwrap().for_each(drop); - let characters = entity_gateway.get_characters_by_user(&user1).await; + let characters = entity_gateway.get_characters_by_user(&user1).await.unwrap(); let char = characters[0].as_ref().unwrap(); assert!(char.meseta == 277); assert!(char.bank_meseta == 23); @@ -969,7 +969,7 @@ async fn test_deposit_too_much_meseta() { let (user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await; char1.meseta = 300; char1.bank_meseta = 999980; - entity_gateway.save_character(&char1).await; + entity_gateway.save_character(&char1).await.unwrap(); let mut ship = ShipServerState::builder() .gateway(entity_gateway.clone()) @@ -994,7 +994,7 @@ async fn test_deposit_too_much_meseta() { unknown: 0, })))).await.unwrap().for_each(drop); - let characters = entity_gateway.get_characters_by_user(&user1).await; + let characters = entity_gateway.get_characters_by_user(&user1).await.unwrap(); let char = characters[0].as_ref().unwrap(); assert!(char.meseta == 300); assert!(char.bank_meseta == 999980); @@ -1033,7 +1033,7 @@ async fn test_deposit_meseta_when_bank_is_maxed() { unknown: 0, })))).await.unwrap().for_each(drop); - let characters = entity_gateway.get_characters_by_user(&user1).await; + let characters = entity_gateway.get_characters_by_user(&user1).await.unwrap(); let char = characters[0].as_ref().unwrap(); assert!(char.meseta == 300); assert!(char.bank_meseta == 999999); @@ -1063,7 +1063,7 @@ async fn test_withdraw_individual_item() { character_id: char1.id, name: item::BankName("".to_string()) } - }).await; + }).await.unwrap(); let mut ship = ShipServerState::builder() .gateway(entity_gateway.clone()) @@ -1096,7 +1096,7 @@ async fn test_withdraw_individual_item() { if create_item.item_id == 0x20000 )); - let items = entity_gateway.get_items_by_character(&char1).await; + let items = entity_gateway.get_items_by_character(&char1).await.unwrap(); let inventory_item_ids = items.iter() .filter_map(|item| { if let item::ItemLocation::Inventory{..} = item.location { @@ -1129,7 +1129,7 @@ async fn test_withdraw_stacked_item() { character_id: char1.id, name: item::BankName("".to_string()) } - }).await; + }).await.unwrap(); } let mut ship = ShipServerState::builder() @@ -1163,7 +1163,7 @@ async fn test_withdraw_stacked_item() { if create_item.item_id == 0x10002 )); - let items = entity_gateway.get_items_by_character(&char1).await; + let items = entity_gateway.get_items_by_character(&char1).await.unwrap(); let inventory_item_ids = items.iter() .filter_map(|item| { if let item::ItemLocation::Inventory {..} = item.location { @@ -1196,7 +1196,7 @@ async fn test_withdraw_partial_stacked_item() { character_id: char1.id, name: item::BankName("".into()) } - }).await; + }).await.unwrap(); } let mut ship = ShipServerState::builder() @@ -1230,7 +1230,7 @@ async fn test_withdraw_partial_stacked_item() { if create_item.item_id == 0x10002 )); - let items = entity_gateway.get_items_by_character(&char1).await; + let items = entity_gateway.get_items_by_character(&char1).await.unwrap(); let bank_item_ids = items.iter() .filter_map(|item| { if let item::ItemLocation::Bank {..} = item.location { @@ -1276,7 +1276,7 @@ async fn test_withdraw_stacked_item_with_stack_already_in_inventory() { slot: 0, equipped: false, } - }).await; + }).await.unwrap(); entity_gateway.create_item( item::NewItemEntity { @@ -1289,7 +1289,7 @@ async fn test_withdraw_stacked_item_with_stack_already_in_inventory() { character_id: char1.id, name: item::BankName("".into()), } - }).await; + }).await.unwrap(); } let mut ship = ShipServerState::builder() @@ -1323,7 +1323,7 @@ async fn test_withdraw_stacked_item_with_stack_already_in_inventory() { if create_item.item_id == 0x10000 )); - let items = entity_gateway.get_items_by_character(&char1).await; + let items = entity_gateway.get_items_by_character(&char1).await.unwrap(); let inventory_item_ids = items.iter() .filter_map(|item| { if let item::ItemLocation::Inventory {..} = item.location { @@ -1355,7 +1355,7 @@ async fn test_withdraw_stacked_item_with_full_stack_in_inventory() { character_id: char1.id, name: item::BankName("".into()), } - }).await; + }).await.unwrap(); } for _ in 0..10 { @@ -1371,7 +1371,7 @@ async fn test_withdraw_stacked_item_with_full_stack_in_inventory() { slot: 0, equipped: false, } - }).await; + }).await.unwrap(); } let mut ship = ShipServerState::builder() @@ -1399,7 +1399,7 @@ async fn test_withdraw_stacked_item_with_full_stack_in_inventory() { assert!(packets.is_err()); - let items = entity_gateway.get_items_by_character(&char1).await; + let items = entity_gateway.get_items_by_character(&char1).await.unwrap(); let bank_item_ids = items.iter() .filter_map(|item| { if let item::ItemLocation::Bank {..} = item.location { @@ -1447,7 +1447,7 @@ async fn test_withdraw_individual_item_in_full_inventory() { character_id: char1.id, name: item::BankName("".to_string()) } - }).await; + }).await.unwrap(); for i in 0..30 { entity_gateway.create_item( @@ -1467,7 +1467,7 @@ async fn test_withdraw_individual_item_in_full_inventory() { slot: i, equipped: false, } - }).await; + }).await.unwrap(); } let mut ship = ShipServerState::builder() @@ -1495,7 +1495,7 @@ async fn test_withdraw_individual_item_in_full_inventory() { assert!(packets.is_err()); - let items = entity_gateway.get_items_by_character(&char1).await; + let items = entity_gateway.get_items_by_character(&char1).await.unwrap(); let bank_item_ids = items.iter() .filter_map(|item| { if let item::ItemLocation::Bank {..} = item.location { @@ -1539,7 +1539,7 @@ async fn test_withdraw_stacked_item_in_full_inventory() { character_id: char1.id, name: item::BankName("".to_string()) } - }).await; + }).await.unwrap(); } for i in 0..30 { @@ -1560,7 +1560,7 @@ async fn test_withdraw_stacked_item_in_full_inventory() { slot: i, equipped: false, } - }).await; + }).await.unwrap(); } let mut ship = ShipServerState::builder() @@ -1588,7 +1588,7 @@ async fn test_withdraw_stacked_item_in_full_inventory() { assert!(packets.is_err()); - let items = entity_gateway.get_items_by_character(&char1).await; + let items = entity_gateway.get_items_by_character(&char1).await.unwrap(); let bank_item_ids = items.iter() .filter_map(|item| { if let item::ItemLocation::Bank {..} = item.location { @@ -1632,7 +1632,7 @@ async fn test_withdraw_stacked_item_in_full_inventory_with_partial_stack() { character_id: char1.id, name: item::BankName("".to_string()) } - }).await; + }).await.unwrap(); } for i in 0..29 { @@ -1653,7 +1653,7 @@ async fn test_withdraw_stacked_item_in_full_inventory_with_partial_stack() { slot: i, equipped: false, } - }).await; + }).await.unwrap(); } for _ in 0..2 { @@ -1669,7 +1669,7 @@ async fn test_withdraw_stacked_item_in_full_inventory_with_partial_stack() { slot: 29, equipped: false, } - }).await; + }).await.unwrap(); } let mut ship = ShipServerState::builder() @@ -1695,7 +1695,7 @@ async fn test_withdraw_stacked_item_in_full_inventory_with_partial_stack() { unknown: 0, })))).await.unwrap().for_each(drop); - let items = entity_gateway.get_items_by_character(&char1).await; + let items = entity_gateway.get_items_by_character(&char1).await.unwrap(); let bank_item_ids = items.iter() .filter_map(|item| { if let item::ItemLocation::Bank {..} = item.location { @@ -1727,7 +1727,7 @@ async fn test_withdraw_meseta() { let (user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await; char1.bank_meseta = 300; - entity_gateway.save_character(&char1).await; + entity_gateway.save_character(&char1).await.unwrap(); let mut ship = ShipServerState::builder() .gateway(entity_gateway.clone()) @@ -1752,7 +1752,7 @@ async fn test_withdraw_meseta() { unknown: 0, })))).await.unwrap().for_each(drop); - let characters = entity_gateway.get_characters_by_user(&user1).await; + let characters = entity_gateway.get_characters_by_user(&user1).await.unwrap(); let char = characters[0].as_ref().unwrap(); assert!(char.meseta == 23); assert!(char.bank_meseta == 277); @@ -1765,7 +1765,7 @@ async fn test_withdraw_too_much_meseta() { let (user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await; char1.meseta = 999980; char1.bank_meseta = 300; - entity_gateway.save_character(&char1).await; + entity_gateway.save_character(&char1).await.unwrap(); let mut ship = ShipServerState::builder() .gateway(entity_gateway.clone()) @@ -1790,7 +1790,7 @@ async fn test_withdraw_too_much_meseta() { unknown: 0, })))).await.unwrap().for_each(drop); - let characters = entity_gateway.get_characters_by_user(&user1).await; + let characters = entity_gateway.get_characters_by_user(&user1).await.unwrap(); let char = characters[0].as_ref().unwrap(); assert!(char.meseta == 999980); assert!(char.bank_meseta == 300); @@ -1803,7 +1803,7 @@ async fn test_withdraw_meseta_inventory_is_maxed() { let (user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await; char1.meseta = 999999; char1.bank_meseta = 300; - entity_gateway.save_character(&char1).await; + entity_gateway.save_character(&char1).await.unwrap(); let mut ship = ShipServerState::builder() .gateway(entity_gateway.clone()) @@ -1828,7 +1828,7 @@ async fn test_withdraw_meseta_inventory_is_maxed() { unknown: 0, })))).await.unwrap().for_each(drop); - let characters = entity_gateway.get_characters_by_user(&user1).await; + let characters = entity_gateway.get_characters_by_user(&user1).await.unwrap(); let char = characters[0].as_ref().unwrap(); assert!(char.meseta == 999999); assert!(char.bank_meseta == 300); diff --git a/tests/test_character.rs b/tests/test_character.rs index b05fda4..8dca699 100644 --- a/tests/test_character.rs +++ b/tests/test_character.rs @@ -24,8 +24,8 @@ async fn test_save_options() { options: 12345, })).await.unwrap().for_each(drop); - let characters = entity_gateway.get_characters_by_user(&user1).await; + let characters = entity_gateway.get_characters_by_user(&user1).await.unwrap(); let char = characters[0].as_ref().unwrap(); assert!(char.option_flags == 12345); -} \ No newline at end of file +} diff --git a/tests/test_item_pickup.rs b/tests/test_item_pickup.rs index 3f83927..ec77f62 100644 --- a/tests/test_item_pickup.rs +++ b/tests/test_item_pickup.rs @@ -29,7 +29,7 @@ async fn test_pick_up_item_stack_of_items_already_in_inventory() { slot: 0, equipped: false, } - }).await; + }).await.unwrap(); for (slot, tool) in vec![item::tool::ToolType::Monomate, item::tool::ToolType::Monofluid].into_iter().enumerate() { for _ in 0..5 { @@ -45,7 +45,7 @@ async fn test_pick_up_item_stack_of_items_already_in_inventory() { slot: slot, equipped: false, } - }).await; + }).await.unwrap(); } } @@ -80,7 +80,7 @@ async fn test_pick_up_item_stack_of_items_already_in_inventory() { unknown: [0; 3] })))).await.unwrap().for_each(drop); - let p1_items = entity_gateway.get_items_by_character(&char1).await; + let p1_items = entity_gateway.get_items_by_character(&char1).await.unwrap(); assert!(p1_items.len() == 6); let p1_item_ids = p1_items.iter().map(|item| { @@ -116,7 +116,7 @@ async fn test_pick_up_item_stack_of_items_not_already_held() { slot: 0, equipped: false, } - }).await; + }).await.unwrap(); let mut ship = ShipServerState::builder() .gateway(entity_gateway.clone()) @@ -149,7 +149,7 @@ async fn test_pick_up_item_stack_of_items_not_already_held() { unknown: [0; 3] })))).await.unwrap().for_each(drop); - let p1_items = entity_gateway.get_items_by_character(&char1).await; + let p1_items = entity_gateway.get_items_by_character(&char1).await.unwrap(); assert!(p1_items.len() == 1); let first_item = p1_items.get(0).unwrap(); @@ -184,11 +184,11 @@ async fn test_pick_up_meseta_when_inventory_full() { slot: slot, equipped: false, } - }).await; + }).await.unwrap(); } char2.meseta = 300; - entity_gateway.save_character(&char2).await; + entity_gateway.save_character(&char2).await.unwrap(); let mut ship = ShipServerState::builder() .gateway(entity_gateway.clone()) @@ -227,12 +227,12 @@ async fn test_pick_up_meseta_when_inventory_full() { unknown: [0; 3] })))).await.unwrap().for_each(drop); - let p1_items = entity_gateway.get_items_by_character(&char1).await; + let p1_items = entity_gateway.get_items_by_character(&char1).await.unwrap(); assert!(p1_items.len() == 30); - let characters1 = entity_gateway.get_characters_by_user(&user1).await; + let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap(); let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap(); - let characters2 = entity_gateway.get_characters_by_user(&user2).await; + let characters2 = entity_gateway.get_characters_by_user(&user2).await.unwrap(); let c2 = characters2.get(0).as_ref().unwrap().as_ref().unwrap(); assert!(c1.meseta == 23); assert!(c2.meseta == 277); @@ -263,7 +263,7 @@ async fn test_pick_up_partial_stacked_item_when_inventory_is_otherwise_full() { slot: slot, equipped: false, } - }).await; + }).await.unwrap(); } entity_gateway.create_item( @@ -278,7 +278,7 @@ async fn test_pick_up_partial_stacked_item_when_inventory_is_otherwise_full() { slot: 29, equipped: false, } - }).await; + }).await.unwrap(); entity_gateway.create_item( item::NewItemEntity { item: item::ItemDetail::Tool( @@ -291,7 +291,7 @@ async fn test_pick_up_partial_stacked_item_when_inventory_is_otherwise_full() { slot: 0, equipped: false, } - }).await; + }).await.unwrap(); let mut ship = ShipServerState::builder() .gateway(entity_gateway.clone()) @@ -324,7 +324,7 @@ async fn test_pick_up_partial_stacked_item_when_inventory_is_otherwise_full() { unknown: [0; 3] })))).await.unwrap().for_each(drop); - let p1_items = entity_gateway.get_items_by_character(&char1).await; + let p1_items = entity_gateway.get_items_by_character(&char1).await.unwrap(); assert!(p1_items.len() == 31); let monomate1 = p1_items.get(29).unwrap(); @@ -362,7 +362,7 @@ async fn test_can_not_pick_up_item_when_inventory_full() { slot: slot, equipped: false, } - }).await; + }).await.unwrap(); } entity_gateway.create_item( @@ -382,7 +382,7 @@ async fn test_can_not_pick_up_item_when_inventory_full() { slot: 0, equipped: false, } - }).await; + }).await.unwrap(); let mut ship = ShipServerState::builder() .gateway(entity_gateway.clone()) @@ -415,10 +415,10 @@ async fn test_can_not_pick_up_item_when_inventory_full() { unknown: [0; 3] })))).await.unwrap().for_each(drop); - let p1_items = entity_gateway.get_items_by_character(&char1).await; + let p1_items = entity_gateway.get_items_by_character(&char1).await.unwrap(); assert!(p1_items.len() == 30); - let p2_items = entity_gateway.get_items_by_character(&char2).await; + let p2_items = entity_gateway.get_items_by_character(&char2).await.unwrap(); assert!(p2_items.len() == 0); ship.handle(ClientId(2), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::PickupItem(PickupItem { @@ -429,7 +429,7 @@ async fn test_can_not_pick_up_item_when_inventory_full() { unknown: [0; 3] })))).await.unwrap().for_each(drop); - let p2_items = entity_gateway.get_items_by_character(&char2).await; + let p2_items = entity_gateway.get_items_by_character(&char2).await.unwrap(); assert!(p2_items.len() == 1); } @@ -440,7 +440,7 @@ async fn test_can_not_drop_more_meseta_than_is_held() { let (user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await; char1.meseta = 300; - entity_gateway.save_character(&char1).await; + entity_gateway.save_character(&char1).await.unwrap(); let mut ship = ShipServerState::builder() .gateway(entity_gateway.clone()) @@ -469,7 +469,7 @@ async fn test_can_not_drop_more_meseta_than_is_held() { })))).await; assert!(split_attempt.is_err()); - let characters1 = entity_gateway.get_characters_by_user(&user1).await; + let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap(); let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap(); assert!(c1.meseta == 300); } @@ -494,7 +494,7 @@ async fn test_pick_up_stack_that_would_exceed_stack_limit() { slot: 0, equipped: false, } - }).await; + }).await.unwrap(); } for _ in 0..6 { entity_gateway.create_item( @@ -509,7 +509,7 @@ async fn test_pick_up_stack_that_would_exceed_stack_limit() { slot: 0, equipped: false, } - }).await; + }).await.unwrap(); } let mut ship = ShipServerState::builder() @@ -544,10 +544,10 @@ async fn test_pick_up_stack_that_would_exceed_stack_limit() { })))).await.unwrap().collect::>(); assert!(packets.len() == 0); - let p1_items = entity_gateway.get_items_by_character(&char1).await; + let p1_items = entity_gateway.get_items_by_character(&char1).await.unwrap(); assert!(p1_items.len() == 6); - let p2_items = entity_gateway.get_items_by_character(&char2).await; + let p2_items = entity_gateway.get_items_by_character(&char2).await.unwrap(); assert!(p2_items.len() == 0); } @@ -559,9 +559,9 @@ async fn test_can_not_pick_up_meseta_when_full() { let (user2, mut char2) = new_user_character(&mut entity_gateway, "a2", "a").await; char1.meseta = 999999; - entity_gateway.save_character(&char1).await; + entity_gateway.save_character(&char1).await.unwrap(); char2.meseta = 300; - entity_gateway.save_character(&char2).await; + entity_gateway.save_character(&char2).await.unwrap(); let mut ship = ShipServerState::builder() .gateway(entity_gateway.clone()) @@ -601,9 +601,9 @@ async fn test_can_not_pick_up_meseta_when_full() { })))).await.unwrap().collect::>(); assert!(packets.len() == 0); - let characters1 = entity_gateway.get_characters_by_user(&user1).await; + let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap(); let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap(); - let characters2 = entity_gateway.get_characters_by_user(&user2).await; + let characters2 = entity_gateway.get_characters_by_user(&user2).await.unwrap(); let c2 = characters2.get(0).as_ref().unwrap().as_ref().unwrap(); assert!(c1.meseta == 999999); assert!(c2.meseta == 277); @@ -617,9 +617,9 @@ async fn test_meseta_caps_at_999999_when_trying_to_pick_up_more() { let (user2, mut char2) = new_user_character(&mut entity_gateway, "a2", "a").await; char1.meseta = 999998; - entity_gateway.save_character(&char1).await; + entity_gateway.save_character(&char1).await.unwrap(); char2.meseta = 300; - entity_gateway.save_character(&char2).await; + entity_gateway.save_character(&char2).await.unwrap(); let mut ship = ShipServerState::builder() .gateway(entity_gateway.clone()) @@ -658,9 +658,9 @@ async fn test_meseta_caps_at_999999_when_trying_to_pick_up_more() { unknown: [0; 3] })))).await.unwrap().for_each(drop); - let characters1 = entity_gateway.get_characters_by_user(&user1).await; + let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap(); let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap(); - let characters2 = entity_gateway.get_characters_by_user(&user2).await; + let characters2 = entity_gateway.get_characters_by_user(&user2).await.unwrap(); let c2 = characters2.get(0).as_ref().unwrap().as_ref().unwrap(); assert!(c1.meseta == 999999); assert!(c2.meseta == 277); @@ -686,7 +686,7 @@ async fn test_player_drops_partial_stack_and_other_player_picks_it_up() { slot: 0, equipped: false, } - }).await; + }).await.unwrap(); } let mut ship = ShipServerState::builder() @@ -726,7 +726,7 @@ async fn test_player_drops_partial_stack_and_other_player_picks_it_up() { unknown: [0; 3] })))).await.unwrap().for_each(drop); - let p1_items = entity_gateway.get_items_by_character(&char1).await; + let p1_items = entity_gateway.get_items_by_character(&char1).await.unwrap(); assert!(p1_items.len() == 3); let p1_item_ids = p1_items.iter().map(|item| { @@ -742,7 +742,7 @@ async fn test_player_drops_partial_stack_and_other_player_picks_it_up() { }); assert!(all_items_are_monomates); - let p2_items = entity_gateway.get_items_by_character(&char2).await; + let p2_items = entity_gateway.get_items_by_character(&char2).await.unwrap(); assert!(p2_items.len() == 2); let p2_item_ids = p2_items.iter().map(|item| { diff --git a/tests/test_item_use.rs b/tests/test_item_use.rs index 297a5e3..f1cff0b 100644 --- a/tests/test_item_use.rs +++ b/tests/test_item_use.rs @@ -32,7 +32,7 @@ async fn test_use_monomate() { slot: slot, equipped: false, } - }).await; + }).await.unwrap(); } } @@ -49,7 +49,7 @@ async fn test_use_monomate() { item_id: 0x10000, })))).await.unwrap().for_each(drop); - let items = entity_gateway.get_items_by_character(&char1).await; + let items = entity_gateway.get_items_by_character(&char1).await.unwrap(); assert!(items.iter().filter(|item| { if let item::ItemDetail::Tool(t) = item.item { t.tool == item::tool::ToolType::Monomate @@ -88,7 +88,7 @@ async fn test_use_monomate_twice() { slot: slot, equipped: false, } - }).await; + }).await.unwrap(); } } @@ -110,7 +110,7 @@ async fn test_use_monomate_twice() { item_id: 0x10000, })))).await.unwrap().for_each(drop); - let items = entity_gateway.get_items_by_character(&char1).await; + let items = entity_gateway.get_items_by_character(&char1).await.unwrap(); assert!(items.iter().filter(|item| { if let item::ItemDetail::Tool(t) = item.item { t.tool == item::tool::ToolType::Monomate @@ -149,7 +149,7 @@ async fn test_use_last_monomate() { slot: slot, equipped: false, } - }).await; + }).await.unwrap(); } } @@ -166,7 +166,7 @@ async fn test_use_last_monomate() { item_id: 0x10000, })))).await.unwrap().for_each(drop); - let items = entity_gateway.get_items_by_character(&char1).await; + let items = entity_gateway.get_items_by_character(&char1).await.unwrap(); assert!(items.iter().filter(|item| { if let item::ItemDetail::Tool(t) = item.item { t.tool == item::tool::ToolType::Monomate @@ -203,7 +203,7 @@ async fn test_use_nonstackable_tool() { slot: 0, equipped: false, } - }).await; + }).await.unwrap(); let mut ship = ShipServerState::builder() .gateway(entity_gateway.clone()) @@ -218,7 +218,7 @@ async fn test_use_nonstackable_tool() { item_id: 0x10000, })))).await.unwrap().for_each(drop); - let items = entity_gateway.get_items_by_character(&char1).await; + let items = entity_gateway.get_items_by_character(&char1).await.unwrap(); assert!(items.len() == 0); } @@ -242,7 +242,7 @@ async fn test_use_materials() { slot: slot, equipped: false, } - }).await; + }).await.unwrap(); } } @@ -269,7 +269,7 @@ async fn test_use_materials() { item_id: 0x10001, })))).await.unwrap().for_each(drop); - let items = entity_gateway.get_items_by_character(&char1).await; + let items = entity_gateway.get_items_by_character(&char1).await.unwrap(); assert!(items.iter().filter(|item| { if let item::ItemDetail::Tool(t) = item.item { t.tool == item::tool::ToolType::PowerMaterial @@ -287,7 +287,7 @@ async fn test_use_materials() { } }).count() == 3); - let characters = entity_gateway.get_characters_by_user(&user1).await; + let characters = entity_gateway.get_characters_by_user(&user1).await.unwrap(); let char = characters[0].as_ref().unwrap(); assert!(char.materials.power == 1); diff --git a/tests/test_mags.rs b/tests/test_mags.rs index aa2e299..f1b628d 100644 --- a/tests/test_mags.rs +++ b/tests/test_mags.rs @@ -27,7 +27,7 @@ async fn test_mag_feed() { slot: 0, equipped: true, } - }).await; + }).await.unwrap(); for _ in 0..7 { entity_gateway.create_item( item::NewItemEntity { @@ -41,7 +41,7 @@ async fn test_mag_feed() { slot: 1, equipped: false, } - }).await; + }).await.unwrap(); } let mut ship = ShipServerState::builder() @@ -60,7 +60,7 @@ async fn test_mag_feed() { })))).await.unwrap().for_each(drop); } - let p1_items = entity_gateway.get_items_by_character(&char1).await; + let p1_items = entity_gateway.get_items_by_character(&char1).await.unwrap(); let mag = p1_items.get(0).unwrap(); match &mag.item { item::ItemDetail::Mag(mag) => { @@ -82,10 +82,10 @@ async fn test_mag_change_owner() { let (_user2, mut char2) = new_user_character(&mut entity_gateway, "a2", "a").await; char1.char_class = CharacterClass::RAmarl; char1.section_id = SectionID::Redria; - entity_gateway.save_character(&char1).await; + entity_gateway.save_character(&char1).await.unwrap(); char2.char_class = CharacterClass::FOmarl; char2.section_id = SectionID::Whitill; - entity_gateway.save_character(&char2).await; + entity_gateway.save_character(&char2).await.unwrap(); entity_gateway.create_item( item::NewItemEntity { @@ -97,7 +97,7 @@ async fn test_mag_change_owner() { slot: 0, equipped: true, } - }).await; + }).await.unwrap(); let mut ship = ShipServerState::builder() .gateway(entity_gateway.clone()) @@ -128,7 +128,7 @@ async fn test_mag_change_owner() { unknown: [0; 3] })))).await.unwrap().for_each(drop); - let p2_items = entity_gateway.get_items_by_character(&char2).await; + let p2_items = entity_gateway.get_items_by_character(&char2).await.unwrap(); let mag = p2_items.get(0).unwrap(); match &mag.item { item::ItemDetail::Mag(mag) => { @@ -170,7 +170,7 @@ async fn test_mag_cell() { mag: mag.id, } }).await.unwrap(); - entity_gateway.feed_mag(&mag.id, &fed_tool.id).await; + entity_gateway.feed_mag(&mag.id, &fed_tool.id).await.unwrap(); } entity_gateway.create_item( item::NewItemEntity { @@ -184,7 +184,7 @@ async fn test_mag_cell() { slot: 1, equipped: false, } - }).await; + }).await.unwrap(); let mut ship = ShipServerState::builder() .gateway(entity_gateway.clone()) @@ -199,7 +199,7 @@ async fn test_mag_cell() { item_id: 0x10001, })))).await.unwrap().for_each(drop); - let p1_items = entity_gateway.get_items_by_character(&char1).await; + let p1_items = entity_gateway.get_items_by_character(&char1).await.unwrap(); let mag = p1_items.get(0).unwrap(); match &mag.item { item::ItemDetail::Mag(mag) => { diff --git a/tests/test_shops.rs b/tests/test_shops.rs index d254b58..bf5f48d 100644 --- a/tests/test_shops.rs +++ b/tests/test_shops.rs @@ -17,7 +17,7 @@ async fn test_player_opens_weapon_shop() { let (_user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await; char1.exp = 80000000; - entity_gateway.save_character(&char1).await; + entity_gateway.save_character(&char1).await.unwrap(); let mut ship = ShipServerState::builder() .gateway(entity_gateway.clone()) @@ -47,7 +47,7 @@ async fn test_player_opens_tool_shop() { let (_user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await; char1.exp = 80000000; - entity_gateway.save_character(&char1).await; + entity_gateway.save_character(&char1).await.unwrap(); let mut ship = ShipServerState::builder() .gateway(entity_gateway.clone()) @@ -77,7 +77,7 @@ async fn test_player_opens_armor_shop() { let (_user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await; char1.exp = 80000000; - entity_gateway.save_character(&char1).await; + entity_gateway.save_character(&char1).await.unwrap(); let mut ship = ShipServerState::builder() .gateway(entity_gateway.clone()) @@ -108,7 +108,7 @@ async fn test_player_buys_from_weapon_shop() { let (user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await; char1.exp = 80000000; char1.meseta = 999999; - entity_gateway.save_character(&char1).await; + entity_gateway.save_character(&char1).await.unwrap(); let mut ship = ShipServerState::builder() .gateway(entity_gateway.clone()) @@ -132,10 +132,10 @@ async fn test_player_buys_from_weapon_shop() { unknown1: 0, })))).await.unwrap().for_each(drop); - let characters1 = entity_gateway.get_characters_by_user(&user1).await; + let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap(); let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap(); assert!(c1.meseta < 999999); - let p1_items = entity_gateway.get_items_by_character(&char1).await; + let p1_items = entity_gateway.get_items_by_character(&char1).await.unwrap(); assert_eq!(p1_items.len(), 1); } @@ -146,7 +146,7 @@ async fn test_player_buys_from_tool_shop() { let (user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await; char1.exp = 80000000; char1.meseta = 999999; - entity_gateway.save_character(&char1).await; + entity_gateway.save_character(&char1).await.unwrap(); let mut ship = ShipServerState::builder() .gateway(entity_gateway.clone()) @@ -170,10 +170,10 @@ async fn test_player_buys_from_tool_shop() { unknown1: 0, })))).await.unwrap().for_each(drop); - let characters1 = entity_gateway.get_characters_by_user(&user1).await; + let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap(); let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap(); assert!(c1.meseta < 999999); - let p1_items = entity_gateway.get_items_by_character(&char1).await; + let p1_items = entity_gateway.get_items_by_character(&char1).await.unwrap(); assert_eq!(p1_items.len(), 1); } @@ -184,7 +184,7 @@ async fn test_player_buys_multiple_from_tool_shop() { let (user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await; char1.exp = 80000000; char1.meseta = 999999; - entity_gateway.save_character(&char1).await; + entity_gateway.save_character(&char1).await.unwrap(); let mut ship = ShipServerState::builder() .gateway(entity_gateway.clone()) @@ -208,10 +208,10 @@ async fn test_player_buys_multiple_from_tool_shop() { unknown1: 0, })))).await.unwrap().for_each(drop); - let characters1 = entity_gateway.get_characters_by_user(&user1).await; + let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap(); let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap(); assert!(c1.meseta < 999999); - let p1_items = entity_gateway.get_items_by_character(&char1).await; + let p1_items = entity_gateway.get_items_by_character(&char1).await.unwrap(); assert_eq!(p1_items.len(), 5); } @@ -222,7 +222,7 @@ async fn test_player_buys_from_armor_shop() { let (user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await; char1.exp = 80000000; char1.meseta = 999999; - entity_gateway.save_character(&char1).await; + entity_gateway.save_character(&char1).await.unwrap(); let mut ship = ShipServerState::builder() .gateway(entity_gateway.clone()) @@ -246,10 +246,10 @@ async fn test_player_buys_from_armor_shop() { unknown1: 0, })))).await.unwrap().for_each(drop); - let characters1 = entity_gateway.get_characters_by_user(&user1).await; + let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap(); let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap(); assert!(c1.meseta < 999999); - let p1_items = entity_gateway.get_items_by_character(&char1).await; + let p1_items = entity_gateway.get_items_by_character(&char1).await.unwrap(); assert_eq!(p1_items.len(), 1); } @@ -265,7 +265,7 @@ async fn test_other_clients_see_purchase() { let (_user2, _char2) = new_user_character(&mut entity_gateway, "a2", "a").await; char1.exp = 80000000; char1.meseta = 999999; - entity_gateway.save_character(&char1).await; + entity_gateway.save_character(&char1).await.unwrap(); let mut ship = ShipServerState::builder() .gateway(entity_gateway.clone()) @@ -308,7 +308,7 @@ async fn test_other_clients_see_stacked_purchase() { let (_user2, _char2) = new_user_character(&mut entity_gateway, "a2", "a").await; char1.exp = 80000000; char1.meseta = 999999; - entity_gateway.save_character(&char1).await; + entity_gateway.save_character(&char1).await.unwrap(); entity_gateway.create_item( item::NewItemEntity { item: item::ItemDetail::Tool( @@ -385,10 +385,10 @@ async fn test_buying_item_without_enough_mseseta() { })))).await; assert!(packets.is_err()); - let characters1 = entity_gateway.get_characters_by_user(&user1).await; + let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap(); let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap(); assert_eq!(c1.meseta, 0); - let p1_items = entity_gateway.get_items_by_character(&char1).await; + let p1_items = entity_gateway.get_items_by_character(&char1).await.unwrap(); assert_eq!(p1_items.len(), 0); } @@ -399,7 +399,7 @@ async fn test_player_double_buys_from_tool_shop() { let (user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await; char1.exp = 80000000; char1.meseta = 999999; - entity_gateway.save_character(&char1).await; + entity_gateway.save_character(&char1).await.unwrap(); let mut ship = ShipServerState::builder() .gateway(entity_gateway.clone()) @@ -441,10 +441,10 @@ async fn test_player_double_buys_from_tool_shop() { unknown1: 0, })))).await.unwrap().for_each(drop); - let characters1 = entity_gateway.get_characters_by_user(&user1).await; + let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap(); let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap(); assert!(c1.meseta < 999999); - let p1_items = entity_gateway.get_items_by_character(&char1).await; + let p1_items = entity_gateway.get_items_by_character(&char1).await.unwrap(); assert_eq!(p1_items.len(), 9); } @@ -456,7 +456,7 @@ async fn test_techs_disappear_from_shop_when_bought() { let (_user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await; char1.exp = 80000000; char1.meseta = 999999; - entity_gateway.save_character(&char1).await; + entity_gateway.save_character(&char1).await.unwrap(); let mut ship = ShipServerState::builder() .gateway(entity_gateway.clone()) @@ -502,7 +502,7 @@ async fn test_techs_disappear_from_shop_when_bought() { unknown1: 0, })))).await.unwrap().for_each(drop); - let p1_items = entity_gateway.get_items_by_character(&char1).await; + let p1_items = entity_gateway.get_items_by_character(&char1).await.unwrap(); assert!(p1_items[0].item != p1_items[1].item); } @@ -514,7 +514,7 @@ async fn test_units_disappear_from_shop_when_bought() { let (_user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await; char1.exp = 80000000; char1.meseta = 999999; - entity_gateway.save_character(&char1).await; + entity_gateway.save_character(&char1).await.unwrap(); let mut ship = ShipServerState::builder() .gateway(entity_gateway.clone()) @@ -560,6 +560,6 @@ async fn test_units_disappear_from_shop_when_bought() { unknown1: 0, })))).await.unwrap().for_each(drop); - let p1_items = entity_gateway.get_items_by_character(&char1).await; + let p1_items = entity_gateway.get_items_by_character(&char1).await.unwrap(); assert!(p1_items[0].item != p1_items[1].item); } From 578e4c7cf884ddd653381bf8c8fa9749cc8f98a4 Mon Sep 17 00:00:00 2001 From: jake Date: Sun, 25 Oct 2020 23:42:39 -0600 Subject: [PATCH 10/27] properly handle disconnections in interserver connections --- src/common/mainloop/interserver.rs | 40 ++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/src/common/mainloop/interserver.rs b/src/common/mainloop/interserver.rs index 8d8124b..34143a9 100644 --- a/src/common/mainloop/interserver.rs +++ b/src/common/mainloop/interserver.rs @@ -39,7 +39,7 @@ impl MessageReceiver { let size = u32::from_le_bytes(size_buf) as usize; let mut payload = vec![0u8; size]; - self.socket.read_exact(&mut payload).await.map_err(|err| MessageReceiverError::Disconnected)?; + self.socket.read_exact(&mut payload).await.map_err(|_| MessageReceiverError::Disconnected)?; let payload = String::from_utf8(payload).map_err(|_| MessageReceiverError::InvalidPayload)?; let msg = serde_json::from_str(&payload).map_err(|_| MessageReceiverError::InvalidPayload)?; @@ -65,7 +65,13 @@ where loop { info!("interserver loop"); - let action = action_receiver.recv().await.unwrap(); + let action = match action_receiver.recv().await { + Ok(action) => action, + Err(err) => { + warn!("error in iterserver state loop {:?}", err); + continue; + } + }; let mut state = state.lock().await; match action { @@ -94,12 +100,12 @@ where }, InterserverInputAction::Disconnect(server_id) => { let actions = state.on_disconnect(server_id).await; + ships.remove(&server_id); for (server, action) in actions { if let Some(sender) = ships.get_mut(&server) { sender.send(action).await; } } - break; } } } @@ -164,7 +170,8 @@ where } }, Err(err) => { - warn!("error in send_loop: {:?}, {:?}", server_id, err) + warn!("error in send_loop: {:?}, {:?}", server_id, err); + break; } } } @@ -204,20 +211,33 @@ pub fn ship_connect_mainloop(state: Arc socket, + Err(err) => { + info!("err trying to connect to loginserv {:?}", err); + async_std::task::sleep(Duration::from_secs(10)).await; + continue; + } + }; id += 1; let server_id = crate::common::interserver::ServerId(id); + info!("found loginserv: {:?} {:?}", server_id, socket); let (client_sender, client_receiver) = async_std::sync::channel(64); - info!("ship connected to login: {:?}", socket); login_recv_loop(server_id, socket.clone(), server_state_sender.clone(), client_sender).await; interserver_send_loop(server_id, socket.clone(), client_receiver).await; + + let mut buf = [0u8; 1]; loop { - if let Err(_) = socket.peer_addr() { - info!("ship connected to login: {:?}", socket); - break; + let peek = socket.peek(&mut buf).await; + match peek { + Ok(len) if len == 0 => { + break + }, + _ => { + } } - async_std::task::sleep(Duration::from_secs(10)).await; } } })) From 3543cc5b5af1d1f1973564ba0d5ea217a2788f61 Mon Sep 17 00:00:00 2001 From: jake Date: Sun, 25 Oct 2020 23:59:50 -0600 Subject: [PATCH 11/27] logging in login and ship --- src/bin/login.rs | 23 +++++++++++++++++++++++ src/bin/main.rs | 2 +- src/bin/ship.rs | 23 +++++++++++++++++++++++ 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/src/bin/login.rs b/src/bin/login.rs index 0ed44e0..7fec40c 100644 --- a/src/bin/login.rs +++ b/src/bin/login.rs @@ -5,6 +5,29 @@ use elseware::login::character::CharacterServerState; use elseware::common::mainloop::{login_mainloop, character_mainloop}; fn main() { + let colors = fern::colors::ColoredLevelConfig::new() + .error(fern::colors::Color::Red) + .warn(fern::colors::Color::Yellow) + .info(fern::colors::Color::Green) + .debug(fern::colors::Color::White) + .trace(fern::colors::Color::BrightBlack); + let stdio = fern::Dispatch::new() + .level(log::LevelFilter::Debug) + .format(move |out, message, record| { + out.finish(format_args!( + "\x1B[{}m[{}][{}][{}] {}\x1B[0m", + colors.get_color(&record.level()).to_fg_str(), + chrono::Local::now().format("%Y-%m-%d %H:%M:%S"), + record.target(), + record.level(), + message, + )) + }) + .chain(std::io::stdout()); + fern::Dispatch::new() + .chain(stdio) + .apply().unwrap(); + let db_host = std::env::var("DB_HOST").unwrap(); let db_username = std::env::var("DB_USERNAME").unwrap(); let db_password = std::env::var("DB_PASSWORD").unwrap(); diff --git a/src/bin/main.rs b/src/bin/main.rs index a23ff54..0bfbed6 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -54,7 +54,7 @@ fn main() { for i in 0..5 { let fake_user = NewUserAccountEntity { email: format!("fake{}@email.com", i), - username: if i == 0 { "hiz".to_string() } else { format!("hi{}", i+1) }, + username: if i == 0 { "hi".to_string() } else { format!("hi{}", i+1) }, password: bcrypt::hash("qwer", 5).unwrap(), guildcard: i + 1, team_id: None, diff --git a/src/bin/ship.rs b/src/bin/ship.rs index 78cfa5a..304680b 100644 --- a/src/bin/ship.rs +++ b/src/bin/ship.rs @@ -5,6 +5,29 @@ use elseware::ship::ship::ShipServerStateBuilder; use elseware::common::mainloop::ship_mainloop; fn main() { + let colors = fern::colors::ColoredLevelConfig::new() + .error(fern::colors::Color::Red) + .warn(fern::colors::Color::Yellow) + .info(fern::colors::Color::Green) + .debug(fern::colors::Color::White) + .trace(fern::colors::Color::BrightBlack); + let stdio = fern::Dispatch::new() + .level(log::LevelFilter::Debug) + .format(move |out, message, record| { + out.finish(format_args!( + "\x1B[{}m[{}][{}][{}] {}\x1B[0m", + colors.get_color(&record.level()).to_fg_str(), + chrono::Local::now().format("%Y-%m-%d %H:%M:%S"), + record.target(), + record.level(), + message, + )) + }) + .chain(std::io::stdout()); + fern::Dispatch::new() + .chain(stdio) + .apply().unwrap(); + let db_host = std::env::var("DB_HOST").unwrap(); let db_username = std::env::var("DB_USERNAME").unwrap(); let db_password = std::env::var("DB_PASSWORD").unwrap(); From 174445c175a4e6ff316f0447f44214377c6e7158 Mon Sep 17 00:00:00 2001 From: jake Date: Mon, 26 Oct 2020 00:01:05 -0600 Subject: [PATCH 12/27] properly load techs --- src/entity/gateway/postgres/models.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/entity/gateway/postgres/models.rs b/src/entity/gateway/postgres/models.rs index f60a9cf..46b84d5 100644 --- a/src/entity/gateway/postgres/models.rs +++ b/src/entity/gateway/postgres/models.rs @@ -242,7 +242,7 @@ impl Into for PgCharacter { prop_y: self.prop_y, }, techs: CharacterTechniques { - techs: self.techs.iter().enumerate().take(19).map(|(i, t)| (tech::Technique::from_value(i as u8), TechLevel(*t)) ).collect() + techs: self.techs.iter().enumerate().take(19).filter(|(_, t)| **t != 0xFF).map(|(i, t)| (tech::Technique::from_value(i as u8), TechLevel(*t)) ).collect() }, config: CharacterConfig { raw_data: vec_to_array(self.config) From b3e0674ca553d2c1ae5fb6de7f05c9beba602796 Mon Sep 17 00:00:00 2001 From: jake Date: Mon, 26 Oct 2020 00:02:48 -0600 Subject: [PATCH 13/27] fix more tests + fix warnings --- src/bin/main.rs | 109 +++++++++++++++++++--- src/bin/ship.rs | 1 - src/common/mainloop/client.rs | 59 ------------ src/entity/account.rs | 3 - src/entity/gateway/postgres/models.rs | 7 +- src/entity/gateway/postgres/postgres.rs | 8 +- src/login/character.rs | 30 +++--- src/login/login.rs | 29 +++--- src/ship/drops/rare_drop_table.rs | 2 +- src/ship/items/manager.rs | 40 ++++---- src/ship/items/use_tool.rs | 30 ++---- src/ship/packet/handler/auth.rs | 2 +- src/ship/packet/handler/communication.rs | 2 +- src/ship/packet/handler/direct_message.rs | 8 +- src/ship/packet/handler/lobby.rs | 2 +- src/ship/packet/handler/message.rs | 8 +- src/ship/packet/handler/settings.rs | 6 +- src/ship/ship.rs | 8 +- src/ship/shops/armor.rs | 4 - src/ship/shops/tool.rs | 31 ------ tests/common.rs | 1 - tests/test_bank.rs | 2 +- tests/test_exp_gain.rs | 2 +- tests/test_shops.rs | 2 +- 24 files changed, 182 insertions(+), 214 deletions(-) diff --git a/src/bin/main.rs b/src/bin/main.rs index 0bfbed6..5611f45 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -1,11 +1,9 @@ use std::net::Ipv4Addr; -use std::time::SystemTime; use log::{info}; use elseware::patch::patch::{PatchServerState, generate_patch_tree, load_config, load_motd}; use elseware::login::login::LoginServerState; use elseware::login::character::CharacterServerState; -use elseware::ship::ship::ShipServerState; use elseware::ship::ship::ShipServerStateBuilder; use elseware::entity::account::{NewUserAccountEntity, NewUserSettingsEntity}; use elseware::entity::gateway::{EntityGateway, InMemoryGateway, PostgresGateway}; @@ -64,10 +62,10 @@ fn main() { flags: 0, }; let fake_user = entity_gateway.create_user(fake_user).await.unwrap(); - entity_gateway.create_user_settings(NewUserSettingsEntity::new(fake_user.id)).await; + entity_gateway.create_user_settings(NewUserSettingsEntity::new(fake_user.id)).await.unwrap(); let mut character = NewCharacterEntity::new(fake_user.id); character.name = format!("Test Char {}", i*2); - entity_gateway.create_character(character).await; + entity_gateway.create_character(character).await.unwrap(); let mut character = NewCharacterEntity::new(fake_user.id); character.slot = 2; character.name = "ItemRefactor".into(); @@ -75,6 +73,41 @@ fn main() { character.meseta = 999999; let character = entity_gateway.create_character(character).await.unwrap(); + for _ in 0..3 { + entity_gateway.create_item( + item::NewItemEntity { + item: item::ItemDetail::Weapon( + item::weapon::Weapon { + weapon: item::weapon::WeaponType::Vulcan, + grind: 0, + special: None, + attrs: [None, None, None], + tekked: true, + modifiers: Vec::new(), + } + ), + location: item::ItemLocation::Bank { + character_id: character.id, + name: item::BankName("".to_string()) + } + }).await.unwrap(); + } + + for _ in 0..8 { + entity_gateway.create_item( + NewItemEntity { + item: ItemDetail::Tool ( + item::tool::Tool { + tool: item::tool::ToolType::Monomate, + } + ), + location: item::ItemLocation::Bank { + character_id: character.id, + name: item::BankName("".to_string()) + } + }).await.unwrap(); + } + entity_gateway.create_item( NewItemEntity { item: ItemDetail::Weapon( @@ -94,7 +127,7 @@ fn main() { slot: 0, equipped: false, } - }).await; + }).await.unwrap(); entity_gateway.create_item( NewItemEntity { item: ItemDetail::Weapon( @@ -114,7 +147,7 @@ fn main() { slot: 1, equipped: false, } - }).await; + }).await.unwrap(); entity_gateway.create_item( NewItemEntity { item: ItemDetail::Weapon( @@ -134,7 +167,7 @@ fn main() { slot: 2, equipped: true, } - }).await; + }).await.unwrap(); entity_gateway.create_item( NewItemEntity { item: ItemDetail::Weapon( @@ -154,7 +187,7 @@ fn main() { slot: 3, equipped: true, } - }).await; + }).await.unwrap(); entity_gateway.create_item( NewItemEntity { item: ItemDetail::Weapon( @@ -174,7 +207,59 @@ fn main() { slot: 4, equipped: true, } - }).await; + }).await.unwrap(); + + let mag = entity_gateway.create_item( + item::NewItemEntity { + item: item::ItemDetail::Mag(item::mag::Mag::baby_mag(0)), + location: item::ItemLocation::Inventory { + character_id: character.id, + slot: 5, + equipped: true, + } + }).await.unwrap(); + + for _ in 0..10 { + let fed_tool = entity_gateway.create_item( + NewItemEntity { + item: ItemDetail::Tool ( + item::tool::Tool { + tool: item::tool::ToolType::Monomate, + } + ), + location: item::ItemLocation::FedToMag { + mag: mag.id, + } + }).await.unwrap(); + entity_gateway.feed_mag(&mag.id, &fed_tool.id).await.unwrap(); + } + //entity_gateway.bank(&mag.id).await; + entity_gateway.change_mag_owner(&mag.id, &character).await.unwrap(); + + entity_gateway.create_item( + item::NewItemEntity { + item: ItemDetail::Tool ( + item::tool::Tool { + tool: item::tool::ToolType::CellOfMag502, + } + ), + location: item::ItemLocation::Inventory { + character_id: character.id, + slot: 6, + equipped: true, + } + }).await.unwrap(); + let cell = entity_gateway.create_item( + item::NewItemEntity { + item: ItemDetail::Tool ( + item::tool::Tool { + tool: item::tool::ToolType::CellOfMag502, + } + ), + location: item::ItemLocation::Consumed, + }).await.unwrap(); + entity_gateway.use_mag_cell(&mag.id, &cell.id).await.unwrap(); + entity_gateway.create_item( NewItemEntity { item: ItemDetail::Weapon( @@ -326,7 +411,7 @@ fn main() { let thread_entity_gateway = entity_gateway.clone(); info!("[ship] starting server"); let ship_state = ShipServerStateBuilder::new() - .name("Sona-Nyl".into()) + .name("US/Sona-Nyl".into()) .ip(Ipv4Addr::new(127,0,0,1)) .port(elseware::ship::ship::SHIP_PORT) .gateway(thread_entity_gateway) @@ -335,7 +420,7 @@ fn main() { let thread_entity_gateway = entity_gateway.clone(); let ship_state = ShipServerStateBuilder::new() - .name("Dylath-Leen".into()) + .name("EU/Dylath-Leen".into()) .ip(Ipv4Addr::new(127,0,0,1)) .port(elseware::ship::ship::SHIP_PORT+2000) .gateway(thread_entity_gateway) @@ -344,7 +429,7 @@ fn main() { let thread_entity_gateway = entity_gateway.clone(); let ship_state = ShipServerStateBuilder::new() - .name("Thalarion".into()) + .name("JP/Thalarion".into()) .ip(Ipv4Addr::new(127,0,0,1)) .port(elseware::ship::ship::SHIP_PORT+3000) .gateway(thread_entity_gateway) diff --git a/src/bin/ship.rs b/src/bin/ship.rs index 304680b..d993ebf 100644 --- a/src/bin/ship.rs +++ b/src/bin/ship.rs @@ -1,6 +1,5 @@ use log::{info}; use elseware::entity::gateway::postgres::PostgresGateway; -use elseware::ship::ship::ShipServerState; use elseware::ship::ship::ShipServerStateBuilder; use elseware::common::mainloop::ship_mainloop; diff --git a/src/common/mainloop/client.rs b/src/common/mainloop/client.rs index ff9a71c..9e91b81 100644 --- a/src/common/mainloop/client.rs +++ b/src/common/mainloop/client.rs @@ -139,65 +139,6 @@ enum ServerStateAction { Disconnect, } -async fn server_state_loop(mut state: STATE, - server_state_receiver: async_std::sync::Receiver, R>>) where - STATE: ServerState + Send + 'static, - S: SendServerPacket + std::fmt::Debug + Send + 'static, - R: RecvServerPacket + std::fmt::Debug + Send + 'static, - E: std::fmt::Debug + Send, -{ - async_std::task::spawn(async move { - let mut clients = HashMap::new(); - - loop { - let action = server_state_receiver.recv().await.unwrap(); - - match action { - ClientAction::NewClient(client_id, sender) => { - clients.insert(client_id, sender.clone()); - for action in state.on_connect(client_id) { - match action { - OnConnect::Cipher((inc, outc)) => { - sender.send(ServerStateAction::Cipher(inc, outc)).await; - }, - OnConnect::Packet(pkt) => { - sender.send(ServerStateAction::Packet(pkt)).await; - } - } - } - }, - ClientAction::Packet(client_id, pkt) => { - let pkts = state.handle(client_id, &pkt).await; - match pkts { - Ok(pkts) => { - for (client_id, pkt) in pkts { - if let Some(client) = clients.get_mut(&client_id) { - client.send(ServerStateAction::Packet(pkt)).await; - } - } - }, - Err(err) => { - warn!("[client {:?} state handler error] {:?}", client_id, err); - } - } - }, - ClientAction::Disconnect(client_id) => { - let pkts = state.on_disconnect(client_id); - for (client_id, pkt) in pkts { - if let Some(client) = clients.get_mut(&client_id) { - client.send(ServerStateAction::Packet(pkt)).await; - } - } - - if let Some(client) = clients.get_mut(&client_id) { - client.send(ServerStateAction::Disconnect).await; - } - } - } - } - }); -} - async fn client_recv_loop(client_id: ClientId, socket: Arc, cipher: Arc>>, diff --git a/src/entity/account.rs b/src/entity/account.rs index 7f45350..7071553 100644 --- a/src/entity/account.rs +++ b/src/entity/account.rs @@ -1,6 +1,3 @@ -#![allow(dead_code)] -use std::time::SystemTime; - use libpso::character::settings; use libpso::character::guildcard; diff --git a/src/entity/gateway/postgres/models.rs b/src/entity/gateway/postgres/models.rs index 46b84d5..e1bbde5 100644 --- a/src/entity/gateway/postgres/models.rs +++ b/src/entity/gateway/postgres/models.rs @@ -1,18 +1,13 @@ use std::collections::HashMap; use std::convert::Into; use serde::{Serialize, Deserialize}; -use futures::TryStreamExt; -use libpso::character::{settings, guildcard}; +use libpso::character::settings; use libpso::util::vec_to_array; use crate::entity::account::*; use crate::entity::character::*; -use crate::entity::gateway::EntityGateway; use crate::entity::item::*; use crate::ship::map::MapArea; -use sqlx::postgres::PgPoolOptions; -use sqlx::Row; -use sqlx::Execute; #[derive(Debug, sqlx::FromRow)] pub struct PgUserAccount { id: i32, diff --git a/src/entity/gateway/postgres/postgres.rs b/src/entity/gateway/postgres/postgres.rs index 17877df..a57893a 100644 --- a/src/entity/gateway/postgres/postgres.rs +++ b/src/entity/gateway/postgres/postgres.rs @@ -1,12 +1,8 @@ -use std::convert::{From, TryFrom, Into, TryInto}; -use serde::{Serialize, Deserialize}; +use std::convert::{From, TryFrom, Into}; use futures::future::join_all; use futures::TryStreamExt; -//use futures::StreamExt; use async_std::stream::StreamExt; -//use futures::StreamExt; -use libpso::character::{settings, guildcard}; -use libpso::util::vec_to_array; +use libpso::character::guildcard; use crate::entity::account::*; use crate::entity::character::*; use crate::entity::gateway::{EntityGateway, GatewayError}; diff --git a/src/login/character.rs b/src/login/character.rs index 99b6ebf..07c4873 100644 --- a/src/login/character.rs +++ b/src/login/character.rs @@ -24,7 +24,7 @@ use crate::entity::item::weapon::Weapon; use crate::entity::item::armor::Armor; use crate::entity::item::tech::Technique; use crate::entity::item::tool::Tool; -use crate::entity::item::mag::{Mag, MagType}; +use crate::entity::item::mag::Mag; use crate::entity::character::{CharacterEntity, NewCharacterEntity, CharacterClass, TechLevel}; use crate::login::login::get_login_status; @@ -184,7 +184,6 @@ async fn new_character(entity_gateway: &mut EG, user: &UserAc } character.meseta = 300; - let character = entity_gateway.create_character(character).await.unwrap(); let new_weapon = match character.char_class { @@ -209,7 +208,7 @@ async fn new_character(entity_gateway: &mut EG, user: &UserAc character_id: character.id, slot: 0, equipped: true, - }}).await; + }}).await.unwrap(); entity_gateway.create_item( NewItemEntity { @@ -225,7 +224,7 @@ async fn new_character(entity_gateway: &mut EG, user: &UserAc character_id: character.id, slot: 1, equipped: true, - }}).await; + }}).await.unwrap(); let mut mag = Mag::baby_mag(character.appearance.skin); mag.change_owner(character.char_class, character.section_id); @@ -236,7 +235,7 @@ async fn new_character(entity_gateway: &mut EG, user: &UserAc character_id: character.id, slot: 2, equipped: true, - }}).await; + }}).await.unwrap(); for _ in 0..4 { entity_gateway.create_item( @@ -249,7 +248,7 @@ async fn new_character(entity_gateway: &mut EG, user: &UserAc character_id: character.id, slot: 3, equipped: false, - }}).await; + }}).await.unwrap(); entity_gateway.create_item( NewItemEntity { item: ItemDetail::Tool ( @@ -260,7 +259,7 @@ async fn new_character(entity_gateway: &mut EG, user: &UserAc character_id: character.id, slot: 4, equipped: false, - }}).await; + }}).await.unwrap(); } } @@ -406,7 +405,7 @@ impl CharacterServerState { let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?; let mut user = client.user.as_mut().unwrap(); user.flags = setflag.flags; - self.entity_gateway.save_user(&user).await; + self.entity_gateway.save_user(&user).await.unwrap(); Ok(None.into_iter()) } @@ -444,7 +443,7 @@ impl CharacterServerState { client.session.action = SessionAction::SelectCharacter; client.session.character_slot = preview.slot as u8; user.flags = 0; - self.entity_gateway.save_user(&user).await; + self.entity_gateway.save_user(&user).await.unwrap(); Ok(vec![SendCharacterPacket::LoginResponse(LoginResponse::by_char_select(user.guildcard, user.team_id.unwrap_or(1), client.session)), @@ -543,7 +542,7 @@ impl InterserverActor for CharacterServerState { type RecvMessage = ShipMessage; type Error = (); - async fn on_connect(&mut self, id: ServerId) -> Vec<(ServerId, Self::SendMessage)> { + async fn on_connect(&mut self, _id: ServerId) -> Vec<(ServerId, Self::SendMessage)> { Vec::new() } @@ -652,8 +651,7 @@ mod test { use super::*; use crate::entity::account::*; use libpso::character::{settings, character}; - use std::time::SystemTime; - use crate::entity::gateway::{InMemoryGateway}; + use crate::entity::gateway::{InMemoryGateway, GatewayError}; #[async_std::test] async fn test_option_send() { @@ -663,8 +661,8 @@ mod test { #[async_trait::async_trait] impl EntityGateway for TestData { - async fn get_user_settings_by_user(&self, user: &UserAccountEntity) -> Option { - Some(UserSettingsEntity { + async fn get_user_settings_by_user(&self, user: &UserAccountEntity) -> Result { + Ok(UserSettingsEntity { id: UserSettingsId(0), user_id: user.id, settings: settings::UserSettings::default() @@ -684,6 +682,7 @@ mod test { created_at: chrono::Utc::now(), team_id: None, flags: 0, + activated: true, }); server.clients.insert(ClientId(5), clientstate); @@ -727,6 +726,7 @@ mod test { muted_until: None, created_at: chrono::Utc::now(), flags: 0, + activated: true, }); let mut server = CharacterServerState::new(test_data.clone()); @@ -762,7 +762,7 @@ mod test { } })).await.unwrap().collect::>(); assert!(send.len() == 2); - let chars = test_data.get_characters_by_user(&fake_user.user.unwrap()).await; + let chars = test_data.get_characters_by_user(&fake_user.user.unwrap()).await.unwrap(); assert!(chars[1].as_ref().unwrap().name == "\tEtest name"); assert!(chars[0].is_none()); } diff --git a/src/login/login.rs b/src/login/login.rs index af17189..05013bc 100644 --- a/src/login/login.rs +++ b/src/login/login.rs @@ -144,9 +144,9 @@ impl ServerState for LoginServerState { #[cfg(test)] mod test { - use std::time::SystemTime; use super::*; use crate::entity::account::{UserAccountId}; + use crate::entity::gateway::GatewayError; const LOGIN_PACKET: RecvLoginPacket = RecvLoginPacket::Login(Login { tag: 65536, @@ -180,9 +180,9 @@ mod test { #[async_trait::async_trait] impl EntityGateway for TestData { - async fn get_user_by_name(&self, name: String) -> Option { + async fn get_user_by_name(&self, name: String) -> Result { assert!(name == "testuser"); - Some(UserAccountEntity { + Ok(UserAccountEntity { id: UserAccountId(1), username: "testuser".to_owned(), password: bcrypt::hash("mypassword", 5).unwrap(), @@ -192,11 +192,12 @@ mod test { muted_until: None, created_at: chrono::Utc::now(), flags: 0, + activated: true, }) } }; - let mut server = LoginServerState::new(TestData {}); + let mut server = LoginServerState::new(TestData {}, "127.0.0.1".parse().unwrap()); let send = server.handle(ClientId(1), &LOGIN_PACKET).await.unwrap().collect::>(); assert!(send == vec![ @@ -230,12 +231,12 @@ mod test { #[async_trait::async_trait] impl EntityGateway for TestData { - async fn get_user_by_name(&self, _name: String) -> Option { - None + async fn get_user_by_name(&self, _name: String) -> Result { + Err(GatewayError::Error) } } - let mut server = LoginServerState::new(TestData {}); + let mut server = LoginServerState::new(TestData {}, "127.0.0.1".parse().unwrap()); let send = server.handle(ClientId(1), &LOGIN_PACKET).await.unwrap().collect::>(); assert!(send == vec![ @@ -264,9 +265,9 @@ mod test { #[async_trait::async_trait] impl EntityGateway for TestData { - async fn get_user_by_name(&self, name: String) -> Option { + async fn get_user_by_name(&self, name: String) -> Result { assert!(name == "testuser"); - Some(UserAccountEntity { + Ok(UserAccountEntity { id: UserAccountId(1), username: "testuser".to_owned(), password: bcrypt::hash("notpassword", 5).unwrap(), @@ -276,11 +277,12 @@ mod test { muted_until: None, created_at: chrono::Utc::now(), flags: 0, + activated: true, }) } } - let mut server = LoginServerState::new(TestData {}); + let mut server = LoginServerState::new(TestData {}, "127.0.0.1".parse().unwrap()); let send = server.handle(ClientId(1), &LOGIN_PACKET).await.unwrap().collect::>(); assert!(send == vec![ @@ -309,9 +311,9 @@ mod test { #[async_trait::async_trait] impl EntityGateway for TestData { - async fn get_user_by_name(&self, name: String) -> Option { + async fn get_user_by_name(&self, name: String) -> Result { assert!(name == "testuser"); - Some(UserAccountEntity { + Ok(UserAccountEntity { id: UserAccountId(1), username: "testuser".to_owned(), password: bcrypt::hash("mypassword", 5).unwrap(), @@ -321,11 +323,12 @@ mod test { muted_until: None, created_at: chrono::Utc::now(), flags: 0, + activated: true, }) } } - let mut server = LoginServerState::new(TestData {}); + let mut server = LoginServerState::new(TestData {}, "127.0.0.1".parse().unwrap()); let send = server.handle(ClientId(1), &LOGIN_PACKET).await.unwrap().collect::>(); assert!(send == vec![ diff --git a/src/ship/drops/rare_drop_table.rs b/src/ship/drops/rare_drop_table.rs index 1056f99..9e08e7c 100644 --- a/src/ship/drops/rare_drop_table.rs +++ b/src/ship/drops/rare_drop_table.rs @@ -136,7 +136,7 @@ impl RareDropTable { tool: tool, }) }, - RareDropItem::Mag(mag) => { + RareDropItem::Mag(_mag) => { ItemDropType::Mag(Mag::baby_mag(rng.gen_range(0, 18))) } } diff --git a/src/ship/items/manager.rs b/src/ship/items/manager.rs index 8e7ebc8..dbd91fe 100644 --- a/src/ship/items/manager.rs +++ b/src/ship/items/manager.rs @@ -305,9 +305,9 @@ impl ItemManager { slot: slot.0, equipped: false, } - ).await; + ).await?; if let Some(_) = new_inventory_item.mag() { - entity_gateway.change_mag_owner(&new_inventory_item.entity_id, character).await; + entity_gateway.change_mag_owner(&new_inventory_item.entity_id, character).await?; } }, None => { @@ -329,7 +329,7 @@ impl ItemManager { slot: slot.0, equipped: false, } - ).await; + ).await?; } if stacked_floor_item.count() != new_inventory_item.count() { @@ -349,7 +349,7 @@ impl ItemManager { return Err(ItemManagerError::CouldNotAddToInventory(item_id)); } character.meseta = std::cmp::min(character.meseta + meseta_floor_item.meseta.0, 999999); - entity_gateway.save_character(&character).await; + entity_gateway.save_character(&character).await?; TriggerCreateItem::No }, None => { @@ -470,7 +470,7 @@ impl ItemManager { y: item_drop_location.2, z: item_drop_location.3, } - ).await; + ).await?; }, InventoryItem::Stacked(stacked_inventory_item) => { let stacked_floor_item = shared_floor.drop_stacked_inventory_item(stacked_inventory_item, item_drop_location); @@ -483,7 +483,7 @@ impl ItemManager { y: item_drop_location.2, z: item_drop_location.3, } - ).await; + ).await?; } }, } @@ -504,7 +504,7 @@ impl ItemManager { return Err(ItemManagerError::CouldNotDropMeseta) } character.meseta -= amount; - entity_gateway.save_character(&character).await; + entity_gateway.save_character(&character).await?; let item_id = self.room_item_id_counter.get_mut(room_id).ok_or(ItemManagerError::NoCharacter(character.id))?(); let floor_item = FloorItem::Meseta(MesetaFloorItem { @@ -547,7 +547,7 @@ impl ItemManager { y: 0.0, z: drop_location.z, } - ).await; + ).await?; } Ok(stacked_floor_item) @@ -565,10 +565,10 @@ impl ItemManager { for entity_id in consumed_item.entity_ids() { entity_gateway.change_item_location(&entity_id, - ItemLocation::Consumed).await; + ItemLocation::Consumed).await?; } - update_inventory_slots(entity_gateway, character, &inventory).await; + update_inventory_slots(entity_gateway, character, &inventory).await?; Ok(consumed_item) } @@ -592,7 +592,7 @@ impl ItemManager { ItemLocation::Bank { character_id: character.id, name: BankName("".to_string()) - }).await; + }).await?; }, BankItem::Stacked(stacked_bank_item) => { for entity_id in &stacked_bank_item.entity_ids { @@ -600,12 +600,12 @@ impl ItemManager { ItemLocation::Bank { character_id: character.id, name: BankName("".to_string()) - }).await; + }).await?; } } } - update_inventory_slots(entity_gateway, character, &inventory).await; + update_inventory_slots(entity_gateway, character, &inventory).await?; Ok(()) } @@ -631,7 +631,7 @@ impl ItemManager { character_id: character.id, slot: slot, equipped: false, - }).await; + }).await?; }, (InventoryItem::Stacked(stacked_inventory_item), slot) => { for entity_id in &stacked_inventory_item.entity_ids { @@ -640,7 +640,7 @@ impl ItemManager { character_id: character.id, slot: slot, equipped: false, - }).await; + }).await?; } } } @@ -676,13 +676,13 @@ impl ItemManager { mag.feed(consumed_tool_type); for entity_id in consumed_tool.entity_ids() { - entity_gateway.feed_mag(&individual_item.entity_id, &entity_id).await; + entity_gateway.feed_mag(&individual_item.entity_id, &entity_id).await?; entity_gateway.change_item_location(&entity_id, ItemLocation::FedToMag { mag: individual_item.entity_id, - }).await; + }).await?; } - update_inventory_slots(entity_gateway, character, &inventory).await; + update_inventory_slots(entity_gateway, character, &inventory).await?; Ok(()) } @@ -796,7 +796,7 @@ impl ItemManager { } _ => {} } - update_inventory_slots(entity_gateway, character, &inventory).await; + update_inventory_slots(entity_gateway, character, &inventory).await?; Ok(()) } @@ -838,7 +838,7 @@ impl ItemManager { character_id: character.id, slot: slot.0, equipped: false, - }).await;//.ok_or(ItemManagerError::EntityGatewayError)?; + }).await?; } picked_up_item.item_id }; diff --git a/src/ship/items/use_tool.rs b/src/ship/items/use_tool.rs index a3afa10..671ca53 100644 --- a/src/ship/items/use_tool.rs +++ b/src/ship/items/use_tool.rs @@ -1,14 +1,8 @@ use thiserror::Error; use crate::entity::gateway::EntityGateway; use crate::entity::character::CharacterEntity; -use crate::entity::item::{ItemEntityId, ItemDetail}; -use crate::entity::item::tool::ToolType; use crate::entity::item::mag::MagCell; -use crate::ship::items::{ItemManager, ClientItemId, CharacterInventory, ConsumedItem}; - - - - +use crate::ship::items::{CharacterInventory, ConsumedItem}; #[derive(Error, Debug)] #[error("")] @@ -18,45 +12,39 @@ pub enum UseItemError { InvalidItem, } - - - - -//pub fn use_tool() - pub async fn power_material(entity_gateway: &mut EG, character: &mut CharacterEntity) { character.materials.power += 1; - entity_gateway.save_character(character).await; + entity_gateway.save_character(character).await.unwrap(); } pub async fn mind_material(entity_gateway: &mut EG, character: &mut CharacterEntity) { character.materials.mind += 1; - entity_gateway.save_character(character).await; + entity_gateway.save_character(character).await.unwrap(); } pub async fn evade_material(entity_gateway: &mut EG, character: &mut CharacterEntity) { character.materials.evade += 1; - entity_gateway.save_character(character).await; + entity_gateway.save_character(character).await.unwrap(); } pub async fn def_material(entity_gateway: &mut EG, character: &mut CharacterEntity) { character.materials.def += 1; - entity_gateway.save_character(character).await; + entity_gateway.save_character(character).await.unwrap(); } pub async fn luck_material(entity_gateway: &mut EG, character: &mut CharacterEntity) { character.materials.luck += 1; - entity_gateway.save_character(character).await; + entity_gateway.save_character(character).await.unwrap(); } pub async fn hp_material(entity_gateway: &mut EG, character: &mut CharacterEntity) { character.materials.hp += 1; - entity_gateway.save_character(character).await; + entity_gateway.save_character(character).await.unwrap(); } pub async fn tp_material(entity_gateway: &mut EG, character: &mut CharacterEntity) { character.materials.tp += 1; - entity_gateway.save_character(character).await; + entity_gateway.save_character(character).await.unwrap(); } async fn mag_cell(entity_gateway: &mut EG, used_cell: &ConsumedItem, inventory: &mut CharacterInventory, mag_cell_type: MagCell) -> Result<(), UseItemError> { @@ -71,7 +59,7 @@ async fn mag_cell(entity_gateway: &mut EG, used_cell: &Consum actual_mag.apply_mag_cell(mag_cell_type); for mag_entity_id in mag_item.entity_ids() { for cell_entity_id in used_cell.entity_ids() { - entity_gateway.use_mag_cell(&mag_entity_id, &cell_entity_id).await; + entity_gateway.use_mag_cell(&mag_entity_id, &cell_entity_id).await.unwrap(); } } diff --git a/src/ship/packet/handler/auth.rs b/src/ship/packet/handler/auth.rs index 7cd5c20..93476a3 100644 --- a/src/ship/packet/handler/auth.rs +++ b/src/ship/packet/handler/auth.rs @@ -27,7 +27,7 @@ pub async fn validate_login(id: ClientId, .clone(); let settings = entity_gateway.get_user_settings_by_user(&user).await?; - item_manager.load_character(entity_gateway, &character).await; + item_manager.load_character(entity_gateway, &character).await?; clients.insert(id, ClientState::new(user, settings, character, pkt.session)); vec![SendShipPacket::LoginResponse(response), SendShipPacket::ShipBlockList(ShipBlockList::new(&&ship_name, 3))] } diff --git a/src/ship/packet/handler/communication.rs b/src/ship/packet/handler/communication.rs index 0f8e81a..087913b 100644 --- a/src/ship/packet/handler/communication.rs +++ b/src/ship/packet/handler/communication.rs @@ -42,6 +42,6 @@ pub async fn write_infoboard(id: ClientId, -> Box + Send> { let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id)).unwrap(); client.character.info_board.update_infoboard(new_infoboard); - entity_gateway.save_character(&client.character).await; + entity_gateway.save_character(&client.character).await.unwrap(); Box::new(None.into_iter()) } diff --git a/src/ship/packet/handler/direct_message.rs b/src/ship/packet/handler/direct_message.rs index 5ed7751..7084516 100644 --- a/src/ship/packet/handler/direct_message.rs +++ b/src/ship/packet/handler/direct_message.rs @@ -97,7 +97,7 @@ where item: item_drop, }; let client = clients.get_mut(&area_client.client).ok_or(ShipError::ClientNotFound(area_client.client))?; - let floor_item = item_manager.enemy_drop_item_on_local_floor(entity_gateway, &client.character, item_drop).await.unwrap(); // TODO: unwrap + let floor_item = item_manager.enemy_drop_item_on_local_floor(entity_gateway, &client.character, item_drop).await?; let item_drop_msg = builder::message::item_drop(request_item.client, request_item.target, &floor_item)?; item_drop_packets.push((area_client.client, SendShipPacket::Message(Message::new(GameMessage::ItemDrop(item_drop_msg))))); @@ -236,7 +236,7 @@ where if client.character.meseta > bank_interaction.meseta_amount && (bank_interaction.meseta_amount + client.character.bank_meseta) <= 999999 { client.character.meseta -= bank_interaction.meseta_amount; client.character.bank_meseta += bank_interaction.meseta_amount; - entity_gateway.save_character(&client.character).await; + entity_gateway.save_character(&client.character).await?; } Vec::new() } @@ -251,7 +251,7 @@ where if client.character.meseta + bank_interaction.meseta_amount <= 999999 { client.character.meseta += bank_interaction.meseta_amount; client.character.bank_meseta -= bank_interaction.meseta_amount; - entity_gateway.save_character(&client.character).await; + entity_gateway.save_character(&client.character).await?; } Vec::new() } @@ -361,7 +361,7 @@ where } client.character.meseta -= item.price() as u32; - entity_gateway.save_character(&client.character).await; + entity_gateway.save_character(&client.character).await?; let inventory_item = item_manager.player_buys_item(entity_gateway, &client.character, item, ClientItemId(buy_item.item_id), buy_item.amount as usize).await?; let create = builder::message::create_withdrawn_inventory_item(area_client, inventory_item)?; diff --git a/src/ship/packet/handler/lobby.rs b/src/ship/packet/handler/lobby.rs index f8a898d..af9dcbb 100644 --- a/src/ship/packet/handler/lobby.rs +++ b/src/ship/packet/handler/lobby.rs @@ -101,7 +101,7 @@ pub async fn change_lobby(id: ClientId, } } } - item_manager.load_character(entity_gateway, &client.character).await; + item_manager.load_character(entity_gateway, &client.character).await?; let join_lobby = packet::builder::lobby::join_lobby(id, lobby, client_location, clients, item_manager, level_table)?; let addto = packet::builder::lobby::add_to_lobby(id, lobby, client_location, clients, item_manager, level_table)?; let neighbors = client_location.get_client_neighbors(id).unwrap(); diff --git a/src/ship/packet/handler/message.rs b/src/ship/packet/handler/message.rs index cde8059..8934b19 100644 --- a/src/ship/packet/handler/message.rs +++ b/src/ship/packet/handler/message.rs @@ -58,7 +58,7 @@ pub async fn request_exp(id: ClientId, } client.character.exp += exp_gain; - entity_gateway.save_character(&client.character).await; + entity_gateway.save_character(&client.character).await?; Ok(exp_pkts) } @@ -243,7 +243,7 @@ where let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?; if client.character.meseta >= charge.meseta { client.character.meseta -= charge.meseta; - entity_gateway.save_character(&client.character).await; + entity_gateway.save_character(&client.character).await?; Ok(Box::new(None.into_iter())) } else { Err(ShipError::NotEnoughMeseta(id, client.character.meseta)) @@ -278,7 +278,7 @@ where let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?; if client.character.meseta >= 10 { client.character.meseta -= 10; - entity_gateway.save_character(&client.character).await; + entity_gateway.save_character(&client.character).await?; Ok(Box::new(None.into_iter())) } else { Err(ShipError::NotEnoughMeseta(id, client.character.meseta)) @@ -355,4 +355,4 @@ where } Ok(Box::new(None.into_iter())) -} \ No newline at end of file +} diff --git a/src/ship/packet/handler/settings.rs b/src/ship/packet/handler/settings.rs index 26b632d..b2df392 100644 --- a/src/ship/packet/handler/settings.rs +++ b/src/ship/packet/handler/settings.rs @@ -10,7 +10,7 @@ pub async fn update_config(id: ClientId, -> Box + Send> { let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id)).unwrap(); client.character.config.update(update_config); - entity_gateway.save_character(&client.character).await; + entity_gateway.save_character(&client.character).await.unwrap(); Box::new(None.into_iter()) } @@ -22,6 +22,6 @@ pub async fn save_options(id: ClientId, // // TODO: don't unwrap? let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id)).unwrap(); client.character.option_flags = save_options.options; - entity_gateway.save_character(&client.character).await; + entity_gateway.save_character(&client.character).await.unwrap(); Box::new(None.into_iter()) -} \ No newline at end of file +} diff --git a/src/ship/ship.rs b/src/ship/ship.rs index 7f1e3b2..0f51bc7 100644 --- a/src/ship/ship.rs +++ b/src/ship/ship.rs @@ -29,7 +29,7 @@ use crate::ship::room; use crate::ship::quests; use crate::ship::map::{MapsError, MapAreaError, MapArea}; use crate::ship::packet::handler; -use crate::ship::shops::{ShopType, WeaponShop, ToolShop, ArmorShop, WeaponShopItem, ToolShopItem, ArmorShopItem}; +use crate::ship::shops::{WeaponShop, ToolShop, ArmorShop, WeaponShopItem, ToolShopItem, ArmorShopItem}; pub const SHIP_PORT: u16 = 23423; pub const QUEST_CATEGORY_MENU_ID: u32 = 0xA2; @@ -568,7 +568,7 @@ impl ServerState for ShipServerState { RecvShipPacket::DoneLoadingQuest(_) => { handler::quest::done_loading_quest(id, &mut self.clients, &self.client_location)? }, - RecvShipPacket::FullCharacterData(full_character_data) => { + RecvShipPacket::FullCharacterData(_full_character_data) => { Box::new(None.into_iter()) }, RecvShipPacket::SaveOptions(save_options) => { @@ -622,11 +622,11 @@ impl InterserverActor for ShipServerState { })) ] } - async fn action(&mut self, id: ServerId, msg: Self::RecvMessage) -> Result, Self::Error> { + async fn action(&mut self, _id: ServerId, _msg: Self::RecvMessage) -> Result, Self::Error> { Ok(Vec::new()) } - async fn on_disconnect(&mut self, id: ServerId) -> Vec<(ServerId, Self::SendMessage)> { + async fn on_disconnect(&mut self, _id: ServerId) -> Vec<(ServerId, Self::SendMessage)> { Vec::new() } } diff --git a/src/ship/shops/armor.rs b/src/ship/shops/armor.rs index 17869d9..8920fcb 100644 --- a/src/ship/shops/armor.rs +++ b/src/ship/shops/armor.rs @@ -1,4 +1,3 @@ -use std::collections::HashMap; use std::fs::File; use std::io::Read; use std::path::PathBuf; @@ -6,9 +5,6 @@ use std::convert::TryInto; use serde::Deserialize; use rand::{Rng, SeedableRng}; use rand::distributions::{WeightedIndex, Distribution}; -use rand::seq::{SliceRandom, IteratorRandom}; -use crate::entity::character::SectionID; -use crate::ship::room::Difficulty; use crate::entity::item::ItemDetail; use crate::entity::item::armor::{Armor, ArmorType}; use crate::entity::item::shield::{Shield, ShieldType}; diff --git a/src/ship/shops/tool.rs b/src/ship/shops/tool.rs index c3ecaa9..7eecd3d 100644 --- a/src/ship/shops/tool.rs +++ b/src/ship/shops/tool.rs @@ -6,9 +6,6 @@ use std::convert::TryInto; use serde::Deserialize; use rand::{Rng, SeedableRng}; use rand::distributions::{WeightedIndex, Distribution}; -use rand::seq::{SliceRandom, IteratorRandom}; -use crate::entity::character::SectionID; -use crate::ship::room::Difficulty; use crate::entity::item::ItemDetail; use crate::entity::item::tool::{Tool, ToolType}; use crate::entity::item::tech::{Technique, TechniqueDisk}; @@ -206,34 +203,6 @@ impl ToolShop { } } - fn generate_tech(&mut self, character_level: usize) -> ToolShopItem { - let tier = self.techs.0.iter() - .filter(|t| t.level <= character_level) - .last() - .unwrap(); - - let mut tier = tier.techs.iter() - .map(|(tech, entry)| { - (tech, entry) - }); - - - let tech_choice = WeightedIndex::new(tier.clone().map(|(_, e)| e.probability)).unwrap(); - let tech_detail = tier.nth(tech_choice.sample(&mut self.rng)).unwrap(); - let tech_level = match tech_detail.1.level { - TechLevel::Set{set_level} => set_level, - TechLevel::Level{level_divisor} => std::cmp::max(std::cmp::min(character_level, 99)/level_divisor, 1), - TechLevel::Range{min, max} => self.rng.gen_range(min, max+1), - }; - - ToolShopItem::Tech( - TechniqueDisk { - tech: *tech_detail.0, - level: tech_level as u32, - } - ) - } - fn generate_tech_types(&mut self, character_level: usize) -> Vec { let tier = self.techs.0.iter() .filter(|t| t.level <= character_level) diff --git a/tests/common.rs b/tests/common.rs index 1eebef3..2d59654 100644 --- a/tests/common.rs +++ b/tests/common.rs @@ -1,5 +1,4 @@ #![allow(dead_code)] -use std::time::SystemTime; use elseware::common::serverstate::{ClientId, ServerState}; use elseware::entity::gateway::EntityGateway; diff --git a/tests/test_bank.rs b/tests/test_bank.rs index 5ae4085..08bb984 100644 --- a/tests/test_bank.rs +++ b/tests/test_bank.rs @@ -1008,7 +1008,7 @@ async fn test_deposit_meseta_when_bank_is_maxed() { let (user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await; char1.meseta = 300; char1.bank_meseta = 999999; - entity_gateway.save_character(&char1).await; + entity_gateway.save_character(&char1).await.unwrap(); let mut ship = ShipServerState::builder() .gateway(entity_gateway.clone()) diff --git a/tests/test_exp_gain.rs b/tests/test_exp_gain.rs index 192ad3f..9614558 100644 --- a/tests/test_exp_gain.rs +++ b/tests/test_exp_gain.rs @@ -54,7 +54,7 @@ async fn test_character_levels_up() { let (_user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a").await; char1.exp = 49; - entity_gateway.save_character(&char1).await; + entity_gateway.save_character(&char1).await.unwrap(); let mut ship = ShipServerState::builder() .gateway(entity_gateway.clone()) diff --git a/tests/test_shops.rs b/tests/test_shops.rs index bf5f48d..74c4a33 100644 --- a/tests/test_shops.rs +++ b/tests/test_shops.rs @@ -321,7 +321,7 @@ async fn test_other_clients_see_stacked_purchase() { slot: 0, equipped: false, } - }).await; + }).await.unwrap(); let mut ship = ShipServerState::builder() .gateway(entity_gateway.clone()) From a14aee4e292c25ae198ca8db2573e8fec592164c Mon Sep 17 00:00:00 2001 From: jake Date: Tue, 27 Oct 2020 06:29:20 -0600 Subject: [PATCH 14/27] handle unactivated accounts in the correct spot --- src/bin/main.rs | 1 + src/entity/account.rs | 1 + src/entity/gateway/inmemory.rs | 2 +- src/entity/gateway/postgres/postgres.rs | 3 ++- src/login/login.rs | 4 ++++ src/ship/packet/handler/auth.rs | 31 +++++++++++-------------- tests/common.rs | 1 + 7 files changed, 23 insertions(+), 20 deletions(-) diff --git a/src/bin/main.rs b/src/bin/main.rs index 5611f45..16af628 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -60,6 +60,7 @@ fn main() { muted_until: None, created_at: chrono::Utc::now(), flags: 0, + activated: true, }; let fake_user = entity_gateway.create_user(fake_user).await.unwrap(); entity_gateway.create_user_settings(NewUserSettingsEntity::new(fake_user.id)).await.unwrap(); diff --git a/src/entity/account.rs b/src/entity/account.rs index 7071553..1276cf8 100644 --- a/src/entity/account.rs +++ b/src/entity/account.rs @@ -23,6 +23,7 @@ pub struct NewUserAccountEntity { pub muted_until: Option>, pub created_at: chrono::DateTime, pub flags: u32, + pub activated: bool, } #[derive(Clone, Debug)] diff --git a/src/entity/gateway/inmemory.rs b/src/entity/gateway/inmemory.rs index 01ec302..6341638 100644 --- a/src/entity/gateway/inmemory.rs +++ b/src/entity/gateway/inmemory.rs @@ -47,7 +47,7 @@ impl EntityGateway for InMemoryGateway { muted_until: user.muted_until, created_at: user.created_at, flags: user.flags, - activated: true, + activated: user.activated, }; users.insert(user.id, user.clone()); Ok(user) diff --git a/src/entity/gateway/postgres/postgres.rs b/src/entity/gateway/postgres/postgres.rs index a57893a..ffa11cd 100644 --- a/src/entity/gateway/postgres/postgres.rs +++ b/src/entity/gateway/postgres/postgres.rs @@ -93,10 +93,11 @@ impl PostgresGateway { #[async_trait::async_trait] impl EntityGateway for PostgresGateway { async fn create_user(&mut self, user: NewUserAccountEntity) -> Result { - let new_user = sqlx::query_as::<_, PgUserAccount>("insert into user_accounts (email, username, password) values ($1, $2, $3) returning *;") + let new_user = sqlx::query_as::<_, PgUserAccount>("insert into user_accounts (email, username, password, activated) values ($1, $2, $3, $4) returning *;") .bind(user.email) .bind(user.username) .bind(user.password) + .bind(user.activated) .fetch_one(&self.pool).await?; Ok(new_user.into()) } diff --git a/src/login/login.rs b/src/login/login.rs index 05013bc..95e8b08 100644 --- a/src/login/login.rs +++ b/src/login/login.rs @@ -61,6 +61,10 @@ pub async fn get_login_status(entity_gateway: &impl EntityGateway, pkt: &Login) 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).await.map_err(|_| AccountStatus::InvalidUser)?; + if !user.activated { + return Err(AccountStatus::PayUp) + } + let verified = bcrypt::verify(password, user.password.as_str()).map_err(|_err| AccountStatus::Error)?; match verified { true => if user.banned_until.map(|banned| banned > chrono::Utc::now()).unwrap_or(false) { diff --git a/src/ship/packet/handler/auth.rs b/src/ship/packet/handler/auth.rs index 93476a3..9617998 100644 --- a/src/ship/packet/handler/auth.rs +++ b/src/ship/packet/handler/auth.rs @@ -15,25 +15,20 @@ pub async fn validate_login(id: ClientId, -> Result, ShipError> { Ok(match get_login_status(entity_gateway, pkt).await { Ok(user) => { - if user.activated { - let mut response = LoginResponse::by_status(AccountStatus::Ok, Session::new()); - response.guildcard = user.id.0 as u32; - response.team_id = user.team_id.map_or(31, |ti| ti) as u32; - let characters = entity_gateway.get_characters_by_user(&user).await?; - let character = characters - .get(pkt.session.character_slot as usize) - .ok_or(ShipError::InvalidSlot(id, pkt.session.character_slot as u32))?.as_ref() - .ok_or(ShipError::NoCharacterInSlot(id, pkt.session.character_slot as u32))? - .clone(); - let settings = entity_gateway.get_user_settings_by_user(&user).await?; + let mut response = LoginResponse::by_status(AccountStatus::Ok, Session::new()); + response.guildcard = user.id.0 as u32; + response.team_id = user.team_id.map_or(31, |ti| ti) as u32; + let characters = entity_gateway.get_characters_by_user(&user).await?; + let character = characters + .get(pkt.session.character_slot as usize) + .ok_or(ShipError::InvalidSlot(id, pkt.session.character_slot as u32))?.as_ref() + .ok_or(ShipError::NoCharacterInSlot(id, pkt.session.character_slot as u32))? + .clone(); + let settings = entity_gateway.get_user_settings_by_user(&user).await?; - item_manager.load_character(entity_gateway, &character).await?; - clients.insert(id, ClientState::new(user, settings, character, pkt.session)); - vec![SendShipPacket::LoginResponse(response), SendShipPacket::ShipBlockList(ShipBlockList::new(&&ship_name, 3))] - } - else { - vec![SendShipPacket::LoginResponse(LoginResponse::by_status(AccountStatus::Locked, Session::new()))] - } + item_manager.load_character(entity_gateway, &character).await?; + clients.insert(id, ClientState::new(user, settings, character, pkt.session)); + vec![SendShipPacket::LoginResponse(response), SendShipPacket::ShipBlockList(ShipBlockList::new(&&ship_name, 3))] }, Err(err) => { vec![SendShipPacket::LoginResponse(LoginResponse::by_status(err, Session::new()))] diff --git a/tests/common.rs b/tests/common.rs index 2d59654..0b66360 100644 --- a/tests/common.rs +++ b/tests/common.rs @@ -23,6 +23,7 @@ pub async fn new_user_character(entity_gateway: &mut EG, user muted_until: None, created_at: chrono::Utc::now(), flags: 0, + activated: true, }; let user = entity_gateway.create_user(new_user).await.unwrap(); From b249a3fed5a08747424658613e1214e54c7201e7 Mon Sep 17 00:00:00 2001 From: jake Date: Tue, 27 Oct 2020 06:36:07 -0600 Subject: [PATCH 15/27] fix inventory slot and stacked items --- .../postgres/migrations/V0001__initial.sql | 6 ++--- src/entity/gateway/postgres/postgres.rs | 27 +++++++------------ 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/src/entity/gateway/postgres/migrations/V0001__initial.sql b/src/entity/gateway/postgres/migrations/V0001__initial.sql index c5805f1..1e5a925 100644 --- a/src/entity/gateway/postgres/migrations/V0001__initial.sql +++ b/src/entity/gateway/postgres/migrations/V0001__initial.sql @@ -79,9 +79,9 @@ create table item_location ( created_at timestamptz default current_timestamp not null ); -create table inventory_slots ( - pchar integer references player_character not null, - items integer[30] /* references item (id) */ +create table inventory_slot ( + item integer references item not null unique, + slot integer not null ); create table weapon_modifier ( diff --git a/src/entity/gateway/postgres/postgres.rs b/src/entity/gateway/postgres/postgres.rs index ffa11cd..965bcf4 100644 --- a/src/entity/gateway/postgres/postgres.rs +++ b/src/entity/gateway/postgres/postgres.rs @@ -172,7 +172,6 @@ impl EntityGateway for PostgresGateway { ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28, $29, $30, $31) returning *;"#; let character = sqlx::query_as::<_, PgCharacter>(q) - //sqlx::query(q) .bind(char.user_id.0) .bind(char.slot as i16) .bind(char.name) @@ -206,9 +205,6 @@ impl EntityGateway for PostgresGateway { .bind(char.option_flags as i32) .fetch_one(&self.pool).await?; - sqlx::query("insert into inventory_slots (pchar) values ($1)") - .bind(character.id) - .execute(&self.pool).await?; Ok(character.into()) } @@ -280,23 +276,22 @@ impl EntityGateway for PostgresGateway { let new_item = sqlx::query_as::<_, PgItem>("insert into item (item) values ($1) returning *;") .bind(sqlx::types::Json(PgItemDetail::from(item.item))) .fetch_one(&mut tx).await?; - let location = if let ItemLocation::Inventory{character_id, slot, ..} = &item.location { + let location = if let ItemLocation::Inventory{slot, ..} = &item.location { sqlx::query("insert into item_location (item, location) values ($1, $2)") .bind(new_item.id) .bind(sqlx::types::Json(PgItemLocationDetail::from(item.location.clone()))) .execute(&mut tx).await?; - sqlx::query("update inventory_slots set items[$2] = $1 where pchar = $3") + sqlx::query("insert into inventory_slot (item, slot) values ($1, $2)") .bind(new_item.id) .bind(*slot as i32) - .bind(character_id.0 as i32) .execute(&mut tx).await?; sqlx::query_as::<_, PgItemLocation>(r#"select item_location.item, - jsonb_set(item_location.location, '{Inventory,slot}', (array_position(inventory_slots.items, item.id))::text::jsonb) as location, + jsonb_set(item_location.location, '{Inventory,slot}', inventory_slot.slot::text::jsonb) as location, item_location.created_at from item_location join item on item.id = item_location.item - join inventory_slots on inventory_slots.pchar = cast (item_location.location -> 'Inventory' ->> 'character_id' as integer) + join inventory_slot on inventory_slot.item = item.id where item.id = $1 order by item_location.created_at limit 1"#) @@ -319,15 +314,13 @@ impl EntityGateway for PostgresGateway { async fn change_item_location(&mut self, item_id: &ItemEntityId, item_location: ItemLocation) -> Result<(), GatewayError> { let mut tx = self.pool.begin().await?; - if let ItemLocation::Inventory{character_id, slot, ..} = &item_location { - sqlx::query("update inventory_slots set items[array_position(items, $1)] = null where pchar = $2 and items[array_position(items, $1)] is not null") + if let ItemLocation::Inventory{slot, ..} = &item_location { + sqlx::query("delete from inventory_slot where item = $1") .bind(item_id.0 as i32) - .bind(character_id.0 as i32) .execute(&mut tx).await?; - sqlx::query("update inventory_slots set items[$2] = $1 where pchar = $3") - .bind(item_id.0 as i32) + sqlx::query("insert into inventory_slot (item, slot) values ($1, $2)") + .bind(item_id.0) .bind(*slot as i32) - .bind(character_id.0 as i32) .execute(&mut tx).await?; sqlx::query(r#"insert into item_location (item, location) select $1, $2 @@ -377,14 +370,14 @@ impl EntityGateway for PostgresGateway { item.id, case when item_location.location -> 'Inventory' is not null then - jsonb_set(item_location.location, '{Inventory,slot}', (array_position(inventory_slots.items, item.id))::text::jsonb) + jsonb_set(item_location.location, '{Inventory,slot}', inventory_slot.slot::text::jsonb) else item_location.location end, item.item from item_location join item on item.id = item_location.item - join inventory_slots on inventory_slots.pchar = $1 + join inventory_slot on inventory_slot.item = item.id order by item_location.item, item_location.created_at desc ) as i where cast (location -> 'Inventory' ->> 'character_id' as integer) = $1 From a02cb578258349c0f0e13ed39872033aac83870c Mon Sep 17 00:00:00 2001 From: jake Date: Tue, 27 Oct 2020 06:36:34 -0600 Subject: [PATCH 16/27] remove ship from shiplist when it disconnects --- src/login/character.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/login/character.rs b/src/login/character.rs index 07c4873..2e98ad9 100644 --- a/src/login/character.rs +++ b/src/login/character.rs @@ -558,6 +558,7 @@ impl InterserverActor for CharacterServerState { } async fn on_disconnect(&mut self, id: ServerId) -> Vec<(ServerId, Self::SendMessage)> { + self.ships.remove(&id); Vec::new() } } From 05596cec4f20a987294b2dcdc19702ecabb1c52c Mon Sep 17 00:00:00 2001 From: jake Date: Tue, 27 Oct 2020 22:27:12 -0600 Subject: [PATCH 17/27] change serverstate on_connect and on_disconnect to async --- src/common/mainloop/client.rs | 4 ++-- src/common/serverstate.rs | 4 ++-- src/login/login.rs | 4 ++-- src/patch/patch.rs | 4 ++-- src/ship/ship.rs | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/common/mainloop/client.rs b/src/common/mainloop/client.rs index 9e91b81..d8f3af9 100644 --- a/src/common/mainloop/client.rs +++ b/src/common/mainloop/client.rs @@ -224,7 +224,7 @@ async fn state_client_loop(state: Arc>, match action { ClientAction::NewClient(client_id, sender) => { clients.insert(client_id, sender.clone()); - for action in state.on_connect(client_id) { + for action in state.on_connect(client_id).await { match action { OnConnect::Cipher((inc, outc)) => { sender.send(ServerStateAction::Cipher(inc, outc)).await; @@ -251,7 +251,7 @@ async fn state_client_loop(state: Arc>, } }, ClientAction::Disconnect(client_id) => { - let pkts = state.on_disconnect(client_id); + let pkts = state.on_disconnect(client_id).await; for (client_id, pkt) in pkts { if let Some(client) = clients.get_mut(&client_id) { client.send(ServerStateAction::Packet(pkt)).await; diff --git a/src/common/serverstate.rs b/src/common/serverstate.rs index f1573ae..d22c9c6 100644 --- a/src/common/serverstate.rs +++ b/src/common/serverstate.rs @@ -24,9 +24,9 @@ pub trait ServerState { type RecvPacket: RecvServerPacket; type PacketError; - fn on_connect(&mut self, id: ClientId) -> Vec>; + async fn on_connect(&mut self, id: ClientId) -> Vec>; async fn handle(&mut self, id: ClientId, pkt: &Self::RecvPacket) -> Result + Send>, Self::PacketError>; - fn on_disconnect(&mut self, id: ClientId) -> Vec<(ClientId, Self::SendPacket)>; + async fn on_disconnect(&mut self, id: ClientId) -> Vec<(ClientId, Self::SendPacket)>; } diff --git a/src/login/login.rs b/src/login/login.rs index 95e8b08..e2c8bc2 100644 --- a/src/login/login.rs +++ b/src/login/login.rs @@ -113,7 +113,7 @@ impl ServerState for LoginServerState { type RecvPacket = RecvLoginPacket; type PacketError = LoginError; - fn on_connect(&mut self, _id: ClientId) -> Vec> { + async fn on_connect(&mut self, _id: ClientId) -> Vec> { let mut rng = rand::thread_rng(); let mut server_key = [0u8; 48]; @@ -140,7 +140,7 @@ impl ServerState for LoginServerState { }) } - fn on_disconnect(&mut self, _id: ClientId) -> Vec<(ClientId, SendLoginPacket)> { + async fn on_disconnect(&mut self, _id: ClientId) -> Vec<(ClientId, SendLoginPacket)> { Vec::new() } } diff --git a/src/patch/patch.rs b/src/patch/patch.rs index b96616e..ec88b5c 100644 --- a/src/patch/patch.rs +++ b/src/patch/patch.rs @@ -160,7 +160,7 @@ impl ServerState for PatchServerState { type RecvPacket = RecvPatchPacket; type PacketError = PatchError; - fn on_connect(&mut self, _id: ClientId) -> Vec> { + async fn on_connect(&mut self, _id: ClientId) -> Vec> { let mut rng = rand::thread_rng(); let key_in: u32 = rng.gen(); let key_out: u32 = rng.gen(); @@ -202,7 +202,7 @@ impl ServerState for PatchServerState { }) } - fn on_disconnect(&mut self, _id: ClientId) -> Vec<(ClientId, SendPatchPacket)> { + async fn on_disconnect(&mut self, _id: ClientId) -> Vec<(ClientId, SendPatchPacket)> { Vec::new() } } diff --git a/src/ship/ship.rs b/src/ship/ship.rs index 0f51bc7..10cecac 100644 --- a/src/ship/ship.rs +++ b/src/ship/ship.rs @@ -456,7 +456,7 @@ impl ServerState for ShipServerState { type RecvPacket = RecvShipPacket; type PacketError = ShipError; - fn on_connect(&mut self, _id: ClientId) -> Vec> { + async fn on_connect(&mut self, _id: ClientId) -> Vec> { let mut rng = rand::thread_rng(); let mut server_key = [0u8; 48]; @@ -577,7 +577,7 @@ impl ServerState for ShipServerState { }) } - fn on_disconnect(&mut self, id: ClientId) -> Vec<(ClientId, SendShipPacket)> { + async fn on_disconnect(&mut self, id: ClientId) -> Vec<(ClientId, SendShipPacket)> { // TODO: don't unwrap! let client = self.clients.get(&id).unwrap(); let area_client = self.client_location.get_local_client(id).unwrap(); From c802bceb3c5a2548089b7ba0df2e534edb142731 Mon Sep 17 00:00:00 2001 From: jake Date: Tue, 27 Oct 2020 22:31:54 -0600 Subject: [PATCH 18/27] prevent double logins --- src/bin/main.rs | 1 - src/entity/account.rs | 29 ++++++++++- src/entity/gateway/inmemory.rs | 5 +- .../postgres/migrations/V0001__initial.sql | 5 +- src/entity/gateway/postgres/models.rs | 8 ++- src/login/character.rs | 26 ++++++++-- src/login/login.rs | 52 +++++++++++++++---- src/ship/packet/handler/auth.rs | 9 ++-- src/ship/ship.rs | 5 ++ tests/common.rs | 6 +-- 10 files changed, 118 insertions(+), 28 deletions(-) diff --git a/src/bin/main.rs b/src/bin/main.rs index 16af628..fcd99af 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -58,7 +58,6 @@ fn main() { team_id: None, banned_until: None, muted_until: None, - created_at: chrono::Utc::now(), flags: 0, activated: true, }; diff --git a/src/entity/account.rs b/src/entity/account.rs index 1276cf8..9727bc7 100644 --- a/src/entity/account.rs +++ b/src/entity/account.rs @@ -21,9 +21,24 @@ pub struct NewUserAccountEntity { pub team_id: Option, pub banned_until: Option>, pub muted_until: Option>, - pub created_at: chrono::DateTime, pub flags: u32, - pub activated: bool, + pub activated: bool +} + +impl Default for NewUserAccountEntity { + fn default() -> NewUserAccountEntity { + NewUserAccountEntity { + email: "".into(), + username: "".into(), + password: "".into(), + guildcard: 0xFFFFFFFF, + team_id: None, + banned_until: None, + muted_until: None, + flags: 0, + activated: false, + } + } } #[derive(Clone, Debug)] @@ -38,8 +53,18 @@ pub struct UserAccountEntity { pub created_at: chrono::DateTime, pub flags: u32, // TODO: is this used for anything other than character creation? pub activated: bool, + pub at_login: bool, + pub at_character: bool, + pub at_ship: bool, } +impl UserAccountEntity { + pub fn is_currently_online(&self) -> bool { + self.at_login | self.at_character | self.at_ship + } +} + + #[derive(Clone, Debug)] pub struct NewUserSettingsEntity { pub user_id: UserAccountId, diff --git a/src/entity/gateway/inmemory.rs b/src/entity/gateway/inmemory.rs index 6341638..89a47e2 100644 --- a/src/entity/gateway/inmemory.rs +++ b/src/entity/gateway/inmemory.rs @@ -45,9 +45,12 @@ impl EntityGateway for InMemoryGateway { team_id: user.team_id, banned_until: user.banned_until, muted_until: user.muted_until, - created_at: user.created_at, + 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) diff --git a/src/entity/gateway/postgres/migrations/V0001__initial.sql b/src/entity/gateway/postgres/migrations/V0001__initial.sql index 1e5a925..b4cd507 100644 --- a/src/entity/gateway/postgres/migrations/V0001__initial.sql +++ b/src/entity/gateway/postgres/migrations/V0001__initial.sql @@ -9,7 +9,10 @@ create table user_accounts ( flags integer default 0 not null, activated boolean default false not null, game_session integer, - interserver_session integer + interserver_session integer, + at_login boolean default false not null, + at_character boolean default false not null, + at_ship boolean default false not null ); create table user_settings ( diff --git a/src/entity/gateway/postgres/models.rs b/src/entity/gateway/postgres/models.rs index e1bbde5..b870da5 100644 --- a/src/entity/gateway/postgres/models.rs +++ b/src/entity/gateway/postgres/models.rs @@ -18,6 +18,9 @@ pub struct PgUserAccount { created_at: chrono::DateTime, flags: i32, activated: bool, + at_login: bool, + at_character: bool, + at_ship: bool, } impl Into for PgUserAccount { @@ -32,7 +35,10 @@ impl Into for PgUserAccount { flags: self.flags as u32, guildcard: self.id as u32 + 1, team_id: None, - activated: self.activated + activated: self.activated, + at_login: self.at_login, + at_character: self.at_character, + at_ship: self.at_ship, } } } diff --git a/src/login/character.rs b/src/login/character.rs index 2e98ad9..a855912 100644 --- a/src/login/character.rs +++ b/src/login/character.rs @@ -27,7 +27,7 @@ use crate::entity::item::tool::Tool; use crate::entity::item::mag::Mag; use crate::entity::character::{CharacterEntity, NewCharacterEntity, CharacterClass, TechLevel}; -use crate::login::login::get_login_status; +use crate::login::login::{get_login_status, check_if_already_online}; pub const CHARACTER_PORT: u16 = 12001; const SHIP_MENU_ID: u32 = 1; @@ -39,6 +39,7 @@ pub enum CharacterError { CouldNotLoadSettings, CouldNotLoadCharacters, CouldNotLoadGuildcard, + DbError, } #[derive(Debug)] @@ -280,8 +281,11 @@ impl CharacterServerState { async fn validate_login(&mut self, id: ClientId, pkt: &Login) -> Result, CharacterError> { let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?; - Ok(match get_login_status(&self.entity_gateway, pkt).await { - Ok(user) => { + Ok(match get_login_status(&self.entity_gateway, pkt).await.and_then(check_if_already_online) { + Ok(mut user) => { + user.at_character = true; + self.entity_gateway.save_user(&user).await.map_err(|_| CharacterError::DbError)?; + let mut response = LoginResponse::by_status(AccountStatus::Ok, Session::new()); response.guildcard = user.guildcard; response.team_id = user.team_id.map_or(0, |ti| ti) as u32; @@ -471,7 +475,7 @@ impl ServerState for CharacterServerState { type RecvPacket = RecvCharacterPacket; type PacketError = CharacterError; - fn on_connect(&mut self, id: ClientId) -> Vec> { + async fn on_connect(&mut self, id: ClientId) -> Vec> { self.clients.insert(id, ClientState::new()); let mut rng = rand::thread_rng(); @@ -531,7 +535,13 @@ impl ServerState for CharacterServerState { }) } - fn on_disconnect(&mut self, _id: ClientId) -> Vec<(ClientId, SendCharacterPacket)> { + async fn on_disconnect(&mut self, id: ClientId) -> Vec<(ClientId, SendCharacterPacket)> { + if let Some(client) = self.clients.remove(&id) { + if let Some(mut user) = client.user { + user.at_character= false; + self.entity_gateway.save_user(&user).await; + } + } Vec::new() } } @@ -684,6 +694,9 @@ mod test { team_id: None, flags: 0, activated: true, + at_login: false, + at_character: false, + at_ship: false, }); server.clients.insert(ClientId(5), clientstate); @@ -728,6 +741,9 @@ mod test { created_at: chrono::Utc::now(), flags: 0, activated: true, + at_login: false, + at_character: false, + at_ship: false, }); let mut server = CharacterServerState::new(test_data.clone()); diff --git a/src/login/login.rs b/src/login/login.rs index e2c8bc2..9bcb0c7 100644 --- a/src/login/login.rs +++ b/src/login/login.rs @@ -1,5 +1,6 @@ // TODO: rename this module to auth +use std::collections::HashMap; use std::net; use rand::Rng; @@ -21,6 +22,7 @@ pub const COMMUNICATION_PORT: u16 = 12123; #[derive(Debug)] pub enum LoginError { + DbError } @@ -61,6 +63,10 @@ pub async fn get_login_status(entity_gateway: &impl EntityGateway, pkt: &Login) 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).await.map_err(|_| AccountStatus::InvalidUser)?; + if user.is_currently_online() { + return Err(AccountStatus::AlreadyOnline) + } + if !user.activated { return Err(AccountStatus::PayUp) } @@ -77,10 +83,19 @@ pub async fn get_login_status(entity_gateway: &impl EntityGateway, pkt: &Login) } } +pub fn check_if_already_online(user: UserAccountEntity) -> Result { + if user.is_currently_online() { + Err(AccountStatus::PayUp) + } + else { + Ok(user) + } +} pub struct LoginServerState { character_server_ip: net::Ipv4Addr, entity_gateway: EG, + clients: HashMap, } impl LoginServerState { @@ -88,20 +103,24 @@ impl LoginServerState { LoginServerState { entity_gateway: entity_gateway, character_server_ip: character_server_ip.into(), + clients: HashMap::new(), } } - async fn validate_login(&mut self, pkt: &Login) -> Vec { - match get_login_status(&self.entity_gateway, pkt).await { - Ok(_user) => { + async fn validate_login(&mut self, id: ClientId, pkt: &Login) -> Result, LoginError> { + match get_login_status(&self.entity_gateway, pkt).await.and_then(check_if_already_online) { + Ok(mut user) => { + user.at_login = true; + self.entity_gateway.save_user(&user).await.map_err(|_| LoginError::DbError)?; + self.clients.insert(id, user.username.clone()); + let response = SendLoginPacket::LoginResponse(LoginResponse::by_status(AccountStatus::Ok, pkt.session)); - //let ip = net::Ipv4Addr::new(127,0,0,1); let ip = u32::from_ne_bytes(self.character_server_ip.octets()); - vec![response, - SendLoginPacket::RedirectClient(RedirectClient::new(ip, crate::login::character::CHARACTER_PORT))] + Ok(vec![response, + SendLoginPacket::RedirectClient(RedirectClient::new(ip, crate::login::character::CHARACTER_PORT))]) }, Err(err) => { - vec![SendLoginPacket::LoginResponse(LoginResponse::by_status(err, pkt.session))] + Ok(vec![SendLoginPacket::LoginResponse(LoginResponse::by_status(err, pkt.session))]) } } } @@ -131,7 +150,7 @@ impl ServerState for LoginServerState { -> Result + Send>, LoginError> { Ok(match pkt { RecvLoginPacket::Login(login) => { - Box::new(self.validate_login(login).await + Box::new(self.validate_login(id, login).await? .into_iter() .map(move |pkt| { (id, pkt) @@ -140,7 +159,13 @@ impl ServerState for LoginServerState { }) } - async fn on_disconnect(&mut self, _id: ClientId) -> Vec<(ClientId, SendLoginPacket)> { + async fn on_disconnect(&mut self, id: ClientId) -> Vec<(ClientId, SendLoginPacket)> { + if let Some(username) = self.clients.remove(&id) { + if let Ok(mut user) = self.entity_gateway.get_user_by_name(username).await { + user.at_login = false; + self.entity_gateway.save_user(&user).await; + } + } Vec::new() } } @@ -197,6 +222,9 @@ mod test { created_at: chrono::Utc::now(), flags: 0, activated: true, + at_login: false, + at_character: false, + at_ship: false, }) } }; @@ -282,6 +310,9 @@ mod test { created_at: chrono::Utc::now(), flags: 0, activated: true, + at_login: false, + at_character: false, + at_ship: false, }) } } @@ -328,6 +359,9 @@ mod test { created_at: chrono::Utc::now(), flags: 0, activated: true, + at_login: false, + at_character: false, + at_ship: false, }) } } diff --git a/src/ship/packet/handler/auth.rs b/src/ship/packet/handler/auth.rs index 9617998..c389c6c 100644 --- a/src/ship/packet/handler/auth.rs +++ b/src/ship/packet/handler/auth.rs @@ -2,7 +2,7 @@ use libpso::packet::login::{Login, LoginResponse, AccountStatus, Session}; use libpso::packet::ship::*; use crate::common::serverstate::ClientId; use crate::ship::ship::{SendShipPacket, ShipError, ClientState, Clients}; -use crate::login::login::get_login_status; +use crate::login::login::{get_login_status, check_if_already_online}; use crate::entity::gateway::EntityGateway; use crate::ship::items::ItemManager; @@ -13,8 +13,11 @@ pub async fn validate_login(id: ClientId, item_manager: &mut ItemManager, ship_name: &String) -> Result, ShipError> { - Ok(match get_login_status(entity_gateway, pkt).await { - Ok(user) => { + Ok(match get_login_status(entity_gateway, pkt).await.and_then(check_if_already_online) { + Ok(mut user) => { + user.at_ship= true; + entity_gateway.save_user(&user).await?; + let mut response = LoginResponse::by_status(AccountStatus::Ok, Session::new()); response.guildcard = user.id.0 as u32; response.team_id = user.team_id.map_or(31, |ti| ti) as u32; diff --git a/src/ship/ship.rs b/src/ship/ship.rs index 10cecac..1c5830b 100644 --- a/src/ship/ship.rs +++ b/src/ship/ship.rs @@ -600,6 +600,11 @@ impl ServerState for ShipServerState { self.client_location.remove_client_from_area(id); self.item_manager.remove_character_from_room(&client.character); + if let Some(mut client) = self.clients.remove(&id) { + client.user.at_ship = false; + self.entity_gateway.save_user(&client.user).await; + } + neighbors.into_iter().map(|n| { (n.client, pkt.clone()) }).collect() diff --git a/tests/common.rs b/tests/common.rs index 0b66360..7e7c925 100644 --- a/tests/common.rs +++ b/tests/common.rs @@ -18,12 +18,8 @@ pub async fn new_user_character(entity_gateway: &mut EG, user username: username.into(), password: bcrypt::hash(password, 5).unwrap(), guildcard: 1, - team_id: None, - banned_until: None, - muted_until: None, - created_at: chrono::Utc::now(), - flags: 0, activated: true, + ..NewUserAccountEntity::default() }; let user = entity_gateway.create_user(new_user).await.unwrap(); From 01fe0931b168ec0dac51c9a29391f9e3dd978d52 Mon Sep 17 00:00:00 2001 From: jake Date: Thu, 29 Oct 2020 19:09:22 -0600 Subject: [PATCH 19/27] make itementity serializable --- src/entity/item/armor.rs | 4 ++-- src/entity/item/esweapon.rs | 2 +- src/entity/item/mag.rs | 4 ++-- src/entity/item/mod.rs | 5 +++-- src/entity/item/shield.rs | 2 +- src/entity/item/tool.rs | 2 +- src/entity/item/unit.rs | 2 +- src/entity/item/weapon.rs | 10 +++++----- 8 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/entity/item/armor.rs b/src/entity/item/armor.rs index 48e41ee..c3cefb5 100644 --- a/src/entity/item/armor.rs +++ b/src/entity/item/armor.rs @@ -289,7 +289,7 @@ impl ArmorType { } -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub enum ArmorModifier { AddSlot { addslot: ItemEntityId, @@ -297,7 +297,7 @@ pub enum ArmorModifier { } -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct Armor { pub armor: ArmorType, pub dfp: u8, diff --git a/src/entity/item/esweapon.rs b/src/entity/item/esweapon.rs index 3251924..c8713db 100644 --- a/src/entity/item/esweapon.rs +++ b/src/entity/item/esweapon.rs @@ -169,7 +169,7 @@ impl ESWeaponSpecial { } } -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ESWeapon { pub esweapon: ESWeaponType, pub special: Option, diff --git a/src/entity/item/mag.rs b/src/entity/item/mag.rs index 2087036..55222c8 100644 --- a/src/entity/item/mag.rs +++ b/src/entity/item/mag.rs @@ -519,7 +519,7 @@ pub enum MagModifier { OwnerChange(CharacterClass, SectionID) } -#[derive(Debug, Copy, Clone, PartialEq, Deserialize, enum_utils::FromStr)] +#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize, enum_utils::FromStr)] pub enum PhotonBlast { Farlla, Estlla, @@ -529,7 +529,7 @@ pub enum PhotonBlast { MyllaYoulla, } -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct Mag { pub mag: MagType, def: u16, diff --git a/src/entity/item/mod.rs b/src/entity/item/mod.rs index 165f207..d3629cc 100644 --- a/src/entity/item/mod.rs +++ b/src/entity/item/mod.rs @@ -8,11 +8,12 @@ pub mod unit; pub mod mag; pub mod esweapon; +use serde::{Serialize, Deserialize}; use crate::entity::character::CharacterEntityId; use crate::ship::map::MapArea; use crate::ship::drops::ItemDropType; -#[derive(PartialEq, Copy, Clone, Debug, Hash, Eq, PartialOrd, Ord)] +#[derive(PartialEq, Copy, Clone, Debug, Hash, Eq, PartialOrd, Ord, Serialize, Deserialize)] pub struct ItemEntityId(pub u32); #[derive(Hash, PartialEq, Eq, Debug, Clone)] pub struct ItemId(u32); @@ -88,7 +89,7 @@ pub enum ItemParseError { InvalidBytes } -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub enum ItemDetail { Weapon(weapon::Weapon), Armor(armor::Armor), diff --git a/src/entity/item/shield.rs b/src/entity/item/shield.rs index 29ce984..6e69b43 100644 --- a/src/entity/item/shield.rs +++ b/src/entity/item/shield.rs @@ -519,7 +519,7 @@ impl ShieldType { } -#[derive(Debug, Copy, Clone, PartialEq)] +#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)] pub struct Shield { pub shield: ShieldType, pub dfp: u8, diff --git a/src/entity/item/tool.rs b/src/entity/item/tool.rs index 5b95dde..09ef9a5 100644 --- a/src/entity/item/tool.rs +++ b/src/entity/item/tool.rs @@ -648,7 +648,7 @@ impl ToolType { } -#[derive(Copy, Clone, Debug, PartialEq)] +#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct Tool { pub tool: ToolType, } diff --git a/src/entity/item/unit.rs b/src/entity/item/unit.rs index 477c422..3e2de42 100644 --- a/src/entity/item/unit.rs +++ b/src/entity/item/unit.rs @@ -331,7 +331,7 @@ pub enum UnitModifier { MinusMinus, } -#[derive(Debug, Copy, Clone, PartialEq)] +#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)] pub struct Unit { pub unit: UnitType, pub modifier: Option, diff --git a/src/entity/item/weapon.rs b/src/entity/item/weapon.rs index 3953da3..a692677 100644 --- a/src/entity/item/weapon.rs +++ b/src/entity/item/weapon.rs @@ -32,7 +32,7 @@ impl Attribute { } } -#[derive(Debug, Copy, Clone, PartialEq)] +#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)] pub struct WeaponAttribute { pub attr: Attribute, pub value: i8, @@ -1332,14 +1332,14 @@ impl WeaponType { } -#[derive(Debug, Copy, Clone, PartialEq)] +#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)] pub enum TekSpecialModifier { Plus, Neutral, Minus, } -#[derive(Debug, Copy, Clone, PartialEq)] +#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)] pub enum TekPercentModifier { PlusPlus, Plus, @@ -1348,7 +1348,7 @@ pub enum TekPercentModifier { MinusMinus, } -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub enum WeaponModifier { AddPercents { attr: WeaponAttribute, @@ -1364,7 +1364,7 @@ pub enum WeaponModifier { }, } -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct Weapon { pub weapon: WeaponType, pub special: Option, From cae89cd2ac6a61a23545e81c257697b991a96a24 Mon Sep 17 00:00:00 2001 From: jake Date: Thu, 29 Oct 2020 19:34:09 -0600 Subject: [PATCH 20/27] get_items_by_character takes character id not character entity --- src/entity/gateway/entitygateway.rs | 2 +- src/entity/gateway/inmemory.rs | 6 ++--- src/entity/gateway/postgres/postgres.rs | 4 ++-- src/ship/items/manager.rs | 2 +- tests/test_bank.rs | 32 ++++++++++++------------- tests/test_item_pickup.rs | 22 ++++++++--------- tests/test_item_use.rs | 10 ++++---- tests/test_mags.rs | 6 ++--- tests/test_shops.rs | 16 ++++++------- 9 files changed, 50 insertions(+), 50 deletions(-) diff --git a/src/entity/gateway/entitygateway.rs b/src/entity/gateway/entitygateway.rs index 7a28563..ee6c1fa 100644 --- a/src/entity/gateway/entitygateway.rs +++ b/src/entity/gateway/entitygateway.rs @@ -85,7 +85,7 @@ pub trait EntityGateway: Send + Sync + Clone { unimplemented!(); } - async fn get_items_by_character(&self, _char: &CharacterEntity) -> Result, GatewayError> { + async fn get_items_by_character(&self, _char_id: &CharacterEntityId) -> Result, GatewayError> { unimplemented!(); } } diff --git a/src/entity/gateway/inmemory.rs b/src/entity/gateway/inmemory.rs index 89a47e2..12d25e7 100644 --- a/src/entity/gateway/inmemory.rs +++ b/src/entity/gateway/inmemory.rs @@ -205,14 +205,14 @@ impl EntityGateway for InMemoryGateway { Ok(()) } - async fn get_items_by_character(&self, character: &CharacterEntity) -> Result, GatewayError> { + async fn get_items_by_character(&self, character_id: &CharacterEntityId) -> Result, GatewayError> { let items = self.items.lock().unwrap(); Ok(items .iter() .filter(|(_, k)| { match k.location { - ItemLocation::Inventory{character_id, ..} => character_id == character.id, - ItemLocation::Bank{character_id, ..} => character_id == character.id, + ItemLocation::Inventory{character_id, ..} => character_id == character_id, + ItemLocation::Bank{character_id, ..} => character_id == character_id, _ => false } }) diff --git a/src/entity/gateway/postgres/postgres.rs b/src/entity/gateway/postgres/postgres.rs index 965bcf4..5318cc2 100644 --- a/src/entity/gateway/postgres/postgres.rs +++ b/src/entity/gateway/postgres/postgres.rs @@ -364,7 +364,7 @@ impl EntityGateway for PostgresGateway { Ok(()) } - async fn get_items_by_character(&self, char: &CharacterEntity) -> Result, GatewayError> { + async fn get_items_by_character(&self, char_id: &CharacterEntityId) -> Result, GatewayError> { let q = r#"select * from ( select distinct on (item_location.item) item.id, @@ -384,7 +384,7 @@ impl EntityGateway for PostgresGateway { or cast (location -> 'Bank' ->> 'character_id' as integer) = $1 "#; let items = sqlx::query_as::<_, PgItemWithLocation>(q) - .bind(char.id.0) + .bind(char_id.0) .fetch(&self.pool); Ok(join_all(items .filter_map(|item: Result| { diff --git a/src/ship/items/manager.rs b/src/ship/items/manager.rs index dbd91fe..ce80e77 100644 --- a/src/ship/items/manager.rs +++ b/src/ship/items/manager.rs @@ -116,7 +116,7 @@ impl ItemManager { // TODO: Result pub async fn load_character(&mut self, entity_gateway: &mut EG, character: &CharacterEntity) -> Result<(), ItemManagerError> { - let items = entity_gateway.get_items_by_character(&character).await?; + let items = entity_gateway.get_items_by_character(&character.id).await?; let inventory_items = items.clone().into_iter() .filter_map(|item| { match item.location { diff --git a/tests/test_bank.rs b/tests/test_bank.rs index 08bb984..7add54c 100644 --- a/tests/test_bank.rs +++ b/tests/test_bank.rs @@ -295,7 +295,7 @@ async fn test_deposit_individual_item() { && player_no_longer_has_item.amount == 0 )); - let items = entity_gateway.get_items_by_character(&char1).await.unwrap(); + let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap(); let bank_item_ids = items.iter() .filter_map(|item| { if let item::ItemLocation::Bank {..} = item.location { @@ -364,7 +364,7 @@ async fn test_deposit_stacked_item() { && player_no_longer_has_item.amount == 3 )); - let items = entity_gateway.get_items_by_character(&char1).await.unwrap(); + let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap(); let bank_item_ids = items.iter() .filter_map(|item| { if let item::ItemLocation::Bank {..} = item.location { @@ -433,7 +433,7 @@ async fn test_deposit_partial_stacked_item() { && player_no_longer_has_item.amount == 2 )); - let items = entity_gateway.get_items_by_character(&char1).await.unwrap(); + let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap(); let bank_item_ids = items.iter() .filter_map(|item| { if let item::ItemLocation::Bank {..} = item.location { @@ -528,7 +528,7 @@ async fn test_deposit_stacked_item_with_stack_already_in_bank() { && player_no_longer_has_item.amount == 2 )); - let items = entity_gateway.get_items_by_character(&char1).await.unwrap(); + let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap(); let bank_item_ids = items.iter() .filter_map(|item| { if let item::ItemLocation::Bank {..} = item.location { @@ -604,7 +604,7 @@ async fn test_deposit_stacked_item_with_full_stack_in_bank() { assert!(packets.is_err()); - let items = entity_gateway.get_items_by_character(&char1).await.unwrap(); + let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap(); let bank_item_ids = items.iter() .filter_map(|item| { if let item::ItemLocation::Bank {..} = item.location { @@ -700,7 +700,7 @@ async fn test_deposit_individual_item_in_full_bank() { assert!(packets.is_err()); - let items = entity_gateway.get_items_by_character(&char1).await.unwrap(); + let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap(); let bank_item_ids = items.iter() .filter_map(|item| { if let item::ItemLocation::Bank {..} = item.location { @@ -793,7 +793,7 @@ async fn test_deposit_stacked_item_in_full_bank() { assert!(packets.is_err()); - let items = entity_gateway.get_items_by_character(&char1).await.unwrap(); + let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap(); let bank_item_ids = items.iter() .filter_map(|item| { if let item::ItemLocation::Bank {..} = item.location { @@ -899,7 +899,7 @@ async fn test_deposit_stacked_item_in_full_bank_with_partial_stack() { unknown: 0, })))).await.unwrap().for_each(drop); - let items = entity_gateway.get_items_by_character(&char1).await.unwrap(); + let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap(); let bank_item_ids = items.iter() .filter_map(|item| { if let item::ItemLocation::Bank {..} = item.location { @@ -1096,7 +1096,7 @@ async fn test_withdraw_individual_item() { if create_item.item_id == 0x20000 )); - let items = entity_gateway.get_items_by_character(&char1).await.unwrap(); + let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap(); let inventory_item_ids = items.iter() .filter_map(|item| { if let item::ItemLocation::Inventory{..} = item.location { @@ -1163,7 +1163,7 @@ async fn test_withdraw_stacked_item() { if create_item.item_id == 0x10002 )); - let items = entity_gateway.get_items_by_character(&char1).await.unwrap(); + let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap(); let inventory_item_ids = items.iter() .filter_map(|item| { if let item::ItemLocation::Inventory {..} = item.location { @@ -1230,7 +1230,7 @@ async fn test_withdraw_partial_stacked_item() { if create_item.item_id == 0x10002 )); - let items = entity_gateway.get_items_by_character(&char1).await.unwrap(); + let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap(); let bank_item_ids = items.iter() .filter_map(|item| { if let item::ItemLocation::Bank {..} = item.location { @@ -1323,7 +1323,7 @@ async fn test_withdraw_stacked_item_with_stack_already_in_inventory() { if create_item.item_id == 0x10000 )); - let items = entity_gateway.get_items_by_character(&char1).await.unwrap(); + let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap(); let inventory_item_ids = items.iter() .filter_map(|item| { if let item::ItemLocation::Inventory {..} = item.location { @@ -1399,7 +1399,7 @@ async fn test_withdraw_stacked_item_with_full_stack_in_inventory() { assert!(packets.is_err()); - let items = entity_gateway.get_items_by_character(&char1).await.unwrap(); + let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap(); let bank_item_ids = items.iter() .filter_map(|item| { if let item::ItemLocation::Bank {..} = item.location { @@ -1495,7 +1495,7 @@ async fn test_withdraw_individual_item_in_full_inventory() { assert!(packets.is_err()); - let items = entity_gateway.get_items_by_character(&char1).await.unwrap(); + let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap(); let bank_item_ids = items.iter() .filter_map(|item| { if let item::ItemLocation::Bank {..} = item.location { @@ -1588,7 +1588,7 @@ async fn test_withdraw_stacked_item_in_full_inventory() { assert!(packets.is_err()); - let items = entity_gateway.get_items_by_character(&char1).await.unwrap(); + let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap(); let bank_item_ids = items.iter() .filter_map(|item| { if let item::ItemLocation::Bank {..} = item.location { @@ -1695,7 +1695,7 @@ async fn test_withdraw_stacked_item_in_full_inventory_with_partial_stack() { unknown: 0, })))).await.unwrap().for_each(drop); - let items = entity_gateway.get_items_by_character(&char1).await.unwrap(); + let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap(); let bank_item_ids = items.iter() .filter_map(|item| { if let item::ItemLocation::Bank {..} = item.location { diff --git a/tests/test_item_pickup.rs b/tests/test_item_pickup.rs index ec77f62..51f1d47 100644 --- a/tests/test_item_pickup.rs +++ b/tests/test_item_pickup.rs @@ -80,7 +80,7 @@ async fn test_pick_up_item_stack_of_items_already_in_inventory() { unknown: [0; 3] })))).await.unwrap().for_each(drop); - let p1_items = entity_gateway.get_items_by_character(&char1).await.unwrap(); + let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap(); assert!(p1_items.len() == 6); let p1_item_ids = p1_items.iter().map(|item| { @@ -149,7 +149,7 @@ async fn test_pick_up_item_stack_of_items_not_already_held() { unknown: [0; 3] })))).await.unwrap().for_each(drop); - let p1_items = entity_gateway.get_items_by_character(&char1).await.unwrap(); + let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap(); assert!(p1_items.len() == 1); let first_item = p1_items.get(0).unwrap(); @@ -227,7 +227,7 @@ async fn test_pick_up_meseta_when_inventory_full() { unknown: [0; 3] })))).await.unwrap().for_each(drop); - let p1_items = entity_gateway.get_items_by_character(&char1).await.unwrap(); + let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap(); assert!(p1_items.len() == 30); let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap(); @@ -324,7 +324,7 @@ async fn test_pick_up_partial_stacked_item_when_inventory_is_otherwise_full() { unknown: [0; 3] })))).await.unwrap().for_each(drop); - let p1_items = entity_gateway.get_items_by_character(&char1).await.unwrap(); + let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap(); assert!(p1_items.len() == 31); let monomate1 = p1_items.get(29).unwrap(); @@ -415,10 +415,10 @@ async fn test_can_not_pick_up_item_when_inventory_full() { unknown: [0; 3] })))).await.unwrap().for_each(drop); - let p1_items = entity_gateway.get_items_by_character(&char1).await.unwrap(); + let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap(); assert!(p1_items.len() == 30); - let p2_items = entity_gateway.get_items_by_character(&char2).await.unwrap(); + let p2_items = entity_gateway.get_items_by_character(&char2.id).await.unwrap(); assert!(p2_items.len() == 0); ship.handle(ClientId(2), &RecvShipPacket::DirectMessage(DirectMessage::new(0, GameMessage::PickupItem(PickupItem { @@ -429,7 +429,7 @@ async fn test_can_not_pick_up_item_when_inventory_full() { unknown: [0; 3] })))).await.unwrap().for_each(drop); - let p2_items = entity_gateway.get_items_by_character(&char2).await.unwrap(); + let p2_items = entity_gateway.get_items_by_character(&char2.id).await.unwrap(); assert!(p2_items.len() == 1); } @@ -544,10 +544,10 @@ async fn test_pick_up_stack_that_would_exceed_stack_limit() { })))).await.unwrap().collect::>(); assert!(packets.len() == 0); - let p1_items = entity_gateway.get_items_by_character(&char1).await.unwrap(); + let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap(); assert!(p1_items.len() == 6); - let p2_items = entity_gateway.get_items_by_character(&char2).await.unwrap(); + let p2_items = entity_gateway.get_items_by_character(&char2.id).await.unwrap(); assert!(p2_items.len() == 0); } @@ -726,7 +726,7 @@ async fn test_player_drops_partial_stack_and_other_player_picks_it_up() { unknown: [0; 3] })))).await.unwrap().for_each(drop); - let p1_items = entity_gateway.get_items_by_character(&char1).await.unwrap(); + let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap(); assert!(p1_items.len() == 3); let p1_item_ids = p1_items.iter().map(|item| { @@ -742,7 +742,7 @@ async fn test_player_drops_partial_stack_and_other_player_picks_it_up() { }); assert!(all_items_are_monomates); - let p2_items = entity_gateway.get_items_by_character(&char2).await.unwrap(); + let p2_items = entity_gateway.get_items_by_character(&char2.id).await.unwrap(); assert!(p2_items.len() == 2); let p2_item_ids = p2_items.iter().map(|item| { diff --git a/tests/test_item_use.rs b/tests/test_item_use.rs index f1cff0b..bdee01f 100644 --- a/tests/test_item_use.rs +++ b/tests/test_item_use.rs @@ -49,7 +49,7 @@ async fn test_use_monomate() { item_id: 0x10000, })))).await.unwrap().for_each(drop); - let items = entity_gateway.get_items_by_character(&char1).await.unwrap(); + let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap(); assert!(items.iter().filter(|item| { if let item::ItemDetail::Tool(t) = item.item { t.tool == item::tool::ToolType::Monomate @@ -110,7 +110,7 @@ async fn test_use_monomate_twice() { item_id: 0x10000, })))).await.unwrap().for_each(drop); - let items = entity_gateway.get_items_by_character(&char1).await.unwrap(); + let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap(); assert!(items.iter().filter(|item| { if let item::ItemDetail::Tool(t) = item.item { t.tool == item::tool::ToolType::Monomate @@ -166,7 +166,7 @@ async fn test_use_last_monomate() { item_id: 0x10000, })))).await.unwrap().for_each(drop); - let items = entity_gateway.get_items_by_character(&char1).await.unwrap(); + let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap(); assert!(items.iter().filter(|item| { if let item::ItemDetail::Tool(t) = item.item { t.tool == item::tool::ToolType::Monomate @@ -218,7 +218,7 @@ async fn test_use_nonstackable_tool() { item_id: 0x10000, })))).await.unwrap().for_each(drop); - let items = entity_gateway.get_items_by_character(&char1).await.unwrap(); + let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap(); assert!(items.len() == 0); } @@ -269,7 +269,7 @@ async fn test_use_materials() { item_id: 0x10001, })))).await.unwrap().for_each(drop); - let items = entity_gateway.get_items_by_character(&char1).await.unwrap(); + let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap(); assert!(items.iter().filter(|item| { if let item::ItemDetail::Tool(t) = item.item { t.tool == item::tool::ToolType::PowerMaterial diff --git a/tests/test_mags.rs b/tests/test_mags.rs index f1b628d..a0f6fe8 100644 --- a/tests/test_mags.rs +++ b/tests/test_mags.rs @@ -60,7 +60,7 @@ async fn test_mag_feed() { })))).await.unwrap().for_each(drop); } - let p1_items = entity_gateway.get_items_by_character(&char1).await.unwrap(); + let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap(); let mag = p1_items.get(0).unwrap(); match &mag.item { item::ItemDetail::Mag(mag) => { @@ -128,7 +128,7 @@ async fn test_mag_change_owner() { unknown: [0; 3] })))).await.unwrap().for_each(drop); - let p2_items = entity_gateway.get_items_by_character(&char2).await.unwrap(); + let p2_items = entity_gateway.get_items_by_character(&char2.id).await.unwrap(); let mag = p2_items.get(0).unwrap(); match &mag.item { item::ItemDetail::Mag(mag) => { @@ -199,7 +199,7 @@ async fn test_mag_cell() { item_id: 0x10001, })))).await.unwrap().for_each(drop); - let p1_items = entity_gateway.get_items_by_character(&char1).await.unwrap(); + let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap(); let mag = p1_items.get(0).unwrap(); match &mag.item { item::ItemDetail::Mag(mag) => { diff --git a/tests/test_shops.rs b/tests/test_shops.rs index 74c4a33..0574947 100644 --- a/tests/test_shops.rs +++ b/tests/test_shops.rs @@ -135,7 +135,7 @@ async fn test_player_buys_from_weapon_shop() { let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap(); let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap(); assert!(c1.meseta < 999999); - let p1_items = entity_gateway.get_items_by_character(&char1).await.unwrap(); + let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap(); assert_eq!(p1_items.len(), 1); } @@ -173,7 +173,7 @@ async fn test_player_buys_from_tool_shop() { let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap(); let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap(); assert!(c1.meseta < 999999); - let p1_items = entity_gateway.get_items_by_character(&char1).await.unwrap(); + let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap(); assert_eq!(p1_items.len(), 1); } @@ -211,7 +211,7 @@ async fn test_player_buys_multiple_from_tool_shop() { let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap(); let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap(); assert!(c1.meseta < 999999); - let p1_items = entity_gateway.get_items_by_character(&char1).await.unwrap(); + let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap(); assert_eq!(p1_items.len(), 5); } @@ -249,7 +249,7 @@ async fn test_player_buys_from_armor_shop() { let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap(); let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap(); assert!(c1.meseta < 999999); - let p1_items = entity_gateway.get_items_by_character(&char1).await.unwrap(); + let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap(); assert_eq!(p1_items.len(), 1); } @@ -388,7 +388,7 @@ async fn test_buying_item_without_enough_mseseta() { let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap(); let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap(); assert_eq!(c1.meseta, 0); - let p1_items = entity_gateway.get_items_by_character(&char1).await.unwrap(); + let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap(); assert_eq!(p1_items.len(), 0); } @@ -444,7 +444,7 @@ async fn test_player_double_buys_from_tool_shop() { let characters1 = entity_gateway.get_characters_by_user(&user1).await.unwrap(); let c1 = characters1.get(0).as_ref().unwrap().as_ref().unwrap(); assert!(c1.meseta < 999999); - let p1_items = entity_gateway.get_items_by_character(&char1).await.unwrap(); + let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap(); assert_eq!(p1_items.len(), 9); } @@ -502,7 +502,7 @@ async fn test_techs_disappear_from_shop_when_bought() { unknown1: 0, })))).await.unwrap().for_each(drop); - let p1_items = entity_gateway.get_items_by_character(&char1).await.unwrap(); + let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap(); assert!(p1_items[0].item != p1_items[1].item); } @@ -560,6 +560,6 @@ async fn test_units_disappear_from_shop_when_bought() { unknown1: 0, })))).await.unwrap().for_each(drop); - let p1_items = entity_gateway.get_items_by_character(&char1).await.unwrap(); + let p1_items = entity_gateway.get_items_by_character(&char1.id).await.unwrap(); assert!(p1_items[0].item != p1_items[1].item); } From 66d25ed15533a80f65dba1ebfe628bb40477af7f Mon Sep 17 00:00:00 2001 From: jake Date: Thu, 29 Oct 2020 19:40:43 -0600 Subject: [PATCH 21/27] fix name shadowing --- src/entity/gateway/inmemory.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/entity/gateway/inmemory.rs b/src/entity/gateway/inmemory.rs index 12d25e7..602d869 100644 --- a/src/entity/gateway/inmemory.rs +++ b/src/entity/gateway/inmemory.rs @@ -205,14 +205,14 @@ impl EntityGateway for InMemoryGateway { Ok(()) } - async fn get_items_by_character(&self, character_id: &CharacterEntityId) -> Result, GatewayError> { + async fn get_items_by_character(&self, char_id: &CharacterEntityId) -> Result, GatewayError> { let items = self.items.lock().unwrap(); Ok(items .iter() .filter(|(_, k)| { match k.location { - ItemLocation::Inventory{character_id, ..} => character_id == character_id, - ItemLocation::Bank{character_id, ..} => character_id == character_id, + ItemLocation::Inventory{character_id, ..} => character_id == *char_id, + ItemLocation::Bank{character_id, ..} => character_id == *char_id, _ => false } }) From 99cc651fd9a2ea6733637f8ebb3b0d66b7cbe412 Mon Sep 17 00:00:00 2001 From: jake Date: Thu, 29 Oct 2020 22:10:28 -0600 Subject: [PATCH 22/27] add enumiter to item types --- Cargo.toml | 2 ++ src/entity/item/armor.rs | 2 +- src/entity/item/esweapon.rs | 4 ++-- src/entity/item/mag.rs | 2 +- src/entity/item/shield.rs | 2 +- src/entity/item/tech.rs | 2 +- src/entity/item/tool.rs | 2 +- src/entity/item/unit.rs | 2 +- src/entity/item/weapon.rs | 4 ++-- 9 files changed, 12 insertions(+), 10 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 52c528e..ccd7a08 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,4 +32,6 @@ lazy_static = "1.4.0" barrel = { version = "0.6.5", features = ["pg"] } refinery = { version = "0.3.0", features = ["postgres"] } sqlx = { version = "0.4.0-beta.1", features = ["postgres", "json", "chrono"] } +strum = "0.19.5" +strum_macros = "0.19" diff --git a/src/entity/item/armor.rs b/src/entity/item/armor.rs index c3cefb5..a87c974 100644 --- a/src/entity/item/armor.rs +++ b/src/entity/item/armor.rs @@ -7,7 +7,7 @@ pub enum ItemParseError { InvalidArmorType, } -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, enum_utils::FromStr, derive_more::Display)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, enum_utils::FromStr, derive_more::Display, strum_macros::EnumIter)] pub enum ArmorType { Frame, Armor, diff --git a/src/entity/item/esweapon.rs b/src/entity/item/esweapon.rs index c8713db..ace5ec1 100644 --- a/src/entity/item/esweapon.rs +++ b/src/entity/item/esweapon.rs @@ -9,7 +9,7 @@ pub enum ItemParseError { InvalidESWeaponName, } -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, strum_macros::EnumIter)] pub enum ESWeaponType { Saber = 0, Sword, @@ -121,7 +121,7 @@ impl ESWeaponType { } } -#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, strum_macros::EnumIter)] pub enum ESWeaponSpecial { Jellen = 1, Zalure, diff --git a/src/entity/item/mag.rs b/src/entity/item/mag.rs index 55222c8..0cb0384 100644 --- a/src/entity/item/mag.rs +++ b/src/entity/item/mag.rs @@ -64,7 +64,7 @@ pub enum ItemParseError { InvalidMagBytes, } -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, enum_utils::FromStr, derive_more::Display)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, enum_utils::FromStr, derive_more::Display, strum_macros::EnumIter)] pub enum MagType { Mag, Varuna, diff --git a/src/entity/item/shield.rs b/src/entity/item/shield.rs index 6e69b43..852e3a0 100644 --- a/src/entity/item/shield.rs +++ b/src/entity/item/shield.rs @@ -6,7 +6,7 @@ pub enum ItemParseError { InvalidShieldType, } -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, enum_utils::FromStr, derive_more::Display)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, enum_utils::FromStr, derive_more::Display, strum_macros::EnumIter)] pub enum ShieldType { Barrier, Shield, diff --git a/src/entity/item/tech.rs b/src/entity/item/tech.rs index 0403afa..49882fc 100644 --- a/src/entity/item/tech.rs +++ b/src/entity/item/tech.rs @@ -1,7 +1,7 @@ use serde::{Serialize, Deserialize}; -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, enum_utils::FromStr, derive_more::Display)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, enum_utils::FromStr, derive_more::Display, strum_macros::EnumIter)] pub enum Technique { Foie, Gifoie, diff --git a/src/entity/item/tool.rs b/src/entity/item/tool.rs index 09ef9a5..707b61b 100644 --- a/src/entity/item/tool.rs +++ b/src/entity/item/tool.rs @@ -6,7 +6,7 @@ pub enum ItemParseError { InvalidToolType, } -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, enum_utils::FromStr, derive_more::Display)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, enum_utils::FromStr, derive_more::Display, strum_macros::EnumIter)] pub enum ToolType { Monomate, Dimate, diff --git a/src/entity/item/unit.rs b/src/entity/item/unit.rs index 3e2de42..e7731fc 100644 --- a/src/entity/item/unit.rs +++ b/src/entity/item/unit.rs @@ -6,7 +6,7 @@ pub enum ItemParseError { InvalidUnitType, } -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, enum_utils::FromStr, derive_more::Display)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, enum_utils::FromStr, derive_more::Display, strum_macros::EnumIter)] pub enum UnitType { KnightPower, GeneralPower, diff --git a/src/entity/item/weapon.rs b/src/entity/item/weapon.rs index a692677..3b70e4a 100644 --- a/src/entity/item/weapon.rs +++ b/src/entity/item/weapon.rs @@ -45,7 +45,7 @@ impl WeaponAttribute { } -#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)] +#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize, strum_macros::EnumIter)] pub enum WeaponSpecial { Draw = 1, Drain, @@ -141,7 +141,7 @@ impl WeaponSpecial { } } -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, enum_utils::FromStr, derive_more::Display)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, enum_utils::FromStr, derive_more::Display, strum_macros::EnumIter)] pub enum WeaponType { Saber, Brand, From bacf30997844dec197a28a1e380f0401db630653 Mon Sep 17 00:00:00 2001 From: jake Date: Fri, 30 Oct 2020 21:20:03 -0600 Subject: [PATCH 23/27] on_connect/on_disconnect return results --- src/common/mainloop/client.rs | 43 +++++++++++++++++-------- src/common/serverstate.rs | 4 +-- src/entity/gateway/postgres/postgres.rs | 2 +- src/login/character.rs | 10 +++--- src/login/login.rs | 10 +++--- src/patch/patch.rs | 10 +++--- src/ship/ship.rs | 12 +++---- 7 files changed, 53 insertions(+), 38 deletions(-) diff --git a/src/common/mainloop/client.rs b/src/common/mainloop/client.rs index d8f3af9..383f0a6 100644 --- a/src/common/mainloop/client.rs +++ b/src/common/mainloop/client.rs @@ -224,15 +224,23 @@ async fn state_client_loop(state: Arc>, match action { ClientAction::NewClient(client_id, sender) => { clients.insert(client_id, sender.clone()); - for action in state.on_connect(client_id).await { - match action { - OnConnect::Cipher((inc, outc)) => { - sender.send(ServerStateAction::Cipher(inc, outc)).await; - }, - OnConnect::Packet(pkt) => { - sender.send(ServerStateAction::Packet(pkt)).await; + let actions = state.on_connect(client_id).await; + match actions { + Ok(actions) => { + for action in actions { + match action { + OnConnect::Cipher((inc, outc)) => { + sender.send(ServerStateAction::Cipher(inc, outc)).await; + }, + OnConnect::Packet(pkt) => { + sender.send(ServerStateAction::Packet(pkt)).await; + } + } } } + Err(err) => { + warn!("[client {:?} state on_connect error] {:?}", client_id, err); + } } }, ClientAction::Packet(client_id, pkt) => { @@ -252,14 +260,21 @@ async fn state_client_loop(state: Arc>, }, ClientAction::Disconnect(client_id) => { let pkts = state.on_disconnect(client_id).await; - for (client_id, pkt) in pkts { - if let Some(client) = clients.get_mut(&client_id) { - client.send(ServerStateAction::Packet(pkt)).await; - } - } + match pkts { + Ok(pkts) => { + for (client_id, pkt) in pkts { + if let Some(client) = clients.get_mut(&client_id) { + client.send(ServerStateAction::Packet(pkt)).await; + } + } - if let Some(client) = clients.get_mut(&client_id) { - client.send(ServerStateAction::Disconnect).await; + if let Some(client) = clients.get_mut(&client_id) { + client.send(ServerStateAction::Disconnect).await; + } + } + Err(err) => { + warn!("[client {:?} state on_disconnect error] {:?}", client_id, err); + } } } } diff --git a/src/common/serverstate.rs b/src/common/serverstate.rs index d22c9c6..ba9caa6 100644 --- a/src/common/serverstate.rs +++ b/src/common/serverstate.rs @@ -24,9 +24,9 @@ pub trait ServerState { type RecvPacket: RecvServerPacket; type PacketError; - async fn on_connect(&mut self, id: ClientId) -> Vec>; + async fn on_connect(&mut self, id: ClientId) -> Result>, Self::PacketError>; async fn handle(&mut self, id: ClientId, pkt: &Self::RecvPacket) -> Result + Send>, Self::PacketError>; - async fn on_disconnect(&mut self, id: ClientId) -> Vec<(ClientId, Self::SendPacket)>; + async fn on_disconnect(&mut self, id: ClientId) -> Result, Self::PacketError>; } diff --git a/src/entity/gateway/postgres/postgres.rs b/src/entity/gateway/postgres/postgres.rs index 5318cc2..266a98b 100644 --- a/src/entity/gateway/postgres/postgres.rs +++ b/src/entity/gateway/postgres/postgres.rs @@ -144,7 +144,7 @@ impl EntityGateway for PostgresGateway { } async fn get_user_settings_by_user(&self, user: &UserAccountEntity) -> Result { - let settings = sqlx::query_as::<_, PgUserSettings>("select * from user_settings where id = $1") + let settings = sqlx::query_as::<_, PgUserSettings>("select * from user_settings where user_account = $1") .bind(user.id.0) .fetch_one(&self.pool).await?; Ok(settings.into()) diff --git a/src/login/character.rs b/src/login/character.rs index a855912..5bfc2e1 100644 --- a/src/login/character.rs +++ b/src/login/character.rs @@ -475,7 +475,7 @@ impl ServerState for CharacterServerState { type RecvPacket = RecvCharacterPacket; type PacketError = CharacterError; - async fn on_connect(&mut self, id: ClientId) -> Vec> { + async fn on_connect(&mut self, id: ClientId) -> Result>, CharacterError> { self.clients.insert(id, ClientState::new()); let mut rng = rand::thread_rng(); @@ -485,10 +485,10 @@ impl ServerState for CharacterServerState { rng.fill(&mut server_key[..]); rng.fill(&mut client_key[..]); - vec![OnConnect::Packet(SendCharacterPacket::LoginWelcome(LoginWelcome::new(server_key, client_key))), + Ok(vec![OnConnect::Packet(SendCharacterPacket::LoginWelcome(LoginWelcome::new(server_key, client_key))), OnConnect::Cipher((Box::new(PSOBBCipher::new(ELSEWHERE_PARRAY, ELSEWHERE_PRIVATE_KEY, client_key)), Box::new(PSOBBCipher::new(ELSEWHERE_PARRAY, ELSEWHERE_PRIVATE_KEY, server_key)))) - ] + ]) } async fn handle(&mut self, id: ClientId, pkt: &RecvCharacterPacket) @@ -535,14 +535,14 @@ impl ServerState for CharacterServerState { }) } - async fn on_disconnect(&mut self, id: ClientId) -> Vec<(ClientId, SendCharacterPacket)> { + async fn on_disconnect(&mut self, id: ClientId) -> Result, CharacterError> { if let Some(client) = self.clients.remove(&id) { if let Some(mut user) = client.user { user.at_character= false; self.entity_gateway.save_user(&user).await; } } - Vec::new() + Ok(Vec::new()) } } diff --git a/src/login/login.rs b/src/login/login.rs index 9bcb0c7..6066dd2 100644 --- a/src/login/login.rs +++ b/src/login/login.rs @@ -132,7 +132,7 @@ impl ServerState for LoginServerState { type RecvPacket = RecvLoginPacket; type PacketError = LoginError; - async fn on_connect(&mut self, _id: ClientId) -> Vec> { + async fn on_connect(&mut self, _id: ClientId) -> Result>, LoginError> { let mut rng = rand::thread_rng(); let mut server_key = [0u8; 48]; @@ -140,10 +140,10 @@ impl ServerState for LoginServerState { rng.fill(&mut server_key[..]); rng.fill(&mut client_key[..]); - vec![OnConnect::Packet(SendLoginPacket::LoginWelcome(LoginWelcome::new(server_key, client_key))), + Ok(vec![OnConnect::Packet(SendLoginPacket::LoginWelcome(LoginWelcome::new(server_key, client_key))), OnConnect::Cipher((Box::new(PSOBBCipher::new(ELSEWHERE_PARRAY, ELSEWHERE_PRIVATE_KEY, client_key)), Box::new(PSOBBCipher::new(ELSEWHERE_PARRAY, ELSEWHERE_PRIVATE_KEY, server_key)))) - ] + ]) } async fn handle(&mut self, id: ClientId, pkt: &Self::RecvPacket) @@ -159,14 +159,14 @@ impl ServerState for LoginServerState { }) } - async fn on_disconnect(&mut self, id: ClientId) -> Vec<(ClientId, SendLoginPacket)> { + async fn on_disconnect(&mut self, id: ClientId) -> Result, LoginError> { if let Some(username) = self.clients.remove(&id) { if let Ok(mut user) = self.entity_gateway.get_user_by_name(username).await { user.at_login = false; self.entity_gateway.save_user(&user).await; } } - Vec::new() + Ok(Vec::new()) } } diff --git a/src/patch/patch.rs b/src/patch/patch.rs index ec88b5c..65cbc3f 100644 --- a/src/patch/patch.rs +++ b/src/patch/patch.rs @@ -160,14 +160,14 @@ impl ServerState for PatchServerState { type RecvPacket = RecvPatchPacket; type PacketError = PatchError; - async fn on_connect(&mut self, _id: ClientId) -> Vec> { + async fn on_connect(&mut self, _id: ClientId) -> Result>, PatchError> { let mut rng = rand::thread_rng(); let key_in: u32 = rng.gen(); let key_out: u32 = rng.gen(); - vec![OnConnect::Packet(SendPatchPacket::PatchWelcome(PatchWelcome::new(key_out, key_in))), + Ok(vec![OnConnect::Packet(SendPatchPacket::PatchWelcome(PatchWelcome::new(key_out, key_in))), OnConnect::Cipher((Box::new(PSOPCCipher::new(key_in)), Box::new(PSOPCCipher::new(key_out)))) - ] + ]) } async fn handle(&mut self, id: ClientId, pkt: &RecvPatchPacket) @@ -202,8 +202,8 @@ impl ServerState for PatchServerState { }) } - async fn on_disconnect(&mut self, _id: ClientId) -> Vec<(ClientId, SendPatchPacket)> { - Vec::new() + async fn on_disconnect(&mut self, _id: ClientId) -> Result, PatchError> { + Ok(Vec::new()) } } diff --git a/src/ship/ship.rs b/src/ship/ship.rs index 1c5830b..7a098fe 100644 --- a/src/ship/ship.rs +++ b/src/ship/ship.rs @@ -456,7 +456,7 @@ impl ServerState for ShipServerState { type RecvPacket = RecvShipPacket; type PacketError = ShipError; - async fn on_connect(&mut self, _id: ClientId) -> Vec> { + async fn on_connect(&mut self, _id: ClientId) -> Result>, ShipError> { let mut rng = rand::thread_rng(); let mut server_key = [0u8; 48]; @@ -464,10 +464,10 @@ impl ServerState for ShipServerState { rng.fill(&mut server_key[..]); rng.fill(&mut client_key[..]); - vec![OnConnect::Packet(SendShipPacket::ShipWelcome(ShipWelcome::new(server_key, client_key))), + Ok(vec![OnConnect::Packet(SendShipPacket::ShipWelcome(ShipWelcome::new(server_key, client_key))), OnConnect::Cipher((Box::new(PSOBBCipher::new(ELSEWHERE_PARRAY, ELSEWHERE_PRIVATE_KEY, client_key)), Box::new(PSOBBCipher::new(ELSEWHERE_PARRAY, ELSEWHERE_PRIVATE_KEY, server_key)))) - ] + ]) } async fn handle(&mut self, id: ClientId, pkt: &RecvShipPacket) @@ -577,7 +577,7 @@ impl ServerState for ShipServerState { }) } - async fn on_disconnect(&mut self, id: ClientId) -> Vec<(ClientId, SendShipPacket)> { + async fn on_disconnect(&mut self, id: ClientId) -> Result, ShipError> { // TODO: don't unwrap! let client = self.clients.get(&id).unwrap(); let area_client = self.client_location.get_local_client(id).unwrap(); @@ -605,9 +605,9 @@ impl ServerState for ShipServerState { self.entity_gateway.save_user(&client.user).await; } - neighbors.into_iter().map(|n| { + Ok(neighbors.into_iter().map(|n| { (n.client, pkt.clone()) - }).collect() + }).collect()) } } From 164a8a1ad82d6404b892eb8ae90927c58bbc26ce Mon Sep 17 00:00:00 2001 From: jake Date: Fri, 30 Oct 2020 21:20:28 -0600 Subject: [PATCH 24/27] disable duplicate account checking since its super bugged --- src/login/login.rs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/login/login.rs b/src/login/login.rs index 6066dd2..1683977 100644 --- a/src/login/login.rs +++ b/src/login/login.rs @@ -58,15 +58,15 @@ impl SendServerPacket for SendLoginPacket { } } - pub async 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).await.map_err(|_| AccountStatus::InvalidUser)?; - if user.is_currently_online() { + /*if user.is_currently_online() { return Err(AccountStatus::AlreadyOnline) - } + }*/ + log::info!("user: {}, activated {}", user.username, user.activated); if !user.activated { return Err(AccountStatus::PayUp) } @@ -84,12 +84,15 @@ pub async fn get_login_status(entity_gateway: &impl EntityGateway, pkt: &Login) } pub fn check_if_already_online(user: UserAccountEntity) -> Result { + Ok(user) + /* if user.is_currently_online() { - Err(AccountStatus::PayUp) - } + Err(AccountStatus::PayUp) +} else { - Ok(user) - } + Ok(user) +} + */ } pub struct LoginServerState { From b517fb561ccbe455ce17d4f24692f97c2e7f6afd Mon Sep 17 00:00:00 2001 From: jake Date: Fri, 30 Oct 2020 21:22:26 -0600 Subject: [PATCH 25/27] fix some things --- src/login/login.rs | 4 ++++ src/ship/ship.rs | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/login/login.rs b/src/login/login.rs index 1683977..c6d818f 100644 --- a/src/login/login.rs +++ b/src/login/login.rs @@ -230,6 +230,10 @@ mod test { at_ship: false, }) } + + async fn save_user(&mut self, user: &UserAccountEntity) -> Result<(), GatewayError> { + Ok(()) + } }; let mut server = LoginServerState::new(TestData {}, "127.0.0.1".parse().unwrap()); diff --git a/src/ship/ship.rs b/src/ship/ship.rs index 7a098fe..d27c10f 100644 --- a/src/ship/ship.rs +++ b/src/ship/ship.rs @@ -494,7 +494,8 @@ impl ServerState for ShipServerState { handler::quest::load_quest(id, questmenuselect, &self.quests, &mut self.clients, &self.client_location, &mut self.rooms)? }, RecvShipPacket::MenuDetail(_menudetail) => { - unreachable!(); + //unreachable!(); + Box::new(Vec::new().into_iter()) }, RecvShipPacket::RoomPasswordReq(room_password_req) => { if room_password_req.password == self.rooms[room_password_req.item as usize].as_ref() From ad612615c7840e51cf56d7dcc9066bd2b7b7c4a6 Mon Sep 17 00:00:00 2001 From: jake Date: Fri, 30 Oct 2020 21:27:00 -0600 Subject: [PATCH 26/27] rebases are hard --- src/ship/items/manager.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/ship/items/manager.rs b/src/ship/items/manager.rs index ce80e77..b037f59 100644 --- a/src/ship/items/manager.rs +++ b/src/ship/items/manager.rs @@ -48,7 +48,6 @@ pub enum ItemManagerError { CannotGetIndividualItem, InvalidSlot(u8, u8), // slots available, slot attempted NoArmorEquipped, - ItemIdNotInInventory(ClientItemId), GatewayError(#[from] crate::entity::gateway::GatewayError) } From 586eb28c498fb211529c05c2aaca7621ed8dc5f2 Mon Sep 17 00:00:00 2001 From: jake Date: Fri, 30 Oct 2020 21:43:54 -0600 Subject: [PATCH 27/27] fix tests --- tests/test_item_equip.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_item_equip.rs b/tests/test_item_equip.rs index ebc866e..484c161 100644 --- a/tests/test_item_equip.rs +++ b/tests/test_item_equip.rs @@ -31,7 +31,7 @@ async fn test_equip_unit_from_equip_menu() { slot: 0, equipped: true, } - }).await; + }).await.unwrap(); entity_gateway.create_item( item::NewItemEntity { @@ -87,7 +87,7 @@ async fn test_equip_unit_from_equip_menu() { unknown1: 0, })))).await.unwrap().for_each(drop); - let items = entity_gateway.get_items_by_character(&char1).await; + let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap(); let (unit1, unit2) = (&items[1], &items[2]); let unit1_equipped = match unit1.location { @@ -194,7 +194,7 @@ async fn test_unequip_armor_with_units() { unknown1: 0, })))).await.unwrap().for_each(drop); - let items = entity_gateway.get_items_by_character(&char1).await; + let items = entity_gateway.get_items_by_character(&char1.id).await.unwrap(); let (armor, unit1, unit2) = (&items[0], &items[1], &items[2]); let armor_equipped = match armor.location {