mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
Core/ChatCommands: make ExactSequence more readable
This commit is contained in:
@@ -655,11 +655,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() !=
|
||||
|
||||
@@ -331,7 +331,8 @@ inline std::vector<uint8> HexStrToByteVector(std::string_view str, bool reverse
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -1366,7 +1366,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)
|
||||
@@ -1471,7 +1471,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;
|
||||
@@ -1518,7 +1518,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)
|
||||
@@ -1526,10 +1526,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))
|
||||
{
|
||||
|
||||
@@ -49,8 +49,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
|
||||
{
|
||||
@@ -506,7 +506,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;
|
||||
|
||||
@@ -206,7 +206,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)
|
||||
{
|
||||
@@ -232,7 +232,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
if (operationArg->holds_alternative<ExactSequence<'r', 'e', 'm', 'o', 'v', 'e'>>())
|
||||
if (operationArg->holds_alternative<EXACT_SEQUENCE("remove")>())
|
||||
{
|
||||
if (!playerNameArg)
|
||||
return false;
|
||||
|
||||
@@ -318,7 +318,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)
|
||||
@@ -328,7 +328,7 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
if (spellArg.holds_alternative<ExactSequence<'a', 'l', 'l'>>())
|
||||
if (spellArg.holds_alternative<EXACT_SEQUENCE("all")>())
|
||||
{
|
||||
target->RemoveAllAuras();
|
||||
return true;
|
||||
|
||||
@@ -51,8 +51,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
|
||||
{
|
||||
@@ -691,7 +691,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)
|
||||
@@ -1089,7 +1089,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())
|
||||
@@ -1145,7 +1145,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())
|
||||
@@ -1331,7 +1331,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;
|
||||
@@ -1372,7 +1372,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;
|
||||
|
||||
@@ -108,7 +108,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);
|
||||
|
||||
Reference in New Issue
Block a user