diff --git a/src/script/api/script_log.cpp b/src/script/api/script_log.cpp index eeee4e620f..faaf03e6c2 100644 --- a/src/script/api/script_log.cpp +++ b/src/script/api/script_log.cpp @@ -90,3 +90,11 @@ free(log->type); delete log; } + +/* static */ void ScriptLog::LogOnce(ScriptLog::ScriptLogType level, std::string &&message) +{ + if (ScriptObject::IsNewUniqueLogMessage(message)) { + ScriptLog::Log(level, message.c_str()); + ScriptObject::RegisterUniqueLogMessage(std::move(message)); + } +} diff --git a/src/script/api/script_log.hpp b/src/script/api/script_log.hpp index a71e09c2ef..c9d4a4a7c9 100644 --- a/src/script/api/script_log.hpp +++ b/src/script/api/script_log.hpp @@ -75,6 +75,12 @@ public: */ static void FreeLogPointer(); + /** + * Log this message once. + * @api -all + */ + static void LogOnce(ScriptLog::ScriptLogType level, std::string &&message); + private: /** * Internal command to log the message in a common way. diff --git a/src/script/api/script_object.cpp b/src/script/api/script_object.cpp index 4f6a53e4bf..950362cd8a 100644 --- a/src/script/api/script_object.cpp +++ b/src/script/api/script_object.cpp @@ -411,3 +411,13 @@ void ScriptObject::InitializeRandomizers() ScriptObject::GetRandomizer(owner).SetSeed(random.Next()); } } + +/* static */ bool ScriptObject::IsNewUniqueLogMessage(const std::string &msg) +{ + return !GetStorage()->seen_unique_log_messages.contains(msg); +} + +/* static */ void ScriptObject::RegisterUniqueLogMessage(std::string &&msg) +{ + GetStorage()->seen_unique_log_messages.emplace(std::move(msg)); +} diff --git a/src/script/api/script_object.hpp b/src/script/api/script_object.hpp index 70526c118c..2109b7db2d 100644 --- a/src/script/api/script_object.hpp +++ b/src/script/api/script_object.hpp @@ -304,6 +304,10 @@ protected: */ static char *GetString(StringID string); + static bool IsNewUniqueLogMessage(const std::string &msg); + + static void RegisterUniqueLogMessage(std::string &&msg); + private: /** * Store a new_vehicle_id per company. diff --git a/src/script/api/script_text.cpp b/src/script/api/script_text.cpp index 3ec3c79935..65ed9354c0 100644 --- a/src/script/api/script_text.cpp +++ b/src/script/api/script_text.cpp @@ -170,12 +170,12 @@ const std::string ScriptText::GetEncodedText() return buf; } -void ScriptText::_TextParamError(const std::string &msg) +void ScriptText::_TextParamError(std::string msg) { if (this->GetActiveInstance()->IsTextParamMismatchAllowed()) { - ScriptLog::Error(msg.c_str()); + ScriptLog::LogOnce(ScriptLog::LOG_ERROR, std::move(msg)); } else { - throw Script_FatalError(msg); + throw Script_FatalError(std::move(msg)); } } diff --git a/src/script/api/script_text.hpp b/src/script/api/script_text.hpp index 0d86576138..13d61f0710 100644 --- a/src/script/api/script_text.hpp +++ b/src/script/api/script_text.hpp @@ -135,7 +135,7 @@ private: std::variant param[SCRIPT_TEXT_MAX_PARAMETERS]; int paramc; - void _TextParamError(const std::string &msg); + void _TextParamError(std::string msg); /** * Internal function for recursive calling this function over multiple diff --git a/src/script/script_fatalerror.hpp b/src/script/script_fatalerror.hpp index 96c64e0b9d..2c1d44ace7 100644 --- a/src/script/script_fatalerror.hpp +++ b/src/script/script_fatalerror.hpp @@ -22,6 +22,9 @@ public: Script_FatalError(const std::string &msg) : msg(msg) {} + Script_FatalError(std::string &&msg) : + msg(std::move(msg)) + {} /** * The error message associated with the fatal error. diff --git a/src/script/script_storage.hpp b/src/script/script_storage.hpp index b41b27ce23..4f1978c8fe 100644 --- a/src/script/script_storage.hpp +++ b/src/script/script_storage.hpp @@ -16,6 +16,7 @@ #include "../group.h" #include "../goal_type.h" #include "../story_type.h" +#include "../3rdparty/robin_hood/robin_hood.h" #include "table/strings.h" #include @@ -66,6 +67,8 @@ private: void *event_data; ///< Pointer to the event data storage. void *log_data; ///< Pointer to the log data storage. + robin_hood::unordered_node_set seen_unique_log_messages; ///< Messages which have already been logged once and don't need to be logged again + public: ScriptStorage() : mode (nullptr),