mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-18 08:28:32 +01:00
Core/ChatCommands: Move Trinity::ChatCommands::Variant from boost::variant to std::variant, which means we no longer need visitors
This commit is contained in:
@@ -31,9 +31,9 @@ struct AchievementVisitor
|
|||||||
};
|
};
|
||||||
char const* Trinity::ChatCommands::ArgInfo<AchievementEntry const*>::TryConsume(AchievementEntry const*& data, char const* args)
|
char const* Trinity::ChatCommands::ArgInfo<AchievementEntry const*>::TryConsume(AchievementEntry const*& data, char const* args)
|
||||||
{
|
{
|
||||||
Variant <Hyperlink<achievement>, uint32> val;
|
Variant<Hyperlink<achievement>, uint32> val;
|
||||||
if ((args = CommandArgsConsumerSingle<decltype(val)>::TryConsumeTo(val, args)))
|
if ((args = CommandArgsConsumerSingle<decltype(val)>::TryConsumeTo(val, args)))
|
||||||
data = boost::apply_visitor(AchievementVisitor(), val);
|
data = val.visit(AchievementVisitor());
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,7 +47,7 @@ char const* Trinity::ChatCommands::ArgInfo<GameTele const*>::TryConsume(GameTele
|
|||||||
{
|
{
|
||||||
Variant<Hyperlink<tele>, std::string> val;
|
Variant<Hyperlink<tele>, std::string> val;
|
||||||
if ((args = CommandArgsConsumerSingle<decltype(val)>::TryConsumeTo(val, args)))
|
if ((args = CommandArgsConsumerSingle<decltype(val)>::TryConsumeTo(val, args)))
|
||||||
data = boost::apply_visitor(GameTeleVisitor(), val);
|
data = val.visit(GameTeleVisitor());
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,21 +61,22 @@ char const* Trinity::ChatCommands::ArgInfo<SpellInfo const*>::TryConsume(SpellIn
|
|||||||
{
|
{
|
||||||
Variant<Hyperlink<spell>, uint32> val;
|
Variant<Hyperlink<spell>, uint32> val;
|
||||||
if ((args = CommandArgsConsumerSingle<decltype(val)>::TryConsumeTo(val, args)))
|
if ((args = CommandArgsConsumerSingle<decltype(val)>::TryConsumeTo(val, args)))
|
||||||
data = boost::apply_visitor(SpellInfoVisitor(), val);
|
data = val.visit(SpellInfoVisitor());
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct BoolVisitor
|
|
||||||
{
|
|
||||||
using value_type = bool;
|
|
||||||
value_type operator()(uint32 i) const { return !!i; }
|
|
||||||
value_type operator()(ExactSequence<'o', 'n'>) const { return true; }
|
|
||||||
value_type operator()(ExactSequence<'o', 'f', 'f'>) const { return false; }
|
|
||||||
};
|
|
||||||
char const* Trinity::ChatCommands::ArgInfo<bool>::TryConsume(bool& data, char const* args)
|
char const* Trinity::ChatCommands::ArgInfo<bool>::TryConsume(bool& data, char const* args)
|
||||||
{
|
{
|
||||||
Variant<uint32, ExactSequence<'o', 'n'>, ExactSequence<'o', 'f', 'f'>> val;
|
std::string val;
|
||||||
if ((args = CommandArgsConsumerSingle<decltype(val)>::TryConsumeTo(val, args)))
|
if ((args = CommandArgsConsumerSingle<std::string>::TryConsumeTo(val, args)))
|
||||||
data = boost::apply_visitor(BoolVisitor(), val);
|
{
|
||||||
|
strToLower(val);
|
||||||
|
if (val == "on" || val == "yes" || val == "true" || val == "1" || val == "y")
|
||||||
|
data = true;
|
||||||
|
else if (val == "off" || val == "no" || val == "false" || val == "0" || val == "n")
|
||||||
|
data = false;
|
||||||
|
else
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ struct ArgInfo<T, std::enable_if_t<std::is_integral_v<T> && std::is_signed_v<T>>
|
|||||||
static char const* TryConsume(T& val, char const* args)
|
static char const* TryConsume(T& val, char const* args)
|
||||||
{
|
{
|
||||||
char const* next = args;
|
char const* next = args;
|
||||||
std::string token(args, tokenize(next));
|
std::string token(args, Trinity::Impl::ChatCommands::tokenize(next));
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
size_t processedChars = 0;
|
size_t processedChars = 0;
|
||||||
@@ -70,7 +70,7 @@ struct ArgInfo<T, std::enable_if_t<std::is_integral_v<T> && std::is_unsigned_v<T
|
|||||||
static char const* TryConsume(T& val, char const* args)
|
static char const* TryConsume(T& val, char const* args)
|
||||||
{
|
{
|
||||||
char const* next = args;
|
char const* next = args;
|
||||||
std::string token(args, tokenize(next));
|
std::string token(args, Trinity::Impl::ChatCommands::tokenize(next));
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
size_t processedChars = 0;
|
size_t processedChars = 0;
|
||||||
@@ -90,7 +90,7 @@ struct ArgInfo<T, std::enable_if_t<std::is_floating_point_v<T>>>
|
|||||||
static char const* TryConsume(T& val, char const* args)
|
static char const* TryConsume(T& val, char const* args)
|
||||||
{
|
{
|
||||||
char const* next = args;
|
char const* next = args;
|
||||||
std::string token(args, tokenize(next));
|
std::string token(args, Trinity::Impl::ChatCommands::tokenize(next));
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
size_t processedChars = 0;
|
size_t processedChars = 0;
|
||||||
@@ -110,7 +110,7 @@ struct ArgInfo<std::string, void>
|
|||||||
static char const* TryConsume(std::string& val, char const* args)
|
static char const* TryConsume(std::string& val, char const* args)
|
||||||
{
|
{
|
||||||
char const* next = args;
|
char const* next = args;
|
||||||
if (size_t len = tokenize(next))
|
if (size_t len = Trinity::Impl::ChatCommands::tokenize(next))
|
||||||
{
|
{
|
||||||
val.assign(args, len);
|
val.assign(args, len);
|
||||||
return next;
|
return next;
|
||||||
|
|||||||
@@ -20,58 +20,50 @@
|
|||||||
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
namespace Trinity
|
namespace Trinity::ChatCommands
|
||||||
{
|
|
||||||
namespace ChatCommands
|
|
||||||
{
|
{
|
||||||
|
static constexpr char COMMAND_DELIMITER = ' ';
|
||||||
|
|
||||||
static constexpr char COMMAND_DELIMITER = ' ';
|
template <typename T, typename = void>
|
||||||
|
struct tag_base
|
||||||
|
{
|
||||||
|
using type = T;
|
||||||
|
};
|
||||||
|
|
||||||
/***************** HELPERS *************************\
|
template <typename T>
|
||||||
|* These really aren't for outside use... *|
|
using tag_base_t = typename tag_base<T>::type;
|
||||||
\***************************************************/
|
|
||||||
inline std::size_t tokenize(char const*& end)
|
|
||||||
{
|
|
||||||
std::size_t len = 0;
|
|
||||||
for (; *end && *end != COMMAND_DELIMITER; ++end, ++len);
|
|
||||||
for (; *end && *end == COMMAND_DELIMITER; ++end);
|
|
||||||
return len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename = void>
|
namespace Trinity::Impl::ChatCommands
|
||||||
struct tag_base
|
|
||||||
{
|
{
|
||||||
using type = T;
|
/***************** HELPERS *************************\
|
||||||
};
|
|* These really aren't for outside use... *|
|
||||||
|
\***************************************************/
|
||||||
|
inline std::size_t tokenize(char const*& end)
|
||||||
|
{
|
||||||
|
std::size_t len = 0;
|
||||||
|
for (; *end && *end != Trinity::ChatCommands::COMMAND_DELIMITER; ++end, ++len);
|
||||||
|
for (; *end && *end == Trinity::ChatCommands::COMMAND_DELIMITER; ++end);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T, typename... Ts>
|
||||||
using tag_base_t = typename tag_base<T>::type;
|
struct are_all_assignable
|
||||||
|
{
|
||||||
|
static constexpr bool value = (std::is_assignable_v<T&, Ts> && ...);
|
||||||
|
};
|
||||||
|
|
||||||
template <typename...>
|
template <std::size_t index, typename T1, typename... Ts>
|
||||||
struct are_all_assignable
|
struct get_nth : get_nth<index-1, Ts...> { };
|
||||||
{
|
|
||||||
static constexpr bool value = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T1, typename T2, typename... Ts>
|
template <typename T1, typename... Ts>
|
||||||
struct are_all_assignable<T1, T2, Ts...>
|
struct get_nth<0, T1, Ts...>
|
||||||
{
|
{
|
||||||
static constexpr bool value = std::is_assignable_v<T1&, T2> && are_all_assignable<T1, Ts...>::value;
|
using type = T1;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <std::size_t index, typename T1, typename... Ts>
|
template <std::size_t index, typename... Ts>
|
||||||
struct get_nth : get_nth<index-1, Ts...> { };
|
using get_nth_t = typename get_nth<index, Ts...>::type;
|
||||||
|
|
||||||
template <typename T1, typename... Ts>
|
|
||||||
struct get_nth<0, T1, Ts...>
|
|
||||||
{
|
|
||||||
using type = T1;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <std::size_t index, typename... Ts>
|
|
||||||
using get_nth_t = typename get_nth<index, Ts...>::type;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -22,150 +22,158 @@
|
|||||||
#include "ChatCommandHelpers.h"
|
#include "ChatCommandHelpers.h"
|
||||||
#include "Hyperlinks.h"
|
#include "Hyperlinks.h"
|
||||||
#include "Optional.h"
|
#include "Optional.h"
|
||||||
#include <boost/variant.hpp>
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <variant>
|
||||||
|
|
||||||
namespace Trinity
|
namespace Trinity::ChatCommands
|
||||||
{
|
{
|
||||||
namespace ChatCommands
|
/************************** CONTAINER TAGS **********************************************\
|
||||||
{
|
|* Simple holder classes to differentiate between extraction methods *|
|
||||||
/************************** CONTAINER TAGS **********************************************\
|
|* Should inherit from ContainerTag for template identification *|
|
||||||
|* Simple holder classes to differentiate between extraction methods *|
|
|* Must implement the following: *|
|
||||||
|* Should inherit from ContainerTag for template identification *|
|
|* - TryConsume: char const* -> char const* *|
|
||||||
|* Must implement the following: *|
|
|* returns nullptr if no match, otherwise pointer to first character of next token *|
|
||||||
|* - TryConsume: char const* -> char const* *|
|
|* - typedef value_type of type that is contained within the tag *|
|
||||||
|* returns nullptr if no match, otherwise pointer to first character of next token *|
|
|* - cast operator to value_type *|
|
||||||
|* - typedef value_type of type that is contained within the tag *|
|
|* *|
|
||||||
|* - cast operator to value_type *|
|
\****************************************************************************************/
|
||||||
|* *|
|
struct ContainerTag {};
|
||||||
\****************************************************************************************/
|
template <typename T>
|
||||||
struct ContainerTag {};
|
struct tag_base<T, std::enable_if_t<std::is_base_of_v<ContainerTag, T>>>
|
||||||
template <typename T>
|
|
||||||
struct tag_base<T, std::enable_if_t<std::is_base_of_v<ContainerTag, T>>>
|
|
||||||
{
|
|
||||||
using type = typename T::value_type;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <char c1, char... chars>
|
|
||||||
struct ExactSequence : public ContainerTag
|
|
||||||
{
|
|
||||||
using value_type = void;
|
|
||||||
|
|
||||||
static constexpr bool isSingleChar = !sizeof...(chars);
|
|
||||||
|
|
||||||
template <bool C = isSingleChar>
|
|
||||||
static typename std::enable_if_t<!C, char const*> _TryConsume(char const* pos)
|
|
||||||
{
|
{
|
||||||
if (*(pos++) == c1)
|
using type = typename T::value_type;
|
||||||
return ExactSequence<chars...>::_TryConsume(pos);
|
};
|
||||||
else
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <bool C = isSingleChar>
|
template <char c1, char... chars>
|
||||||
static typename std::enable_if_t<C, char const*> _TryConsume(char const* pos)
|
struct ExactSequence : public ContainerTag
|
||||||
{
|
{
|
||||||
if (*(pos++) != c1)
|
using value_type = void;
|
||||||
return nullptr;
|
|
||||||
// if more of string is left, tokenize should return 0 (otherwise we didn't reach end of token yet)
|
|
||||||
return *pos && tokenize(pos) ? nullptr : pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
char const* TryConsume(char const* pos) const { return ExactSequence::_TryConsume(pos); }
|
static char const* _TryConsume(char const* pos)
|
||||||
};
|
|
||||||
|
|
||||||
template <typename linktag>
|
|
||||||
struct Hyperlink : public ContainerTag
|
|
||||||
{
|
|
||||||
typedef typename linktag::value_type value_type;
|
|
||||||
typedef advstd::remove_cvref_t<value_type> storage_type;
|
|
||||||
|
|
||||||
public:
|
|
||||||
operator value_type() const { return val; }
|
|
||||||
value_type operator*() const { return val; }
|
|
||||||
storage_type const* operator->() const { return &val; }
|
|
||||||
|
|
||||||
char const* TryConsume(char const* pos)
|
|
||||||
{
|
{
|
||||||
Trinity::Hyperlinks::HyperlinkInfo info = Trinity::Hyperlinks::ParseHyperlink(pos);
|
if (*(pos++) == c1)
|
||||||
// invalid hyperlinks cannot be consumed
|
{
|
||||||
if (!info)
|
if constexpr (sizeof...(chars))
|
||||||
|
return ExactSequence<chars...>::_TryConsume(pos);
|
||||||
|
else if (Trinity::Impl::ChatCommands::tokenize(pos)) /* we did not consume the entire token */
|
||||||
|
return nullptr;
|
||||||
|
else
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
else
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
// check if we got the right tag
|
|
||||||
if (info.tag.second != strlen(linktag::tag()))
|
|
||||||
return nullptr;
|
|
||||||
if (strncmp(info.tag.first, linktag::tag(), strlen(linktag::tag())) != 0)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
// store value
|
|
||||||
if (!linktag::StoreTo(val, info.data.first, info.data.second))
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
// finally, skip to end of token
|
|
||||||
pos = info.next;
|
|
||||||
tokenize(pos);
|
|
||||||
|
|
||||||
// return final pos
|
|
||||||
return pos;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
char const* TryConsume(char const* pos) const { return ExactSequence::_TryConsume(pos); }
|
||||||
storage_type val;
|
};
|
||||||
};
|
|
||||||
|
|
||||||
// pull in link tags for user convenience
|
template <typename linktag>
|
||||||
using namespace ::Trinity::Hyperlinks::LinkTags;
|
struct Hyperlink : public ContainerTag
|
||||||
|
{
|
||||||
|
using value_type = typename linktag::value_type;
|
||||||
|
using storage_type = typedef advstd::remove_cvref_t<value_type>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
operator value_type() const { return val; }
|
||||||
|
value_type operator*() const { return val; }
|
||||||
|
storage_type const* operator->() const { return &val; }
|
||||||
|
|
||||||
|
char const* TryConsume(char const* pos)
|
||||||
|
{
|
||||||
|
Trinity::Hyperlinks::HyperlinkInfo info = Trinity::Hyperlinks::ParseHyperlink(pos);
|
||||||
|
// invalid hyperlinks cannot be consumed
|
||||||
|
if (!info)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
// check if we got the right tag
|
||||||
|
if (info.tag.second != strlen(linktag::tag()))
|
||||||
|
return nullptr;
|
||||||
|
if (strncmp(info.tag.first, linktag::tag(), strlen(linktag::tag())) != 0)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
// store value
|
||||||
|
if (!linktag::StoreTo(val, info.data.first, info.data.second))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
// finally, skip to end of token
|
||||||
|
pos = info.next;
|
||||||
|
Trinity::Impl::ChatCommands::tokenize(pos);
|
||||||
|
|
||||||
|
// return final pos
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
storage_type val;
|
||||||
|
};
|
||||||
|
|
||||||
|
// pull in link tags for user convenience
|
||||||
|
using namespace ::Trinity::Hyperlinks::LinkTags;
|
||||||
|
}
|
||||||
|
|
||||||
/************************** VARIANT TAG LOGIC *********************************\
|
/************************** VARIANT TAG LOGIC *********************************\
|
||||||
|* This has some special handling over in ChatCommand.h *|
|
|* This has some special handling over in ChatCommand.h *|
|
||||||
\******************************************************************************/
|
\******************************************************************************/
|
||||||
|
|
||||||
template <typename T>
|
namespace Trinity::Impl
|
||||||
struct CastToVisitor {
|
|
||||||
using result_type = T;
|
|
||||||
|
|
||||||
template <typename U>
|
|
||||||
T operator()(U const& v) const { return v; }
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T1, typename... Ts>
|
|
||||||
struct Variant : public boost::variant<T1, Ts...>
|
|
||||||
{
|
{
|
||||||
using first_type = tag_base_t<T1>;
|
|
||||||
static constexpr bool have_operators = are_all_assignable<first_type, tag_base_t<Ts>...>::value;
|
|
||||||
|
|
||||||
template <bool C = have_operators>
|
|
||||||
operator std::enable_if_t<C, first_type>()
|
|
||||||
{
|
|
||||||
return operator*();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <bool C = have_operators>
|
|
||||||
std::enable_if_t<C, first_type> operator*()
|
|
||||||
{
|
|
||||||
return boost::apply_visitor(CastToVisitor<first_type>(), *this);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <bool C = have_operators>
|
|
||||||
std::enable_if_t<C, first_type const&> operator*() const
|
|
||||||
{
|
|
||||||
return boost::apply_visitor(CastToVisitor<first_type const&>(), *this);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
Variant& operator=(T&& arg) { boost::variant<T1, Ts...>::operator=(std::forward<T>(arg)); return *this; }
|
struct CastToVisitor {
|
||||||
|
template <typename U>
|
||||||
template <size_t index>
|
T operator()(U const& v) const { return v; }
|
||||||
decltype(auto) get() const { return boost::get<get_nth_t<index, T1, Ts...>>(*this); }
|
};
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Trinity::ChatCommands
|
||||||
|
{
|
||||||
|
template <typename T1, typename... Ts>
|
||||||
|
struct Variant : public std::variant<T1, Ts...>
|
||||||
|
{
|
||||||
|
using first_type = tag_base_t<T1>;
|
||||||
|
static constexpr bool have_operators = Trinity::Impl::ChatCommands::are_all_assignable<first_type, tag_base_t<Ts>...>::value;
|
||||||
|
|
||||||
|
template <bool C = have_operators>
|
||||||
|
std::enable_if_t<C, first_type> operator*() const
|
||||||
|
{
|
||||||
|
return visit(Trinity::Impl::CastToVisitor<first_type>());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <bool C = have_operators>
|
||||||
|
operator std::enable_if_t<C, first_type>() const
|
||||||
|
{
|
||||||
|
return operator*();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
Variant& operator=(T&& arg) { std::variant<T1, Ts...>::operator=(std::forward<T>(arg)); return *this; }
|
||||||
|
|
||||||
|
template <size_t index>
|
||||||
|
constexpr decltype(auto) get() { return std::get<index>(*this); }
|
||||||
|
template <size_t index>
|
||||||
|
constexpr decltype(auto) get() const { return std::get<index>(*this); }
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
constexpr decltype(auto) visit(T&& arg) const { return std::visit(std::forward<T>(arg), *this); }
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
constexpr bool holds_alternative() const { return std::holds_alternative<T>(*this); }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/* make the correct operator<< to use explicit, because otherwise the compiler gets confused with the implicit std::variant conversion */
|
||||||
|
namespace std
|
||||||
|
{
|
||||||
|
template <typename... Ts>
|
||||||
|
auto operator<<(std::ostream& os, Trinity::ChatCommands::Variant<Ts...> const& v) -> std::enable_if_t<Trinity::ChatCommands::Variant<Ts...>::have_operators, std::ostream&>
|
||||||
|
{
|
||||||
|
return (os << *v);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -31,212 +31,209 @@ class SpellInfo;
|
|||||||
class Quest;
|
class Quest;
|
||||||
struct TalentEntry;
|
struct TalentEntry;
|
||||||
|
|
||||||
namespace Trinity
|
namespace Trinity::Hyperlinks
|
||||||
{
|
|
||||||
namespace Hyperlinks
|
|
||||||
{
|
{
|
||||||
|
|
||||||
struct AchievementLinkData
|
struct AchievementLinkData
|
||||||
{
|
|
||||||
AchievementEntry const* Achievement;
|
|
||||||
ObjectGuid::LowType CharacterId;
|
|
||||||
bool IsFinished;
|
|
||||||
uint16 Year;
|
|
||||||
uint8 Month;
|
|
||||||
uint8 Day;
|
|
||||||
uint32 Criteria[4];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct GlyphLinkData
|
|
||||||
{
|
|
||||||
GlyphPropertiesEntry const* Glyph;
|
|
||||||
GlyphSlotEntry const* Slot;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ItemLinkData
|
|
||||||
{
|
|
||||||
ItemTemplate const* Item;
|
|
||||||
uint32 EnchantId;
|
|
||||||
uint32 GemEnchantId[3];
|
|
||||||
int32 RandomPropertyId;
|
|
||||||
int32 RandomPropertySeed;
|
|
||||||
uint8 RenderLevel;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct QuestLinkData
|
|
||||||
{
|
|
||||||
::Quest const* Quest;
|
|
||||||
uint8 QuestLevel;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TalentLinkData
|
|
||||||
{
|
|
||||||
TalentEntry const* Talent;
|
|
||||||
uint8 Rank;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TradeskillLinkData
|
|
||||||
{
|
|
||||||
SpellInfo const* Spell;
|
|
||||||
uint16 CurValue;
|
|
||||||
uint16 MaxValue;
|
|
||||||
ObjectGuid Owner;
|
|
||||||
std::string KnownRecipes;
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace LinkTags {
|
|
||||||
|
|
||||||
/************************** LINK TAGS ***************************************************\
|
|
||||||
|* Link tags must abide by the following: *|
|
|
||||||
|* - MUST expose ::value_type typedef *|
|
|
||||||
|* - storage type is remove_cvref_t<value_type> *|
|
|
||||||
|* - MUST expose static ::tag method, void -> const char* *|
|
|
||||||
|* - this method SHOULD be constexpr *|
|
|
||||||
|* - returns identifier string for the link ("creature", "creature_entry", "item") *|
|
|
||||||
|* - MUST expose static ::StoreTo method, (storage&, char const*, size_t) *|
|
|
||||||
|* - assign value_type& based on content of std::string(char const*, size_t) *|
|
|
||||||
|* - return value indicates success/failure *|
|
|
||||||
|* - for integral/string types this can be achieved by extending base_tag *|
|
|
||||||
\****************************************************************************************/
|
|
||||||
struct base_tag
|
|
||||||
{
|
{
|
||||||
static bool StoreTo(std::string& val, char const* pos, size_t len)
|
AchievementEntry const* Achievement;
|
||||||
|
ObjectGuid::LowType CharacterId;
|
||||||
|
bool IsFinished;
|
||||||
|
uint16 Year;
|
||||||
|
uint8 Month;
|
||||||
|
uint8 Day;
|
||||||
|
uint32 Criteria[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GlyphLinkData
|
||||||
|
{
|
||||||
|
GlyphPropertiesEntry const* Glyph;
|
||||||
|
GlyphSlotEntry const* Slot;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ItemLinkData
|
||||||
|
{
|
||||||
|
ItemTemplate const* Item;
|
||||||
|
uint32 EnchantId;
|
||||||
|
uint32 GemEnchantId[3];
|
||||||
|
int32 RandomPropertyId;
|
||||||
|
int32 RandomPropertySeed;
|
||||||
|
uint8 RenderLevel;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QuestLinkData
|
||||||
|
{
|
||||||
|
::Quest const* Quest;
|
||||||
|
uint8 QuestLevel;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TalentLinkData
|
||||||
|
{
|
||||||
|
TalentEntry const* Talent;
|
||||||
|
uint8 Rank;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TradeskillLinkData
|
||||||
|
{
|
||||||
|
SpellInfo const* Spell;
|
||||||
|
uint16 CurValue;
|
||||||
|
uint16 MaxValue;
|
||||||
|
ObjectGuid Owner;
|
||||||
|
std::string KnownRecipes;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace LinkTags {
|
||||||
|
|
||||||
|
/************************** LINK TAGS ***************************************************\
|
||||||
|
|* Link tags must abide by the following: *|
|
||||||
|
|* - MUST expose ::value_type typedef *|
|
||||||
|
|* - storage type is remove_cvref_t<value_type> *|
|
||||||
|
|* - MUST expose static ::tag method, void -> const char* *|
|
||||||
|
|* - this method SHOULD be constexpr *|
|
||||||
|
|* - returns identifier string for the link ("creature", "creature_entry", "item") *|
|
||||||
|
|* - MUST expose static ::StoreTo method, (storage&, char const*, size_t) *|
|
||||||
|
|* - assign value_type& based on content of std::string(char const*, size_t) *|
|
||||||
|
|* - return value indicates success/failure *|
|
||||||
|
|* - for integral/string types this can be achieved by extending base_tag *|
|
||||||
|
\****************************************************************************************/
|
||||||
|
struct base_tag
|
||||||
{
|
{
|
||||||
val.assign(pos, len);
|
static bool StoreTo(std::string& val, char const* pos, size_t len)
|
||||||
return true;
|
{
|
||||||
}
|
val.assign(pos, len);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static std::enable_if_t<std::is_integral_v<T> && std::is_unsigned_v<T>, bool> StoreTo(T& val, char const* pos, size_t len)
|
static std::enable_if_t<std::is_integral_v<T> && std::is_unsigned_v<T>, bool> StoreTo(T& val, char const* pos, size_t len)
|
||||||
|
{
|
||||||
|
try { val = std::stoull(std::string(pos, len)); }
|
||||||
|
catch (...) { return false; }
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static std::enable_if_t<std::is_integral_v<T> && std::is_signed_v<T>, bool> StoreTo(T& val, char const* pos, size_t len)
|
||||||
|
{
|
||||||
|
try { val = std::stoll(std::string(pos, len)); }
|
||||||
|
catch (...) { return false; }
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool StoreTo(ObjectGuid& val, char const* pos, size_t len)
|
||||||
|
{
|
||||||
|
try { val.Set(std::stoul(std::string(pos, len), nullptr, 16)); }
|
||||||
|
catch (...) { return false; }
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#define make_base_tag(ltag, type) struct ltag : public base_tag { using value_type = type; static constexpr char const* tag() { return #ltag; } }
|
||||||
|
make_base_tag(area, uint32);
|
||||||
|
make_base_tag(areatrigger, uint32);
|
||||||
|
make_base_tag(creature, ObjectGuid::LowType);
|
||||||
|
make_base_tag(creature_entry, uint32);
|
||||||
|
make_base_tag(gameevent, uint32);
|
||||||
|
make_base_tag(gameobject, ObjectGuid::LowType);
|
||||||
|
make_base_tag(gameobject_entry, uint32);
|
||||||
|
make_base_tag(itemset, uint32);
|
||||||
|
make_base_tag(player, std::string const&);
|
||||||
|
make_base_tag(skill, uint32);
|
||||||
|
make_base_tag(taxinode, uint32);
|
||||||
|
make_base_tag(tele, uint32);
|
||||||
|
make_base_tag(title, uint32);
|
||||||
|
#undef make_base_tag
|
||||||
|
|
||||||
|
struct TC_GAME_API achievement
|
||||||
{
|
{
|
||||||
try { val = std::stoull(std::string(pos, len)); }
|
using value_type = AchievementLinkData const&;
|
||||||
catch (...) { return false; }
|
static constexpr char const* tag() { return "achievement"; }
|
||||||
return true;
|
static bool StoreTo(AchievementLinkData& val, char const* pos, size_t len);
|
||||||
}
|
};
|
||||||
|
|
||||||
template <typename T>
|
struct TC_GAME_API enchant
|
||||||
static std::enable_if_t<std::is_integral_v<T> && std::is_signed_v<T>, bool> StoreTo(T& val, char const* pos, size_t len)
|
|
||||||
{
|
{
|
||||||
try { val = std::stoll(std::string(pos, len)); }
|
using value_type = SpellInfo const*;
|
||||||
catch (...) { return false; }
|
static constexpr char const* tag() { return "enchant"; }
|
||||||
return true;
|
static bool StoreTo(SpellInfo const*& val, char const* pos, size_t len);
|
||||||
}
|
};
|
||||||
|
|
||||||
static bool StoreTo(ObjectGuid& val, char const* pos, size_t len)
|
struct TC_GAME_API glyph
|
||||||
{
|
{
|
||||||
try { val.Set(std::stoul(std::string(pos, len), nullptr, 16)); }
|
using value_type = GlyphLinkData const&;
|
||||||
catch (...) { return false; }
|
static constexpr char const* tag() { return "glyph"; };
|
||||||
return true;
|
static bool StoreTo(GlyphLinkData& val, char const* pos, size_t len);
|
||||||
}
|
};
|
||||||
};
|
|
||||||
|
|
||||||
#define make_base_tag(ltag, type) struct ltag : public base_tag { using value_type = type; static constexpr char const* tag() { return #ltag; } }
|
struct TC_GAME_API item
|
||||||
make_base_tag(area, uint32);
|
{
|
||||||
make_base_tag(areatrigger, uint32);
|
using value_type = ItemLinkData const&;
|
||||||
make_base_tag(creature, ObjectGuid::LowType);
|
static constexpr char const* tag() { return "item"; }
|
||||||
make_base_tag(creature_entry, uint32);
|
static bool StoreTo(ItemLinkData& val, char const* pos, size_t len);
|
||||||
make_base_tag(gameevent, uint32);
|
};
|
||||||
make_base_tag(gameobject, ObjectGuid::LowType);
|
|
||||||
make_base_tag(gameobject_entry, uint32);
|
|
||||||
make_base_tag(itemset, uint32);
|
|
||||||
make_base_tag(player, std::string const&);
|
|
||||||
make_base_tag(skill, uint32);
|
|
||||||
make_base_tag(taxinode, uint32);
|
|
||||||
make_base_tag(tele, uint32);
|
|
||||||
make_base_tag(title, uint32);
|
|
||||||
#undef make_base_tag
|
|
||||||
|
|
||||||
struct TC_GAME_API achievement
|
struct TC_GAME_API quest
|
||||||
{
|
{
|
||||||
using value_type = AchievementLinkData const&;
|
using value_type = QuestLinkData const&;
|
||||||
static constexpr char const* tag() { return "achievement"; }
|
static constexpr char const* tag() { return "quest"; }
|
||||||
static bool StoreTo(AchievementLinkData& val, char const* pos, size_t len);
|
static bool StoreTo(QuestLinkData& val, char const* pos, size_t len);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TC_GAME_API enchant
|
struct TC_GAME_API spell
|
||||||
{
|
{
|
||||||
using value_type = SpellInfo const*;
|
using value_type = SpellInfo const*;
|
||||||
static constexpr char const* tag() { return "enchant"; }
|
static constexpr char const* tag() { return "spell"; }
|
||||||
static bool StoreTo(SpellInfo const*& val, char const* pos, size_t len);
|
static bool StoreTo(SpellInfo const*& val, char const* pos, size_t len);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TC_GAME_API glyph
|
struct TC_GAME_API talent
|
||||||
{
|
{
|
||||||
using value_type = GlyphLinkData const&;
|
using value_type = TalentLinkData const&;
|
||||||
static constexpr char const* tag() { return "glyph"; };
|
static constexpr char const* tag() { return "talent"; }
|
||||||
static bool StoreTo(GlyphLinkData& val, char const* pos, size_t len);
|
static bool StoreTo(TalentLinkData& val, char const* pos, size_t len);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TC_GAME_API item
|
struct TC_GAME_API trade
|
||||||
{
|
{
|
||||||
using value_type = ItemLinkData const&;
|
using value_type = TradeskillLinkData const&;
|
||||||
static constexpr char const* tag() { return "item"; }
|
static constexpr char const* tag() { return "trade"; }
|
||||||
static bool StoreTo(ItemLinkData& val, char const* pos, size_t len);
|
static bool StoreTo(TradeskillLinkData& val, char const* pos, size_t len);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TC_GAME_API quest
|
|
||||||
{
|
|
||||||
using value_type = QuestLinkData const&;
|
|
||||||
static constexpr char const* tag() { return "quest"; }
|
|
||||||
static bool StoreTo(QuestLinkData& val, char const* pos, size_t len);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TC_GAME_API spell
|
|
||||||
{
|
|
||||||
using value_type = SpellInfo const*;
|
|
||||||
static constexpr char const* tag() { return "spell"; }
|
|
||||||
static bool StoreTo(SpellInfo const*& val, char const* pos, size_t len);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TC_GAME_API talent
|
|
||||||
{
|
|
||||||
using value_type = TalentLinkData const&;
|
|
||||||
static constexpr char const* tag() { return "talent"; }
|
|
||||||
static bool StoreTo(TalentLinkData& val, char const* pos, size_t len);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TC_GAME_API trade
|
|
||||||
{
|
|
||||||
using value_type = TradeskillLinkData const&;
|
|
||||||
static constexpr char const* tag() { return "trade"; }
|
|
||||||
static bool StoreTo(TradeskillLinkData& val, char const* pos, size_t len);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
struct HyperlinkColor
|
|
||||||
{
|
|
||||||
HyperlinkColor(uint32 c) : r(c >> 16), g(c >> 8), b(c), a(c >> 24) {}
|
|
||||||
uint8 r, g, b, a;
|
|
||||||
bool operator==(uint32 c) const
|
|
||||||
{
|
|
||||||
if ((c & 0xff) ^ b)
|
|
||||||
return false;
|
|
||||||
if (((c >>= 8) & 0xff) ^ g)
|
|
||||||
return false;
|
|
||||||
if (((c >>= 8) & 0xff) ^ r)
|
|
||||||
return false;
|
|
||||||
if ((c >>= 8) ^ a)
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
struct HyperlinkInfo
|
struct HyperlinkColor
|
||||||
{
|
{
|
||||||
HyperlinkInfo(char const* n = nullptr, uint32 c = 0, char const* tS = nullptr, size_t tL = 0, char const* dS = nullptr, size_t dL = 0, char const* cS = nullptr, size_t cL = 0) :
|
HyperlinkColor(uint32 c) : r(c >> 16), g(c >> 8), b(c), a(c >> 24) {}
|
||||||
next(n), color(c), tag(tS, tL), data(dS, dL), text(cS, cL) {}
|
uint8 r, g, b, a;
|
||||||
|
bool operator==(uint32 c) const
|
||||||
|
{
|
||||||
|
if ((c & 0xff) ^ b)
|
||||||
|
return false;
|
||||||
|
if (((c >>= 8) & 0xff) ^ g)
|
||||||
|
return false;
|
||||||
|
if (((c >>= 8) & 0xff) ^ r)
|
||||||
|
return false;
|
||||||
|
if ((c >>= 8) ^ a)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
explicit operator bool() { return next; }
|
struct HyperlinkInfo
|
||||||
char const* const next;
|
{
|
||||||
HyperlinkColor const color;
|
HyperlinkInfo(char const* n = nullptr, uint32 c = 0, char const* tS = nullptr, size_t tL = 0, char const* dS = nullptr, size_t dL = 0, char const* cS = nullptr, size_t cL = 0) :
|
||||||
std::pair<char const*, size_t> const tag;
|
next(n), color(c), tag(tS, tL), data(dS, dL), text(cS, cL) {}
|
||||||
std::pair<char const*, size_t> const data;
|
|
||||||
std::pair<char const*, size_t> const text;
|
explicit operator bool() { return next; }
|
||||||
};
|
char const* const next;
|
||||||
HyperlinkInfo TC_GAME_API ParseHyperlink(char const* pos);
|
HyperlinkColor const color;
|
||||||
bool TC_GAME_API CheckAllLinks(std::string const&);
|
std::pair<char const*, size_t> const tag;
|
||||||
|
std::pair<char const*, size_t> const data;
|
||||||
|
std::pair<char const*, size_t> const text;
|
||||||
|
};
|
||||||
|
HyperlinkInfo TC_GAME_API ParseHyperlink(char const* pos);
|
||||||
|
bool TC_GAME_API CheckAllLinks(std::string const&);
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user