From 83e6c9cf30fd152573c93f73709bcd4af5d51973 Mon Sep 17 00:00:00 2001 From: jake Date: Fri, 30 Oct 2020 22:24:05 -0600 Subject: [PATCH 01/11] remove unused files --- src/login_main.rs | 112 ---------------------------------------------- src/patch_main.rs | 44 ------------------ 2 files changed, 156 deletions(-) delete mode 100644 src/login_main.rs delete mode 100644 src/patch_main.rs diff --git a/src/login_main.rs b/src/login_main.rs deleted file mode 100644 index a98b009..0000000 --- a/src/login_main.rs +++ /dev/null @@ -1,112 +0,0 @@ -#![feature(const_generics)] - -mod common; -mod login; -mod entity; - -use std::thread; -use std::collections::HashMap; - -use bcrypt; - -use libpso::character::settings; -use libpso::character::character as pso_character; -use libpso::character::guildcard; -use libpso::{utf8_to_array, utf8_to_utf16_array}; - -use entity::gateway::EntityGateway; -use entity::account::{UserAccount, UserSettings, GuildCardData}; -use entity::character::Character; - -use login::login::LoginServerState; -use login::character::CharacterServerState; - -use std::time::SystemTime; - -#[derive(Clone)] -struct LoginStubData { - users: HashMap, - characters: [Option ;4], -} - -impl LoginStubData { - fn new() -> LoginStubData { - let mut c = pso_character::Character::default(); - c.name = utf8_to_utf16_array!("Test Char", 16); - - let mut users = HashMap::new(); - users.insert("hi".to_string(), UserAccount { - id: 1, - username: "hi".to_owned(), - password: bcrypt::hash("qwer", 5).unwrap(), - guildcard: None, - team_id: None, - banned: false, - muted_until: SystemTime::now(), - created_at: SystemTime::now(), - flags: 0, - }); - - LoginStubData { - users: users, - - characters: [Some(Character { - id: 1, - slot: 0, - user_id: 1, - character: c, - }), - None, None, None] - } - } -} - -impl EntityGateway for LoginStubData { - fn get_user_by_name(&self, username: String) -> Option { - self.users.get(&username).map(|user| user.clone()) - } - - fn get_user_settings_by_user(&self, user: &UserAccount) -> Option { - Some(UserSettings { - id: 0, - user_id: user.id, - settings: settings::UserSettings::default() - }) - } - - fn set_user(&mut self, user: &UserAccount) { - self.users.insert(user.username.clone(), user.clone()); - } - - fn get_characters_by_user(&self, _user: &UserAccount) -> [Option; 4] { - self.characters - } - - fn set_character(&mut self, char: &Character) { - self.characters[char.slot as usize] = Some(char.clone()); - } - - fn get_guild_card_data_by_user(&self, user: &UserAccount) -> GuildCardData { - GuildCardData { - id: 1, - user_id: user.id, - guildcard: guildcard::GuildCardData::default(), - } - } -} - -fn main() { - println!("[login+character] starting server"); - - let auth_thread = thread::spawn(|| { - let auth_state = LoginServerState::new(LoginStubData::new()); - common::mainloop::mainloop(auth_state, login::login::LOGIN_PORT); - }); - let char_thread = thread::spawn(|| { - let char_state = CharacterServerState::new(LoginStubData::new()); - common::mainloop::mainloop(char_state, login::character::CHARACTER_PORT); - }); - - auth_thread.join().unwrap(); - char_thread.join().unwrap(); -} diff --git a/src/patch_main.rs b/src/patch_main.rs deleted file mode 100644 index 271e8fa..0000000 --- a/src/patch_main.rs +++ /dev/null @@ -1,44 +0,0 @@ -#![feature(const_generics)] - -mod common; -mod patch; -use crate::patch::patch::{PatchServerState, PatchTreeIterItem, generate_patch_tree, load_config, load_motd}; - -fn main() { - println!("[patch] starting server"); - - let patch_config = load_config(); - let patch_motd: String = load_motd(); - - if let Err(_) = std::fs::read_dir(patch_config.path.as_str()) { - println!("Patch directory {} does not exist. Attempting to create it...", patch_config.path.as_str()); - if let Err(err) = std::fs::create_dir(patch_config.path.as_str()) { - panic!("Failed to create patch directory! \n{}", err); - } - } - - let (patch_file_tree, patch_file_lookup) = generate_patch_tree(patch_config.path.as_str()); - println!("[patch] files to patch:"); - let mut indent = 0; - for item in patch_file_tree.flatten() { - match item { - PatchTreeIterItem::Directory(path) => { - let s = path.to_str().unwrap(); - println!("{: >2$}\u{2517}\u{2500}\u{2500} {}", "", s, indent * 4); - indent += 1; - }, - PatchTreeIterItem::File(path, id) => { - let s = path.to_str().unwrap(); - println!("{: >3$}\u{2520}\u{2500}\u{2500} {} ({})", "", s, id, indent * 4); - }, - PatchTreeIterItem::UpDirectory => { - indent -= 1; - } - } - } - - let patch_state = PatchServerState::new(patch_file_tree, patch_file_lookup, patch_motd); - common::mainloop::mainloop(patch_state, patch_config.port); - - println!("[patch] exiting..."); -} From 498cf4ef43c50ad28e31bf6d9fd6976fc6bc4b35 Mon Sep 17 00:00:00 2001 From: jake Date: Fri, 30 Oct 2020 22:58:10 -0600 Subject: [PATCH 02/11] remove panic when failing to load a battle param --- src/ship/monster.rs | 56 ++++++++++++++++++++++----------------------- src/ship/room.rs | 3 ++- 2 files changed, 29 insertions(+), 30 deletions(-) diff --git a/src/ship/monster.rs b/src/ship/monster.rs index b313680..1bdb5b7 100644 --- a/src/ship/monster.rs +++ b/src/ship/monster.rs @@ -12,6 +12,7 @@ pub enum MonsterParseError { UnknownMonster(String), } +pub struct MonsterStatError; #[derive(Debug, Serialize, Deserialize, Copy, Clone, Hash, Eq, PartialEq, enum_utils::FromStr, derive_more::Display)] pub enum MonsterType { @@ -175,40 +176,37 @@ fn load_battle_param(filename: &str) -> HashMap { }).collect() } -pub fn load_monster_stats_table(mode: &RoomMode) -> HashMap { +pub fn load_monster_stats_table(mode: &RoomMode) -> Result, MonsterStatError> { match mode { - RoomMode::Multi {episode: Episode::One, difficulty: Difficulty::Normal} => load_battle_param("ep1_multi_normal.toml"), - RoomMode::Multi {episode: Episode::One, difficulty: Difficulty::Hard} => load_battle_param("ep1_multi_hard.toml"), - RoomMode::Multi {episode: Episode::One, difficulty: Difficulty::VeryHard} => load_battle_param("ep1_multi_veryhard.toml"), - RoomMode::Multi {episode: Episode::One, difficulty: Difficulty::Ultimate} => load_battle_param("ep1_multi_ultimate.toml"), + RoomMode::Multi {episode: Episode::One, difficulty: Difficulty::Normal} => Ok(load_battle_param("ep1_multi_normal.toml")), + RoomMode::Multi {episode: Episode::One, difficulty: Difficulty::Hard} => Ok(load_battle_param("ep1_multi_hard.toml")), + RoomMode::Multi {episode: Episode::One, difficulty: Difficulty::VeryHard} => Ok(load_battle_param("ep1_multi_veryhard.toml")), + RoomMode::Multi {episode: Episode::One, difficulty: Difficulty::Ultimate} => Ok(load_battle_param("ep1_multi_ultimate.toml")), - RoomMode::Multi {episode: Episode::Two, difficulty: Difficulty::Normal} => load_battle_param("ep2_multi_normal.toml"), - RoomMode::Multi {episode: Episode::Two, difficulty: Difficulty::Hard} => load_battle_param("ep2_multi_hard.toml"), - RoomMode::Multi {episode: Episode::Two, difficulty: Difficulty::VeryHard} => load_battle_param("ep2_multi_veryhard.toml"), - RoomMode::Multi {episode: Episode::Two, difficulty: Difficulty::Ultimate} => load_battle_param("ep2_multi_ultimate.toml"), + RoomMode::Multi {episode: Episode::Two, difficulty: Difficulty::Normal} => Ok(load_battle_param("ep2_multi_normal.toml")), + RoomMode::Multi {episode: Episode::Two, difficulty: Difficulty::Hard} => Ok(load_battle_param("ep2_multi_hard.toml")), + RoomMode::Multi {episode: Episode::Two, difficulty: Difficulty::VeryHard} => Ok(load_battle_param("ep2_multi_veryhard.toml")), + RoomMode::Multi {episode: Episode::Two, difficulty: Difficulty::Ultimate} => Ok(load_battle_param("ep2_multi_ultimate.toml")), - RoomMode::Multi {episode: Episode::Four, difficulty: Difficulty::Normal} => load_battle_param("ep4_multi_normal.toml"), - RoomMode::Multi {episode: Episode::Four, difficulty: Difficulty::Hard} => load_battle_param("ep4_multi_hard.toml"), - RoomMode::Multi {episode: Episode::Four, difficulty: Difficulty::VeryHard} => load_battle_param("ep4_multi_veryhard.toml"), - RoomMode::Multi {episode: Episode::Four, difficulty: Difficulty::Ultimate} => load_battle_param("ep4_multi_ultimate.toml"), + RoomMode::Multi {episode: Episode::Four, difficulty: Difficulty::Normal} => Ok(load_battle_param("ep4_multi_normal.toml")), + RoomMode::Multi {episode: Episode::Four, difficulty: Difficulty::Hard} => Ok(load_battle_param("ep4_multi_hard.toml")), + RoomMode::Multi {episode: Episode::Four, difficulty: Difficulty::VeryHard} => Ok(load_battle_param("ep4_multi_veryhard.toml")), + RoomMode::Multi {episode: Episode::Four, difficulty: Difficulty::Ultimate} => Ok(load_battle_param("ep4_multi_ultimate.toml")), + RoomMode::Single {episode: Episode::One, difficulty: Difficulty::Normal} => Ok(load_battle_param("ep1_solo_normal.toml")), + RoomMode::Single {episode: Episode::One, difficulty: Difficulty::Hard} => Ok(load_battle_param("ep1_solo_hard.toml")), + RoomMode::Single {episode: Episode::One, difficulty: Difficulty::VeryHard} => Ok(load_battle_param("ep1_solo_veryhard.toml")), + RoomMode::Single {episode: Episode::One, difficulty: Difficulty::Ultimate} => Ok(load_battle_param("ep1_solo_ultimate.toml")), + RoomMode::Single {episode: Episode::Two, difficulty: Difficulty::Normal} => Ok(load_battle_param("ep2_solo_normal.toml")), + RoomMode::Single {episode: Episode::Two, difficulty: Difficulty::Hard} => Ok(load_battle_param("ep2_solo_hard.toml")), + RoomMode::Single {episode: Episode::Two, difficulty: Difficulty::VeryHard} => Ok(load_battle_param("ep2_solo_veryhard.toml")), + RoomMode::Single {episode: Episode::Two, difficulty: Difficulty::Ultimate} => Ok(load_battle_param("ep2_solo_ultimate.toml")), - - RoomMode::Single {episode: Episode::One, difficulty: Difficulty::Normal} => load_battle_param("ep1_solo_normal.toml"), - RoomMode::Single {episode: Episode::One, difficulty: Difficulty::Hard} => load_battle_param("ep1_solo_hard.toml"), - RoomMode::Single {episode: Episode::One, difficulty: Difficulty::VeryHard} => load_battle_param("ep1_solo_veryhard.toml"), - RoomMode::Single {episode: Episode::One, difficulty: Difficulty::Ultimate} => load_battle_param("ep1_solo_ultimate.toml"), - - RoomMode::Single {episode: Episode::Two, difficulty: Difficulty::Normal} => load_battle_param("ep2_solo_normal.toml"), - RoomMode::Single {episode: Episode::Two, difficulty: Difficulty::Hard} => load_battle_param("ep2_solo_hard.toml"), - RoomMode::Single {episode: Episode::Two, difficulty: Difficulty::VeryHard} => load_battle_param("ep2_solo_veryhard.toml"), - RoomMode::Single {episode: Episode::Two, difficulty: Difficulty::Ultimate} => load_battle_param("ep2_solo_ultimate.toml"), - - RoomMode::Single {episode: Episode::Four, difficulty: Difficulty::Normal} => load_battle_param("ep4_solo_normal.toml"), - RoomMode::Single {episode: Episode::Four, difficulty: Difficulty::Hard} => load_battle_param("ep4_solo_hard.toml"), - RoomMode::Single {episode: Episode::Four, difficulty: Difficulty::VeryHard} => load_battle_param("ep4_solo_veryhard.toml"), - RoomMode::Single {episode: Episode::Four, difficulty: Difficulty::Ultimate} => load_battle_param("ep4_solo_ultimate.toml"), - _ => panic!(), + RoomMode::Single {episode: Episode::Four, difficulty: Difficulty::Normal} => Ok(load_battle_param("ep4_solo_normal.toml")), + RoomMode::Single {episode: Episode::Four, difficulty: Difficulty::Hard} => Ok(load_battle_param("ep4_solo_hard.toml")), + RoomMode::Single {episode: Episode::Four, difficulty: Difficulty::VeryHard} => Ok(load_battle_param("ep4_solo_veryhard.toml")), + RoomMode::Single {episode: Episode::Four, difficulty: Difficulty::Ultimate} => Ok(load_battle_param("ep4_solo_ultimate.toml")), + _ => Err(MonsterStatError), } } diff --git a/src/ship/room.rs b/src/ship/room.rs index c2d1c8a..904267e 100644 --- a/src/ship/room.rs +++ b/src/ship/room.rs @@ -13,6 +13,7 @@ pub enum RoomCreationError { InvalidMode, InvalidEpisode(u8), InvalidDifficulty(u8), + CouldNotLoadMonsterStats(RoomMode), } @@ -231,7 +232,7 @@ impl RoomState { }; Ok(RoomState { - monster_stats: Box::new(load_monster_stats_table(&room_mode)), + monster_stats: Box::new(load_monster_stats_table(&room_mode).map_err(|_| RoomCreationError::CouldNotLoadMonsterStats(room_mode.clone()))?), mode: room_mode, random_seed: rand::thread_rng().gen(), name: String::from_utf16_lossy(&create_room.name).trim_matches(char::from(0)).into(), From ce3e58d45925fd0e1e1bc2b79880c678d450ac2b Mon Sep 17 00:00:00 2001 From: jake Date: Fri, 30 Oct 2020 23:09:01 -0600 Subject: [PATCH 03/11] remove unwraps in ship on_disconnect --- src/ship/ship.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/ship/ship.rs b/src/ship/ship.rs index 610b1be..d431c96 100644 --- a/src/ship/ship.rs +++ b/src/ship/ship.rs @@ -22,7 +22,7 @@ use crate::entity::gateway::{EntityGateway, GatewayError}; use crate::entity::account::{UserAccountEntity, UserSettingsEntity}; use crate::entity::character::{CharacterEntity, SectionID}; -use crate::ship::location::{ClientLocation, RoomLobby, MAX_ROOMS, ClientLocationError}; +use crate::ship::location::{ClientLocation, RoomLobby, MAX_ROOMS, ClientLocationError, GetNeighborError, GetClientsError, GetAreaError}; use crate::ship::items; use crate::ship::room; @@ -45,6 +45,9 @@ pub enum ShipError { InvalidSlot(ClientId, u32), TooManyClients, ClientLocationError(#[from] ClientLocationError), + GetNeighborError(#[from] GetNeighborError), + GetClientsError(#[from] GetClientsError), + GetAreaError(#[from] GetAreaError), MapsError(#[from] MapsError), MapAreaError(#[from] MapAreaError), InvalidRoom(u32), @@ -582,11 +585,11 @@ impl ServerState for ShipServerState { 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(); - let neighbors = self.client_location.get_client_neighbors(id).unwrap(); + let client = self.clients.get(&id).ok_or(ShipError::ClientNotFound(id))?; + let area_client = self.client_location.get_local_client(id)?; + let neighbors = self.client_location.get_client_neighbors(id)?; - let pkt = match self.client_location.get_area(id).unwrap() { + let pkt = match self.client_location.get_area(id)? { RoomLobby::Room(room) => { if neighbors.len() == 0 { self.rooms[room.0] = None; From e8fd37e32d3f41580d016f0ca61d68908c058bbf Mon Sep 17 00:00:00 2001 From: jake Date: Sat, 31 Oct 2020 10:50:14 -0600 Subject: [PATCH 04/11] save_item -> change_item, impl for postgres --- src/entity/gateway/entitygateway.rs | 2 +- src/entity/gateway/inmemory.rs | 7 +++++-- src/entity/gateway/postgres/postgres.rs | 8 ++++++++ src/ship/items/manager.rs | 22 +++------------------- 4 files changed, 17 insertions(+), 22 deletions(-) diff --git a/src/entity/gateway/entitygateway.rs b/src/entity/gateway/entitygateway.rs index ee6c1fa..1327eaf 100644 --- a/src/entity/gateway/entitygateway.rs +++ b/src/entity/gateway/entitygateway.rs @@ -65,7 +65,7 @@ pub trait EntityGateway: Send + Sync + Clone { unimplemented!(); } - async fn save_item(&mut self, _item: &ItemEntity) -> Result<(), GatewayError> { + async fn change_item(&mut self, _id: &ItemEntityId, _item: &ItemDetail) -> Result<(), GatewayError> { unimplemented!(); } diff --git a/src/entity/gateway/inmemory.rs b/src/entity/gateway/inmemory.rs index 602d869..e943376 100644 --- a/src/entity/gateway/inmemory.rs +++ b/src/entity/gateway/inmemory.rs @@ -165,9 +165,12 @@ impl EntityGateway for InMemoryGateway { Ok(new_item) } - async fn save_item(&mut self, item: &ItemEntity) -> Result<(), GatewayError> { + async fn change_item(&mut self, id: &ItemEntityId, item: &ItemDetail) -> Result<(), GatewayError> { let mut items = self.items.lock().unwrap(); - items.insert(item.id, item.clone()); + if let Some((_, ref mut old_item)) = items.iter_mut().find(|(existing_id, _)| **existing_id == *id) { + old_item.item = item.clone(); + } + Ok(()) } diff --git a/src/entity/gateway/postgres/postgres.rs b/src/entity/gateway/postgres/postgres.rs index 266a98b..bbc8d39 100644 --- a/src/entity/gateway/postgres/postgres.rs +++ b/src/entity/gateway/postgres/postgres.rs @@ -312,6 +312,14 @@ impl EntityGateway for PostgresGateway { }) } + async fn change_item(&mut self, id: &ItemEntityId, item: &ItemDetail) -> Result<(), GatewayError> { + sqlx::query("update item set item = $1 where id = $2") + .bind(sqlx::types::Json(PgItemDetail::from(item.clone()))) + .bind(id.0) + .execute(&self.pool).await?; + Ok(()) + } + 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{slot, ..} = &item_location { diff --git a/src/ship/items/manager.rs b/src/ship/items/manager.rs index 642ec51..a78e8b7 100644 --- a/src/ship/items/manager.rs +++ b/src/ship/items/manager.rs @@ -933,16 +933,8 @@ impl ItemManager { character_id: character.id, slot: slot, equipped: true, - }).await; - entity_gateway.save_item(&ItemEntity{ - id: inventory_item.entity_id, - location: ItemLocation::Inventory{ - character_id: character.id, - slot: slot, - equipped: true, - }, - item: inventory_item.item.clone(), - }).await; + }).await?; + entity_gateway.change_item(&inventory_item.entity_id, &inventory_item.item).await?; Ok(()) } @@ -968,15 +960,7 @@ impl ItemManager { slot: slot, equipped: false, }).await; - entity_gateway.save_item(&ItemEntity{ - id: inventory_item.entity_id, - location: ItemLocation::Inventory{ - character_id: character.id, - slot: slot, - equipped: false, - }, - item: inventory_item.item.clone(), - }).await; + entity_gateway.change_item(&inventory_item.entity_id, &inventory_item.item).await?; Ok(()) } From 72141ace2c9106ad562584b5bfc05dde7523a104 Mon Sep 17 00:00:00 2001 From: jake Date: Sat, 31 Oct 2020 19:04:42 -0600 Subject: [PATCH 05/11] remove unneeded warnings --- src/ship/items/manager.rs | 2 +- src/ship/packet/handler/direct_message.rs | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/ship/items/manager.rs b/src/ship/items/manager.rs index a78e8b7..46c45a0 100644 --- a/src/ship/items/manager.rs +++ b/src/ship/items/manager.rs @@ -215,7 +215,7 @@ impl ItemManager { let inventory = self.character_inventory.get_mut(&character.id).unwrap(); inventory.initialize_item_ids(base_inventory_id); let base_bank_id = ((area_client.local_client.id() as u32) << 21) | 0x20000; - let default_bank = self.character_bank.get_mut(&character.id);//.unwrap().get_mut(&BankName("".to_string())); + let default_bank = self.character_bank.get_mut(&character.id); match default_bank { Some(default_bank) => { default_bank.initialize_item_ids(base_bank_id); diff --git a/src/ship/packet/handler/direct_message.rs b/src/ship/packet/handler/direct_message.rs index 7084516..b31477b 100644 --- a/src/ship/packet/handler/direct_message.rs +++ b/src/ship/packet/handler/direct_message.rs @@ -82,7 +82,6 @@ where let client_and_drop = clients_in_area.into_iter() .filter_map(|area_client| { room.drop_table.get_drop(&monster.map_area, &monster.monster).map(|item_drop_type| { - warn!("drop is? {:?}", item_drop_type); (area_client, item_drop_type) }) }); @@ -180,7 +179,6 @@ EG: EntityGateway let client_and_drop = clients_in_area.into_iter() .filter_map(|area_client| { room.drop_table.get_box_drop(&box_object.map, &box_object).map(|item_drop_type| { - warn!("drop is? {:?}", item_drop_type); (area_client, item_drop_type) }) }); From 5e9a94081cd9ff6fc11eb3d38063d68b933927b9 Mon Sep 17 00:00:00 2001 From: jake Date: Sat, 31 Oct 2020 19:13:45 -0600 Subject: [PATCH 06/11] remove unwrap --- src/ship/packet/handler/message.rs | 2 +- src/ship/ship.rs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ship/packet/handler/message.rs b/src/ship/packet/handler/message.rs index c1efe6b..937a08c 100644 --- a/src/ship/packet/handler/message.rs +++ b/src/ship/packet/handler/message.rs @@ -26,7 +26,7 @@ pub async fn request_exp(id: ClientId, .ok_or_else(|| ShipError::InvalidRoom(room_id.0 as u32))?; let monster = room.maps.enemy_by_id(request_exp.enemy_id as usize)?; - let monster_stats = room.monster_stats.get(&monster.monster).unwrap(); + let monster_stats = room.monster_stats.get(&monster.monster).ok_or(ShipError::UnknownMonster(monster.monster.clone()))?; let exp_gain = if request_exp.last_hitter == 1 { monster_stats.exp diff --git a/src/ship/ship.rs b/src/ship/ship.rs index d431c96..ddbcb2d 100644 --- a/src/ship/ship.rs +++ b/src/ship/ship.rs @@ -66,6 +66,7 @@ pub enum ShipError { NotEnoughMeseta(ClientId, u32), ShopError, GatewayError(#[from] GatewayError), + UnknownMonster(crate::ship::monster::MonsterType), } #[derive(Debug)] From 3a095a928d15a47cb1953f099fd67fb5c7be54ea Mon Sep 17 00:00:00 2001 From: jake Date: Sat, 31 Oct 2020 23:18:25 -0600 Subject: [PATCH 07/11] fix item ids not being set correctly --- src/ship/packet/handler/room.rs | 5 +- tests/common.rs | 8 +++ tests/test_rooms.rs | 104 ++++++++++++++++++++++++++++++++ 3 files changed, 115 insertions(+), 2 deletions(-) create mode 100644 tests/test_rooms.rs diff --git a/src/ship/packet/handler/room.rs b/src/ship/packet/handler/room.rs index 6bef6b9..b02d28b 100644 --- a/src/ship/packet/handler/room.rs +++ b/src/ship/packet/handler/room.rs @@ -77,6 +77,9 @@ pub fn join_room(id: ClientId, let client = clients.get(&id).ok_or(ShipError::ClientNotFound(id))?; let area_client = client_location.get_local_client(id).map_err(|err| -> ClientLocationError { err.into() })?; + + item_manager.add_character_to_room(room_id, &client.character, area_client); + let leader = client_location.get_room_leader(room_id).map_err(|err| -> ClientLocationError { err.into() })?; let join_room = builder::room::join_room(id, clients, client_location, room_id, &room)?; let add_to = builder::room::add_to_room(id, &client, &area_client, &leader, item_manager, level_table, room_id)?; @@ -84,8 +87,6 @@ pub fn join_room(id: ClientId, let room = rooms.get_mut(room_id.0).unwrap().as_mut().unwrap(); room.bursting = true; - item_manager.add_character_to_room(room_id, &client.character, area_client); - let mut result: Box + Send> = Box::new( vec![(id, SendShipPacket::JoinRoom(join_room))] .into_iter() diff --git a/tests/common.rs b/tests/common.rs index 7e7c925..6b97b0e 100644 --- a/tests/common.rs +++ b/tests/common.rs @@ -59,6 +59,13 @@ pub async fn create_room(ship: &mut ShipServerState, id: create_room_with_difficulty(ship, id, name, password, Difficulty::Normal).await; } +pub async fn leave_room(ship: &mut ShipServerState, id: ClientId) { + ship.handle(id, &RecvShipPacket::LobbySelect(LobbySelect { + menu: 3, + lobby: 0, + })).await.unwrap().for_each(drop); +} + pub async fn create_room_with_difficulty(ship: &mut ShipServerState, id: ClientId, name: &str, password: &str, difficulty: Difficulty) { ship.handle(id, &RecvShipPacket::CreateRoom(CreateRoom { unknown: [0; 2], @@ -79,4 +86,5 @@ pub async fn join_room(ship: &mut ShipServerState, id: Cl menu: ROOM_MENU_ID, item: room_id, })).await.unwrap().for_each(drop); + ship.handle(id, &RecvShipPacket::DoneBursting(DoneBursting {})).await.unwrap().for_each(drop); } diff --git a/tests/test_rooms.rs b/tests/test_rooms.rs new file mode 100644 index 0000000..a21c754 --- /dev/null +++ b/tests/test_rooms.rs @@ -0,0 +1,104 @@ +use elseware::common::serverstate::{ClientId, ServerState}; +use elseware::entity::gateway::{EntityGateway, InMemoryGateway}; +use elseware::entity::item; +use elseware::ship::ship::{ShipServerState, RecvShipPacket, SendShipPacket}; + +use libpso::packet::ship::*; +use libpso::packet::messages::*; + +#[path = "common.rs"] +mod common; +use common::*; + + +#[async_std::test] +async fn test_item_ids_reset_when_rejoining_rooms() { + let mut entity_gateway = InMemoryGateway::new(); + + let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a").await; + let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a").await; + + for slot in 0..3 { + entity_gateway.create_item( + item::NewItemEntity { + item: item::ItemDetail::Weapon( + item::weapon::Weapon { + weapon: item::weapon::WeaponType::Saber, + grind: 0, + special: None, + attrs: [None, None, None], + tekked: true, + modifiers: Vec::new(), + } + ), + location: item::ItemLocation::Inventory { + character_id: char1.id, + slot: slot, + equipped: false, + } + }).await.unwrap(); + } + + for slot in 0..10 { + entity_gateway.create_item( + item::NewItemEntity { + item: item::ItemDetail::Weapon( + item::weapon::Weapon { + weapon: item::weapon::WeaponType::Saber, + grind: 0, + special: None, + attrs: [None, None, None], + tekked: true, + modifiers: Vec::new(), + } + ), + location: item::ItemLocation::Inventory { + character_id: char2.id, + slot: slot, + equipped: false, + } + }).await.unwrap(); + } + + let mut ship = ShipServerState::builder() + .gateway(entity_gateway.clone()) + .build(); + log_in_char(&mut ship, ClientId(1), "a1", "a").await; + log_in_char(&mut ship, ClientId(2), "a2", "a").await; + + join_lobby(&mut ship, ClientId(1)).await; + join_lobby(&mut ship, ClientId(2)).await; + + create_room(&mut ship, ClientId(1), "room", "").await; + let p = ship.handle(ClientId(2), &RecvShipPacket::MenuSelect(MenuSelect { + menu: ROOM_MENU_ID, + item: 0, + })).await.unwrap().collect::>(); + ship.handle(ClientId(2), &RecvShipPacket::DoneBursting(DoneBursting {})).await.unwrap().for_each(drop); + + match &p[1].1 { + SendShipPacket::AddToRoom(add_to) => { + println!("addto {:?}", add_to); + assert_eq!(add_to.playerinfo.inventory.items.iter().map(|k| k.item_id).collect::>(), + vec![0x210000,0x210001,0x210002,0x210003,0x210004,0x210005,0x210006,0x210007,0x210008,0x210009, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]); + }, + _ => panic!(), + } + + leave_room(&mut ship, ClientId(2)).await; + + let p = ship.handle(ClientId(2), &RecvShipPacket::MenuSelect(MenuSelect { + menu: ROOM_MENU_ID, + item: 0, + })).await.unwrap().collect::>(); + + match &p[1].1 { + SendShipPacket::AddToRoom(add_to) => { + assert_eq!(add_to.playerinfo.inventory.items.iter().map(|k| k.item_id).collect::>(), + vec![0x210000,0x210001,0x210002,0x210003,0x210004,0x210005,0x210006,0x210007,0x210008,0x210009, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]); + }, + _ => panic!(), + } +} From a3413083b6cc5bfdc3f0650a267f7292b244a24d Mon Sep 17 00:00:00 2001 From: jake Date: Sun, 1 Nov 2020 07:49:04 -0700 Subject: [PATCH 08/11] add auth for interserver connections --- src/bin/login.rs | 4 +++- src/bin/main.rs | 3 ++- src/bin/ship.rs | 3 +++ src/common/interserver.rs | 2 +- src/login/character.rs | 25 ++++++++++++++++++------- src/ship/ship.rs | 23 +++++++++++++++++------ 6 files changed, 44 insertions(+), 16 deletions(-) diff --git a/src/bin/login.rs b/src/bin/login.rs index 7fec40c..608f994 100644 --- a/src/bin/login.rs +++ b/src/bin/login.rs @@ -3,6 +3,7 @@ use elseware::entity::gateway::postgres::PostgresGateway; use elseware::login::login::LoginServerState; use elseware::login::character::CharacterServerState; use elseware::common::mainloop::{login_mainloop, character_mainloop}; +use elseware::common::interserver::AuthToken; fn main() { let colors = fern::colors::ColoredLevelConfig::new() @@ -33,13 +34,14 @@ fn main() { 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 shipgate_token = std::env::var("SHIPGATE_TOKEN").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, charserv_ip); let login_loop = login_mainloop(login_state, elseware::login::login::LOGIN_PORT); - let char_state = CharacterServerState::new(entity_gateway); + let char_state = CharacterServerState::new(entity_gateway, AuthToken(shipgate_token.into())); let character_loop = character_mainloop(char_state, elseware::login::character::CHARACTER_PORT, elseware::login::login::COMMUNICATION_PORT); info!("[auth/character] starting server"); diff --git a/src/bin/main.rs b/src/bin/main.rs index 529fdc2..70820a6 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -9,6 +9,7 @@ use elseware::entity::account::{NewUserAccountEntity, NewUserSettingsEntity}; use elseware::entity::gateway::{EntityGateway, InMemoryGateway, PostgresGateway}; use elseware::entity::character::NewCharacterEntity; use elseware::entity::item::{NewItemEntity, ItemDetail, ItemLocation}; +use elseware::common::interserver::AuthToken; use elseware::entity::item; use elseware::common::mainloop::*; @@ -405,7 +406,7 @@ fn main() { let thread_entity_gateway = entity_gateway.clone(); info!("[character] starting server"); - let char_state = CharacterServerState::new(thread_entity_gateway); + let char_state = CharacterServerState::new(thread_entity_gateway, AuthToken("".into())); let character_loop = character_mainloop(char_state, elseware::login::character::CHARACTER_PORT, elseware::login::login::COMMUNICATION_PORT); let thread_entity_gateway = entity_gateway.clone(); diff --git a/src/bin/ship.rs b/src/bin/ship.rs index d993ebf..acd0675 100644 --- a/src/bin/ship.rs +++ b/src/bin/ship.rs @@ -2,6 +2,7 @@ use log::{info}; use elseware::entity::gateway::postgres::PostgresGateway; use elseware::ship::ship::ShipServerStateBuilder; use elseware::common::mainloop::ship_mainloop; +use elseware::common::interserver::AuthToken; fn main() { let colors = fern::colors::ColoredLevelConfig::new() @@ -33,6 +34,7 @@ fn main() { let db_dbname = std::env::var("DB_DBNAME").unwrap(); let entity_gateway = PostgresGateway::new(&db_host, &db_dbname, &db_username, &db_password); + let shipgate_token = std::env::var("SHIPGATE_TOKEN").unwrap(); 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() @@ -40,6 +42,7 @@ fn main() { .ip(ip) .port(elseware::ship::ship::SHIP_PORT) .gateway(entity_gateway) + .auth_token(AuthToken(shipgate_token.into())) .build(); let shipgate_ip = std::env::var("SHIPGATE_IP").unwrap().parse().unwrap(); diff --git a/src/common/interserver.rs b/src/common/interserver.rs index f1110f8..bd09913 100644 --- a/src/common/interserver.rs +++ b/src/common/interserver.rs @@ -5,7 +5,7 @@ use crate::entity::character::CharacterEntityId; #[derive(Debug, Copy, Clone, Serialize, Deserialize, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct ServerId(pub usize); -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct AuthToken(pub String); #[derive(Debug, Serialize, Deserialize)] diff --git a/src/login/character.rs b/src/login/character.rs index 5bfc2e1..87da4b6 100644 --- a/src/login/character.rs +++ b/src/login/character.rs @@ -1,6 +1,6 @@ #![allow(dead_code, unused_assignments)] use std::io::Read; -use std::collections::{BTreeMap, HashMap}; +use std::collections::{BTreeMap, BTreeSet, HashMap}; use rand::Rng; use crc::{crc32, Hasher32}; @@ -28,6 +28,7 @@ use crate::entity::item::mag::Mag; use crate::entity::character::{CharacterEntity, NewCharacterEntity, CharacterClass, TechLevel}; use crate::login::login::{get_login_status, check_if_already_online}; +use crate::common::interserver::AuthToken; pub const CHARACTER_PORT: u16 = 12001; const SHIP_MENU_ID: u32 = 1; @@ -174,6 +175,8 @@ pub struct CharacterServerState { clients: HashMap, ships: BTreeMap, level_table: CharacterLevelTable, + auth_token: AuthToken, + authenticated_ships: BTreeSet, } @@ -266,7 +269,7 @@ async fn new_character(entity_gateway: &mut EG, user: &UserAc impl CharacterServerState { - pub fn new(entity_gateway: EG) -> CharacterServerState { + pub fn new(entity_gateway: EG, auth_token: AuthToken) -> CharacterServerState { let (param_header, param_data) = generate_param_data("data/param/"); CharacterServerState { @@ -276,6 +279,8 @@ impl CharacterServerState { clients: HashMap::new(), ships: BTreeMap::new(), level_table: CharacterLevelTable::new(), + auth_token: auth_token, + authenticated_ships: BTreeSet::new(), } } @@ -558,9 +563,15 @@ impl InterserverActor for CharacterServerState { async fn action(&mut self, id: ServerId, msg: Self::RecvMessage) -> Result, Self::Error> { match msg { - ShipMessage::Authenticate(_auth_token) => {}, + ShipMessage::Authenticate(auth_token) => { + if self.auth_token == auth_token { + self.authenticated_ships.insert(id); + } + }, ShipMessage::NewShip(new_ship) => { - self.ships.insert(id, new_ship); + if self.authenticated_ships.contains(&id) { + self.ships.insert(id, new_ship); + } }, _ => {} } @@ -681,7 +692,7 @@ mod test { } } - let mut server = CharacterServerState::new(TestData {}); + let mut server = CharacterServerState::new(TestData {}, AuthToken("".into())); let mut clientstate = ClientState::new(); clientstate.user = Some(UserAccountEntity { id: UserAccountId(1), @@ -716,7 +727,7 @@ mod test { #[derive(Clone)] struct TestData; impl EntityGateway for TestData {} - let mut server = CharacterServerState::new(TestData {}); + let mut server = CharacterServerState::new(TestData {}, AuthToken("".into())); let send = server.handle(ClientId(1), &RecvCharacterPacket::Checksum(Checksum {checksum: 1234, padding: 0, })).await.unwrap().collect::>(); @@ -746,7 +757,7 @@ mod test { at_ship: false, }); - let mut server = CharacterServerState::new(test_data.clone()); + let mut server = CharacterServerState::new(test_data.clone(), AuthToken("".into())); server.clients.insert(ClientId(1), fake_user.clone()); let mut send = server.handle(ClientId(1), &RecvCharacterPacket::SetFlag(SetFlag {flags: 1})).await.unwrap().collect::>(); assert!(test_data.get_user_by_id(UserAccountId(3)).await.unwrap().flags == 1); diff --git a/src/ship/ship.rs b/src/ship/ship.rs index ddbcb2d..66e2fbe 100644 --- a/src/ship/ship.rs +++ b/src/ship/ship.rs @@ -298,6 +298,7 @@ pub struct ShipServerStateBuilder { name: Option, ip: Option, port: Option, + auth_token: Option, } impl ShipServerStateBuilder { @@ -307,6 +308,7 @@ impl ShipServerStateBuilder { name: None, ip: None, port: None, + auth_token: None, } } @@ -330,6 +332,11 @@ impl ShipServerStateBuilder { self } + pub fn auth_token(mut self, auth_token: AuthToken) -> ShipServerStateBuilder { + self.auth_token = Some(auth_token); + self + } + pub fn build(self) -> ShipServerState { ShipServerState { entity_gateway: self.entity_gateway.unwrap(), @@ -343,6 +350,7 @@ impl ShipServerStateBuilder { ip: self.ip.unwrap_or(Ipv4Addr::new(127,0,0,1)), port: self.port.unwrap_or(SHIP_PORT), shops: Box::new(ItemShops::new()), + auth_token: self.auth_token.unwrap_or(AuthToken("".into())), } } } @@ -359,6 +367,7 @@ pub struct ShipServerState { ip: Ipv4Addr, port: u16, shops: Box, + auth_token: AuthToken, } impl ShipServerState { @@ -626,12 +635,14 @@ impl InterserverActor for ShipServerState { type Error = (); async fn on_connect(&mut self, id: ServerId) -> Vec<(ServerId, Self::SendMessage)> { - vec![ /* ShipMessage::Authenticate(AuthToken("hi".into())), */ (id, ShipMessage::NewShip(Ship { - name: self.name.clone(), - ip: self.ip.clone(), - port: self.port, - block_count: 2, - })) ] + vec![ + (id, ShipMessage::Authenticate(self.auth_token.clone())), + (id, ShipMessage::NewShip(Ship { + name: self.name.clone(), + ip: self.ip.clone(), + port: self.port, + block_count: 2, + })) ] } async fn action(&mut self, _id: ServerId, _msg: Self::RecvMessage) -> Result, Self::Error> { From 8717024694cf92304dd9380acab86700a3b1a37e Mon Sep 17 00:00:00 2001 From: jake Date: Sun, 1 Nov 2020 09:04:37 -0700 Subject: [PATCH 09/11] move errors to anyhow to get backtraces --- Cargo.toml | 1 + src/login/character.rs | 33 +++++++++++---------- src/login/login.rs | 14 +++++---- src/ship/ship.rs | 66 +++++++++++++++++++++--------------------- 4 files changed, 59 insertions(+), 55 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ccd7a08..82937c9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,4 +34,5 @@ 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" +anyhow = "1.0.33" diff --git a/src/login/character.rs b/src/login/character.rs index 87da4b6..d720e4e 100644 --- a/src/login/character.rs +++ b/src/login/character.rs @@ -33,7 +33,8 @@ use crate::common::interserver::AuthToken; pub const CHARACTER_PORT: u16 = 12001; const SHIP_MENU_ID: u32 = 1; -#[derive(Debug)] +#[derive(thiserror::Error, Debug)] +#[error("")] pub enum CharacterError { InvalidMenuSelection(u32, u32), ClientNotFound(ClientId), @@ -284,7 +285,7 @@ impl CharacterServerState { } } - async fn validate_login(&mut self, id: ClientId, pkt: &Login) -> Result, CharacterError> { + async fn validate_login(&mut self, id: ClientId, pkt: &Login) -> Result, anyhow::Error> { let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?; Ok(match get_login_status(&self.entity_gateway, pkt).await.and_then(check_if_already_online) { Ok(mut user) => { @@ -304,7 +305,7 @@ impl CharacterServerState { }) } - fn send_ship_list(&mut self, _id: ClientId, _pkt: &Login) -> Result, CharacterError> { + fn send_ship_list(&mut self, _id: ClientId, _pkt: &Login) -> Result, anyhow::Error> { Ok(vec![SendCharacterPacket::Timestamp(Timestamp::new(chrono::Utc::now())), SendCharacterPacket::ShipList(ShipList::new(self.ships.iter().map(|(i, s)| { ShipListEntry { @@ -317,7 +318,7 @@ impl CharacterServerState { ]) } - async fn get_settings(&mut self, id: ClientId) -> Result, CharacterError> { + async fn get_settings(&mut self, id: ClientId) -> Result, anyhow::Error> { let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?; let user = client.user.as_ref().unwrap(); @@ -336,7 +337,7 @@ impl CharacterServerState { Ok(vec![pkt]) } - async fn char_select(&mut self, id: ClientId, select: &CharSelect) -> Result, CharacterError> { + async fn char_select(&mut self, id: ClientId, select: &CharSelect) -> Result, anyhow::Error> { 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.map_err(|_| CharacterError::CouldNotLoadCharacters)?); @@ -382,7 +383,7 @@ impl CharacterServerState { })] } - async fn guildcard_data_header(&mut self, id: ClientId) -> Result, CharacterError> { + async fn guildcard_data_header(&mut self, id: ClientId) -> Result, anyhow::Error> { 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.map_err(|_| CharacterError::CouldNotLoadGuildcard)?; @@ -394,7 +395,7 @@ impl CharacterServerState { Ok(vec![SendCharacterPacket::GuildcardDataHeader(GuildcardDataHeader::new(bytes.len(), crc.sum32()))]) } - fn guildcard_data_chunk(&mut self, id: ClientId, chunk: u32, again: u32) -> Result, CharacterError> { + fn guildcard_data_chunk(&mut self, id: ClientId, chunk: u32, again: u32) -> Result, anyhow::Error> { let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?; Ok(if again != 0 { let start = chunk as usize * GUILD_CARD_CHUNK_SIZE; @@ -410,7 +411,7 @@ impl CharacterServerState { }) } - async fn set_flag(&mut self, id: ClientId, setflag: &SetFlag) -> Result, CharacterError> { + async fn set_flag(&mut self, id: ClientId, setflag: &SetFlag) -> Result, anyhow::Error> { let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?; let mut user = client.user.as_mut().unwrap(); user.flags = setflag.flags; @@ -418,7 +419,7 @@ impl CharacterServerState { Ok(None.into_iter()) } - fn param_data_chunk_request(&mut self, id: ClientId, _request: &ParamDataChunkRequest) -> Result, CharacterError> { + fn param_data_chunk_request(&mut self, id: ClientId, _request: &ParamDataChunkRequest) -> Result, anyhow::Error> { let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?; let chunk = client.param_index; client.param_index += 1; @@ -439,7 +440,7 @@ impl CharacterServerState { // TODO: move USERFLAGS over to SessionAction - async fn character_preview(&mut self, id: ClientId, preview: &CharacterPreview) -> Result, CharacterError> { + async fn character_preview(&mut self, id: ClientId, preview: &CharacterPreview) -> Result, anyhow::Error> { let client = self.clients.get_mut(&id).ok_or(CharacterError::ClientNotFound(id))?; let mut user = client.user.as_mut().unwrap(); if user.flags == USERFLAG_NEWCHAR { @@ -463,9 +464,9 @@ impl CharacterServerState { ]) } - fn select_ship(&mut self, menuselect: &MenuSelect) -> Result, CharacterError> { + fn select_ship(&mut self, menuselect: &MenuSelect) -> Result, anyhow::Error> { if menuselect.menu != SHIP_MENU_ID { - return Err(CharacterError::InvalidMenuSelection(menuselect.menu, menuselect.item)); + Err(CharacterError::InvalidMenuSelection(menuselect.menu, menuselect.item))?; } let ship = self.ships.get(&ServerId(menuselect.item as usize)) @@ -478,9 +479,9 @@ impl CharacterServerState { impl ServerState for CharacterServerState { type SendPacket = SendCharacterPacket; type RecvPacket = RecvCharacterPacket; - type PacketError = CharacterError; + type PacketError = anyhow::Error; - async fn on_connect(&mut self, id: ClientId) -> Result>, CharacterError> { + async fn on_connect(&mut self, id: ClientId) -> Result>, anyhow::Error> { self.clients.insert(id, ClientState::new()); let mut rng = rand::thread_rng(); @@ -497,7 +498,7 @@ impl ServerState for CharacterServerState { } async fn handle(&mut self, id: ClientId, pkt: &RecvCharacterPacket) - -> Result + Send>, CharacterError> { + -> Result + Send>, anyhow::Error> { Ok(match pkt { RecvCharacterPacket::Login(login) => { if login.session.action == SessionAction::SelectCharacter { @@ -540,7 +541,7 @@ impl ServerState for CharacterServerState { }) } - async fn on_disconnect(&mut self, id: ClientId) -> Result, CharacterError> { + async fn on_disconnect(&mut self, id: ClientId) -> Result, anyhow::Error> { if let Some(client) = self.clients.remove(&id) { if let Some(mut user) = client.user { user.at_character= false; diff --git a/src/login/login.rs b/src/login/login.rs index c6d818f..18bfa1a 100644 --- a/src/login/login.rs +++ b/src/login/login.rs @@ -20,7 +20,8 @@ use crate::entity::account::{UserAccountEntity}; pub const LOGIN_PORT: u16 = 12000; pub const COMMUNICATION_PORT: u16 = 12123; -#[derive(Debug)] +#[derive(thiserror::Error, Debug)] +#[error("")] pub enum LoginError { DbError } @@ -110,7 +111,7 @@ impl LoginServerState { } } - async fn validate_login(&mut self, id: ClientId, pkt: &Login) -> Result, LoginError> { + async fn validate_login(&mut self, id: ClientId, pkt: &Login) -> Result, anyhow::Error> { match get_login_status(&self.entity_gateway, pkt).await.and_then(check_if_already_online) { Ok(mut user) => { user.at_login = true; @@ -133,9 +134,10 @@ impl LoginServerState { impl ServerState for LoginServerState { type SendPacket = SendLoginPacket; type RecvPacket = RecvLoginPacket; - type PacketError = LoginError; + //type PacketError = LoginError; + type PacketError = anyhow::Error; - async fn on_connect(&mut self, _id: ClientId) -> Result>, LoginError> { + async fn on_connect(&mut self, _id: ClientId) -> Result>, anyhow::Error> { let mut rng = rand::thread_rng(); let mut server_key = [0u8; 48]; @@ -150,7 +152,7 @@ impl ServerState for LoginServerState { } async fn handle(&mut self, id: ClientId, pkt: &Self::RecvPacket) - -> Result + Send>, LoginError> { + -> Result + Send>, anyhow::Error> { Ok(match pkt { RecvLoginPacket::Login(login) => { Box::new(self.validate_login(id, login).await? @@ -162,7 +164,7 @@ impl ServerState for LoginServerState { }) } - async fn on_disconnect(&mut self, id: ClientId) -> Result, LoginError> { + async fn on_disconnect(&mut self, id: ClientId) -> Result, anyhow::Error> { 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; diff --git a/src/ship/ship.rs b/src/ship/ship.rs index 66e2fbe..2c04c8a 100644 --- a/src/ship/ship.rs +++ b/src/ship/ship.rs @@ -375,93 +375,93 @@ impl ShipServerState { ShipServerStateBuilder::new() } - async fn message(&mut self, id: ClientId, msg: &Message) -> Result + Send>, ShipError> { - match &msg.msg { + async fn message(&mut self, id: ClientId, msg: &Message) -> Result + Send>, anyhow::Error> { + Ok(match &msg.msg { GameMessage::RequestExp(request_exp) => { - handler::message::request_exp(id, request_exp, &mut self.entity_gateway, &self.client_location, &mut self.clients, &mut self.rooms, &self.level_table).await + handler::message::request_exp(id, request_exp, &mut self.entity_gateway, &self.client_location, &mut self.clients, &mut self.rooms, &self.level_table).await? }, GameMessage::PlayerDropItem(player_drop_item) => { - handler::message::player_drop_item(id, player_drop_item, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.rooms, &mut self.item_manager).await + handler::message::player_drop_item(id, player_drop_item, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.rooms, &mut self.item_manager).await? }, GameMessage::DropCoordinates(drop_coordinates) => { - handler::message::drop_coordinates(id, drop_coordinates, &self.client_location, &mut self.clients, &self.rooms) + handler::message::drop_coordinates(id, drop_coordinates, &self.client_location, &mut self.clients, &self.rooms)? }, GameMessage::PlayerNoLongerHasItem(no_longer_has_item) => { - handler::message::split_item_stack(id, no_longer_has_item, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.item_manager).await + handler::message::split_item_stack(id, no_longer_has_item, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.item_manager).await? }, GameMessage::PlayerChangedMap(_) | GameMessage::PlayerChangedMap2(_) | GameMessage::TellOtherPlayerMyLocation(_) | GameMessage::PlayerWarpingToFloor(_) | GameMessage::PlayerTeleported(_) | GameMessage::PlayerStopped(_) | GameMessage::PlayerLoadedIn(_) | GameMessage::PlayerWalking(_) | GameMessage::PlayerRunning(_) | GameMessage::PlayerWarped(_) | GameMessage::PlayerChangedFloor(_) | GameMessage::InitializeSpeechNpc(_) => { - handler::message::update_player_position(id, &msg, &mut self.clients, &mut self.client_location, &self.rooms) + handler::message::update_player_position(id, &msg, &mut self.clients, &mut self.client_location, &self.rooms)? }, GameMessage::ChargeAttack(charge_attack) => { - handler::message::charge_attack(id, charge_attack, &mut self.clients, &mut self.entity_gateway).await + handler::message::charge_attack(id, charge_attack, &mut self.clients, &mut self.entity_gateway).await? }, GameMessage::PlayerUseItem(player_use_item) => { - handler::message::use_item(id, player_use_item, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.item_manager).await + handler::message::use_item(id, player_use_item, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.item_manager).await? }, GameMessage::PlayerUsedMedicalCenter(player_used_medical_center) => { - handler::message::player_used_medical_center(id, &player_used_medical_center, &mut self.entity_gateway, &mut self.clients).await + handler::message::player_used_medical_center(id, &player_used_medical_center, &mut self.entity_gateway, &mut self.clients).await? }, GameMessage::PlayerFeedMag(player_feed_mag) => { - handler::message::player_feed_mag(id, &player_feed_mag, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.item_manager).await + handler::message::player_feed_mag(id, &player_feed_mag, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.item_manager).await? }, GameMessage::PlayerEquipItem(player_equip_item) => { - handler::message::player_equips_item(id, &player_equip_item, &mut self.entity_gateway, &mut self.clients, &mut self.item_manager).await + handler::message::player_equips_item(id, &player_equip_item, &mut self.entity_gateway, &mut self.clients, &mut self.item_manager).await? }, GameMessage::PlayerUnequipItem(player_unequip_item) => { - handler::message::player_unequips_item(id, &player_unequip_item, &mut self.entity_gateway, &mut self.clients, &mut self.item_manager).await + handler::message::player_unequips_item(id, &player_unequip_item, &mut self.entity_gateway, &mut self.clients, &mut self.item_manager).await? }, GameMessage::SortItems(sort_items) => { handler::message::player_sorts_items(id, sort_items, &mut self.entity_gateway, &mut self.clients, &mut self.item_manager).await }, _ => { let cmsg = msg.clone(); - Ok(Box::new(self.client_location.get_client_neighbors(id).unwrap().into_iter() + Box::new(self.client_location.get_client_neighbors(id).unwrap().into_iter() .map(move |client| { (client.client, SendShipPacket::Message(cmsg.clone())) - }))) + })) }, - } + }) } - async fn direct_message(&mut self, id: ClientId, msg: &DirectMessage) -> Result + Send>, ShipError> { + async fn direct_message(&mut self, id: ClientId, msg: &DirectMessage) -> Result + Send>, anyhow::Error> { let target = msg.flag; - match &msg.msg { + Ok(match &msg.msg { GameMessage::GuildcardSend(guildcard_send) => { - Ok(handler::direct_message::guildcard_send(id, guildcard_send, target, &self.client_location, &self.clients)) + handler::direct_message::guildcard_send(id, guildcard_send, target, &self.client_location, &self.clients) }, GameMessage::RequestItem(request_item) => { - handler::direct_message::request_item(id, request_item, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.rooms, &mut self.item_manager).await + handler::direct_message::request_item(id, request_item, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.rooms, &mut self.item_manager).await? }, GameMessage::PickupItem(pickup_item) => { - handler::direct_message::pickup_item(id, pickup_item, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.item_manager).await + handler::direct_message::pickup_item(id, pickup_item, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.item_manager).await? }, GameMessage::BoxDropRequest(box_drop_request) => { - handler::direct_message::request_box_item(id, box_drop_request, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.rooms, &mut self.item_manager).await + handler::direct_message::request_box_item(id, box_drop_request, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.rooms, &mut self.item_manager).await? }, GameMessage::BankRequest(_bank_request) => { - handler::direct_message::send_bank_list(id, &self.clients, &mut self.item_manager).await + handler::direct_message::send_bank_list(id, &self.clients, &mut self.item_manager).await? }, GameMessage::BankInteraction(bank_interaction) => { - handler::direct_message::bank_interaction(id, bank_interaction, &mut self.entity_gateway, &self.client_location, &mut self.clients, &mut self.item_manager).await + handler::direct_message::bank_interaction(id, bank_interaction, &mut self.entity_gateway, &self.client_location, &mut self.clients, &mut self.item_manager).await? }, GameMessage::ShopRequest(shop_request) => { - handler::direct_message::shop_request(id, shop_request, &self.client_location, &mut self.clients, &self.rooms, &self.level_table, &mut self.shops).await + handler::direct_message::shop_request(id, shop_request, &self.client_location, &mut self.clients, &self.rooms, &self.level_table, &mut self.shops).await? }, GameMessage::BuyItem(buy_item) => { - handler::direct_message::buy_item(id, buy_item, &mut self.entity_gateway, &self.client_location, &mut self.clients, &mut self.item_manager).await + handler::direct_message::buy_item(id, buy_item, &mut self.entity_gateway, &self.client_location, &mut self.clients, &mut self.item_manager).await? }, _ => { let cmsg = msg.clone(); - Ok(Box::new(self.client_location.get_all_clients_by_client(id).unwrap().into_iter() + Box::new(self.client_location.get_all_clients_by_client(id).unwrap().into_iter() .filter(move |client| client.local_client.id() == target as u8) .map(move |client| { (client.client, SendShipPacket::DirectMessage(cmsg.clone())) - }))) + })) }, - } + }) } } @@ -469,9 +469,9 @@ impl ShipServerState { impl ServerState for ShipServerState { type SendPacket = SendShipPacket; type RecvPacket = RecvShipPacket; - type PacketError = ShipError; + type PacketError = anyhow::Error; - async fn on_connect(&mut self, _id: ClientId) -> Result>, ShipError> { + async fn on_connect(&mut self, _id: ClientId) -> Result>, anyhow::Error> { let mut rng = rand::thread_rng(); let mut server_key = [0u8; 48]; @@ -486,7 +486,7 @@ impl ServerState for ShipServerState { } async fn handle(&mut self, id: ClientId, pkt: &RecvShipPacket) - -> Result + Send>, ShipError> { + -> Result + Send>, anyhow::Error> { Ok(match pkt { RecvShipPacket::Login(login) => { Box::new(handler::auth::validate_login(id, login, &mut self.entity_gateway, &mut self.clients, &mut self.item_manager, &self.name).await?.into_iter().map(move |pkt| (id, pkt))) @@ -593,7 +593,7 @@ impl ServerState for ShipServerState { }) } - async fn on_disconnect(&mut self, id: ClientId) -> Result, ShipError> { + async fn on_disconnect(&mut self, id: ClientId) -> Result, anyhow::Error> { // TODO: don't unwrap! let client = self.clients.get(&id).ok_or(ShipError::ClientNotFound(id))?; let area_client = self.client_location.get_local_client(id)?; From 73c24a5d200c4b11851a62a750a6dadd8ddc5f83 Mon Sep 17 00:00:00 2001 From: jake Date: Sun, 1 Nov 2020 18:05:09 -0700 Subject: [PATCH 10/11] cleanup --- src/login/login.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/login/login.rs b/src/login/login.rs index 18bfa1a..ca11820 100644 --- a/src/login/login.rs +++ b/src/login/login.rs @@ -63,11 +63,7 @@ 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) - }*/ - log::info!("user: {}, activated {}", user.username, user.activated); if !user.activated { return Err(AccountStatus::PayUp) } @@ -233,7 +229,7 @@ mod test { }) } - async fn save_user(&mut self, user: &UserAccountEntity) -> Result<(), GatewayError> { + async fn save_user(&mut self, _user: &UserAccountEntity) -> Result<(), GatewayError> { Ok(()) } }; From 3dd25c322247ae0a8c5d444f0225fd8a8e76d964 Mon Sep 17 00:00:00 2001 From: jake Date: Mon, 2 Nov 2020 00:03:22 -0700 Subject: [PATCH 11/11] merge conflict --- src/ship/ship.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ship/ship.rs b/src/ship/ship.rs index 2c04c8a..a717acb 100644 --- a/src/ship/ship.rs +++ b/src/ship/ship.rs @@ -414,7 +414,7 @@ impl ShipServerState { handler::message::player_unequips_item(id, &player_unequip_item, &mut self.entity_gateway, &mut self.clients, &mut self.item_manager).await? }, GameMessage::SortItems(sort_items) => { - handler::message::player_sorts_items(id, sort_items, &mut self.entity_gateway, &mut self.clients, &mut self.item_manager).await + handler::message::player_sorts_items(id, sort_items, &mut self.entity_gateway, &mut self.clients, &mut self.item_manager).await? }, _ => { let cmsg = msg.clone();