diff --git a/src/client/game.cpp b/src/client/game.cpp index c9bcaba86..c13e4aa05 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -4536,7 +4536,7 @@ void the_game(bool *kill, error_message = e.what(); errorstream << "ServerError: " << error_message << std::endl; } catch (ModError &e) { - // DO NOT TRANSLATE the `ModError`, it's used by ui.lua + // DO NOT TRANSLATE the `ModError`, it's used by `ui.lua` error_message = std::string("ModError: ") + e.what() + strgettext("\nCheck debug.txt for details."); errorstream << error_message << std::endl; diff --git a/src/server.cpp b/src/server.cpp index 3380ac63c..2dca13cf0 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -74,6 +74,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "database/database-dummy.h" #include "gameparams.h" #include "particles.h" +#include "gettext.h" class ClientNotFoundException : public BaseException { @@ -235,7 +236,7 @@ Server::Server( Address bind_addr, bool dedicated, ChatInterface *iface, - std::string *on_shutdown_errmsg + std::string *shutdown_errmsg ): m_bind_addr(bind_addr), m_path_world(path_world), @@ -254,7 +255,7 @@ Server::Server( m_thread(new ServerThread(this)), m_clients(m_con), m_admin_chat(iface), - m_on_shutdown_errmsg(on_shutdown_errmsg), + m_shutdown_errmsg(shutdown_errmsg), m_modchannel_mgr(new ModChannelMgr()) { if (m_path_world.empty()) @@ -353,14 +354,7 @@ Server::~Server() try { m_script->on_shutdown(); } catch (ModError &e) { - errorstream << "ModError: " << e.what() << std::endl; - if (m_on_shutdown_errmsg) { - if (m_on_shutdown_errmsg->empty()) { - *m_on_shutdown_errmsg = std::string("ModError: ") + e.what(); - } else { - *m_on_shutdown_errmsg += std::string("\nModError: ") + e.what(); - } - } + addShutdownError(e); } infostream << "Server: Saving environment metadata" << std::endl; @@ -3759,6 +3753,23 @@ std::string Server::getBuiltinLuaPath() return porting::path_share + DIR_DELIM + "builtin"; } +// Not thread-safe. +void Server::addShutdownError(const ModError &e) +{ + // DO NOT TRANSLATE the `ModError`, it's used by `ui.lua` + std::string msg = fmtgettext("%s while shutting down: ", "ModError") + + e.what() + strgettext("\nCheck debug.txt for details."); + errorstream << msg << std::endl; + + if (m_shutdown_errmsg) { + if (m_shutdown_errmsg->empty()) { + *m_shutdown_errmsg = msg; + } else { + *m_shutdown_errmsg += "\n\n" + msg; + } + } +} + v3f Server::findSpawnPos() { ServerMap &map = m_env->getServerMap(); diff --git a/src/server.h b/src/server.h index faa23e74e..6c9f80180 100644 --- a/src/server.h +++ b/src/server.h @@ -150,7 +150,7 @@ public: Address bind_addr, bool dedicated, ChatInterface *iface = nullptr, - std::string *on_shutdown_errmsg = nullptr + std::string *shutdown_errmsg = nullptr ); ~Server(); DISABLE_CLASS_COPY(Server); @@ -300,6 +300,9 @@ public: setAsyncFatalError(std::string("Lua: ") + e.what()); } + // Not thread-safe. + void addShutdownError(const ModError &e); + bool showFormspec(const char *name, const std::string &formspec, const std::string &formname); Map & getMap() { return m_env->getMap(); } ServerEnvironment & getEnv() { return *m_env; } @@ -655,9 +658,9 @@ private: ChatInterface *m_admin_chat; std::string m_admin_nick; - // if a mod-error occurs in the on_shutdown callback, the error message will - // be written into this - std::string *const m_on_shutdown_errmsg; + // If a mod error occurs while shutting down, the error message will be + // written into this. + std::string *const m_shutdown_errmsg; /* Map edit event queue. Automatically receives all map edits. diff --git a/src/serverenvironment.cpp b/src/serverenvironment.cpp index 3925dab6d..a2f721b40 100644 --- a/src/serverenvironment.cpp +++ b/src/serverenvironment.cpp @@ -510,8 +510,12 @@ ServerEnvironment::~ServerEnvironment() // This makes the next one delete all active objects. m_active_blocks.clear(); - // Convert all objects to static and delete the active objects - deactivateFarObjects(true); + try { + // Convert all objects to static and delete the active objects + deactivateFarObjects(true); + } catch (ModError &e) { + m_server->addShutdownError(e); + } // Drop/delete map if (m_map)