TrinityCore
ChatCommandTags.h
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#ifndef TRINITY_CHATCOMMANDTAGS_H
19#define TRINITY_CHATCOMMANDTAGS_H
20
21#include "ChatCommandHelpers.h"
22#include "Hyperlinks.h"
23#include "ObjectGuid.h"
24#include "Optional.h"
25#include "Util.h"
26#include <fmt/ostream.h>
27#include <string>
28#include <string_view>
29#include <tuple>
30#include <type_traits>
31#include <utility>
32#include <variant>
33
34class ChatHandler;
35class Player;
36class WorldSession;
37
39{
41 {
43 };
44
45 template <typename T>
46 struct tag_base<T, std::enable_if_t<std::is_base_of_v<ContainerTag, T>>>
47 {
48 using type = typename T::value_type;
49 };
50
51 template <std::size_t Size>
53 {
54 constexpr string_literal(char const (&str)[Size])
55 {
56 std::ranges::copy_n(str, Size, value.begin());
57 }
58
59 constexpr operator std::string_view() const
60 {
61 return { value.data(), value.size() - 1 };
62 }
63
64 std::array<char, Size> value;
65 };
66
67 TC_GAME_API ChatCommandResult TryConsumExactSequencee(std::string_view sequence, ChatHandler const* handler, std::string_view args);
68}
69
71{
72 /************************** CONTAINER TAGS **********************************************\
73 |* Simple holder classes to differentiate between extraction methods *|
74 |* Must inherit from Trinity::Impl::ChatCommands::ContainerTag *|
75 |* Must implement the following: *|
76 |* - TryConsume: ChatHandler const*, std::string_view -> ChatCommandResult *|
77 |* - on match, returns tail of the provided argument string (as std::string_view) *|
78 |* - on specific error, returns error message (as std::string&& or char const*) *|
79 |* - on generic error, returns std::nullopt (this will print command usage) *|
80 |* *|
81 |* - typedef value_type of type that is contained within the tag *|
82 |* - cast operator to value_type *|
83 |* *|
84 \****************************************************************************************/
85
86 template <Impl::ChatCommands::string_literal Sequence>
88 {
89 using value_type = void;
90
91 ChatCommandResult TryConsume(ChatHandler const* handler, std::string_view args) const
92 {
93 return Trinity::Impl::ChatCommands::TryConsumExactSequencee(Sequence, handler, args);
94 }
95 };
96
97#define EXACT_SEQUENCE(str) Trinity::ChatCommands::ExactSequence<str>
98
100 {
101 using value_type = std::string_view;
102
103 using std::string_view::operator=;
104
105 ChatCommandResult TryConsume(ChatHandler const*,std::string_view args)
106 {
107 std::string_view::operator=(args);
108 return std::string_view();
109 }
110 };
111
113 {
114 using value_type = std::wstring;
115
116 using std::wstring::operator=;
117
118 ChatCommandResult TryConsume(ChatHandler const* handler, std::string_view args)
119 {
120 if (Utf8toWStr(args, *this))
121 return std::string_view();
122 else
124 }
125 };
126
128 {
129 using value_type = std::string;
130
131 TC_GAME_API ChatCommandResult TryConsume(ChatHandler const* handler, std::string_view args);
132 };
133
135 {
137
138 AccountIdentifier() : _id(), _name(), _session(nullptr) {}
140
141 operator uint32() const { return _id; }
142 operator std::string const& () const { return _name; }
143 operator std::string_view() const { return _name; }
144
145 uint32 GetID() const { return _id; }
146 std::string const& GetName() const { return _name; }
147 bool IsConnected() { return _session != nullptr; }
148 WorldSession* GetConnectedSession() { return _session; }
149
150 ChatCommandResult TryConsume(ChatHandler const* handler, std::string_view args);
151
152 static Optional<AccountIdentifier> FromTarget(ChatHandler* handler);
153
154 private:
156 std::string _name;
158 };
159
161 {
163
164 PlayerIdentifier() : _name(), _guid(), _player(nullptr) {}
165 PlayerIdentifier(Player& player);
166
167 operator ObjectGuid() const { return _guid; }
168 operator std::string const&() const { return _name; }
169 operator std::string_view() const { return _name; }
170
171 std::string const& GetName() const { return _name; }
172 ObjectGuid GetGUID() const { return _guid; }
173 bool IsConnected() const { return (_player != nullptr); }
174 Player* GetConnectedPlayer() const { return _player; }
175
176 ChatCommandResult TryConsume(ChatHandler const* handler, std::string_view args);
177
178 static Optional<PlayerIdentifier> FromTarget(ChatHandler* handler);
179 static Optional<PlayerIdentifier> FromSelf(ChatHandler* handler);
181 {
182 if (Optional<PlayerIdentifier> fromTarget = FromTarget(handler))
183 return fromTarget;
184 else
185 return FromSelf(handler);
186 }
187
188 private:
189 std::string _name;
192 };
193
194 template <typename linktag>
196 {
197 using value_type = typename linktag::value_type;
198 using storage_type = std::remove_cvref_t<value_type>;
199
200 operator value_type() const { return val; }
201 value_type operator*() const { return val; }
202 storage_type const* operator->() const { return &val; }
203
204 ChatCommandResult TryConsume(ChatHandler const* handler, std::string_view args)
205 {
207 // invalid hyperlinks cannot be consumed
208 if (!info)
209 return std::nullopt;
210
211 // check if we got the right tag
212 if (info.tag != linktag::tag())
213 return std::nullopt;
214
215 // store value
216 if (!linktag::StoreTo(val, info.data))
218
219 // finally, skip any potential delimiters
220 auto [token, next] = Trinity::Impl::ChatCommands::tokenize(info.tail);
221 if (token.empty()) /* empty token = first character is delimiter, skip past it */
222 return next;
223 else
224 return info.tail;
225 }
226
227 private:
229 };
230
231 // pull in link tags for user convenience
232 using namespace ::Trinity::Hyperlinks::LinkTags;
233}
234
235namespace Trinity::Impl
236{
237 template <typename T>
239 {
240 template <typename U>
241 T operator()(U const& v) const { return v; }
242 };
243}
244
245namespace Trinity::ChatCommands
246{
247 template <typename T1, typename... Ts>
248 struct Variant : public std::variant<T1, Ts...>
249 {
250 using base = std::variant<T1, Ts...>;
251
254
255 template <bool C = have_operators>
256 std::enable_if_t<C, first_type> operator*() const
257 {
259 }
260
261 template <bool C = have_operators>
262 operator std::enable_if_t<C, first_type>() const
263 {
264 return operator*();
265 }
266
267 template <bool C = have_operators>
268 std::enable_if_t<C, bool> operator!() const { return !**this; }
269
270 template <typename T>
271 Variant& operator=(T&& arg) { base::operator=(std::forward<T>(arg)); return *this; }
272
273 template <size_t index>
274 constexpr decltype(auto) get() { return std::get<index>(static_cast<base&>(*this)); }
275 template <size_t index>
276 constexpr decltype(auto) get() const { return std::get<index>(static_cast<base const&>(*this)); }
277 template <typename type>
278 constexpr decltype(auto) get() { return std::get<type>(static_cast<base&>(*this)); }
279 template <typename type>
280 constexpr decltype(auto) get() const { return std::get<type>(static_cast<base const&>(*this)); }
281
282 template <typename T>
283 constexpr decltype(auto) visit(T&& arg) { return std::visit(std::forward<T>(arg), static_cast<base&>(*this)); }
284 template <typename T>
285 constexpr decltype(auto) visit(T&& arg) const { return std::visit(std::forward<T>(arg), static_cast<base const&>(*this)); }
286
287 template <typename T>
288 constexpr bool holds_alternative() const { return std::holds_alternative<T>(static_cast<base const&>(*this)); }
289
290 template <bool C = have_operators>
291 friend std::enable_if_t<C, std::ostream&> operator<<(std::ostream& os, Trinity::ChatCommands::Variant<T1, Ts...> const& v)
292 {
293 return (os << *v);
294 }
295 };
296}
297
298template <typename T1, typename... Ts>
299struct fmt::formatter<Trinity::ChatCommands::Variant<T1, Ts...>> : ostream_formatter {};
300
301template <typename T1, typename... Ts>
302struct fmt::printf_formatter<Trinity::ChatCommands::Variant<T1, Ts...>> : formatter<T1>
303{
304 template <typename T, typename OutputIt>
305 auto format(T const& value, basic_format_context<OutputIt, char>& ctx) const -> OutputIt
306 {
307 return formatter<T1>::format(*value, ctx);
308 }
309};
310
311#endif
Trinity::Impl::ChatCommands::ChatCommandResult ChatCommandResult
#define TC_GAME_API
Definition: Define.h:129
uint32_t uint32
Definition: Define.h:148
@ LANG_CMDPARSER_LINKDATA_INVALID
Definition: Language.h:1005
@ LANG_CMDPARSER_INVALID_UTF8
Definition: Language.h:1004
std::optional< T > Optional
Optional helper class to wrap optional values within.
Definition: Optional.h:25
bool Utf8toWStr(char const *utf8str, size_t csize, wchar_t *wstr, size_t &wsize)
Definition: Util.cpp:336
Player session in the World.
Definition: WorldSession.h:979
TokenizeResult tokenize(std::string_view args)
typename tag_base< T >::type tag_base_t
TC_GAME_API ChatCommandResult TryConsumExactSequencee(std::string_view sequence, ChatHandler const *handler, std::string_view args)
TC_GAME_API char const * GetTrinityString(ChatHandler const *handler, TrinityStrings which)
SizeWriter< Underlying, Container > Size(Container const &value)
STL namespace.
std::string const & GetName() const
ChatCommandResult TryConsume(ChatHandler const *handler, std::string_view args) const
std::string const & GetName() const
static Optional< PlayerIdentifier > FromTargetOrSelf(ChatHandler *handler)
TC_GAME_API ChatCommandResult TryConsume(ChatHandler const *handler, std::string_view args)
ChatCommandResult TryConsume(ChatHandler const *, std::string_view args)
constexpr bool holds_alternative() const
constexpr decltype(auto) visit(T &&arg)
Trinity::Impl::ChatCommands::tag_base_t< T1 > first_type
std::enable_if_t< C, first_type > operator*() const
constexpr decltype(auto) visit(T &&arg) const
constexpr decltype(auto) get()
std::enable_if_t< C, bool > operator!() const
std::variant< T1, Ts... > base
static constexpr bool have_operators
friend std::enable_if_t< C, std::ostream & > operator<<(std::ostream &os, Trinity::ChatCommands::Variant< T1, Ts... > const &v)
constexpr decltype(auto) get() const
ChatCommandResult TryConsume(ChatHandler const *handler, std::string_view args)
T operator()(U const &v) const
constexpr string_literal(char const (&str)[Size])
auto format(T const &value, basic_format_context< OutputIt, char > &ctx) const -> OutputIt