From 8717024694cf92304dd9380acab86700a3b1a37e Mon Sep 17 00:00:00 2001 From: jake Date: Sun, 1 Nov 2020 09:04:37 -0700 Subject: [PATCH] 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)?;