From 8b9e32b93f448684db57e3403b285c39450f865b Mon Sep 17 00:00:00 2001
From: kaedr <kaedraar@gmail.com>
Date: Fri, 15 Oct 2021 19:41:31 -0400
Subject: [PATCH 1/4] Fixed obfuscation of error messages caused by previous
 commits

---
 assets/voxygen/i18n/en/main.ron | 2 +-
 voxygen/src/menu/main/mod.rs    | 3 ++-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/assets/voxygen/i18n/en/main.ron b/assets/voxygen/i18n/en/main.ron
index 35a8830591..79c7f4ad90 100644
--- a/assets/voxygen/i18n/en/main.ron
+++ b/assets/voxygen/i18n/en/main.ron
@@ -60,7 +60,7 @@ https://veloren.net/account/."#,
         "main.login.select_language": "Select a language",
         "main.login.client_version": "Client Version",
         "main.login.server_version": "Server Version",
-        "main.login.client_init_failed": "Client failed to initialize.",
+        "main.login.client_init_failed": "Client failed to initialize: {init_fail_reason}",
         "main.login.username_bad_characters": "Username contains invalid characters! (Only alphanumeric, '_' and '-' are allowed)",
         "main.login.username_too_long": "Username is too long! Max length is: {max_len}",
         "main.servers.select_server": "Select a server",
diff --git a/voxygen/src/menu/main/mod.rs b/voxygen/src/menu/main/mod.rs
index c0be40a378..e2bcc6b8ee 100644
--- a/voxygen/src/menu/main/mod.rs
+++ b/voxygen/src/menu/main/mod.rs
@@ -154,7 +154,8 @@ impl PlayState for MainMenuState {
                 global_state.info_message = Some(
                     localized_strings
                         .get("main.login.client_init_failed")
-                        .to_owned(),
+                        .to_owned()
+                        .replace("{init_fail_reason}", e.as_str()),
                 );
             },
             Some(InitMsg::IsAuthTrusted(auth_server)) => {

From 84eb999143bc099a6e96574e15060c2eb57e9e13 Mon Sep 17 00:00:00 2001
From: kaedr <kaedraar@gmail.com>
Date: Sat, 16 Oct 2021 20:15:32 -0400
Subject: [PATCH 2/4] Added localization for server error message display on
 client

---
 assets/voxygen/i18n/en/main.ron |  8 +++++++-
 voxygen/src/menu/main/mod.rs    | 30 ++++++++++++++++++++++++++++--
 2 files changed, 35 insertions(+), 3 deletions(-)

diff --git a/assets/voxygen/i18n/en/main.ron b/assets/voxygen/i18n/en/main.ron
index 79c7f4ad90..48209ec675 100644
--- a/assets/voxygen/i18n/en/main.ron
+++ b/assets/voxygen/i18n/en/main.ron
@@ -64,7 +64,13 @@ https://veloren.net/account/."#,
         "main.login.username_bad_characters": "Username contains invalid characters! (Only alphanumeric, '_' and '-' are allowed)",
         "main.login.username_too_long": "Username is too long! Max length is: {max_len}",
         "main.servers.select_server": "Select a server",
-        "main.servers.singleplayer_error": "Failed to connect to internal server.",
+        "main.servers.singleplayer_error": "Failed to connect to internal server: {sp_error}",
+        "main.servers.network_error": "Server network/socket error: {raw_error}",
+        "main.servers.participant_error": "Participant disconnect/protocol error: {raw_error}",
+        "main.servers.stream_error": "Client connection/compression/(de)serialization error: {raw_error}",
+        "main.servers.database_error": "Server database error: {raw_error}",
+        "main.servers.persistence_error": "Server persistence error (Probably Asset/Character Data related): {raw_error}",
+        "main.servers.other_error": "Server general error: {raw_error}",
 
         // Credits screen
         "main.credits": "Credits",
diff --git a/voxygen/src/menu/main/mod.rs b/voxygen/src/menu/main/mod.rs
index e2bcc6b8ee..f01047eca7 100644
--- a/voxygen/src/menu/main/mod.rs
+++ b/voxygen/src/menu/main/mod.rs
@@ -113,17 +113,43 @@ impl PlayState for MainMenuState {
                         global_state.singleplayer = None;
                         self.init = InitState::None;
                         self.main_menu_ui.cancel_connection();
+                        let server_err = match e {
+                            server::Error::NetworkErr(e) => localized_strings
+                                .get("main.servers.network_error")
+                                .to_owned()
+                                .replace("{raw_error}", e.to_string().as_str()),
+                            server::Error::ParticipantErr(e) => localized_strings
+                                .get("main.servers.participant_error")
+                                .to_owned()
+                                .replace("{raw_error}", e.to_string().as_str()),
+                            server::Error::StreamErr(e) => localized_strings
+                                .get("main.servers.stream_error")
+                                .to_owned()
+                                .replace("{raw_error}", e.to_string().as_str()),
+                            server::Error::DatabaseErr(e) => localized_strings
+                                .get("main.servers.database_error")
+                                .to_owned()
+                                .replace("{raw_error}", e.to_string().as_str()),
+                            server::Error::PersistenceErr(e) => localized_strings
+                                .get("main.servers.persistence_error")
+                                .to_owned()
+                                .replace("{raw_error}", e.to_string().as_str()),
+                            server::Error::Other(e) => localized_strings
+                                .get("main.servers.other_error")
+                                .to_owned()
+                                .replace("{raw_error}", e.to_string().as_str()),
+                        };
                         global_state.info_message = Some(
                             localized_strings
                                 .get("main.servers.singleplayer_error")
-                                .to_owned(),
+                                .to_owned()
+                                .replace("{sp_error}", server_err.as_str()),
                         );
                     },
                     Err(_) => (),
                 }
             }
         }
-
         // Handle window events.
         for event in events {
             // Pass all events to the ui first.

From c21a67a14095c146ad7ce6b37c8d88bf84df9323 Mon Sep 17 00:00:00 2001
From: kaedr <kaedraar@gmail.com>
Date: Sat, 16 Oct 2021 20:16:34 -0400
Subject: [PATCH 3/4] Added handling for connection errors that occur before
 client leaves login screen

---
 voxygen/src/menu/main/ui/mod.rs | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/voxygen/src/menu/main/ui/mod.rs b/voxygen/src/menu/main/ui/mod.rs
index fee8c40660..374422af22 100644
--- a/voxygen/src/menu/main/ui/mod.rs
+++ b/voxygen/src/menu/main/ui/mod.rs
@@ -24,6 +24,7 @@ use crate::settings::Settings;
 use common::assets::{self, AssetExt};
 use rand::{seq::SliceRandom, thread_rng};
 use std::time::Duration;
+use tracing::warn;
 
 // TODO: what is this? (showed up in rebase)
 //const COL1: Color = Color::Rgba(0.07, 0.1, 0.1, 0.9);
@@ -455,11 +456,15 @@ impl Controls {
     }
 
     fn connection_error(&mut self, error: String) {
-        if matches!(&self.screen, Screen::Connecting { .. }) {
+        if matches!(&self.screen, Screen::Connecting { .. })
+            || matches!(&self.screen, Screen::Login { .. })
+        {
             self.screen = Screen::Login {
                 screen: Box::new(login::Screen::new()),
                 error: Some(error),
             }
+        } else {
+            warn!("connection_error invoked on unhandled screen!");
         }
     }
 

From 9e7cb219b8b9913535159623ab366760cf6b14bc Mon Sep 17 00:00:00 2001
From: kaedr <kaedraar@gmail.com>
Date: Sat, 16 Oct 2021 20:41:13 -0400
Subject: [PATCH 4/4] Fixed redundant to_string() call.

---
 voxygen/src/menu/main/mod.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/voxygen/src/menu/main/mod.rs b/voxygen/src/menu/main/mod.rs
index f01047eca7..ba85ee38fb 100644
--- a/voxygen/src/menu/main/mod.rs
+++ b/voxygen/src/menu/main/mod.rs
@@ -137,7 +137,7 @@ impl PlayState for MainMenuState {
                             server::Error::Other(e) => localized_strings
                                 .get("main.servers.other_error")
                                 .to_owned()
-                                .replace("{raw_error}", e.to_string().as_str()),
+                                .replace("{raw_error}", e.as_str()),
                         };
                         global_state.info_message = Some(
                             localized_strings