diff options
author | Treeston <treeston.mmoc@gmail.com> | 2020-09-10 15:19:17 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2022-02-05 21:29:53 +0100 |
commit | 013c9b2cb7404a6d03443eb39f49622dcc99a7fa (patch) | |
tree | 93aa3e890b93528742a7ea0753499c4d1ae7c5c7 /src | |
parent | bdd4ccbd7882f4006717522a6d250e48943ba854 (diff) |
Core/ChatCommands: make ExactSequence more readable
(cherry picked from commit feaaa595cae735bb6093b24a88562c27b2723cfe)
Diffstat (limited to 'src')
-rw-r--r-- | src/common/Utilities/Util.cpp | 5 | ||||
-rw-r--r-- | src/common/Utilities/Util.h | 3 | ||||
-rw-r--r-- | src/server/game/Chat/ChatCommands/ChatCommandTags.h | 43 | ||||
-rw-r--r-- | src/server/scripts/Commands/cs_ahbot.cpp | 4 | ||||
-rw-r--r-- | src/server/scripts/Commands/cs_debug.cpp | 14 | ||||
-rw-r--r-- | src/server/scripts/Commands/cs_gobject.cpp | 6 | ||||
-rw-r--r-- | src/server/scripts/Commands/cs_message.cpp | 4 | ||||
-rw-r--r-- | src/server/scripts/Commands/cs_misc.cpp | 4 | ||||
-rw-r--r-- | src/server/scripts/Commands/cs_npc.cpp | 14 | ||||
-rw-r--r-- | src/server/scripts/Commands/cs_tele.cpp | 2 |
10 files changed, 54 insertions, 45 deletions
diff --git a/src/common/Utilities/Util.cpp b/src/common/Utilities/Util.cpp index 0d65f1f7f81..511e4b99684 100644 --- a/src/common/Utilities/Util.cpp +++ b/src/common/Utilities/Util.cpp @@ -840,11 +840,6 @@ bool StringEqualI(std::string_view str1, std::string_view str2) }); } -bool StringStartsWith(std::string_view haystack, std::string_view needle) -{ - return (haystack.substr(0, needle.length()) == needle); -} - bool StringContainsStringI(std::string_view haystack, std::string_view needle) { return haystack.end() != diff --git a/src/common/Utilities/Util.h b/src/common/Utilities/Util.h index 8708405882e..61f3d17acf8 100644 --- a/src/common/Utilities/Util.h +++ b/src/common/Utilities/Util.h @@ -369,7 +369,8 @@ inline std::vector<uint8> HexStrToByteVector(std::string_view str, bool reverse TC_COMMON_API float DegToRad(float degrees); TC_COMMON_API bool StringEqualI(std::string_view str1, std::string_view str2); -TC_COMMON_API bool StringStartsWith(std::string_view haystack, std::string_view needle); +inline bool StringStartsWith(std::string_view haystack, std::string_view needle) { return (haystack.substr(0, needle.length()) == needle); } +inline bool StringStartsWithI(std::string_view haystack, std::string_view needle) { return StringEqualI(haystack.substr(0, needle.length()), needle); } TC_COMMON_API bool StringContainsStringI(std::string_view haystack, std::string_view needle); template <typename T> inline bool ValueContainsStringI(std::pair<T, std::string_view> const& haystack, std::string_view needle) diff --git a/src/server/game/Chat/ChatCommands/ChatCommandTags.h b/src/server/game/Chat/ChatCommands/ChatCommandTags.h index be21c5e0506..879d1559dfa 100644 --- a/src/server/game/Chat/ChatCommands/ChatCommandTags.h +++ b/src/server/game/Chat/ChatCommands/ChatCommandTags.h @@ -24,6 +24,8 @@ #include "ObjectGuid.h" #include "Optional.h" #include "Util.h" +#include <boost/preprocessor/repetition/repeat.hpp> +#include <boost/preprocessor/punctuation/comma_if.hpp> #include <cmath> #include <cstring> #include <iostream> @@ -45,6 +47,22 @@ namespace Trinity::Impl::ChatCommands { using type = typename T::value_type; }; + + template <size_t N> + inline constexpr char GetChar(char const (&s)[N], size_t i) + { + static_assert(N <= 25, "The EXACT_SEQUENCE macro can only be used with up to 25 character long literals. Specify them char-by-char (null terminated) as parameters to ExactSequence<> instead."); + return i >= N ? '\0' : s[i]; + } + +#define CHATCOMMANDS_IMPL_SPLIT_LITERAL_EXTRACT_CHAR(z, i, strliteral) \ + BOOST_PP_COMMA_IF(i) Trinity::Impl::ChatCommands::GetChar(strliteral, i) + +#define CHATCOMMANDS_IMPL_SPLIT_LITERAL_CONSTRAINED(maxlen, strliteral) \ + BOOST_PP_REPEAT(maxlen, CHATCOMMANDS_IMPL_SPLIT_LITERAL_EXTRACT_CHAR, strliteral) + + // this creates always 25 elements - "abc" -> 'a', 'b', 'c', '\0', '\0', ... up to 25 +#define CHATCOMMANDS_IMPL_SPLIT_LITERAL(strliteral) CHATCOMMANDS_IMPL_SPLIT_LITERAL_CONSTRAINED(25, strliteral) } namespace Trinity::ChatCommands @@ -60,35 +78,30 @@ namespace Trinity::ChatCommands |* *| \****************************************************************************************/ - template <char c1, char... chars> + template <char... chars> struct ExactSequence : Trinity::Impl::ChatCommands::ContainerTag { using value_type = void; - static constexpr size_t N = (sizeof...(chars) + 1); - - static bool Match(char const* pos) - { - if (std::toupper(*(pos++)) != std::toupper(c1)) - return false; - else if constexpr (sizeof...(chars) > 0) - return ExactSequence<chars...>::Match(pos); - else - return true; - } - Optional<std::string_view> TryConsume(std::string_view args) const { - if ((N <= args.length()) && ExactSequence::Match(args.data())) + if (StringStartsWithI(args, _string)) { - auto [remainingToken, tail] = Trinity::Impl::ChatCommands::tokenize(args.substr(N)); + 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; } return std::nullopt; } + + private: + static constexpr std::array<char, sizeof...(chars)> _storage = { chars... }; + static_assert(!_storage.empty() && (_storage.back() == '\0'), "ExactSequence parameters must be null terminated! Use the EXACT_SEQUENCE macro to make this easier!"); + static constexpr std::string_view _string = { _storage.data() }; }; +#define EXACT_SEQUENCE(str) Trinity::ChatCommands::ExactSequence<CHATCOMMANDS_IMPL_SPLIT_LITERAL(str)> + struct Tail : std::string_view, Trinity::Impl::ChatCommands::ContainerTag { using value_type = std::string_view; diff --git a/src/server/scripts/Commands/cs_ahbot.cpp b/src/server/scripts/Commands/cs_ahbot.cpp index bb932fdb0dc..8ce3331d1fe 100644 --- a/src/server/scripts/Commands/cs_ahbot.cpp +++ b/src/server/scripts/Commands/cs_ahbot.cpp @@ -115,7 +115,7 @@ public: return true; } - static bool HandleAHBotRebuildCommand(ChatHandler* /*handler*/, Optional<ExactSequence<'a', 'l', 'l'>> all) + static bool HandleAHBotRebuildCommand(ChatHandler* /*handler*/, Optional<EXACT_SEQUENCE("all")> all) { sAuctionBot->Rebuild(all.has_value()); return true; @@ -128,7 +128,7 @@ public: return true; } - static bool HandleAHBotStatusCommand(ChatHandler* handler, Optional<ExactSequence<'a', 'l', 'l'>> all) + static bool HandleAHBotStatusCommand(ChatHandler* handler, Optional<EXACT_SEQUENCE("all")> all) { std::unordered_map<AuctionHouseType, AuctionHouseBotStatusInfoPerType> statusInfo; sAuctionBot->PrepareStatusInfos(statusInfo); diff --git a/src/server/scripts/Commands/cs_debug.cpp b/src/server/scripts/Commands/cs_debug.cpp index 0ab2286f3b5..d1f81fac578 100644 --- a/src/server/scripts/Commands/cs_debug.cpp +++ b/src/server/scripts/Commands/cs_debug.cpp @@ -164,7 +164,7 @@ public: return true; } - static bool HandleDebugWarModeFactionBalanceCommand(ChatHandler* handler, Variant<uint32, ExactSequence<'a','l','l','i','a','n','c','e'>, ExactSequence<'h','o','r','d','e'>, ExactSequence<'n','e','u','t','r','a','l'>, ExactSequence<'o','f','f'>> command, Optional<int32> rewardValue) + static bool HandleDebugWarModeFactionBalanceCommand(ChatHandler* handler, Variant<uint32, EXACT_SEQUENCE("alliance"), EXACT_SEQUENCE("horde"), EXACT_SEQUENCE("neutral"), EXACT_SEQUENCE("off")> command, Optional<int32> rewardValue) { // USAGE: .debug pvp fb <alliance|horde|neutral|off> [pct] // neutral Sets faction balance off. @@ -1227,7 +1227,7 @@ public: return true; } - static bool HandleDebugBoundaryCommand(ChatHandler* handler, Optional<ExactSequence<'f', 'i', 'l','l'>> fill, Optional<uint32> durationArg) + static bool HandleDebugBoundaryCommand(ChatHandler* handler, Optional<EXACT_SEQUENCE("fill")> fill, Optional<uint32> durationArg) { Player* player = handler->GetPlayer(); if (!player) @@ -1351,7 +1351,7 @@ public: return true; } - static bool HandleDebugNearGraveyard(ChatHandler* handler, Optional<ExactSequence<'l', 'i', 'n', 'k', 'e', 'd'>> linked) + static bool HandleDebugNearGraveyard(ChatHandler* handler, Optional<EXACT_SEQUENCE("linked")> linked) { Player* player = handler->GetPlayer(); WorldSafeLocsEntry const* nearestLoc = nullptr; @@ -1399,7 +1399,7 @@ public: return true; } - static bool HandleDebugInstanceSpawns(ChatHandler* handler, Variant<uint32, ExactSequence<'e', 'x', 'p', 'l', 'a', 'i', 'n'>> optArg) + static bool HandleDebugInstanceSpawns(ChatHandler* handler, Variant<uint32, EXACT_SEQUENCE("explain")> optArg) { Player const* const player = handler->GetPlayer(); if (!player) @@ -1407,10 +1407,10 @@ public: bool explain = false; uint32 groupID = 0; - if (optArg.holds_alternative<ExactSequence<'e', 'x', 'p', 'l', 'a', 'i', 'n'>>()) - explain = true; - else + if (optArg.holds_alternative<uint32>()) groupID = optArg.get<uint32>(); + else + explain = true; if (groupID && !sObjectMgr->GetSpawnGroupData(groupID)) { diff --git a/src/server/scripts/Commands/cs_gobject.cpp b/src/server/scripts/Commands/cs_gobject.cpp index f2556ba8804..f87498b76c5 100644 --- a/src/server/scripts/Commands/cs_gobject.cpp +++ b/src/server/scripts/Commands/cs_gobject.cpp @@ -51,8 +51,8 @@ using GameObjectSpawnId = Variant<Hyperlink<gameobject>, ObjectGuid::LowType>; using GameObjectEntry = Variant<Hyperlink<gameobject_entry>, uint32>; // definitions are over in cs_npc.cpp -bool HandleNpcSpawnGroup(ChatHandler* handler, std::vector<Variant<uint32, ExactSequence<'f','o','r','c','e'>, ExactSequence<'i','g','n','o','r','e','r','e','s','p','a','w','n'>>> const& opts); -bool HandleNpcDespawnGroup(ChatHandler* handler, std::vector<Variant<uint32, ExactSequence<'r','e','m','o','v','e','r','e','s','p','a','w','n','t','i','m','e'>>> const& opts); +bool HandleNpcSpawnGroup(ChatHandler* handler, std::vector<Variant<uint32, EXACT_SEQUENCE("force"), EXACT_SEQUENCE("ignorerespawn")>> const& opts); +bool HandleNpcDespawnGroup(ChatHandler* handler, std::vector<Variant<uint32, EXACT_SEQUENCE("removerespawntime")>> const& opts); class gobject_commandscript : public CommandScript { @@ -496,7 +496,7 @@ public: } //show info of gameobject - static bool HandleGameObjectInfoCommand(ChatHandler* handler, Optional<ExactSequence<'g', 'u', 'i', 'd'>> isGuid, Variant<Hyperlink<gameobject_entry>, Hyperlink<gameobject>, uint32> data) + static bool HandleGameObjectInfoCommand(ChatHandler* handler, Optional<EXACT_SEQUENCE("guid")> isGuid, Variant<Hyperlink<gameobject_entry>, Hyperlink<gameobject>, uint32> data) { uint32 entry = 0; uint32 type = 0; diff --git a/src/server/scripts/Commands/cs_message.cpp b/src/server/scripts/Commands/cs_message.cpp index 157961594ab..503912ef564 100644 --- a/src/server/scripts/Commands/cs_message.cpp +++ b/src/server/scripts/Commands/cs_message.cpp @@ -205,7 +205,7 @@ public: } // Enable/Disable accepting whispers (for GM) - static bool HandleWhispersCommand(ChatHandler* handler, Optional<Variant<bool, ExactSequence<'r', 'e', 'm', 'o', 'v', 'e'>>> operationArg, Optional<std::string> playerNameArg) + static bool HandleWhispersCommand(ChatHandler* handler, Optional<Variant<bool, EXACT_SEQUENCE("remove")>> operationArg, Optional<std::string> playerNameArg) { if (!operationArg) { @@ -231,7 +231,7 @@ public: } } - if (operationArg->holds_alternative<ExactSequence<'r', 'e', 'm', 'o', 'v', 'e'>>()) + if (operationArg->holds_alternative<EXACT_SEQUENCE("remove")>()) { if (!playerNameArg) return false; diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index a46df10186a..49eb1b27807 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -323,7 +323,7 @@ public: return true; } - static bool HandleUnAuraCommand(ChatHandler* handler, Variant<SpellInfo const*, ExactSequence<'a', 'l', 'l'>> spellArg) + static bool HandleUnAuraCommand(ChatHandler* handler, Variant<SpellInfo const*, EXACT_SEQUENCE("all")> spellArg) { Unit* target = handler->getSelectedUnit(); if (!target) @@ -333,7 +333,7 @@ public: return false; } - if (spellArg.holds_alternative<ExactSequence<'a', 'l', 'l'>>()) + if (spellArg.holds_alternative<EXACT_SEQUENCE("all")>()) { target->RemoveAllAuras(); return true; diff --git a/src/server/scripts/Commands/cs_npc.cpp b/src/server/scripts/Commands/cs_npc.cpp index b4bd7f6fc51..6112f51c7a9 100644 --- a/src/server/scripts/Commands/cs_npc.cpp +++ b/src/server/scripts/Commands/cs_npc.cpp @@ -53,8 +53,8 @@ using CreatureSpawnId = Variant<Hyperlink<creature>, ObjectGuid::LowType>; using CreatureEntry = Variant<Hyperlink<creature_entry>, uint32>; // shared with cs_gobject.cpp, definitions are at the bottom of this file -bool HandleNpcSpawnGroup(ChatHandler* handler, std::vector<Variant<uint32, ExactSequence<'f','o','r','c','e'>, ExactSequence<'i','g','n','o','r','e','r','e','s','p','a','w','n'>>> const& opts); -bool HandleNpcDespawnGroup(ChatHandler* handler, std::vector<Variant<uint32, ExactSequence<'r','e','m','o','v','e','r','e','s','p','a','w','n','t','i','m','e'>>> const& opts); +bool HandleNpcSpawnGroup(ChatHandler* handler, std::vector<Variant<uint32, EXACT_SEQUENCE("force"), EXACT_SEQUENCE("ignorerespawn")>> const& opts); +bool HandleNpcDespawnGroup(ChatHandler* handler, std::vector<Variant<uint32, EXACT_SEQUENCE("removerespawntime")>> const& opts); class npc_commandscript : public CommandScript { @@ -724,7 +724,7 @@ public: * additional parameter: NODEL - so no waypoints are deleted, if you * change the movement type */ - static bool HandleNpcSetMoveTypeCommand(ChatHandler* handler, Optional<CreatureSpawnId> lowGuid, Variant<ExactSequence<'s','t','a','y'>, ExactSequence<'r','a','n','d','o','m'>, ExactSequence<'w','a','y'>> type, Optional<ExactSequence<'n','o','d','e','l'>> nodel) + static bool HandleNpcSetMoveTypeCommand(ChatHandler* handler, Optional<CreatureSpawnId> lowGuid, Variant<EXACT_SEQUENCE("stay"), EXACT_SEQUENCE("random"), EXACT_SEQUENCE("way")> type, Optional<EXACT_SEQUENCE("nodel")> nodel) { // 3 arguments: // GUID (optional - you can also select the creature) @@ -1149,7 +1149,7 @@ public: return true; } - static bool HandleNpcEvadeCommand(ChatHandler* handler, Optional<CreatureAI::EvadeReason> why, Optional<ExactSequence<'f','o','r','c','e'>> force) + static bool HandleNpcEvadeCommand(ChatHandler* handler, Optional<CreatureAI::EvadeReason> why, Optional<EXACT_SEQUENCE("force")> force) { Creature* creatureTarget = handler->getSelectedCreature(); if (!creatureTarget || creatureTarget->IsPet()) @@ -1202,7 +1202,7 @@ public: } } } - static bool HandleNpcShowLootCommand(ChatHandler* handler, Optional<ExactSequence<'a','l','l'>> all) + static bool HandleNpcShowLootCommand(ChatHandler* handler, Optional<EXACT_SEQUENCE("all")> all) { Creature* creatureTarget = handler->getSelectedCreature(); if (!creatureTarget || creatureTarget->IsPet()) @@ -1388,7 +1388,7 @@ void AddSC_npc_commandscript() new npc_commandscript(); } -bool HandleNpcSpawnGroup(ChatHandler* handler, std::vector<Variant<uint32, ExactSequence<'f','o','r','c','e'>, ExactSequence<'i','g','n','o','r','e','r','e','s','p','a','w','n'>>> const& opts) +bool HandleNpcSpawnGroup(ChatHandler* handler, std::vector<Variant<uint32, EXACT_SEQUENCE("force"), EXACT_SEQUENCE("ignorerespawn")>> const& opts) { if (opts.empty()) return false; @@ -1429,7 +1429,7 @@ bool HandleNpcSpawnGroup(ChatHandler* handler, std::vector<Variant<uint32, Exact return true; } -bool HandleNpcDespawnGroup(ChatHandler* handler, std::vector<Variant<uint32, ExactSequence<'r','e','m','o','v','e','r','e','s','p','a','w','n','t','i','m','e'>>> const& opts) +bool HandleNpcDespawnGroup(ChatHandler* handler, std::vector<Variant<uint32, EXACT_SEQUENCE("removerespawntime")>> const& opts) { if (opts.empty()) return false; diff --git a/src/server/scripts/Commands/cs_tele.cpp b/src/server/scripts/Commands/cs_tele.cpp index 1ea36d72dda..de6812816d3 100644 --- a/src/server/scripts/Commands/cs_tele.cpp +++ b/src/server/scripts/Commands/cs_tele.cpp @@ -109,7 +109,7 @@ public: } // teleport player to given game_tele.entry - static bool HandleTeleNameCommand(ChatHandler* handler, Optional<PlayerIdentifier> player, Variant<GameTele const*, ExactSequence<'$','h','o','m','e'>> where) + static bool HandleTeleNameCommand(ChatHandler* handler, Optional<PlayerIdentifier> player, Variant<GameTele const*, EXACT_SEQUENCE("$home")> where) { if (!player) player = PlayerIdentifier::FromTargetOrSelf(handler); |