From 378691aaa286822ee20e0428d278f2bca6e7438e Mon Sep 17 00:00:00 2001 From: Treeston Date: Sat, 12 Sep 2020 19:42:10 +0200 Subject: [3.3.5] Core/ChatCommands: Show error messages from argument parsers (PR #25443) (cherry picked from commit 75f9e7396e35360f3016cc0cb21e72e20f5d96d5) --- src/common/Define.h | 3 + src/common/Utilities/Util.cpp | 21 ++- src/common/Utilities/Util.h | 13 ++ src/server/game/Chat/Chat.cpp | 6 +- src/server/game/Chat/Chat.h | 8 +- src/server/game/Chat/ChatCommands/ChatCommand.h | 70 ++++----- .../game/Chat/ChatCommands/ChatCommandArgs.cpp | 63 ++++---- .../game/Chat/ChatCommands/ChatCommandArgs.h | 158 +++++++++++++-------- .../game/Chat/ChatCommands/ChatCommandHelpers.cpp | 30 ++++ .../game/Chat/ChatCommands/ChatCommandHelpers.h | 45 ++++++ .../game/Chat/ChatCommands/ChatCommandTags.cpp | 32 +++-- .../game/Chat/ChatCommands/ChatCommandTags.h | 37 +++-- src/server/game/Miscellaneous/Language.h | 33 ++--- src/server/game/World/World.h | 4 +- src/server/scripts/Commands/cs_gobject.cpp | 4 +- src/server/scripts/Commands/cs_npc.cpp | 4 +- src/server/worldserver/CommandLine/CliRunnable.cpp | 11 +- src/server/worldserver/RemoteAccess/RASession.cpp | 6 +- src/server/worldserver/RemoteAccess/RASession.h | 4 +- src/server/worldserver/TCSoap/TCSoap.h | 4 +- 20 files changed, 351 insertions(+), 205 deletions(-) create mode 100644 src/server/game/Chat/ChatCommands/ChatCommandHelpers.cpp (limited to 'src') diff --git a/src/common/Define.h b/src/common/Define.h index 1e73dd3069c..b43dfbf610c 100644 --- a/src/common/Define.h +++ b/src/common/Define.h @@ -144,6 +144,9 @@ #define SZFMTD "%" PRIuPTR +#define STRING_VIEW_FMT "%.*s" +#define STRING_VIEW_FMT_ARG(str) static_cast((str).length()), (str).data() + typedef int64_t int64; typedef int32_t int32; typedef int16_t int16; diff --git a/src/common/Utilities/Util.cpp b/src/common/Utilities/Util.cpp index 511e4b99684..ad98bd5e491 100644 --- a/src/common/Utilities/Util.cpp +++ b/src/common/Utilities/Util.cpp @@ -21,6 +21,7 @@ #include "IpAddress.h" #include "StringConvert.h" #include "StringFormat.h" +#include #include #include #include @@ -831,19 +832,25 @@ void Trinity::Impl::HexStrToByteArray(std::string_view str, uint8* out, size_t o } } -bool StringEqualI(std::string_view str1, std::string_view str2) +bool StringEqualI(std::string_view a, std::string_view b) { - return std::equal(str1.begin(), str1.end(), str2.begin(), str2.end(), - [](char a, char b) - { - return std::tolower(a) == std::tolower(b); - }); + return std::equal(a.begin(), a.end(), b.begin(), b.end(), [](char c1, char c2) { return std::tolower(c1) == std::tolower(c2); }); } bool StringContainsStringI(std::string_view haystack, std::string_view needle) { return haystack.end() != - std::search(haystack.begin(), haystack.end(), needle.begin(), needle.end(), [](char c1, char c2) { return std::toupper(c1) == std::toupper(c2); }); + std::search(haystack.begin(), haystack.end(), needle.begin(), needle.end(), [](char c1, char c2) { return std::tolower(c1) == std::tolower(c2); }); +} + +bool StringCompareLessI(std::string_view a, std::string_view b) +{ + return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end(), [](char c1, char c2) { return std::tolower(c1) < std::tolower(c2); }); +} + +std::string GetTypeName(std::type_info const& info) +{ + return boost::core::demangle(info.name()); } float DegToRad(float degrees) diff --git a/src/common/Utilities/Util.h b/src/common/Utilities/Util.h index 61f3d17acf8..8a24981c837 100644 --- a/src/common/Utilities/Util.h +++ b/src/common/Utilities/Util.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -377,6 +378,12 @@ inline bool ValueContainsStringI(std::pair const& haystack, { return StringContainsStringI(haystack.second, needle); } +TC_COMMON_API bool StringCompareLessI(std::string_view a, std::string_view b); + +struct StringCompareLessI_T +{ + bool operator()(std::string_view a, std::string_view b) const { return StringCompareLessI(a, b); } +}; // simple class for not-modifyable list template @@ -599,6 +606,12 @@ Ret* Coalesce(T1* first, T*... rest) return static_cast(first); } +TC_COMMON_API std::string GetTypeName(std::type_info const&); +template +std::string GetTypeName() { return GetTypeName(typeid(T)); } +template +std::enable_if_t, std::type_info>, std::string> GetTypeName(T&& v) { return GetTypeName(typeid(v)); } + template struct NonDefaultConstructible { diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp index ec572e72704..dc26c3cf0c7 100644 --- a/src/server/game/Chat/Chat.cpp +++ b/src/server/game/Chat/Chat.cpp @@ -175,7 +175,7 @@ bool ChatHandler::hasStringAbbr(const char* name, const char* part) return true; } -void ChatHandler::SendSysMessage(const char *str, bool escapeCharacters) +void ChatHandler::SendSysMessage(std::string_view str, bool escapeCharacters) { std::string msg{ str }; @@ -998,7 +998,7 @@ bool CliHandler::isAvailable(ChatCommand const& cmd) const return cmd.AllowConsole; } -void CliHandler::SendSysMessage(const char *str, bool /*escapeCharacters*/) +void CliHandler::SendSysMessage(std::string_view str, bool /*escapeCharacters*/) { m_print(m_callbackArg, str); m_print(m_callbackArg, "\r\n"); @@ -1155,7 +1155,7 @@ void AddonChannelCommandHandler::SendFailed() // f Command failed, no body } // m Command message, message in body -void AddonChannelCommandHandler::SendSysMessage(char const* str, bool escapeCharacters) +void AddonChannelCommandHandler::SendSysMessage(std::string_view str, bool escapeCharacters) { ASSERT(echo); if (!hadAck) diff --git a/src/server/game/Chat/Chat.h b/src/server/game/Chat/Chat.h index d46b58446c4..9aa32019ae2 100644 --- a/src/server/game/Chat/Chat.h +++ b/src/server/game/Chat/Chat.h @@ -49,7 +49,7 @@ class TC_GAME_API ChatHandler // function with different implementation for chat/console virtual char const* GetTrinityString(uint32 entry) const; - virtual void SendSysMessage(char const* str, bool escapeCharacters = false); + virtual void SendSysMessage(std::string_view str, bool escapeCharacters = false); void SendSysMessage(uint32 entry); @@ -138,14 +138,14 @@ class TC_GAME_API ChatHandler class TC_GAME_API CliHandler : public ChatHandler { public: - typedef void Print(void*, char const*); + using Print = void(void*, std::string_view); explicit CliHandler(void* callbackArg, Print* zprint) : m_callbackArg(callbackArg), m_print(zprint) { } // overwrite functions char const* GetTrinityString(uint32 entry) const override; bool isAvailable(ChatCommand const& cmd) const override; bool HasPermission(uint32 /*permission*/) const override { return true; } - void SendSysMessage(const char *str, bool escapeCharacters) override; + void SendSysMessage(std::string_view, bool escapeCharacters) override; bool ParseCommands(char const* str) override; std::string GetNameLink() const override; bool needReportToTarget(Player* chr) const override; @@ -164,7 +164,7 @@ class TC_GAME_API AddonChannelCommandHandler : public ChatHandler using ChatHandler::ChatHandler; bool ParseCommands(char const* str) override; - void SendSysMessage(char const* str, bool escapeCharacters) override; + void SendSysMessage(std::string_view, bool escapeCharacters) override; using ChatHandler::SendSysMessage; bool IsHumanReadable() const override { return humanReadable; } diff --git a/src/server/game/Chat/ChatCommands/ChatCommand.h b/src/server/game/Chat/ChatCommands/ChatCommand.h index 28d84629eea..7b36a72d2f4 100644 --- a/src/server/game/Chat/ChatCommands/ChatCommand.h +++ b/src/server/game/Chat/ChatCommands/ChatCommand.h @@ -25,77 +25,72 @@ #include "Errors.h" #include "ObjectGuid.h" #include "Optional.h" +#include "StringFormat.h" #include #include #include #include class ChatHandler; -class CommandArgs; namespace Trinity::Impl::ChatCommands { - template - struct SingleConsumer - { - static Optional TryConsumeTo(T& val, std::string_view args) - { - return ArgInfo::TryConsume(val, args); - } - }; - - /* - for backwards compatibility, consumes the rest of the string - new code should use the Tail/WTail tags defined in ChatCommandTags - */ - template <> - struct SingleConsumer - { - static Optional TryConsumeTo(char const*& arg, std::string_view args) { arg = args.data(); return std::string_view(); } - }; - - // forward declaration // ConsumeFromOffset contains the bounds check for offset, then hands off to MultiConsumer // the call stack is MultiConsumer -> ConsumeFromOffset -> MultiConsumer -> ConsumeFromOffset etc - // MultiConsumer calls SingleConsumer in each iteration + // MultiConsumer goes into ArgInfo for parsing on each iteration template - Optional ConsumeFromOffset(Tuple&, std::string_view args); + ChatCommandResult ConsumeFromOffset(Tuple&, ChatHandler const* handler, std::string_view args); template struct MultiConsumer { - static Optional TryConsumeTo(Tuple& tuple, std::string_view args) + static ChatCommandResult TryConsumeTo(Tuple& tuple, ChatHandler const* handler, std::string_view args) { - if (Optional next = SingleConsumer::TryConsumeTo(std::get(tuple), args)) - return ConsumeFromOffset(tuple, *next); + ChatCommandResult next = ArgInfo::TryConsume(std::get(tuple), handler, args); + if (next) + return ConsumeFromOffset(tuple, handler, *next); else - return std::nullopt; + return next; } }; template struct MultiConsumer, offset> { - static Optional TryConsumeTo(Tuple& tuple, std::string_view args) + static ChatCommandResult TryConsumeTo(Tuple& tuple, ChatHandler const* handler, std::string_view args) { // try with the argument auto& myArg = std::get(tuple); myArg.emplace(); - if (Optional next = SingleConsumer::TryConsumeTo(myArg.value(), args)) - if ((next = ConsumeFromOffset(tuple, *next))) - return next; + + ChatCommandResult result1 = ArgInfo::TryConsume(myArg.value(), handler, args); + if (result1) + if ((result1 = ConsumeFromOffset(tuple, handler, *result1))) + return result1; // try again omitting the argument myArg = std::nullopt; - return ConsumeFromOffset(tuple, args); + ChatCommandResult result2 = ConsumeFromOffset(tuple, handler, args); + if (result2) + return result2; + if (result1.HasErrorMessage() && result2.HasErrorMessage()) + { + return Trinity::StringFormat("%s \"%s\"\n%s \"%s\"", + GetTrinityString(handler, LANG_CMDPARSER_EITHER), result2.GetErrorMessage().c_str(), + GetTrinityString(handler, LANG_CMDPARSER_OR), result1.GetErrorMessage().c_str()); + } + else if (result1.HasErrorMessage()) + return result1; + else + return result2; } }; template - Optional ConsumeFromOffset(Tuple& tuple, std::string_view args) + ChatCommandResult ConsumeFromOffset([[maybe_unused]] Tuple& tuple, [[maybe_unused]] ChatHandler const* handler, std::string_view args) { if constexpr (offset < std::tuple_size_v) - return MultiConsumer, offset>::TryConsumeTo(tuple, args); + return MultiConsumer, offset>::TryConsumeTo(tuple, handler, args); else if (!args.empty()) /* the entire string must be consumed */ return std::nullopt; else @@ -123,10 +118,15 @@ class TC_GAME_API ChatCommand Tuple arguments; std::get<0>(arguments) = chatHandler; - if (Trinity::Impl::ChatCommands::ConsumeFromOffset(arguments, argsStr)) + Trinity::Impl::ChatCommands::ChatCommandResult result = Trinity::Impl::ChatCommands::ConsumeFromOffset(arguments, chatHandler, argsStr); + if (result) return std::apply(reinterpret_cast(handler), std::move(arguments)); else + { + if (result.HasErrorMessage()) + Trinity::Impl::ChatCommands::SendErrorMessageToHandler(chatHandler, result.GetErrorMessage()); return false; + } }; _handler = reinterpret_cast(handler); } diff --git a/src/server/game/Chat/ChatCommands/ChatCommandArgs.cpp b/src/server/game/Chat/ChatCommands/ChatCommandArgs.cpp index 33db9d4bdf3..ca8fd888f1b 100644 --- a/src/server/game/Chat/ChatCommands/ChatCommandArgs.cpp +++ b/src/server/game/Chat/ChatCommands/ChatCommandArgs.cpp @@ -23,6 +23,7 @@ #include "Util.h" using namespace Trinity::ChatCommands; +using ChatCommandResult = Trinity::Impl::ChatCommands::ChatCommandResult; struct AchievementVisitor { @@ -30,13 +31,14 @@ struct AchievementVisitor value_type operator()(Hyperlink achData) const { return achData->Achievement; } value_type operator()(uint32 achId) const { return sAchievementStore.LookupEntry(achId); } }; -Optional Trinity::Impl::ChatCommands::ArgInfo::TryConsume(AchievementEntry const*& data, std::string_view args) +ChatCommandResult Trinity::Impl::ChatCommands::ArgInfo::TryConsume(AchievementEntry const*& data, ChatHandler const* handler, std::string_view args) { Variant, uint32> val; - Optional next = SingleConsumer::TryConsumeTo(val, args); - if (next) - if ((data = val.visit(AchievementVisitor()))) - return next; + ChatCommandResult result = ArgInfo::TryConsume(val, handler, args); + if (!result || (data = val.visit(AchievementVisitor()))) + return result; + if (uint32* id = std::get_if(&val)) + return FormatTrinityString(handler, LANG_CMDPARSER_ACHIEVEMENT_NO_EXIST, *id); return std::nullopt; } @@ -46,13 +48,14 @@ struct CurrencyTypesVisitor value_type operator()(Hyperlink currency) const { return currency->Currency; } value_type operator()(uint32 currencyId) const { return sCurrencyTypesStore.LookupEntry(currencyId); } }; -Optional Trinity::Impl::ChatCommands::ArgInfo::TryConsume(CurrencyTypesEntry const*& data, std::string_view args) +ChatCommandResult Trinity::Impl::ChatCommands::ArgInfo::TryConsume(CurrencyTypesEntry const*& data, ChatHandler const* handler, std::string_view args) { Variant, uint32> val; - Optional next = SingleConsumer::TryConsumeTo(val, args); - if (next) - if ((data = val.visit(CurrencyTypesVisitor()))) - return next; + ChatCommandResult result = ArgInfo::TryConsume(val, handler, args); + if (!result || (data = val.visit(CurrencyTypesVisitor()))) + return result; + if (uint32* id = std::get_if(&val)) + return FormatTrinityString(handler, LANG_CMDPARSER_CURRENCY_NO_EXIST, *id); return std::nullopt; } @@ -60,16 +63,18 @@ struct GameTeleVisitor { using value_type = GameTele const*; value_type operator()(Hyperlink tele) const { return sObjectMgr->GetGameTele(tele); } - value_type operator()(std::string const& tele) const { return sObjectMgr->GetGameTele(tele); } + value_type operator()(std::string_view tele) const { return sObjectMgr->GetGameTele(tele); } }; -Optional Trinity::Impl::ChatCommands::ArgInfo::TryConsume(GameTele const*& data, std::string_view args) +ChatCommandResult Trinity::Impl::ChatCommands::ArgInfo::TryConsume(GameTele const*& data, ChatHandler const* handler, std::string_view args) { - Variant, std::string> val; - Optional next = SingleConsumer::TryConsumeTo(val, args); - if (next) - if ((data = val.visit(GameTeleVisitor()))) - return next; - return std::nullopt; + Variant, std::string_view> val; + ChatCommandResult result = ArgInfo::TryConsume(val, handler, args); + if (!result || (data = val.visit(GameTeleVisitor()))) + return result; + if (val.holds_alternative>()) + return FormatTrinityString(handler, LANG_CMDPARSER_GAME_TELE_ID_NO_EXIST, static_cast(std::get>(val))); + else + return FormatTrinityString(handler, LANG_CMDPARSER_GAME_TELE_NO_EXIST, STRING_VIEW_FMT_ARG(std::get(val))); } struct ItemTemplateVisitor @@ -78,13 +83,14 @@ struct ItemTemplateVisitor value_type operator()(Hyperlink item) const { return item->Item; } value_type operator()(uint32 item) const { return sObjectMgr->GetItemTemplate(item); } }; -Optional Trinity::Impl::ChatCommands::ArgInfo::TryConsume(ItemTemplate const*& data, std::string_view args) +ChatCommandResult Trinity::Impl::ChatCommands::ArgInfo::TryConsume(ItemTemplate const*& data, ChatHandler const* handler, std::string_view args) { Variant, uint32> val; - Optional next = SingleConsumer::TryConsumeTo(val, args); - if (next) - if ((data = val.visit(ItemTemplateVisitor()))) - return next; + ChatCommandResult result = ArgInfo::TryConsume(val, handler, args); + if (!result || (data = val.visit(ItemTemplateVisitor()))) + return result; + if (uint32* id = std::get_if(&val)) + return FormatTrinityString(handler, LANG_CMDPARSER_ITEM_NO_EXIST, *id); return std::nullopt; } @@ -103,12 +109,13 @@ struct SpellInfoVisitor value_type operator()(uint32 spellId) const { return sSpellMgr->GetSpellInfo(spellId, DIFFICULTY_NONE); } }; -Optional Trinity::Impl::ChatCommands::ArgInfo::TryConsume(SpellInfo const*& data, std::string_view args) +ChatCommandResult Trinity::Impl::ChatCommands::ArgInfo::TryConsume(SpellInfo const*& data, ChatHandler const* handler, std::string_view args) { Variant, Hyperlink, Hyperlink, Hyperlink, Hyperlink, Hyperlink, Hyperlink, Hyperlink, uint32> val; - Optional next = SingleConsumer::TryConsumeTo(val, args); - if (next) - if ((data = val.visit(SpellInfoVisitor()))) - return next; + ChatCommandResult result = ArgInfo::TryConsume(val, handler, args); + if (!result || (data = val.visit(SpellInfoVisitor()))) + return result; + if (uint32* id = std::get_if(&val)) + return FormatTrinityString(handler, LANG_CMDPARSER_SPELL_NO_EXIST, *id); return std::nullopt; } diff --git a/src/server/game/Chat/ChatCommands/ChatCommandArgs.h b/src/server/game/Chat/ChatCommands/ChatCommandArgs.h index 21f27b45752..b36456869d8 100644 --- a/src/server/game/Chat/ChatCommands/ChatCommandArgs.h +++ b/src/server/game/Chat/ChatCommands/ChatCommandArgs.h @@ -22,6 +22,7 @@ #include "ChatCommandTags.h" #include "SmartEnum.h" #include "StringConvert.h" +#include "StringFormat.h" #include "Util.h" #include #include @@ -36,10 +37,13 @@ namespace Trinity::Impl::ChatCommands /************************** ARGUMENT HANDLERS *******************************************\ |* Define how to extract contents of a certain requested type from a string *| |* Must implement the following: *| - |* - TryConsume: T&, std::string_view -> Optional *| - |* returns nullopt if no match, otherwise tail of argument string *| - |* - if nullopt is returned, state of T& is indeterminate *| - |* - otherwise, T& should be initialized to the intended return value *| + |* - TryConsume: T&, ChatHandler const*, std::string_view -> ChatCommandResult *| + |* - on match, returns tail of the provided argument string (as std::string_view) *| + |* - on specific error, returns error message (as std::string&& or char const*) *| + |* - on generic error, returns std::nullopt (this will print command usage) *| + |* *| + |* - if a match is returned, T& should be initialized to the matched value *| + |* - otherwise, the state of T& is indeterminate and caller will not use it *| |* *| \****************************************************************************************/ template @@ -49,7 +53,7 @@ namespace Trinity::Impl::ChatCommands template struct ArgInfo || std::is_floating_point_v>> { - static Optional TryConsume(T& val, std::string_view args) + static ChatCommandResult TryConsume(T& val, ChatHandler const* handler, std::string_view args) { auto [token, tail] = tokenize(args); if (token.empty()) @@ -58,23 +62,33 @@ namespace Trinity::Impl::ChatCommands if (Optional v = StringTo(token, 0)) val = *v; else - return std::nullopt; + return FormatTrinityString(handler, LANG_CMDPARSER_STRING_VALUE_INVALID, STRING_VIEW_FMT_ARG(token), GetTypeName().c_str()); if constexpr (std::is_floating_point_v) { if (!std::isfinite(val)) - return std::nullopt; + return FormatTrinityString(handler, LANG_CMDPARSER_STRING_VALUE_INVALID, STRING_VIEW_FMT_ARG(token), GetTypeName().c_str()); } return tail; } }; + /* + for backwards compatibility, consumes the rest of the string + new code should use the Tail/WTail tags defined in ChatCommandTags + */ + template <> + struct ArgInfo + { + static ChatCommandResult TryConsume(char const*& arg, ChatHandler const*, std::string_view args) { arg = args.data(); return std::string_view(); } + }; + // string_view template <> struct ArgInfo { - static Optional TryConsume(std::string_view& val, std::string_view args) + static ChatCommandResult TryConsume(std::string_view& val, ChatHandler const*, std::string_view args) { auto [token, next] = tokenize(args); if (token.empty()) @@ -88,10 +102,10 @@ namespace Trinity::Impl::ChatCommands template <> struct ArgInfo { - static Optional TryConsume(std::string& val, std::string_view args) + static ChatCommandResult TryConsume(std::string& val, ChatHandler const* handler, std::string_view args) { std::string_view view; - Optional next = ArgInfo::TryConsume(view, args); + ChatCommandResult next = ArgInfo::TryConsume(view, handler, args); if (next) val.assign(view); return next; @@ -102,13 +116,18 @@ namespace Trinity::Impl::ChatCommands template <> struct ArgInfo { - static Optional TryConsume(std::wstring& val, std::string_view args) + static ChatCommandResult TryConsume(std::wstring& val, ChatHandler const* handler, std::string_view args) { std::string_view utf8view; - Optional next = ArgInfo::TryConsume(utf8view, args); + ChatCommandResult next = ArgInfo::TryConsume(utf8view, handler, args); - if (next && Utf8toWStr(utf8view, val)) - return next; + if (next) + { + if (Utf8toWStr(utf8view, val)) + return next; + else + return GetTrinityString(handler, LANG_CMDPARSER_INVALID_UTF8); + } else return std::nullopt; } @@ -118,19 +137,18 @@ namespace Trinity::Impl::ChatCommands template struct ArgInfo>> { - static std::map> MakeSearchMap() + using SearchMap = std::map, StringCompareLessI_T>; + static SearchMap MakeSearchMap() { - std::map> map; + SearchMap map; for (T val : EnumUtils::Iterate()) { EnumText text = EnumUtils::ToString(val); - std::string title(text.Title); - strToLower(title); - std::string constant(text.Constant); - strToLower(constant); + std::string_view title(text.Title); + std::string_view constant(text.Constant); - auto [constantIt, constantNew] = map.try_emplace(constant, val); + auto [constantIt, constantNew] = map.try_emplace(title, val); if (!constantNew) constantIt->second = std::nullopt; @@ -144,21 +162,19 @@ namespace Trinity::Impl::ChatCommands return map; } - static inline std::map> const SearchMap = MakeSearchMap(); + static inline SearchMap const _map = MakeSearchMap(); - static T const* Match(std::string s) + static T const* Match(std::string_view s) { - strToLower(s); - - auto it = SearchMap.lower_bound(s); - if (it == SearchMap.end() || !StringStartsWith(it->first, s)) // not a match + auto it = _map.lower_bound(s); + if (it == _map.end() || !StringStartsWithI(it->first, s)) // not a match return nullptr; - if (it->first != s) // we don't have an exact match - check if it is unique + if (!StringEqualI(it->first, s)) // we don't have an exact match - check if it is unique { auto it2 = it; ++it2; - if (it2 != SearchMap.end() && StringStartsWith(it2->first, s)) // not unique + if ((it2 != _map.end()) && StringStartsWithI(it2->first, s)) // not unique return nullptr; } @@ -168,31 +184,35 @@ namespace Trinity::Impl::ChatCommands return nullptr; } - static Optional TryConsume(T& val, std::string_view args) + static ChatCommandResult TryConsume(T& val, ChatHandler const* handler, std::string_view args) { - std::string strVal; - Optional next = ArgInfo::TryConsume(strVal, args); - - if (next) + std::string_view strVal; + ChatCommandResult next1 = ArgInfo::TryConsume(strVal, handler, args); + if (next1) { if (T const* match = Match(strVal)) { val = *match; - return next; + return next1; } } // Value not found. Try to parse arg as underlying type and cast it to enum type using U = std::underlying_type_t; U uVal = 0; - next = ArgInfo::TryConsume(uVal, args); - if (next && EnumUtils::IsValid(uVal)) + if (ChatCommandResult next2 = ArgInfo::TryConsume(uVal, handler, args)) { - val = static_cast(uVal); - return next; + if (EnumUtils::IsValid(uVal)) + { + val = static_cast(uVal); + return next2; + } } - return std::nullopt; + if (next1) + return FormatTrinityString(handler, LANG_CMDPARSER_STRING_VALUE_INVALID, STRING_VIEW_FMT_ARG(strVal), GetTypeName().c_str()); + else + return next1; } }; @@ -200,9 +220,9 @@ namespace Trinity::Impl::ChatCommands template struct ArgInfo>> { - static Optional TryConsume(T& tag, std::string_view args) + static ChatCommandResult TryConsume(T& tag, ChatHandler const* handler, std::string_view args) { - return tag.TryConsume(args); + return tag.TryConsume(handler, args); } }; @@ -210,16 +230,16 @@ namespace Trinity::Impl::ChatCommands template struct ArgInfo, void> { - static Optional TryConsume(std::vector& val, std::string_view args) + static ChatCommandResult TryConsume(std::vector& val, ChatHandler const* handler, std::string_view args) { val.clear(); - Optional next = ArgInfo::TryConsume(val.emplace_back(), args); + ChatCommandResult next = ArgInfo::TryConsume(val.emplace_back(), handler, args); if (!next) - return std::nullopt; + return next; - while (Optional next2 = ArgInfo::TryConsume(val.emplace_back(), *next)) - next = next2; + while (ChatCommandResult next2 = ArgInfo::TryConsume(val.emplace_back(), handler, *next)) + next = std::move(next2); val.pop_back(); return next; @@ -230,12 +250,12 @@ namespace Trinity::Impl::ChatCommands template struct ArgInfo, void> { - static Optional TryConsume(std::array& val, std::string_view args) + static ChatCommandResult TryConsume(std::array& val, ChatHandler const* handler, std::string_view args) { - Optional next = args; + ChatCommandResult next = args; for (T& t : val) - if (!(next = ArgInfo::TryConsume(t, *next))) - return std::nullopt; + if (!(next = ArgInfo::TryConsume(t, handler, *next))) + break; return next; } }; @@ -248,22 +268,36 @@ namespace Trinity::Impl::ChatCommands static constexpr size_t N = std::variant_size_v; template - static Optional TryAtIndex(Trinity::ChatCommands::Variant& val, [[maybe_unused]] std::string_view args) + static ChatCommandResult TryAtIndex([[maybe_unused]] Trinity::ChatCommands::Variant& val, [[maybe_unused]] ChatHandler const* handler, [[maybe_unused]] std::string_view args) { if constexpr (I < N) { - if (Optional next = ArgInfo>::TryConsume(val.template emplace(), args)) - return next; + ChatCommandResult thisResult = ArgInfo>::TryConsume(val.template emplace(), handler, args); + if (thisResult) + return thisResult; else - return TryAtIndex(val, args); + { + ChatCommandResult nestedResult = TryAtIndex(val, handler, args); + if (!thisResult.HasErrorMessage()) + return nestedResult; + if (!nestedResult.HasErrorMessage()) + return thisResult; + if (StringStartsWith(nestedResult.GetErrorMessage(), "\"")) + return Trinity::StringFormat("\"%s\"\n%s %s", thisResult.GetErrorMessage().c_str(), GetTrinityString(handler, LANG_CMDPARSER_OR), nestedResult.GetErrorMessage().c_str()); + else + return Trinity::StringFormat("\"%s\"\n%s \"%s\"", thisResult.GetErrorMessage().c_str(), GetTrinityString(handler, LANG_CMDPARSER_OR), nestedResult.GetErrorMessage().c_str()); + } } else return std::nullopt; } - static Optional TryConsume(Trinity::ChatCommands::Variant& val, std::string_view args) + static ChatCommandResult TryConsume(Trinity::ChatCommands::Variant& val, ChatHandler const* handler, std::string_view args) { - return TryAtIndex<0>(val, args); + ChatCommandResult result = TryAtIndex<0>(val, handler, args); + if (result.HasErrorMessage() && (result.GetErrorMessage().find('\n') != std::string::npos)) + return Trinity::StringFormat("%s %s", GetTrinityString(handler, LANG_CMDPARSER_EITHER), result.GetErrorMessage().c_str()); + return result; } }; @@ -271,35 +305,35 @@ namespace Trinity::Impl::ChatCommands template <> struct TC_GAME_API ArgInfo { - static Optional TryConsume(AchievementEntry const*&, std::string_view); + static ChatCommandResult TryConsume(AchievementEntry const*&, ChatHandler const*, std::string_view); }; // CurrencyTypesEntry* from numeric id or link template <> struct TC_GAME_API ArgInfo { - static Optional TryConsume(CurrencyTypesEntry const*&, std::string_view); + static ChatCommandResult TryConsume(CurrencyTypesEntry const*&, ChatHandler const*, std::string_view); }; // GameTele* from string name or link template <> struct TC_GAME_API ArgInfo { - static Optional TryConsume(GameTele const*&, std::string_view); + static ChatCommandResult TryConsume(GameTele const*&, ChatHandler const*, std::string_view); }; // ItemTemplate* from numeric id or link template <> struct TC_GAME_API ArgInfo { - static Optional TryConsume(ItemTemplate const*&, std::string_view); + static ChatCommandResult TryConsume(ItemTemplate const*&, ChatHandler const*, std::string_view); }; // SpellInfo const* from spell id or link template <> struct TC_GAME_API ArgInfo { - static Optional TryConsume(SpellInfo const*&, std::string_view); + static ChatCommandResult TryConsume(SpellInfo const*&, ChatHandler const*, std::string_view); }; } diff --git a/src/server/game/Chat/ChatCommands/ChatCommandHelpers.cpp b/src/server/game/Chat/ChatCommands/ChatCommandHelpers.cpp new file mode 100644 index 00000000000..ab64584a389 --- /dev/null +++ b/src/server/game/Chat/ChatCommands/ChatCommandHelpers.cpp @@ -0,0 +1,30 @@ +/* + * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#include "ChatCommandHelpers.h" +#include "Chat.h" + +void Trinity::Impl::ChatCommands::SendErrorMessageToHandler(ChatHandler* handler, std::string_view str) +{ + handler->SendSysMessage(str); + handler->SetSentErrorMessage(true); +} + +char const* Trinity::Impl::ChatCommands::GetTrinityString(ChatHandler const* handler, TrinityStrings which) +{ + return handler->GetTrinityString(which); +} diff --git a/src/server/game/Chat/ChatCommands/ChatCommandHelpers.h b/src/server/game/Chat/ChatCommands/ChatCommandHelpers.h index 712d0c37d48..afa5589e0b7 100644 --- a/src/server/game/Chat/ChatCommands/ChatCommandHelpers.h +++ b/src/server/game/Chat/ChatCommands/ChatCommandHelpers.h @@ -18,8 +18,16 @@ #ifndef TRINITY_CHATCOMMANDHELPERS_H #define TRINITY_CHATCOMMANDHELPERS_H +#include "Define.h" +#include "Language.h" +#include "Optional.h" +#include "StringFormat.h" +#include #include #include +#include + +class ChatHandler; namespace Trinity::Impl::ChatCommands { @@ -82,6 +90,43 @@ namespace Trinity::Impl::ChatCommands template using get_nth_t = typename get_nth::type; + + // this essentially models std::optional, except it can also hold an error message + // it has std::string_view's bool conversion and dereference operators + // + // monostate <-> unspecified error, typically end-of-string reached or parsing failed + // std::string <-> specified error, typically character-not-found or invalid item link + // std::string_view <-> success, string_view is remaining argument string + struct ChatCommandResult + { + ChatCommandResult(std::nullopt_t) : _storage() {} + ChatCommandResult(std::string const&) = delete; + ChatCommandResult(std::string&& s) : _storage(std::in_place_type, std::forward(s)) {} + ChatCommandResult(char const* c) : _storage(std::in_place_type, c) {} + ChatCommandResult(std::string_view s) : _storage(std::in_place_type, s) {} + + ChatCommandResult(ChatCommandResult const&) = delete; + ChatCommandResult(ChatCommandResult&&) = default; + ChatCommandResult& operator=(ChatCommandResult const&) = delete; + ChatCommandResult& operator=(ChatCommandResult&&) = default; + + std::string_view operator*() const { return std::get(_storage); } + bool IsSuccessful() const { return std::holds_alternative(_storage); } + explicit operator bool() const { return IsSuccessful(); } + bool HasErrorMessage() const { return std::holds_alternative(_storage); } + std::string const& GetErrorMessage() const { return std::get(_storage); } + + private: + std::variant _storage; + }; + + TC_GAME_API void SendErrorMessageToHandler(ChatHandler* handler, std::string_view str); + TC_GAME_API char const* GetTrinityString(ChatHandler const* handler, TrinityStrings which); + template + std::string FormatTrinityString(ChatHandler const* handler, TrinityStrings which, Ts&&... args) + { + return Trinity::StringFormat(GetTrinityString(handler, which), std::forward(args)...); + } } #endif diff --git a/src/server/game/Chat/ChatCommands/ChatCommandTags.cpp b/src/server/game/Chat/ChatCommands/ChatCommandTags.cpp index 8c5917e086d..b5b29193312 100644 --- a/src/server/game/Chat/ChatCommands/ChatCommandTags.cpp +++ b/src/server/game/Chat/ChatCommands/ChatCommandTags.cpp @@ -25,19 +25,21 @@ #include "ObjectMgr.h" #include "Player.h" -Optional Trinity::ChatCommands::QuotedString::TryConsume(std::string_view args) +using namespace Trinity::Impl::ChatCommands; + +ChatCommandResult Trinity::ChatCommands::QuotedString::TryConsume(ChatHandler const* handler, std::string_view args) { if (args.empty()) return std::nullopt; if ((args[0] != '"') && (args[0] != '\'')) - return Trinity::Impl::ChatCommands::ArgInfo::TryConsume(*this, args); + return ArgInfo::TryConsume(*this, handler, args); char const QUOTE = args[0]; for (size_t i = 1; i < args.length(); ++i) { if (args[i] == QUOTE) { - auto [remainingToken, tail] = Trinity::Impl::ChatCommands::tokenize(args.substr(i + 1)); + auto [remainingToken, tail] = tokenize(args.substr(i + 1)); if (remainingToken.empty()) // if this is not empty, then we did not consume the full token return tail; else @@ -56,17 +58,17 @@ Optional Trinity::ChatCommands::QuotedString::TryConsume(std:: return std::nullopt; } -Optional Trinity::ChatCommands::AccountIdentifier::TryConsume(std::string_view args) +ChatCommandResult Trinity::ChatCommands::AccountIdentifier::TryConsume(ChatHandler const* handler, std::string_view args) { std::string_view text; - Optional next = Trinity::Impl::ChatCommands::ArgInfo::TryConsume(text, args); + ChatCommandResult next = ArgInfo::TryConsume(text, handler, args); if (!next) - return std::nullopt; + return next; // first try parsing as account name _name.assign(text); if (!Utf8ToUpperOnlyLatin(_name)) - return std::nullopt; + return GetTrinityString(handler, LANG_CMDPARSER_INVALID_UTF8); _id = AccountMgr::GetId(_name); if (_id) // account with name exists, we are done return next; @@ -74,21 +76,21 @@ Optional Trinity::ChatCommands::AccountIdentifier::TryConsume( // try parsing as account id instead Optional id = Trinity::StringTo(text, 10); if (!id) - return std::nullopt; + return FormatTrinityString(handler, LANG_CMDPARSER_ACCOUNT_NAME_NO_EXIST, STRING_VIEW_FMT_ARG(_name)); _id = *id; if (AccountMgr::GetName(_id, _name)) return next; else - return std::nullopt; + return FormatTrinityString(handler, LANG_CMDPARSER_ACCOUNT_ID_NO_EXIST, _id); } -Optional Trinity::ChatCommands::PlayerIdentifier::TryConsume(std::string_view args) +ChatCommandResult Trinity::ChatCommands::PlayerIdentifier::TryConsume(ChatHandler const* handler, std::string_view args) { Variant, ObjectGuid::LowType, std::string_view> val; - Optional next = Trinity::Impl::ChatCommands::ArgInfo::TryConsume(val, args); + ChatCommandResult next = ArgInfo::TryConsume(val, handler, args); if (!next) - return std::nullopt; + return next; if (val.holds_alternative()) { @@ -96,7 +98,7 @@ Optional Trinity::ChatCommands::PlayerIdentifier::TryConsume(s if ((_player = ObjectAccessor::FindPlayerByLowGUID(_guid.GetCounter()))) _name = _player->GetName(); else if (!sCharacterCache->GetCharacterNameByGuid(_guid, _name)) - return std::nullopt; + return FormatTrinityString(handler, LANG_CMDPARSER_CHAR_GUID_NO_EXIST, _guid.ToString().c_str()); return next; } else @@ -107,12 +109,12 @@ Optional Trinity::ChatCommands::PlayerIdentifier::TryConsume(s _name.assign(val.get()); if (!normalizePlayerName(_name)) - return std::nullopt; + return FormatTrinityString(handler, LANG_CMDPARSER_CHAR_NAME_INVALID, STRING_VIEW_FMT_ARG(_name)); if ((_player = ObjectAccessor::FindPlayerByName(_name))) _guid = _player->GetGUID(); else if (!(_guid = sCharacterCache->GetCharacterGuidByName(_name))) - return std::nullopt; + return FormatTrinityString(handler, LANG_CMDPARSER_CHAR_NAME_NO_EXIST, STRING_VIEW_FMT_ARG(_name)); return next; } } diff --git a/src/server/game/Chat/ChatCommands/ChatCommandTags.h b/src/server/game/Chat/ChatCommands/ChatCommandTags.h index 879d1559dfa..dca28d205e8 100644 --- a/src/server/game/Chat/ChatCommands/ChatCommandTags.h +++ b/src/server/game/Chat/ChatCommands/ChatCommandTags.h @@ -41,7 +41,11 @@ class Player; namespace Trinity::Impl::ChatCommands { - struct ContainerTag {}; + struct ContainerTag + { + using ChatCommandResult = Trinity::Impl::ChatCommands::ChatCommandResult; + }; + template struct tag_base>> { @@ -71,8 +75,11 @@ namespace Trinity::ChatCommands |* Simple holder classes to differentiate between extraction methods *| |* Must inherit from Trinity::Impl::ChatCommands::ContainerTag *| |* Must implement the following: *| - |* - TryConsume: std::string_view -> Optional *| - |* returns nullopt if no match, otherwise the tail of the provided argument string *| + |* - TryConsume: ChatHandler const*, std::string_view -> ChatCommandResult *| + |* - on match, returns tail of the provided argument string (as std::string_view) *| + |* - on specific error, returns error message (as std::string&& or char const*) *| + |* - on generic error, returns std::nullopt (this will print command usage) *| + |* *| |* - typedef value_type of type that is contained within the tag *| |* - cast operator to value_type *| |* *| @@ -83,15 +90,17 @@ namespace Trinity::ChatCommands { using value_type = void; - Optional TryConsume(std::string_view args) const + ChatCommandResult TryConsume(ChatHandler const* handler, std::string_view args) const { - if (StringStartsWithI(args, _string)) + std::string_view start = args.substr(0, _string.length()); + if (StringEqualI(start, _string)) { auto [remainingToken, tail] = Trinity::Impl::ChatCommands::tokenize(args.substr(_string.length())); if (remainingToken.empty()) // if this is not empty, then we did not consume the full token return tail; + start = args.substr(0, _string.length() + remainingToken.length()); } - return std::nullopt; + return Trinity::Impl::ChatCommands::FormatTrinityString(handler, LANG_CMDPARSER_EXACT_SEQ_MISMATCH, STRING_VIEW_FMT_ARG(_string), STRING_VIEW_FMT_ARG(start)); } private: @@ -108,7 +117,7 @@ namespace Trinity::ChatCommands using std::string_view::operator=; - Optional TryConsume(std::string_view args) + ChatCommandResult TryConsume(ChatHandler const*,std::string_view args) { std::string_view::operator=(args); return std::string_view(); @@ -121,12 +130,12 @@ namespace Trinity::ChatCommands using std::wstring::operator=; - Optional TryConsume(std::string_view args) + ChatCommandResult TryConsume(ChatHandler const* handler, std::string_view args) { if (Utf8toWStr(args, *this)) return std::string_view(); else - return std::nullopt; + return Trinity::Impl::ChatCommands::GetTrinityString(handler, LANG_CMDPARSER_INVALID_UTF8); } }; @@ -134,7 +143,7 @@ namespace Trinity::ChatCommands { using value_type = std::string; - TC_GAME_API Optional TryConsume(std::string_view args); + TC_GAME_API ChatCommandResult TryConsume(ChatHandler const* handler, std::string_view args); }; struct TC_GAME_API AccountIdentifier : Trinity::Impl::ChatCommands::ContainerTag @@ -148,7 +157,7 @@ namespace Trinity::ChatCommands uint32 GetID() const { return _id; } std::string const& GetName() const { return _name; } - Optional TryConsume(std::string_view args); + ChatCommandResult TryConsume(ChatHandler const* handler, std::string_view args); private: uint32 _id; @@ -171,7 +180,7 @@ namespace Trinity::ChatCommands bool IsConnected() const { return (_player != nullptr); } Player* GetConnectedPlayer() const { return _player; } - Optional TryConsume(std::string_view args); + ChatCommandResult TryConsume(ChatHandler const* handler, std::string_view args); static Optional FromTarget(ChatHandler* handler); static Optional FromSelf(ChatHandler* handler); @@ -199,7 +208,7 @@ namespace Trinity::ChatCommands value_type operator*() const { return val; } storage_type const* operator->() const { return &val; } - Optional TryConsume(std::string_view args) + ChatCommandResult TryConsume(ChatHandler const* handler, std::string_view args) { Trinity::Hyperlinks::HyperlinkInfo info = Trinity::Hyperlinks::ParseSingleHyperlink(args); // invalid hyperlinks cannot be consumed @@ -212,7 +221,7 @@ namespace Trinity::ChatCommands // store value if (!linktag::StoreTo(val, info.data)) - return std::nullopt; + return Trinity::Impl::ChatCommands::GetTrinityString(handler, LANG_CMDPARSER_LINKDATA_INVALID); // finally, skip any potential delimiters auto [token, next] = Trinity::Impl::ChatCommands::tokenize(info.tail); diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h index eb3cfb44ec9..99c4342a3bb 100644 --- a/src/server/game/Miscellaneous/Language.h +++ b/src/server/game/Miscellaneous/Language.h @@ -994,22 +994,23 @@ enum TrinityStrings // 1219-1499 - free // Command argument parsers - LANG_CMDPARSER_EITHER = 1500, // 3.3.5 RESERVED - LANG_CMDPARSER_OR = 1501, // 3.3.5 RESERVED - LANG_CMDPARSER_STRING_VALUE_INVALID = 1502, // 3.3.5 RESERVED - LANG_CMDPARSER_INVALID_UTF8 = 1503, // 3.3.5 RESERVED - LANG_CMDPARSER_LINKDATA_INVALID = 1504, // 3.3.5 RESERVED - LANG_CMDPARSER_ACCOUNT_NAME_NO_EXIST = 1505, // 3.3.5 RESERVED - LANG_CMDPARSER_ACCOUNT_ID_NO_EXIST = 1506, // 3.3.5 RESERVED - LANG_CMDPARSER_CHAR_GUID_NO_EXIST = 1507, // 3.3.5 RESERVED - LANG_CMDPARSER_CHAR_NAME_NO_EXIST = 1508, // 3.3.5 RESERVED - LANG_CMDPARSER_CHAR_NAME_INVALID = 1509, // 3.3.5 RESERVED - LANG_CMDPARSER_ACHIEVEMENT_NO_EXIST = 1510, // 3.3.5 RESERVED - LANG_CMDPARSER_GAME_TELE_ID_NO_EXIST = 1511, // 3.3.5 RESERVED - LANG_CMDPARSER_GAME_TELE_NO_EXIST = 1512, // 3.3.5 RESERVED - LANG_CMDPARSER_ITEM_NO_EXIST = 1513, // 3.3.5 RESERVED - LANG_CMDPARSER_SPELL_NO_EXIST = 1514, // 3.3.5 RESERVED - LANG_CMDPARSER_EXACT_SEQ_MISMATCH = 1515, // 3.3.5 RESERVED + LANG_CMDPARSER_EITHER = 1500, + LANG_CMDPARSER_OR = 1501, + LANG_CMDPARSER_STRING_VALUE_INVALID = 1502, + LANG_CMDPARSER_INVALID_UTF8 = 1503, + LANG_CMDPARSER_LINKDATA_INVALID = 1504, + LANG_CMDPARSER_ACCOUNT_NAME_NO_EXIST = 1505, + LANG_CMDPARSER_ACCOUNT_ID_NO_EXIST = 1506, + LANG_CMDPARSER_CHAR_GUID_NO_EXIST = 1507, + LANG_CMDPARSER_CHAR_NAME_NO_EXIST = 1508, + LANG_CMDPARSER_CHAR_NAME_INVALID = 1509, + LANG_CMDPARSER_ACHIEVEMENT_NO_EXIST = 1510, + LANG_CMDPARSER_GAME_TELE_ID_NO_EXIST = 1511, + LANG_CMDPARSER_GAME_TELE_NO_EXIST = 1512, + LANG_CMDPARSER_ITEM_NO_EXIST = 1513, + LANG_CMDPARSER_SPELL_NO_EXIST = 1514, + LANG_CMDPARSER_EXACT_SEQ_MISMATCH = 1515, + LANG_CMDPARSER_CURRENCY_NO_EXIST = 1516, // 1516-1998 - free LANG_DEBUG_AREATRIGGER_LEFT = 1999, diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index 8d1efd74f0e..f3d18a0b989 100644 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -562,8 +562,8 @@ enum RealmZone /// Storage class for commands issued for delayed execution struct TC_GAME_API CliCommandHolder { - typedef void(*Print)(void*, char const*); - typedef void(*CommandFinished)(void*, bool success); + using Print = void(*)(void*, std::string_view); + using CommandFinished = void(*)(void*, bool success); void* m_callbackArg; char* m_command; diff --git a/src/server/scripts/Commands/cs_gobject.cpp b/src/server/scripts/Commands/cs_gobject.cpp index f87498b76c5..34e8cae35a4 100644 --- a/src/server/scripts/Commands/cs_gobject.cpp +++ b/src/server/scripts/Commands/cs_gobject.cpp @@ -41,9 +41,7 @@ EndScriptData */ #include "PoolMgr.h" #include "RBAC.h" #include "WorldSession.h" -#include #include -#include using namespace Trinity::ChatCommands; @@ -574,7 +572,7 @@ public: handler->PSendSysMessage(LANG_GOINFO_SIZE, gameObjectInfo->size); handler->PSendSysMessage(LANG_OBJECTINFO_AIINFO, gameObjectInfo->AIName.c_str(), sObjectMgr->GetScriptName(gameObjectInfo->ScriptId).c_str()); if (GameObjectAI const* ai = thisGO ? thisGO->AI() : nullptr) - handler->PSendSysMessage(LANG_OBJECTINFO_AITYPE, boost::core::demangle(typeid(*ai).name()).c_str()); + handler->PSendSysMessage(LANG_OBJECTINFO_AITYPE, GetTypeName(*ai).c_str()); if (GameObjectDisplayInfoEntry const* modelInfo = sGameObjectDisplayInfoStore.LookupEntry(displayId)) handler->PSendSysMessage(LANG_GOINFO_MODEL, modelInfo->GeoBoxMax.X, modelInfo->GeoBoxMax.Y, modelInfo->GeoBoxMax.Z, modelInfo->GeoBoxMin.X, modelInfo->GeoBoxMin.Y, modelInfo->GeoBoxMin.Z); diff --git a/src/server/scripts/Commands/cs_npc.cpp b/src/server/scripts/Commands/cs_npc.cpp index 6112f51c7a9..b2ad46337ef 100644 --- a/src/server/scripts/Commands/cs_npc.cpp +++ b/src/server/scripts/Commands/cs_npc.cpp @@ -45,8 +45,6 @@ EndScriptData */ #include "Transport.h" #include "World.h" #include "WorldSession.h" -#include -#include using namespace Trinity::ChatCommands; using CreatureSpawnId = Variant, ObjectGuid::LowType>; @@ -550,7 +548,7 @@ public: handler->PSendSysMessage(LANG_OBJECTINFO_AIINFO, target->GetAIName().c_str(), target->GetScriptName().c_str()); handler->PSendSysMessage(LANG_NPCINFO_REACTSTATE, DescribeReactState(target->GetReactState())); if (CreatureAI const* ai = target->AI()) - handler->PSendSysMessage(LANG_OBJECTINFO_AITYPE, boost::core::demangle(typeid(*ai).name()).c_str()); + handler->PSendSysMessage(LANG_OBJECTINFO_AITYPE, GetTypeName(*ai).c_str()); handler->PSendSysMessage(LANG_NPCINFO_FLAGS_EXTRA, cInfo->flags_extra); for (CreatureFlagsExtra flag : EnumUtils::Iterate()) if (cInfo->flags_extra & flag) diff --git a/src/server/worldserver/CommandLine/CliRunnable.cpp b/src/server/worldserver/CommandLine/CliRunnable.cpp index 29981235cfb..b36e9edf9d1 100644 --- a/src/server/worldserver/CommandLine/CliRunnable.cpp +++ b/src/server/worldserver/CommandLine/CliRunnable.cpp @@ -97,18 +97,17 @@ int cli_hook_func() #endif -void utf8print(void* /*arg*/, char const* str) +void utf8print(void* /*arg*/, std::string_view str) { #if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS - wchar_t wtemp_buf[6000]; - size_t wtemp_len = 6000-1; - if (!Utf8toWStr(str, strlen(str), wtemp_buf, wtemp_len)) + std::wstring wbuf; + if (!Utf8toWStr(str, wbuf)) return; - wprintf(L"%s", wtemp_buf); + wprintf(L"%s", wbuf.c_str()); #else { - printf("%s", str); + printf(STRING_VIEW_FMT, STRING_VIEW_FMT_ARG(str)); fflush(stdout); } #endif diff --git a/src/server/worldserver/RemoteAccess/RASession.cpp b/src/server/worldserver/RemoteAccess/RASession.cpp index 1cd6bbfe01b..8e32177fdc4 100644 --- a/src/server/worldserver/RemoteAccess/RASession.cpp +++ b/src/server/worldserver/RemoteAccess/RASession.cpp @@ -91,7 +91,7 @@ void RASession::Start() _socket.close(); } -int RASession::Send(char const* data) +int RASession::Send(std::string_view data) { std::ostream os(&_writeBuffer); os << data; @@ -204,9 +204,9 @@ bool RASession::ProcessCommand(std::string& command) return false; } -void RASession::CommandPrint(void* callbackArg, char const* text) +void RASession::CommandPrint(void* callbackArg, std::string_view text) { - if (!text || !*text) + if (text.empty()) return; RASession* session = static_cast(callbackArg); diff --git a/src/server/worldserver/RemoteAccess/RASession.h b/src/server/worldserver/RemoteAccess/RASession.h index e775bed5e33..d499727ae9d 100644 --- a/src/server/worldserver/RemoteAccess/RASession.h +++ b/src/server/worldserver/RemoteAccess/RASession.h @@ -42,13 +42,13 @@ public: unsigned short GetRemotePort() const { return _socket.remote_endpoint().port(); } private: - int Send(char const* data); + int Send(std::string_view data); std::string ReadString(); bool CheckAccessLevel(const std::string& user); bool CheckPassword(const std::string& user, const std::string& pass); bool ProcessCommand(std::string& command); - static void CommandPrint(void* callbackArg, char const* text); + static void CommandPrint(void* callbackArg, std::string_view text); static void CommandFinished(void* callbackArg, bool); tcp::socket _socket; diff --git a/src/server/worldserver/TCSoap/TCSoap.h b/src/server/worldserver/TCSoap/TCSoap.h index e45d044983b..be680eb4ba2 100644 --- a/src/server/worldserver/TCSoap/TCSoap.h +++ b/src/server/worldserver/TCSoap/TCSoap.h @@ -38,7 +38,7 @@ class SOAPCommand { } - void appendToPrintBuffer(char const* msg) + void appendToPrintBuffer(std::string_view msg) { m_printBuffer += msg; } @@ -54,7 +54,7 @@ class SOAPCommand return m_success; } - static void print(void* callbackArg, char const* msg) + static void print(void* callbackArg, std::string_view msg) { ((SOAPCommand*)callbackArg)->appendToPrintBuffer(msg); } -- cgit v1.2.3