Core/ChatCommands: Add support for enum type arguments (PR #25242)
(cherry picked from commit 5e40eb20e2789b86d4786d86b4bbb8ae83de5e1e)
This commit is contained in:
committed by
Shauren
parent
2e3c612c80
commit
3923650aeb
@@ -652,6 +652,11 @@ void wstrToUpper(std::wstring& str)
|
||||
std::transform(str.begin(), str.end(), str.begin(), wcharToUpper);
|
||||
}
|
||||
|
||||
void strToLower(std::string& str)
|
||||
{
|
||||
std::transform(str.begin(), str.end(), str.begin(), [](char c) { return std::tolower(c); });
|
||||
}
|
||||
|
||||
void wstrToLower(std::wstring& str)
|
||||
{
|
||||
std::transform(str.begin(), str.end(), str.begin(), wcharToLower);
|
||||
@@ -848,6 +853,20 @@ bool StringToBool(std::string const& str)
|
||||
return lowerStr == "1" || lowerStr == "true" || lowerStr == "yes";
|
||||
}
|
||||
|
||||
bool StringEqualI(std::string const& str1, std::string const& str2)
|
||||
{
|
||||
return std::equal(str1.begin(), str1.end(), str2.begin(), str2.end(),
|
||||
[](char a, char b)
|
||||
{
|
||||
return std::tolower(a) == std::tolower(b);
|
||||
});
|
||||
}
|
||||
|
||||
bool StringStartsWith(std::string const& haystack, std::string const& needle)
|
||||
{
|
||||
return (haystack.rfind(needle, 0) == 0);
|
||||
}
|
||||
|
||||
bool StringContainsStringI(std::string const& haystack, std::string const& needle)
|
||||
{
|
||||
return haystack.end() !=
|
||||
|
||||
@@ -324,6 +324,7 @@ inline bool isUpper(wchar_t wchar)
|
||||
TC_COMMON_API std::wstring wstrCaseAccentInsensitiveParse(std::wstring const& wstr, LocaleConstant locale);
|
||||
|
||||
TC_COMMON_API void wstrToUpper(std::wstring& str);
|
||||
TC_COMMON_API void strToLower(std::string& str);
|
||||
TC_COMMON_API void wstrToLower(std::wstring& str);
|
||||
|
||||
TC_COMMON_API std::wstring GetMainPartOfName(std::wstring const& wname, uint32 declension);
|
||||
@@ -377,6 +378,8 @@ inline std::vector<uint8> HexStrToByteVector(std::string const& str, bool revers
|
||||
TC_COMMON_API bool StringToBool(std::string const& str);
|
||||
TC_COMMON_API float DegToRad(float degrees);
|
||||
|
||||
TC_COMMON_API bool StringEqualI(std::string const& str1, std::string const& str2);
|
||||
TC_COMMON_API bool StringStartsWith(std::string const& haystack, std::string const& needle);
|
||||
TC_COMMON_API bool StringContainsStringI(std::string const& haystack, std::string const& needle);
|
||||
template <typename T>
|
||||
inline bool ValueContainsStringI(std::pair<T, std::string> const& haystack, std::string const& needle)
|
||||
|
||||
@@ -20,6 +20,9 @@
|
||||
|
||||
#include "ChatCommandHelpers.h"
|
||||
#include "ChatCommandTags.h"
|
||||
#include "SmartEnum.h"
|
||||
#include "Util.h"
|
||||
#include <map>
|
||||
|
||||
struct GameTele;
|
||||
|
||||
@@ -99,6 +102,82 @@ struct ArgInfo<std::string, void>
|
||||
}
|
||||
};
|
||||
|
||||
// enum
|
||||
template <typename T>
|
||||
struct ArgInfo<T, std::enable_if_t<std::is_enum_v<T>>>
|
||||
{
|
||||
static std::map<std::string, Optional<T>> MakeSearchMap()
|
||||
{
|
||||
std::map<std::string, Optional<T>> map;
|
||||
for (T val : EnumUtils::Iterate<T>())
|
||||
{
|
||||
EnumText text = EnumUtils::ToString(val);
|
||||
|
||||
std::string title(text.Title);
|
||||
strToLower(title);
|
||||
std::string constant(text.Constant);
|
||||
strToLower(constant);
|
||||
|
||||
auto [constantIt, constantNew] = map.try_emplace(constant, val);
|
||||
if (!constantNew)
|
||||
constantIt->second = std::nullopt;
|
||||
|
||||
if (title != constant)
|
||||
{
|
||||
auto [titleIt, titleNew] = map.try_emplace(title, val);
|
||||
if (!titleNew)
|
||||
titleIt->second = std::nullopt;
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
static inline std::map<std::string, Optional<T>> const SearchMap = MakeSearchMap();
|
||||
|
||||
static T const* Match(std::string s)
|
||||
{
|
||||
strToLower(s);
|
||||
|
||||
auto it = SearchMap.lower_bound(s);
|
||||
if (it == SearchMap.end() || !StringStartsWith(it->first, s)) // not a match
|
||||
return nullptr;
|
||||
|
||||
auto it2 = it;
|
||||
++it2;
|
||||
if (it2 != SearchMap.end() && StringStartsWith(it2->first, s)) // not unique
|
||||
return nullptr;
|
||||
|
||||
if (it->second)
|
||||
return &*it->second;
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static char const* TryConsume(T& val, char const* args)
|
||||
{
|
||||
std::string strVal;
|
||||
char const* ret = ArgInfo<std::string>::TryConsume(strVal, args);
|
||||
|
||||
if (!ret)
|
||||
return nullptr;
|
||||
|
||||
if (T const* tmpVal = Match(strVal))
|
||||
{
|
||||
val = *tmpVal;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Value not found. Try to parse arg as underlying type and cast it to enum type
|
||||
using U = std::underlying_type_t<T>;
|
||||
U uVal = 0;
|
||||
ret = ArgInfo<U>::TryConsume(uVal, args);
|
||||
if (ret)
|
||||
val = static_cast<T>(uVal);
|
||||
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
// a container tag
|
||||
template <typename T>
|
||||
struct ArgInfo<T, std::enable_if_t<std::is_base_of_v<ContainerTag, T>>>
|
||||
|
||||
@@ -549,13 +549,8 @@ public:
|
||||
}
|
||||
|
||||
//set npcflag of creature
|
||||
static bool HandleNpcSetFlagCommand(ChatHandler* handler, char const* args)
|
||||
static bool HandleNpcSetFlagCommand(ChatHandler* handler, NPCFlags npcFlags, NPCFlags2 npcFlags2)
|
||||
{
|
||||
if (!*args)
|
||||
return false;
|
||||
|
||||
uint64 npcFlags = atoull(args);
|
||||
|
||||
Creature* creature = handler->getSelectedCreature();
|
||||
|
||||
if (!creature)
|
||||
@@ -565,14 +560,12 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 raw[2];
|
||||
memcpy(raw, &npcFlags, sizeof(raw));
|
||||
creature->SetNpcFlags(NPCFlags(raw[0]));
|
||||
creature->SetNpcFlags2(NPCFlags2(raw[1]));
|
||||
creature->SetNpcFlags(npcFlags);
|
||||
creature->SetNpcFlags2(npcFlags2);
|
||||
|
||||
WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_CREATURE_NPCFLAG);
|
||||
|
||||
stmt->setUInt64(0, npcFlags);
|
||||
stmt->setUInt64(0, uint64(npcFlags) | (uint64(npcFlags2) << 32));
|
||||
stmt->setUInt32(1, creature->GetEntry());
|
||||
|
||||
WorldDatabase.Execute(stmt);
|
||||
|
||||
Reference in New Issue
Block a user