mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
Core/ChatCommands: Implement achievement link parsing
(cherry picked from commit a4c666dc3d)
This commit is contained in:
@@ -18,10 +18,25 @@
|
||||
#include "ChatCommandArgs.h"
|
||||
#include "ChatCommand.h"
|
||||
#include "ChatCommandHyperlinks.h"
|
||||
#include "DB2Stores.h"
|
||||
#include "ObjectMgr.h"
|
||||
|
||||
using namespace Trinity::ChatCommands;
|
||||
|
||||
struct AchievementVisitor
|
||||
{
|
||||
using value_type = AchievementEntry const*;
|
||||
value_type operator()(Hyperlink<achievement> achData) const { return achData->achievement; }
|
||||
value_type operator()(uint32 achId) const { return sAchievementStore.LookupEntry(achId); }
|
||||
};
|
||||
char const* Trinity::ChatCommands::ArgInfo<AchievementEntry const*>::TryConsume(AchievementEntry const*& data, char const* args)
|
||||
{
|
||||
Variant <Hyperlink<achievement>, uint32> val;
|
||||
if ((args = CommandArgsConsumerSingle<decltype(val)>::TryConsumeTo(val, args)))
|
||||
data = boost::apply_visitor(AchievementVisitor(), val);
|
||||
return args;
|
||||
}
|
||||
|
||||
struct GameTeleVisitor
|
||||
{
|
||||
using value_type = GameTele const*;
|
||||
|
||||
@@ -108,6 +108,13 @@ struct ArgInfo<T, std::enable_if_t<advstd::is_base_of_v<ContainerTag, T>>>
|
||||
}
|
||||
};
|
||||
|
||||
// AchievementEntry* from numeric id or link
|
||||
template <>
|
||||
struct TC_GAME_API ArgInfo<AchievementEntry const*>
|
||||
{
|
||||
static char const* TryConsume(AchievementEntry const*&, char const*);
|
||||
};
|
||||
|
||||
// GameTele* from string name or link
|
||||
template <>
|
||||
struct TC_GAME_API ArgInfo<GameTele const*>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
namespace Trinity {
|
||||
namespace ChatCommands {
|
||||
|
||||
static const char COMMAND_DELIMITER = ' ';
|
||||
static constexpr char COMMAND_DELIMITER = ' ';
|
||||
|
||||
/***************** HELPERS *************************\
|
||||
|* These really aren't for outside use... *|
|
||||
|
||||
64
src/server/game/Chat/ChatCommands/ChatCommandHyperlinks.cpp
Normal file
64
src/server/game/Chat/ChatCommands/ChatCommandHyperlinks.cpp
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/>
|
||||
*
|
||||
* 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 "ChatCommandHyperlinks.h"
|
||||
#include "DB2Stores.h"
|
||||
|
||||
static constexpr char HYPERLINK_DELIMITER = ':';
|
||||
|
||||
class AchievementLinkTokenizer
|
||||
{
|
||||
public:
|
||||
AchievementLinkTokenizer(char const* pos, size_t len) : _pos(pos), _len(len), _empty(false) {}
|
||||
|
||||
template <typename T>
|
||||
bool TryConsumeTo(T& val)
|
||||
{
|
||||
if (_empty)
|
||||
return false;
|
||||
|
||||
char const* firstPos = _pos;
|
||||
size_t thisLen = 0;
|
||||
// find next delimiter
|
||||
for (; _len && *_pos != HYPERLINK_DELIMITER; --_len, ++_pos, ++thisLen);
|
||||
if (_len)
|
||||
--_len, ++_pos; // skip the delimiter
|
||||
else
|
||||
_empty = true;
|
||||
|
||||
return Trinity::ChatCommands::base_tag::StoreTo(val, firstPos, thisLen);
|
||||
}
|
||||
|
||||
bool IsEmpty() { return _empty; }
|
||||
|
||||
private:
|
||||
char const* _pos;
|
||||
size_t _len;
|
||||
bool _empty;
|
||||
};
|
||||
|
||||
bool Trinity::ChatCommands::achievement::StoreTo(AchievementLinkData& val, char const* pos, size_t len)
|
||||
{
|
||||
AchievementLinkTokenizer t(pos, len);
|
||||
uint32 achievementId;
|
||||
if (!t.TryConsumeTo(achievementId))
|
||||
return false;
|
||||
val.achievement = sAchievementStore.LookupEntry(achievementId);
|
||||
return val.achievement && t.TryConsumeTo(val.characterId) && t.TryConsumeTo(val.isFinished) &&
|
||||
t.TryConsumeTo(val.month) && t.TryConsumeTo(val.day) && t.TryConsumeTo(val.year) && t.TryConsumeTo(val.criteria[0]) &&
|
||||
t.TryConsumeTo(val.criteria[1]) && t.TryConsumeTo(val.criteria[2]) && t.TryConsumeTo(val.criteria[3]) && t.IsEmpty();
|
||||
}
|
||||
@@ -22,6 +22,8 @@
|
||||
#include "ChatCommandTags.h"
|
||||
#include "ObjectGuid.h"
|
||||
|
||||
struct AchievementEntry;
|
||||
|
||||
namespace Trinity {
|
||||
namespace ChatCommands {
|
||||
|
||||
@@ -34,6 +36,8 @@ struct Hyperlink : public ContainerTag
|
||||
|
||||
public:
|
||||
operator value_type() const { return val; }
|
||||
value_type const& operator*() const { return val; }
|
||||
value_type const* operator->() const { return &val; }
|
||||
|
||||
char const* TryConsume(char const* pos)
|
||||
{
|
||||
@@ -117,7 +121,7 @@ struct base_tag
|
||||
}
|
||||
};
|
||||
|
||||
#define make_base_tag(ltag, type) struct ltag : public base_tag { typedef type value_type; static constexpr char const* tag() { return #ltag; } }
|
||||
#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(areatrigger, uint32);
|
||||
make_base_tag(creature, ObjectGuid::LowType);
|
||||
make_base_tag(creature_entry, uint32);
|
||||
@@ -126,6 +130,24 @@ make_base_tag(taxinode, uint32);
|
||||
make_base_tag(tele, uint32);
|
||||
#undef make_base_tag
|
||||
|
||||
struct AchievementLinkData
|
||||
{
|
||||
AchievementEntry const* achievement;
|
||||
std::string characterId; // TODO: full ObjectGuid (implement parsing guid strings)
|
||||
bool isFinished;
|
||||
uint16 year;
|
||||
uint8 month;
|
||||
uint8 day;
|
||||
uint32 criteria[4];
|
||||
};
|
||||
|
||||
struct TC_GAME_API achievement
|
||||
{
|
||||
using value_type = AchievementLinkData;
|
||||
static constexpr char const* tag() { return "achievement"; }
|
||||
static bool StoreTo(AchievementLinkData& val, char const* pos, size_t len);
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -48,20 +48,8 @@ public:
|
||||
return commandTable;
|
||||
}
|
||||
|
||||
static bool HandleAchievementAddCommand(ChatHandler* handler, char const* args)
|
||||
static bool HandleAchievementAddCommand(ChatHandler* handler, AchievementEntry const* achievementEntry)
|
||||
{
|
||||
if (!*args)
|
||||
return false;
|
||||
|
||||
uint32 achievementId = atoi((char*)args);
|
||||
if (!achievementId)
|
||||
{
|
||||
if (char* id = handler->extractKeyFromLink((char*)args, "Hachievement"))
|
||||
achievementId = atoul(id);
|
||||
if (!achievementId)
|
||||
return false;
|
||||
}
|
||||
|
||||
Player* target = handler->getSelectedPlayer();
|
||||
if (!target)
|
||||
{
|
||||
@@ -69,9 +57,7 @@ public:
|
||||
handler->SetSentErrorMessage(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (AchievementEntry const* achievementEntry = sAchievementStore.LookupEntry(achievementId))
|
||||
target->CompletedAchievement(achievementEntry);
|
||||
target->CompletedAchievement(achievementEntry);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user