diff options
| author | Treeston <treeston.mmoc@gmail.com> | 2020-09-06 23:36:23 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-09-06 23:36:23 +0200 |
| commit | b63d655e20a0facf14fc77798c52ea67d8551fa7 (patch) | |
| tree | 296a3fa0db1abecf9646785b8ee128eab65263fd /src/server/game/Chat/ChatCommands | |
| parent | 67b112f8a4862a521daf96b2f738db81a649e79d (diff) | |
[3.3.5] Scripts/Commands: .arena command conversion (PR #25407)
Diffstat (limited to 'src/server/game/Chat/ChatCommands')
| -rw-r--r-- | src/server/game/Chat/ChatCommands/ChatCommandTags.cpp | 93 | ||||
| -rw-r--r-- | src/server/game/Chat/ChatCommands/ChatCommandTags.h | 99 |
2 files changed, 166 insertions, 26 deletions
diff --git a/src/server/game/Chat/ChatCommands/ChatCommandTags.cpp b/src/server/game/Chat/ChatCommands/ChatCommandTags.cpp new file mode 100644 index 00000000000..0f11f1cd66f --- /dev/null +++ b/src/server/game/Chat/ChatCommands/ChatCommandTags.cpp @@ -0,0 +1,93 @@ +/* + * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "ChatCommandTags.h" + +#include "CharacterCache.h" +#include "Chat.h" +#include "ChatCommandArgs.h" +#include "ObjectAccessor.h" +#include "ObjectMgr.h" +#include "Player.h" + +Optional<std::string_view> Trinity::ChatCommands::QuotedString::TryConsume(std::string_view args) +{ + if (args.empty()) + return std::nullopt; + if ((args[0] != '"') && (args[0] != '\'')) + return Trinity::Impl::ChatCommands::ArgInfo<std::string>::TryConsume(*this, args); + + char const QUOTE = args[0]; + for (size_t i = 1; i < args.length(); ++i) + { + if (args[i] == QUOTE) + { + auto [remainingToken, tail] = Trinity::Impl::ChatCommands::tokenize(args.substr(i + 1)); + if (remainingToken.empty()) // if this is not empty, then we did not consume the full token + return tail; + else + return std::nullopt; + } + + if (args[i] == '\\') + { + ++i; + if (!(i < args.length())) + break; + } + std::string::push_back(args[i]); + } + // if we reach this, we did not find a closing quote + return std::nullopt; +} + +Optional<std::string_view> Trinity::ChatCommands::PlayerIdentifier::TryConsume(std::string_view args) +{ + Variant<Hyperlink<player>, std::string_view> name; + Optional<std::string_view> next = Trinity::Impl::ChatCommands::ArgInfo<decltype(name)>::TryConsume(name, args); + if (!next) + return std::nullopt; + + _name = static_cast<std::string_view>(name); + normalizePlayerName(_name); + + if ((_player = ObjectAccessor::FindPlayerByName(_name))) + _guid = _player->GetGUID(); + else if (!(_guid = sCharacterCache->GetCharacterGuidByName(_name))) + return std::nullopt; + + return next; +} + +Trinity::ChatCommands::PlayerIdentifier::PlayerIdentifier(Player& player) + : _name(player.GetName()), _guid(player.GetGUID()), _player(&player) {} + +/*static*/ Optional<Trinity::ChatCommands::PlayerIdentifier> Trinity::ChatCommands::PlayerIdentifier::FromTarget(ChatHandler* handler) +{ + if (Player* player = handler->GetPlayer()) + if (Player* target = player->GetSelectedPlayer()) + return { *target }; + return std::nullopt; + +} + +/*static*/ Optional<Trinity::ChatCommands::PlayerIdentifier> Trinity::ChatCommands::PlayerIdentifier::FromSelf(ChatHandler* handler) +{ + if (Player* player = handler->GetPlayer()) + return { *player }; + return std::nullopt; +} diff --git a/src/server/game/Chat/ChatCommands/ChatCommandTags.h b/src/server/game/Chat/ChatCommands/ChatCommandTags.h index 1ef1a9d1b97..f2bda962f51 100644 --- a/src/server/game/Chat/ChatCommands/ChatCommandTags.h +++ b/src/server/game/Chat/ChatCommands/ChatCommandTags.h @@ -21,6 +21,7 @@ #include "advstd.h" #include "ChatCommandHelpers.h" #include "Hyperlinks.h" +#include "ObjectGuid.h" #include "Optional.h" #include "Util.h" #include <cmath> @@ -33,6 +34,9 @@ #include <utility> #include <variant> +class ChatHandler; +class Player; + namespace Trinity::Impl::ChatCommands { struct ContainerTag {}; @@ -109,39 +113,82 @@ namespace Trinity::ChatCommands } }; + struct QuotedString : std::string, Trinity::Impl::ChatCommands::ContainerTag + { + using value_type = std::string; + + TC_GAME_API Optional<std::string_view> TryConsume(std::string_view args); + }; + + struct TC_GAME_API PlayerIdentifier : Trinity::Impl::ChatCommands::ContainerTag + { + using value_type = Player*; + + PlayerIdentifier() : _name(), _guid(), _player(nullptr) {} + PlayerIdentifier(Player& player); + + template <typename T> + operator std::enable_if_t<std::is_base_of_v<T, Player>, T*>() const { return static_cast<T*>(_player); } + operator value_type() const { return _player; } + operator ObjectGuid() { return _guid; } + Player* operator->() const { return _player; } + explicit operator bool() const { return (_player != nullptr); } + bool operator!() const { return (_player == nullptr); } + + std::string const& GetName() { return _name; } + ObjectGuid GetGUID() const { return _guid; } + Player* GetPlayer() const { return _player; } + + Optional<std::string_view> TryConsume(std::string_view args); + + static Optional<PlayerIdentifier> FromTarget(ChatHandler* handler); + static Optional<PlayerIdentifier> FromSelf(ChatHandler* handler); + static Optional<PlayerIdentifier> FromTargetOrSelf(ChatHandler* handler) + { + if (Optional<PlayerIdentifier> fromTarget = FromTarget(handler)) + return fromTarget; + else + return FromSelf(handler); + } + + private: + std::string _name; + ObjectGuid _guid; + Player* _player; + }; + template <typename linktag> struct Hyperlink : Trinity::Impl::ChatCommands::ContainerTag { using value_type = typename linktag::value_type; using storage_type = 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; } + operator value_type() const { return val; } + value_type operator*() const { return val; } + storage_type const* operator->() const { return &val; } - Optional<std::string_view> TryConsume(std::string_view args) - { - Trinity::Hyperlinks::HyperlinkInfo info = Trinity::Hyperlinks::ParseSingleHyperlink(args); - // invalid hyperlinks cannot be consumed - if (!info) - return std::nullopt; - - // check if we got the right tag - if (info.tag != linktag::tag()) - return std::nullopt; - - // store value - if (!linktag::StoreTo(val, info.data)) - return std::nullopt; - - // finally, skip any potential delimiters - auto [token, next] = Trinity::Impl::ChatCommands::tokenize(info.tail); - if (token.empty()) /* empty token = first character is delimiter, skip past it */ - return next; - else - return info.tail; - } + Optional<std::string_view> TryConsume(std::string_view args) + { + Trinity::Hyperlinks::HyperlinkInfo info = Trinity::Hyperlinks::ParseSingleHyperlink(args); + // invalid hyperlinks cannot be consumed + if (!info) + return std::nullopt; + + // check if we got the right tag + if (info.tag != linktag::tag()) + return std::nullopt; + + // store value + if (!linktag::StoreTo(val, info.data)) + return std::nullopt; + + // finally, skip any potential delimiters + auto [token, next] = Trinity::Impl::ChatCommands::tokenize(info.tail); + if (token.empty()) /* empty token = first character is delimiter, skip past it */ + return next; + else + return info.tail; + } private: storage_type val; |
