Core/Common: Tokenizer -> Trinity::Tokenize

This commit is contained in:
Treeston authored and Ovahlord committed 2025-07-30 20:51:19 +02:00
1 parent 95329dc15c
commit f95a8bfdca
32 files changed
+410 -350

No files matched your search

+23 -21
View File
@@ -17,6 +17,8 @@
#include "AppenderConsole.h"
#include "LogMessage.h"
#include "StringFormat.h"
#include "StringConvert.h"
#include "Util.h"
#include <sstream>
@@ -24,17 +26,17 @@
#include <Windows.h>
#endif
AppenderConsole::AppenderConsole(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, std::vector<char const*> extraArgs)
AppenderConsole::AppenderConsole(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, std::vector<std::string_view> const& args)
: Appender(id, name, level, flags), _colored(false)
{
for (uint8 i = 0; i < NUM_ENABLED_LOG_LEVELS; ++i)
_colors[i] = ColorTypes(MaxColors);
_colors[i] = ColorTypes(NUM_COLOR_TYPES);
if (!extraArgs.empty())
InitColors(extraArgs[0]);
if (3 < args.size())
InitColors(name, args[3]);
}
void AppenderConsole::InitColors(std::string const& str)
void AppenderConsole::InitColors(std::string const& name, std::string_view str)
{
if (str.empty())
{
@@ -42,23 +44,23 @@ void AppenderConsole::InitColors(std::string const& str)
return;
}
int color[NUM_ENABLED_LOG_LEVELS];
std::istringstream ss(str);
for (uint8 i = 0; i < NUM_ENABLED_LOG_LEVELS; ++i)
std::vector<std::string_view> colorStrs = Trinity::Tokenize(str, ' ', false);
if (colorStrs.size() != NUM_ENABLED_LOG_LEVELS)
{
ss >> color[i];
if (!ss)
return;
if (color[i] < 0 || color[i] >= MaxColors)
return;
throw InvalidAppenderArgsException(Trinity::StringFormat("Log::CreateAppenderFromConfig: Invalid color data '%s' for console appender %s (expected %u entries, got %zu)",
std::string(str).c_str(), name.c_str(), NUM_ENABLED_LOG_LEVELS, colorStrs.size()));
}
for (uint8 i = 0; i < NUM_ENABLED_LOG_LEVELS; ++i)
_colors[i] = ColorTypes(color[i]);
{
if (Optional<uint8> color = Trinity::StringTo<uint8>(colorStrs[i]); color && *color < NUM_COLOR_TYPES)
_colors[i] = static_cast<ColorTypes>(*color);
else
{
throw InvalidAppenderArgsException(Trinity::StringFormat("Log::CreateAppenderFromConfig: Invalid color '%u' for log level %s on console appender %s",
std::string(colorStrs[i]).c_str(), static_cast<uint32>(i), name.c_str()));
}
}
_colored = true;
}
@@ -66,7 +68,7 @@ void AppenderConsole::InitColors(std::string const& str)
void AppenderConsole::SetColor(bool stdout_stream, ColorTypes color)
{
#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS
static WORD WinColorFG[MaxColors] =
static WORD WinColorFG[NUM_COLOR_TYPES] =
{
0, // BLACK
FOREGROUND_RED, // RED
@@ -127,7 +129,7 @@ void AppenderConsole::SetColor(bool stdout_stream, ColorTypes color)
BG_WHITE
};
static uint8 UnixColorFG[MaxColors] =
static uint8 UnixColorFG[NUM_COLOR_TYPES] =
{
FG_BLACK, // BLACK
FG_RED, // RED
@@ -146,7 +148,7 @@ void AppenderConsole::SetColor(bool stdout_stream, ColorTypes color)
FG_WHITE // LWHITE
};
fprintf((stdout_stream? stdout : stderr), "\x1b[%d%sm", UnixColorFG[color], (color >= YELLOW && color < MaxColors ? ";1" : ""));
fprintf((stdout_stream? stdout : stderr), "\x1b[%d%sm", UnixColorFG[color], (color >= YELLOW && color < NUM_COLOR_TYPES ? ";1" : ""));
#endif
}
+4 -5
View File
@@ -36,18 +36,17 @@ enum ColorTypes
LBLUE,
LMAGENTA,
LCYAN,
WHITE
WHITE,
NUM_COLOR_TYPES // SKIP
};
const uint8 MaxColors = uint8(WHITE) + 1;
class TC_COMMON_API AppenderConsole : public Appender
{
public:
static constexpr AppenderType type = APPENDER_CONSOLE;
AppenderConsole(uint8 _id, std::string const& name, LogLevel level, AppenderFlags flags, std::vector<char const*> extraArgs);
void InitColors(const std::string& init_str);
AppenderConsole(uint8 _id, std::string const& name, LogLevel level, AppenderFlags flags, std::vector<std::string_view> const& args);
void InitColors(std::string const& name, std::string_view init_str);
AppenderType getType() const override { return type; }
private:
+17 -10
View File
@@ -18,23 +18,25 @@
#include "AppenderFile.h"
#include "Log.h"
#include "LogMessage.h"
#include "StringConvert.h"
#include "Util.h"
#include <algorithm>
AppenderFile::AppenderFile(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, std::vector<char const*> extraArgs) :
AppenderFile::AppenderFile(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, std::vector<std::string_view> const& args) :
Appender(id, name, level, flags),
logfile(nullptr),
_logDir(sLog->GetLogsDir()),
_maxFileSize(0),
_fileSize(0)
{
if (extraArgs.empty())
throw InvalidAppenderArgsException(Trinity::StringFormat("Log::CreateAppenderFromConfig: Missing file name for appender %s\n", name.c_str()));
if (args.size() < 4)
throw InvalidAppenderArgsException(Trinity::StringFormat("Log::CreateAppenderFromConfig: Missing file name for appender %s", name.c_str()));
_fileName = extraArgs[0];
_fileName.assign(args[3]);
char const* mode = "a";
if (extraArgs.size() > 1)
mode = extraArgs[1];
std::string mode = "a";
if (4 < args.size())
mode.assign(args[4]);
if (flags & APPENDER_FLAGS_USE_TIMESTAMP)
{
@@ -45,14 +47,19 @@ AppenderFile::AppenderFile(uint8 id, std::string const& name, LogLevel level, Ap
_fileName += sLog->GetLogsTimestamp();
}
if (extraArgs.size() > 2)
_maxFileSize = atoi(extraArgs[2]);
if (5 < args.size())
{
if (Optional<uint32> size = Trinity::StringTo<uint32>(args[5]))
_maxFileSize = *size;
else
throw InvalidAppenderArgsException(Trinity::StringFormat("Log::CreateAppenderFromConfig: Invalid size '%s' for appender %s", std::string(args[5]).c_str(), name.c_str()));
}
_dynamicName = std::string::npos != _fileName.find("%s");
_backup = (flags & APPENDER_FLAGS_MAKE_FILE_BACKUP) != 0;
if (!_dynamicName)
logfile = OpenFile(_fileName, mode, !strcmp(mode, "w") && _backup);
logfile = OpenFile(_fileName, mode, (mode == "w") && _backup);
}
AppenderFile::~AppenderFile()
+1 -1
View File
@@ -26,7 +26,7 @@ class TC_COMMON_API AppenderFile : public Appender
public:
static constexpr AppenderType type = APPENDER_FILE;
AppenderFile(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, std::vector<char const*> extraArgs);
AppenderFile(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, std::vector<std::string_view> const& args);
~AppenderFile();
FILE* OpenFile(std::string const& name, std::string const& mode, bool backup);
AppenderType getType() const override { return type; }
+23 -32
View File
@@ -26,6 +26,7 @@
#include "LogMessage.h"
#include "LogOperation.h"
#include "Strand.h"
#include "StringConvert.h"
#include "Util.h"
#include <sstream>
@@ -47,7 +48,7 @@ uint8 Log::NextAppenderId()
return AppenderId++;
}
Appender* Log::GetAppenderByName(std::string const& name)
Appender* Log::GetAppenderByName(std::string_view name)
{
auto it = appenders.begin();
while (it != appenders.end() && it->second && it->second->getName() != name)
@@ -66,10 +67,9 @@ void Log::CreateAppenderFromConfig(std::string const& appenderName)
// if type = Console. optional1 = Color
std::string options = sConfigMgr->GetStringDefault(appenderName, "");
Tokenizer tokens(options, ',');
auto iter = tokens.begin();
std::vector<std::string_view> tokens = Trinity::Tokenize(options, ',', true);
size_t size = tokens.size();
size_t const size = tokens.size();
std::string name = appenderName.substr(9);
if (size < 2)
@@ -79,33 +79,30 @@ void Log::CreateAppenderFromConfig(std::string const& appenderName)
}
AppenderFlags flags = APPENDER_FLAGS_NONE;
AppenderType type = AppenderType(atoi(*iter++));
LogLevel level = LogLevel(atoi(*iter++));
if (level > LOG_LEVEL_FATAL)
{
fprintf(stderr, "Log::CreateAppenderFromConfig: Wrong Log Level %d for appender %s\n", level, name.c_str());
return;
}
if (size > 2)
flags = AppenderFlags(atoi(*iter++));
AppenderType type = AppenderType(Trinity::StringTo<uint8>(tokens[0]).value_or(APPENDER_INVALID));
LogLevel level = LogLevel(Trinity::StringTo<uint8>(tokens[1]).value_or(LOG_LEVEL_INVALID));
auto factoryFunction = appenderFactory.find(type);
if (factoryFunction == appenderFactory.end())
{
fprintf(stderr, "Log::CreateAppenderFromConfig: Unknown type %d for appender %s\n", type, name.c_str());
fprintf(stderr, "Log::CreateAppenderFromConfig: Unknown type '%s' for appender %s\n", std::string(tokens[0]).c_str(), name.c_str());
return;
}
if (level > NUM_ENABLED_LOG_LEVELS)
{
fprintf(stderr, "Log::CreateAppenderFromConfig: Wrong Log Level '%s' for appender %s\n", std::string(tokens[1]).c_str(), name.c_str());
return;
}
try
{
Appender* appender = factoryFunction->second(NextAppenderId(), name, level, flags, std::vector<char const*>(iter, tokens.end()));
Appender* appender = factoryFunction->second(NextAppenderId(), name, level, flags, tokens);
appenders[appender->getId()].reset(appender);
}
catch (InvalidAppenderArgsException const& iaae)
{
fprintf(stderr, "%s", iaae.what());
fprintf(stderr, "%s\n", iaae.what());
}
}
@@ -126,8 +123,7 @@ void Log::CreateLoggerFromConfig(std::string const& appenderName)
return;
}
Tokenizer tokens(options, ',');
Tokenizer::const_iterator iter = tokens.begin();
std::vector<std::string_view> tokens = Trinity::Tokenize(options, ',', true);
if (tokens.size() != 2)
{
@@ -142,10 +138,10 @@ void Log::CreateLoggerFromConfig(std::string const& appenderName)
return;
}
level = LogLevel(atoi(*iter++));
if (level > LOG_LEVEL_FATAL)
level = LogLevel(Trinity::StringTo<uint8>(tokens[0]).value_or(LOG_LEVEL_INVALID));
if (level > NUM_ENABLED_LOG_LEVELS)
{
fprintf(stderr, "Log::CreateLoggerFromConfig: Wrong Log Level %u for logger %s\n", type, name.c_str());
fprintf(stderr, "Log::CreateLoggerFromConfig: Wrong Log Level '%s' for logger %s\n", std::string(tokens[0]).c_str(), name.c_str());
return;
}
@@ -155,20 +151,15 @@ void Log::CreateLoggerFromConfig(std::string const& appenderName)
logger = Trinity::make_unique<Logger>(name, level);
//fprintf(stdout, "Log::CreateLoggerFromConfig: Created Logger %s, Level %u\n", name.c_str(), level);
std::istringstream ss(*iter);
std::string str;
ss >> str;
while (ss)
for (std::string_view appenderName : Trinity::Tokenize(tokens[1], ' ', false))
{
if (Appender* appender = GetAppenderByName(str))
if (Appender* appender = GetAppenderByName(appenderName))
{
logger->addAppender(appender->getId(), appender);
//fprintf(stdout, "Log::CreateLoggerFromConfig: Added Appender %s to Logger %s\n", appender->getName().c_str(), name.c_str());
}
else
fprintf(stderr, "Error while configuring Appender %s in Logger %s. Appender does not exist", str.c_str(), name.c_str());
ss >> str;
fprintf(stderr, "Error while configuring Appender %s in Logger %s. Appender does not exist\n", std::string(appenderName).c_str(), name.c_str());
}
}
@@ -193,7 +184,7 @@ void Log::ReadLoggersFromConfig()
Close(); // Clean any Logger or Appender created
AppenderConsole* appender = new AppenderConsole(NextAppenderId(), "Console", LOG_LEVEL_DEBUG, APPENDER_FLAGS_NONE, std::vector<char const*>());
AppenderConsole* appender = new AppenderConsole(NextAppenderId(), "Console", LOG_LEVEL_DEBUG, APPENDER_FLAGS_NONE, {});
appenders[appender->getId()].reset(appender);
Logger* rootLogger = new Logger(LOGGER_ROOT, LOG_LEVEL_ERROR);
+4 -4
View File
@@ -40,12 +40,12 @@ namespace Trinity
#define LOGGER_ROOT "root"
typedef Appender*(*AppenderCreatorFn)(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, std::vector<char const*>&& extraArgs);
typedef Appender*(*AppenderCreatorFn)(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, std::vector<std::string_view> const& extraArgs);
template <class AppenderImpl>
Appender* CreateAppender(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, std::vector<char const*>&& extraArgs)
Appender* CreateAppender(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, std::vector<std::string_view> const& extraArgs)
{
return new AppenderImpl(id, name, level, flags, std::forward<std::vector<char const*>>(extraArgs));
return new AppenderImpl(id, name, level, flags, extraArgs);
}
class TC_COMMON_API Log
@@ -103,7 +103,7 @@ class TC_COMMON_API Log
void write(std::unique_ptr<LogMessage>&& msg) const;
Logger const* GetLoggerByType(std::string const& type) const;
Appender* GetAppenderByName(std::string const& name);
Appender* GetAppenderByName(std::string_view name);
uint8 NextAppenderId();
void CreateAppenderFromConfig(std::string const& name);
void CreateLoggerFromConfig(std::string const& name);
+9 -4
View File
@@ -18,7 +18,9 @@
#ifndef LogCommon_h__
#define LogCommon_h__
enum LogLevel
#include "Define.h"
enum LogLevel : uint8
{
LOG_LEVEL_DISABLED = 0,
LOG_LEVEL_TRACE = 1,
@@ -28,7 +30,8 @@ enum LogLevel
LOG_LEVEL_ERROR = 5,
LOG_LEVEL_FATAL = 6,
NUM_ENABLED_LOG_LEVELS = 6
NUM_ENABLED_LOG_LEVELS = LOG_LEVEL_FATAL, // SKIP
LOG_LEVEL_INVALID = 0xFF // SKIP
};
enum AppenderType : uint8
@@ -36,10 +39,12 @@ enum AppenderType : uint8
APPENDER_NONE,
APPENDER_CONSOLE,
APPENDER_FILE,
APPENDER_DB
APPENDER_DB,
APPENDER_INVALID = 0xFF // SKIP
};
enum AppenderFlags
enum AppenderFlags : uint8
{
APPENDER_FLAGS_NONE = 0x00,
APPENDER_FLAGS_PREFIX_TIMESTAMP = 0x01,
+1 -1
View File
@@ -80,7 +80,7 @@ void Metric::LoadFromConfigs()
return;
}
Tokenizer tokens(connectionInfo, ';');
std::vector<std::string_view> tokens = Trinity::Tokenize(connectionInfo, ';', true);
if (tokens.size() != 3)
{
TC_LOG_ERROR("metric", "'Metric.ConnectionInfo' specified with wrong format in configuration file.");
+43 -48
View File
@@ -19,6 +19,7 @@
#include "Common.h"
#include "Containers.h"
#include "IpAddress.h"
#include "StringConvert.h"
#include "StringFormat.h"
#include <utf8.h>
#include <algorithm>
@@ -50,39 +51,22 @@ void Trinity::VerifyOsVersion()
#endif
}
Tokenizer::Tokenizer(const std::string &src, const char sep, uint32 vectorReserve /*= 0*/, bool keepEmptyStrings /*= true*/)
std::vector<std::string_view> Trinity::Tokenize(std::string_view str, char sep, bool keepEmpty)
{
m_str = new char[src.length() + 1];
memcpy(m_str, src.c_str(), src.length() + 1);
std::vector<std::string_view> tokens;
if (vectorReserve)
m_storage.reserve(vectorReserve);
char* posold = m_str;
char* posnew = m_str;
for (;;)
size_t start = 0;
for (size_t end = str.find(sep); end != std::string_view::npos; end = str.find(sep, start))
{
if (*posnew == sep)
{
if (keepEmptyStrings || posold != posnew)
m_storage.push_back(posold);
posold = posnew + 1;
*posnew = '\0';
}
else if (*posnew == '\0')
{
// Hack like, but the old code accepted these kind of broken strings,
// so changing it would break other things
if (posold != posnew)
m_storage.push_back(posold);
break;
if (keepEmpty || (start < end))
tokens.push_back(str.substr(start, end - start));
start = end+1;
}
++posnew;
}
if (keepEmpty || (start < str.length()))
tokens.push_back(str.substr(start));
return tokens;
}
void stripLineInvisibleChars(std::string &str)
@@ -183,32 +167,43 @@ std::string secsToTimeString(uint64 timeInSecs, bool shortText, bool hoursOnly)
return ss.str();
}
int64 MoneyStringToMoney(std::string const& moneyString)
Optional<int64> MoneyStringToMoney(std::string const& moneyString)
{
int64 money = 0;
if (!(std::count(moneyString.begin(), moneyString.end(), 'g') == 1 ||
std::count(moneyString.begin(), moneyString.end(), 's') == 1 ||
std::count(moneyString.begin(), moneyString.end(), 'c') == 1))
return 0; // Bad format
bool hadG = false;
bool hadS = false;
bool hadC = false;
Tokenizer tokens(moneyString, ' ');
for (Tokenizer::const_iterator itr = tokens.begin(); itr != tokens.end(); ++itr)
for (std::string_view token : Trinity::Tokenize(moneyString, ' ', false))
{
std::string tokenString(*itr);
size_t gCount = std::count(tokenString.begin(), tokenString.end(), 'g');
size_t sCount = std::count(tokenString.begin(), tokenString.end(), 's');
size_t cCount = std::count(tokenString.begin(), tokenString.end(), 'c');
if (gCount + sCount + cCount != 1)
return 0;
uint32 unit;
switch (token[token.length() - 1])
{
case 'g':
if (hadG) return std::nullopt;
hadG = true;
unit = 100 * 100;
break;
case 's':
if (hadS) return std::nullopt;
hadS = true;
unit = 100;
break;
case 'c':
if (hadC) return std::nullopt;
hadC = true;
unit = 1;
break;
default:
return std::nullopt;
}
uint64 amount = strtoull(*itr, nullptr, 10);
if (gCount == 1)
money += amount * 100 * 100;
else if (sCount == 1)
money += amount * 100;
else if (cCount == 1)
money += amount;
Optional<uint64> amount = Trinity::StringTo<uint32>(token.substr(0, token.length() - 1));
if (amount)
money += (unit * *amount);
else
return std::nullopt;
}
return money;
+10 -26
View File
@@ -20,7 +20,7 @@
#include "Define.h"
#include "Errors.h"
#include "Optional.h"
#include <string>
#include <sstream>
#include <vector>
@@ -30,37 +30,21 @@ namespace Trinity
TC_COMMON_API void VerifyOsVersion();
}
class TC_COMMON_API Tokenizer
namespace Trinity
{
public:
typedef std::vector<char const*> StorageType;
TC_COMMON_API std::vector<std::string_view> Tokenize(std::string_view str, char sep, bool keepEmpty);
typedef StorageType::size_type size_type;
/* this would return string_view into temporary otherwise */
std::vector<std::string_view> Tokenize(std::string&&, char, bool) = delete;
std::vector<std::string_view> Tokenize(std::string const&&, char, bool) = delete;
typedef StorageType::const_iterator const_iterator;
typedef StorageType::reference reference;
typedef StorageType::const_reference const_reference;
public:
Tokenizer(const std::string &src, char const sep, uint32 vectorReserve = 0, bool keepEmptyStrings = true);
~Tokenizer() { delete[] m_str; }
const_iterator begin() const { return m_storage.begin(); }
const_iterator end() const { return m_storage.end(); }
size_type size() const { return m_storage.size(); }
reference operator [] (size_type i) { return m_storage[i]; }
const_reference operator [] (size_type i) const { return m_storage[i]; }
private:
char* m_str;
StorageType m_storage;
};
/* the delete overload means we need to make this explicit */
inline std::vector<std::string_view> Tokenize(char const* str, char sep, bool keepEmpty) { return Tokenize(std::string_view(str ? str : ""), sep, keepEmpty); }
}
TC_COMMON_API void stripLineInvisibleChars(std::string &src);
TC_COMMON_API int64 MoneyStringToMoney(std::string const& moneyString);
TC_COMMON_API Optional<int64> MoneyStringToMoney(std::string const& moneyString);
TC_COMMON_API struct tm* localtime_r(time_t const* time, struct tm *result);
TC_COMMON_API time_t LocalTimeToUTCTime(time_t time);
@@ -33,16 +33,16 @@
MySQLConnectionInfo::MySQLConnectionInfo(std::string const& infoString)
{
Tokenizer tokens(infoString, ';');
std::vector<std::string_view> tokens = Trinity::Tokenize(infoString, ';', true);
if (tokens.size() != 5)
return;
uint8 i = 0;
host.assign(tokens[i++]);
port_or_socket.assign(tokens[i++]);
user.assign(tokens[i++]);
password.assign(tokens[i++]);
database.assign(tokens[i++]);
host.assign(tokens[0]);
port_or_socket.assign(tokens[1]);
user.assign(tokens[2]);
password.assign(tokens[3]);
database.assign(tokens[4]);
}
MySQLConnection::MySQLConnection(MySQLConnectionInfo& connInfo) :
+1 -1
View File
@@ -20,7 +20,7 @@
#include "LogMessage.h"
#include "PreparedStatement.h"
AppenderDB::AppenderDB(uint8 id, std::string const& name, LogLevel level, AppenderFlags /*flags*/, std::vector<char const*> /*extraArgs*/)
AppenderDB::AppenderDB(uint8 id, std::string const& name, LogLevel level, AppenderFlags /*flags*/, std::vector<std::string_view> const& /*args*/)
: Appender(id, name, level), realmId(0), enabled(false) { }
AppenderDB::~AppenderDB() { }
+1 -1
View File
@@ -25,7 +25,7 @@ class TC_DATABASE_API AppenderDB: public Appender
public:
static constexpr AppenderType type = APPENDER_DB;
AppenderDB(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, std::vector<char const*> extraArgs);
AppenderDB(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, std::vector<std::string_view> const& args);
~AppenderDB();
void setRealmId(uint32 realmId) override;
@@ -43,6 +43,7 @@
#include "ReputationMgr.h"
#include "ScriptMgr.h"
#include "SpellMgr.h"
#include "StringConvert.h"
#include "World.h"
#include "WorldSession.h"
#include "WorldStateMgr.h"
@@ -733,9 +734,9 @@ void AchievementMgr<Guild>::LoadFromDB(PreparedQueryResult achievementResult, Pr
CompletedAchievementData& ca = m_completedAchievements[achievementid];
ca.date = time_t(fields[1].GetUInt32());
Tokenizer guids(fields[2].GetString(), ' ');
for (uint32 i = 0; i < guids.size(); ++i)
ca.guids.insert(ObjectGuid(HighGuid::Player, uint32(atol(guids[i]))));
for (std::string_view guid : Trinity::Tokenize(fields[2].GetStringView(), ' ', false))
if (Optional<ObjectGuid::LowType> parsedGuid = Trinity::StringTo<ObjectGuid::LowType>(guid))
ca.guids.insert(ObjectGuid(HighGuid::Player, *parsedGuid));
ca.changed = false;
+6 -6
View File
@@ -28,6 +28,7 @@
#include "ObjectMgr.h"
#include "Player.h"
#include "SocialMgr.h"
#include "StringConvert.h"
#include "World.h"
Channel::Channel(uint32 channelId, uint32 team /*= 0*/, AreaTableEntry const* zoneEntry /*= nullptr*/) :
@@ -86,14 +87,13 @@ Channel::Channel(std::string const& name, uint32 team /*= 0*/) :
if (!db_BannedList.empty())
{
Tokenizer tokens(db_BannedList, ' ');
for (auto const& token : tokens)
for (std::string_view guid : Trinity::Tokenize(db_BannedList, ' ', false))
{
ObjectGuid banned_guid(uint64(atoull(token)));
if (banned_guid)
ObjectGuid banned(Trinity::StringTo<uint64>(guid).value_or(0));
if (banned)
{
TC_LOG_DEBUG("chat.system", "Channel(%s) loaded player %s into bannedStore", name.c_str(), banned_guid.ToString().c_str());
_bannedStore.insert(banned_guid);
TC_LOG_DEBUG("chat.system", "Channel(%s) loaded player %s into bannedStore", name.c_str(), banned.ToString().c_str());
_bannedStore.insert(banned);
}
}
}
+15 -6
View File
@@ -23,6 +23,7 @@
#include "OutdoorPvP.h"
#include "Player.h"
#include "SpellMgr.h"
#include "StringConvert.h"
#include "VMapManager2.h"
#include "World.h"
@@ -103,16 +104,24 @@ void LoadDisables()
if (flags & SPELL_DISABLE_MAP)
{
Tokenizer tokens(params_0, ',');
for (uint8 i = 0; i < tokens.size(); )
data.params[0].insert(atoi(tokens[i++]));
for (std::string_view mapStr : Trinity::Tokenize(params_0, ',', true))
{
if (Optional<uint32> mapId = Trinity::StringTo<uint32>(mapStr))
data.params[0].insert(*mapId);
else
TC_LOG_ERROR("sql.sql", "Disable map '%s' for spell %u is invalid, skipped.", std::string(mapStr).c_str(), entry);
}
}
if (flags & SPELL_DISABLE_AREA)
{
Tokenizer tokens(params_1, ',');
for (uint8 i = 0; i < tokens.size(); )
data.params[1].insert(atoi(tokens[i++]));
for (std::string_view areaStr : Trinity::Tokenize(params_1, ',', true))
{
if (Optional<uint32> areaId = Trinity::StringTo<uint32>(areaStr))
data.params[1].insert(*areaId);
else
TC_LOG_ERROR("sql.sql", "Disable area '%s' for spell %u is invalid, skipped.", std::string(areaStr).c_str(), entry);
}
}
break;
+1 -1
View File
@@ -662,7 +662,7 @@ enum class SpellShapeshiftFormFlags : int32
DEFINE_ENUM_FLAG(SpellShapeshiftFormFlags);
constexpr uint8 TaxiMaskSize = 114;
static constexpr uint8 TaxiMaskSize = 114;
typedef std::array<uint8, TaxiMaskSize> TaxiMask;
enum TaxiNodeFlags
+5 -1
View File
@@ -177,7 +177,11 @@ bool Corpse::LoadCorpseFromDB(ObjectGuid::LowType guid, Field* fields)
SetObjectScale(1.0f);
SetUInt32Value(CORPSE_FIELD_DISPLAY_ID, fields[5].GetUInt32());
_LoadIntoDataField(fields[6].GetString(), CORPSE_FIELD_ITEM, EQUIPMENT_SLOT_END);
if (!_LoadIntoDataField(fields[6].GetString(), CORPSE_FIELD_ITEM, EQUIPMENT_SLOT_END))
{
TC_LOG_ERROR("entities.player", "Corpse (%s, owner: %s) is not created, given equipment info is not valid ('%s')",
GetGUID().ToString().c_str(), GetOwnerGUID().ToString().c_str(), fields[6].GetString().c_str());
}
SetUInt32Value(CORPSE_FIELD_BYTES_1, fields[7].GetUInt32());
SetUInt32Value(CORPSE_FIELD_BYTES_2, fields[8].GetUInt32());
SetUInt32Value(CORPSE_FIELD_FLAGS, fields[9].GetUInt8());
+16 -3
View File
@@ -32,6 +32,7 @@
#include "ScriptMgr.h"
#include "SpellInfo.h"
#include "SpellMgr.h"
#include "StringConvert.h"
#include "TradeData.h"
#include "UpdateData.h"
#include "World.h"
@@ -427,7 +428,10 @@ bool Item::LoadFromDB(ObjectGuid::LowType guid, ObjectGuid owner_guid, Field* fi
ItemTemplate const* proto = GetTemplate();
if (!proto)
{
TC_LOG_ERROR("entities.item", "Invalid entry %u for item %s. Refusing to load.", GetEntry(), GetGUID().ToString().c_str());
return false;
}
// set owner (not if item is only loaded for gbank/auction/mail
if (owner_guid)
@@ -447,10 +451,17 @@ bool Item::LoadFromDB(ObjectGuid::LowType guid, ObjectGuid owner_guid, Field* fi
need_save = true;
}
Tokenizer tokens(fields[4].GetString(), ' ', MAX_ITEM_PROTO_SPELLS);
std::vector<std::string_view> tokens = Trinity::Tokenize(fields[4].GetStringView(), ' ', false);
if (tokens.size() == MAX_ITEM_PROTO_SPELLS)
{
for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i)
SetSpellCharges(i, atoi(tokens[i]));
{
if (Optional<int32> charges = Trinity::StringTo<int32>(tokens[i]))
SetSpellCharges(i, *charges);
else
TC_LOG_ERROR("entities.item", "Invalid charge info '%s' for item %s, charge data not loaded.", std::string(tokens[i]).c_str(), GetGUID().ToString().c_str());
}
}
SetUInt32Value(ITEM_FIELD_FLAGS, fields[5].GetUInt32());
// Remove bind flag for items vs BIND_NONE set
@@ -460,7 +471,9 @@ bool Item::LoadFromDB(ObjectGuid::LowType guid, ObjectGuid owner_guid, Field* fi
need_save = true;
}
_LoadIntoDataField(fields[6].GetString(), ITEM_FIELD_ENCHANTMENT_1_1, MAX_ENCHANTMENT_SLOT * MAX_ENCHANTMENT_OFFSET);
if (!_LoadIntoDataField(fields[6].GetString(), ITEM_FIELD_ENCHANTMENT_1_1, MAX_ENCHANTMENT_SLOT * MAX_ENCHANTMENT_OFFSET))
TC_LOG_WARN("entities.item", "Invalid enchantment data '%s' for item %s. Forcing partial load.", fields[6].GetString().c_str(), GetGUID().ToString().c_str());
m_randomEnchantment.Type = ItemRandomEnchantmentType(fields[7].GetUInt8());
m_randomEnchantment.Id = fields[8].GetUInt32();
if (m_randomEnchantment.Type == ItemRandomEnchantmentType::Property)
+10 -5
View File
@@ -45,6 +45,7 @@
#include "SpellAuraEffects.h"
#include "SpellDefines.h"
#include "SpellMgr.h"
#include "StringConvert.h"
#include "TemporarySummon.h"
#include "Totem.h"
#include "Transport.h"
@@ -783,21 +784,25 @@ uint32 Object::GetUpdateFieldData(Player const* target, uint32*& flags) const
return visibleFlag;
}
void Object::_LoadIntoDataField(std::string const& data, uint32 startOffset, uint32 count)
bool Object::_LoadIntoDataField(std::string const& data, uint32 startOffset, uint32 count)
{
if (data.empty())
return;
return false;
Tokenizer tokens(data, ' ', count);
std::vector<std::string_view> tokens = Trinity::Tokenize(data, ' ', false);
if (tokens.size() != count)
return;
return false;
for (uint32 index = 0; index < count; ++index)
{
m_uint32Values[startOffset + index] = atoul(tokens[index]);
Optional<uint32> val = Trinity::StringTo<uint32>(tokens[index]);
if (!val)
return false;
m_uint32Values[startOffset + index] = *val;
_changesMask.SetBit(startOffset + index);
}
return true;
}
void Object::SetInt32Value(uint16 index, int32 value)
+1 -1
View File
@@ -239,7 +239,7 @@ class TC_GAME_API Object
void _InitValues();
void _Create(ObjectGuid::LowType guidlow, uint32 entry, HighGuid guidhigh);
std::string _ConcatFields(uint16 startIndex, uint16 size) const;
void _LoadIntoDataField(std::string const& data, uint32 startOffset, uint32 count);
[[nodiscard]] bool _LoadIntoDataField(std::string const& data, uint32 startOffset, uint32 count);
uint32 GetUpdateFieldData(Player const* target, uint32*& flags) const;
+40 -59
View File
@@ -101,6 +101,7 @@
#include "SpellHistory.h"
#include "SpellMgr.h"
#include "SpellPackets.h"
#include "StringConvert.h"
#include "TerrainMgr.h"
#include "TicketMgr.h"
#include "TradeData.h"
@@ -16408,23 +16409,6 @@ void Player::SendBindPointUpdate() const
SendDirectMessage(packet.Write());
}
uint32 Player::GetUInt32ValueFromArray(Tokenizer const& data, uint16 index)
{
if (index >= data.size())
return 0;
return (uint32)atoi(data[index]);
}
float Player::GetFloatValueFromArray(Tokenizer const& data, uint16 index)
{
float result;
uint32 temp = Player::GetUInt32ValueFromArray(data, index);
memcpy(&result, &temp, sizeof(result));
return result;
}
bool Player::IsLoading() const
{
return GetSession()->PlayerLoading();
@@ -16450,7 +16434,7 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder const& hol
{
std::string name = "<unknown>";
sCharacterCache->GetCharacterNameByGuid(guid, name);
TC_LOG_ERROR("entities.player", "Player::LoadFromDB: Player '%s' (%s) not found in table `characters`, can't load. ", name.c_str(), guid.ToString().c_str());
TC_LOG_ERROR("entities.player.loading", "Player::LoadFromDB: Player '%s' (%s) not found in table `characters`, can't load. ", name.c_str(), guid.ToString().c_str());
return false;
}
@@ -16462,13 +16446,13 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder const& hol
// player should be able to load/delete character only with correct account!
if (dbAccountId != GetSession()->GetAccountId())
{
TC_LOG_ERROR("entities.player", "Player::LoadFromDB: Player (%s) loading from wrong account (is: %u, should be: %u)", guid.ToString().c_str(), GetSession()->GetAccountId(), dbAccountId);
TC_LOG_ERROR("entities.player.loading", "Player::LoadFromDB: Player (%s) loading from wrong account (is: %u, should be: %u)", guid.ToString().c_str(), GetSession()->GetAccountId(), dbAccountId);
return false;
}
if (holder.GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_BANNED))
{
TC_LOG_ERROR("entities.player", "Player::LoadFromDB: Player (%s) is banned, can't load.", guid.ToString().c_str());
TC_LOG_ERROR("entities.player.loading", "Player::LoadFromDB: Player (%s) is banned, can't load.", guid.ToString().c_str());
return false;
}
@@ -16493,7 +16477,7 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder const& hol
uint8 gender = fields[5].GetUInt8();
if (!IsValidGender(gender))
{
TC_LOG_ERROR("entities.player", "Player::LoadFromDB: Player (%s) has wrong gender (%u), can't load.", guid.ToString().c_str(), gender);
TC_LOG_ERROR("entities.player.loading", "Player::LoadFromDB: Player (%s) has wrong gender (%u), can't load.", guid.ToString().c_str(), gender);
return false;
}
@@ -16505,15 +16489,18 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder const& hol
PlayerInfo const* info = sObjectMgr->GetPlayerInfo(getRace(), getClass());
if (!info)
{
TC_LOG_ERROR("entities.player", "Player::LoadFromDB: Player (%s) has wrong race/class (%u/%u), can't load.", guid.ToString().c_str(), getRace(), getClass());
TC_LOG_ERROR("entities.player.loading", "Player::LoadFromDB: Player (%s) has wrong race/class (%u/%u), can't load.", guid.ToString().c_str(), getRace(), getClass());
return false;
}
SetUInt32Value(UNIT_FIELD_LEVEL, fields[6].GetUInt8());
SetUInt32Value(PLAYER_XP, fields[7].GetUInt32());
_LoadIntoDataField(fields[60].GetString(), PLAYER_EXPLORED_ZONES_1, PLAYER_EXPLORED_ZONES_SIZE);
_LoadIntoDataField(fields[62].GetString(), PLAYER__FIELD_KNOWN_TITLES, KNOWN_TITLES_SIZE*2);
if (!_LoadIntoDataField(fields[60].GetString(), PLAYER_EXPLORED_ZONES_1, PLAYER_EXPLORED_ZONES_SIZE))
TC_LOG_WARN("entities.player.loading", "Player::LoadFromDB: Player (%s) has invalid exploredzones data (%s). Forcing partial load.", guid.ToString().c_str(), fields[60].GetCString());
if (!_LoadIntoDataField(fields[62].GetString(), PLAYER__FIELD_KNOWN_TITLES, KNOWN_TITLES_SIZE * 2))
TC_LOG_WARN("entities.player.loading", "Player::LoadFromDB: Player (%s) has invalid knowntitles mask (%s). Forcing partial load.", guid.ToString().c_str(), fields[62].GetCString());
SetObjectScale(1.0f);
SetFloatValue(UNIT_FIELD_HOVERHEIGHT, 1.0f);
@@ -16546,7 +16533,7 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder const& hol
GetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_FACIAL_STYLE), // facial hair
GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_SKIN_ID))) // skin color
{
TC_LOG_ERROR("entities.player", "Player::LoadFromDB: Player (%s) has wrong Appearance values (Hair/Skin/Color), can't load.", guid.ToString().c_str());
TC_LOG_ERROR("entities.player.loading", "Player::LoadFromDB: Player (%s) has wrong Appearance values (Hair/Skin/Color), can't load.", guid.ToString().c_str());
return false;
}
@@ -16640,7 +16627,7 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder const& hol
bool player_at_bg = false;
if (!mapEntry || !IsPositionValid())
{
TC_LOG_ERROR("entities.player", "Player::LoadFromDB: Player (%s) has invalid coordinates (MapId: %u X: %f Y: %f Z: %f O: %f). Teleport to default race/class locations.",
TC_LOG_ERROR("entities.player.loading", "Player::LoadFromDB: Player (%s) has invalid coordinates (MapId: %u X: %f Y: %f Z: %f O: %f). Teleport to default race/class locations.",
guid.ToString().c_str(), mapId, GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation());
RelocateToHomebind();
}
@@ -16686,7 +16673,7 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder const& hol
//if (mapId == MAPID_INVALID) -- code kept for reference
if (int16(mapId) == int16(-1)) // Battleground Entry Point not found (???)
{
TC_LOG_ERROR("entities.player", "Player::LoadFromDB: Player (%s) was in BG in database, but BG was not found and entry point was invalid! Teleport to default race/class locations.",
TC_LOG_ERROR("entities.player.loading", "Player::LoadFromDB: Player (%s) was in BG in database, but BG was not found and entry point was invalid! Teleport to default race/class locations.",
guid.ToString().c_str());
RelocateToHomebind();
}
@@ -16732,7 +16719,7 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder const& hol
std::fabs(m_movementInfo.transport.pos.GetPositionY()) > 250.0f ||
std::fabs(m_movementInfo.transport.pos.GetPositionZ()) > 250.0f)
{
TC_LOG_ERROR("entities.player", "Player::LoadFromDB: Player (%s) has invalid transport coordinates (X: %f Y: %f Z: %f O: %f). Teleport to bind location.",
TC_LOG_ERROR("entities.player.loading", "Player::LoadFromDB: Player (%s) has invalid transport coordinates (X: %f Y: %f Z: %f O: %f). Teleport to bind location.",
guid.ToString().c_str(), x, y, z, o);
m_movementInfo.transport.Reset();
@@ -16749,7 +16736,7 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder const& hol
}
else
{
TC_LOG_ERROR("entities.player", "Player::LoadFromDB: Player (%s) has problems with transport guid (%u). Teleport to bind location.",
TC_LOG_ERROR("entities.player.loading", "Player::LoadFromDB: Player (%s) has problems with transport guid (%u). Teleport to bind location.",
guid.ToString().c_str(), transLowGUID);
RelocateToHomebind();
@@ -16775,12 +16762,12 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder const& hol
if (!nodeEntry) // don't know taxi start node, teleport to homebind
{
TC_LOG_ERROR("entities.player", "Player::LoadFromDB: Player (%s) has wrong data in taxi destination list, teleport to homebind.", GetGUID().ToString().c_str());
TC_LOG_ERROR("entities.player.loading", "Player::LoadFromDB: Player (%s) has wrong data in taxi destination list, teleport to homebind.", GetGUID().ToString().c_str());
RelocateToHomebind();
}
else // has start node, teleport to it
{
TC_LOG_ERROR("entities.player", "Player::LoadFromDB: Player (%s) has too short taxi destination list, teleport to original node.", GetGUID().ToString().c_str());
TC_LOG_ERROR("entities.player.loading", "Player::LoadFromDB: Player (%s) has too short taxi destination list, teleport to original node.", GetGUID().ToString().c_str());
mapId = nodeEntry->ContinentID;
Relocate(nodeEntry->Pos.X, nodeEntry->Pos.Y, nodeEntry->Pos.Z, 0.0f);
}
@@ -16809,7 +16796,7 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder const& hol
{
if (GetSession()->GetExpansion() < mapEntry->Expansion())
{
TC_LOG_DEBUG("entities.player.loading", "Player::LoadFromDB: Player '%s' (%s) using client without required expansion tried login at non accessible map %u",
TC_LOG_DEBUG("entities.player.loading.loading", "Player::LoadFromDB: Player '%s' (%s) using client without required expansion tried login at non accessible map %u",
GetName().c_str(), GetGUID().ToString().c_str(), mapId);
RelocateToHomebind();
}
@@ -16880,7 +16867,7 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder const& hol
}
else
{
TC_LOG_ERROR("entities.player", "Player::LoadFromDB: Player '%s' (%s) Map: %u, X: %f, Y: %f, Z: %f, O: %f. Areatrigger not found.",
TC_LOG_ERROR("entities.player.loading", "Player::LoadFromDB: Player '%s' (%s) Map: %u, X: %f, Y: %f, Z: %f, O: %f. Areatrigger not found.",
m_name.c_str(), guid.ToString().c_str(), mapId, GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation());
RelocateToHomebind();
map = nullptr;
@@ -16894,7 +16881,7 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder const& hol
map = sMapMgr->CreateMap(mapId, this);
if (!map)
{
TC_LOG_ERROR("entities.player", "Player::LoadFromDB: Player '%s' (%s) Map: %u, X: %f, Y: %f, Z: %f, O: %f. Invalid default map coordinates or instance couldn't be created.",
TC_LOG_ERROR("entities.player.loading", "Player::LoadFromDB: Player '%s' (%s) Map: %u, X: %f, Y: %f, Z: %f, O: %f. Invalid default map coordinates or instance couldn't be created.",
m_name.c_str(), guid.ToString().c_str(), mapId, GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation());
return false;
}
@@ -16944,29 +16931,30 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder const& hol
if (GetSpecsCount() > MAX_TALENT_SPECS || GetActiveSpec() > MAX_TALENT_SPEC || GetSpecsCount() < MIN_TALENT_SPECS)
{
SetActiveSpec(0);
TC_LOG_ERROR("entities.player", "Player %s(GUID: %u) has SpecCount = %u and ActiveSpec = %u.", GetName().c_str(), GetGUID().GetCounter(), GetSpecsCount(), GetActiveSpec());
TC_LOG_ERROR("entities.player.loading", "Player %s(GUID: %u) has SpecCount = %u and ActiveSpec = %u.", GetName().c_str(), GetGUID().GetCounter(), GetSpecsCount(), GetActiveSpec());
}
// Only load selected specializations, learning mastery spells requires this
Tokenizer talentTrees(fields[31].GetString(), ' ', MAX_TALENT_SPECS);
std::vector<std::string_view> talentTrees = Trinity::Tokenize(fields[31].GetStringView(), ' ', false);
for (uint8 i = 0; i < MAX_TALENT_SPECS; ++i)
{
if (i >= talentTrees.size())
break;
uint32 talentTree = atol(talentTrees[i]);
if (sTalentTabStore.LookupEntry(talentTree))
SetPrimaryTalentTree(i, talentTree);
Optional<uint32> talentTree = Trinity::StringTo<uint32>(talentTrees[i]);
if (talentTree && sTalentTabStore.LookupEntry(*talentTree))
SetPrimaryTalentTree(i, *talentTree);
}
m_taxi.LoadTaxiMask(fields[22].GetString()); // must be before InitTaxiNodesForLevel
if (!m_taxi.LoadTaxiMask(fields[22].GetString())) // must be before InitTaxiNodesForLevel
TC_LOG_WARN("entities.player.loading", "Player::LoadFromDB: Player (%s) has invalid taximask (%s) in DB. Forced partial load.", GetGUID().ToString().c_str(), fields[22].GetString().c_str());
uint32 extraflags = fields[37].GetUInt16();
m_stableSlots = fields[38].GetUInt8();
if (m_stableSlots > MAX_PET_STABLES)
{
TC_LOG_ERROR("entities.player", "Player::LoadFromDB: Player (%s) can't have more stable slots than %u, but has %u in DB",
TC_LOG_ERROR("entities.player.loading", "Player::LoadFromDB: Player (%s) can't have more stable slots than %u, but has %u in DB",
GetGUID().ToString().c_str(), MAX_PET_STABLES, uint32(m_stableSlots));
m_stableSlots = MAX_PET_STABLES;
}
@@ -17144,8 +17132,9 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder const& hol
if (i >= talentTrees.size())
break;
uint32 talentTree = atol(talentTrees[i]);
if (talentTree != 0 && !sTalentTabStore.LookupEntry(talentTree) && i == GetActiveSpec())
Optional<uint32> talentTree = Trinity::StringTo<uint32>(talentTrees[i]);
if (talentTree)
if (*talentTree > 0 && !sTalentTabStore.LookupEntry(*talentTree) && i == GetActiveSpec())
SetAtLoginFlag(AT_LOGIN_RESET_TALENTS); // invalid tree, reset talents
}
@@ -17717,11 +17706,14 @@ Item* Player::_LoadItem(CharacterDatabaseTransaction& trans, uint32 zoneId, uint
stmt->setUInt32(0, item->GetGUID().GetCounter());
if (PreparedQueryResult result = CharacterDatabase.Query(stmt))
{
std::string strGUID = (*result)[0].GetString();
Tokenizer GUIDlist(strGUID, ' ');
GuidSet looters;
for (Tokenizer::const_iterator itr = GUIDlist.begin(); itr != GUIDlist.end(); ++itr)
looters.insert(ObjectGuid::Create<HighGuid::Player>(uint32(atoul(*itr))));
for (std::string_view guidStr : Trinity::Tokenize((*result)[0].GetStringView(), ' ', false))
{
if (Optional<ObjectGuid::LowType> guid = Trinity::StringTo<ObjectGuid::LowType>(guidStr))
looters.insert(ObjectGuid::Create<HighGuid::Player>(*guid));
else
TC_LOG_WARN("entities.player.loading", "Player::_LoadInventory: invalid item_soulbound_trade_data GUID '%s' for item %s. Skipped.", std::string(guidStr).c_str(), item->GetGUID().ToString().c_str());
}
if (looters.size() > 1 && item->GetTemplate()->GetMaxStackSize() == 1 && item->IsSoulBound())
{
@@ -17733,7 +17725,7 @@ Item* Player::_LoadItem(CharacterDatabaseTransaction& trans, uint32 zoneId, uint
}
else
{
TC_LOG_DEBUG("entities.player.loading", "Player::_LoadInventory: player (GUID: %u, name: '%s') has item (GUID: %u, entry: %u) with ITEM_FIELD_FLAG_BOP_TRADEABLE flag, but without data in item_soulbound_trade_data. Removing flag.",
TC_LOG_WARN("entities.player.loading", "Player::_LoadInventory: player (GUID: %u, name: '%s') has item (GUID: %u, entry: %u) with ITEM_FIELD_FLAG_BOP_TRADEABLE flag, but without data in item_soulbound_trade_data. Removing flag.",
GetGUID().GetCounter(), GetName().c_str(), item->GetGUID().GetCounter(), item->GetEntry());
item->RemoveFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_BOP_TRADEABLE);
}
@@ -20068,17 +20060,6 @@ void Player::SavePositionInDB(WorldLocation const& loc, uint16 zoneId, ObjectGui
CharacterDatabase.ExecuteOrAppend(trans, stmt);
}
void Player::SetUInt32ValueInArray(Tokenizer& Tokenizer, uint16 index, uint32 value)
{
char buf[11];
snprintf(buf, 11, "%u", value);
if (index >= Tokenizer.size())
return;
Tokenizer[index] = buf;
}
void Player::Customize(CharacterCustomizeInfo const* customizeInfo, CharacterDatabaseTransaction& trans)
{
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GENDER_AND_APPEARANCE);
-3
View File
@@ -1444,8 +1444,6 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
bool IsLoading() const override;
void Initialize(ObjectGuid::LowType guid);
static uint32 GetUInt32ValueFromArray(Tokenizer const& data, uint16 index);
static float GetFloatValueFromArray(Tokenizer const& data, uint16 index);
static uint32 GetZoneIdFromDB(ObjectGuid guid);
static bool LoadPositionFromDB(uint32& mapid, float& x, float& y, float& z, float& o, bool& in_flight, ObjectGuid guid);
@@ -1463,7 +1461,6 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
void SaveInventoryAndGoldToDB(CharacterDatabaseTransaction& trans); // fast save function for item/money cheating preventing
void SaveGoldToDB(CharacterDatabaseTransaction& trans) const;
static void SetUInt32ValueInArray(Tokenizer& data, uint16 index, uint32 value);
static void Customize(CharacterCustomizeInfo const* customizeInfo, CharacterDatabaseTransaction& trans);
static void SavePositionInDB(WorldLocation const& loc, uint16 zoneId, ObjectGuid guid, CharacterDatabaseTransaction& trans);
+24 -10
View File
@@ -19,6 +19,7 @@
#include "DBCStores.h"
#include "ObjectMgr.h"
#include "Player.h"
#include "StringConvert.h"
#include <sstream>
void PlayerTaxi::InitTaxiNodesForLevel(uint32 race, uint32 chrClass, uint8 level)
@@ -68,16 +69,26 @@ void PlayerTaxi::InitTaxiNodesForLevel(uint32 race, uint32 chrClass, uint8 level
}
}
void PlayerTaxi::LoadTaxiMask(std::string const &data)
bool PlayerTaxi::LoadTaxiMask(std::string const& data)
{
Tokenizer tokens(data, ' ');
uint8 index = 0;
for (Tokenizer::const_iterator iter = tokens.begin(); index < TaxiMaskSize && iter != tokens.end(); ++iter, ++index)
bool warn = false;
std::vector<std::string_view> tokens = Trinity::Tokenize(data, ' ', false);
for (uint8 index = 0; (index < TaxiMaskSize) && (index < tokens.size()); ++index)
{
if (Optional<uint32> mask = Trinity::StringTo<uint32>(tokens[index]))
{
// load and set bits only for existing taxi nodes
m_taximask[index] = sTaxiNodesMask[index] & atoul(*iter);
m_taximask[index] = sTaxiNodesMask[index] & *mask;
if (m_taximask[index] != *mask)
warn = true;
}
else
{
m_taximask[index] = 0;
warn = true;
}
}
return !warn;
}
void PlayerTaxi::AppendTaximaskTo(ByteBuffer& data, bool all)
@@ -99,12 +110,15 @@ bool PlayerTaxi::LoadTaxiDestinationsFromString(std::string const& values, uint3
{
ClearTaxiDestinations();
Tokenizer Tokenizer(values, ' ');
std::vector<std::string_view> tokens = Trinity::Tokenize(values, ' ', false);
auto itr = tokens.begin();
for (Tokenizer::const_iterator iter = Tokenizer.begin(); iter != Tokenizer.end(); ++iter)
while ((++itr) != tokens.end())
{
uint32 node = atoul(*iter);
AddTaxiDestination(node);
if (Optional<uint32> node = Trinity::StringTo<uint32>(*itr))
AddTaxiDestination(*node);
else
return false;
}
if (m_TaxiDestinations.empty())
+2 -2
View File
@@ -33,7 +33,7 @@ class TC_GAME_API PlayerTaxi
~PlayerTaxi() { }
// Nodes
void InitTaxiNodesForLevel(uint32 race, uint32 chrClass, uint8 level);
void LoadTaxiMask(std::string const& data);
bool LoadTaxiMask(std::string const& data);
bool IsTaximaskNodeKnown(uint32 nodeidx) const
{
@@ -56,7 +56,7 @@ class TC_GAME_API PlayerTaxi
void AppendTaximaskTo(ByteBuffer& data, bool all);
// Destinations
bool LoadTaxiDestinationsFromString(std::string const& values, uint32 team);
[[nodiscard]] bool LoadTaxiDestinationsFromString(std::string const& values, uint32 team);
std::string SaveTaxiDestinationsToString();
void ClearTaxiDestinations() { m_TaxiDestinations.clear(); }
+13 -12
View File
@@ -19,6 +19,7 @@
#include "Creature.h"
#include "SpellInfo.h"
#include "SpellMgr.h"
#include "StringConvert.h"
CharmInfo::CharmInfo(Unit* unit)
: _unit(unit), _CommandState(COMMAND_FOLLOW), _petnumber(0), _oldReactState(REACT_PASSIVE),
@@ -236,29 +237,29 @@ void CharmInfo::LoadPetActionBar(const std::string& data)
{
InitPetActionBar();
Tokenizer tokens(data, ' ');
std::vector<std::string_view> tokens = Trinity::Tokenize(data, ' ', false);
if (tokens.size() != (ACTION_BAR_INDEX_END-ACTION_BAR_INDEX_START) * 2)
return; // non critical, will reset to default
uint8 index = ACTION_BAR_INDEX_START;
Tokenizer::const_iterator iter = tokens.begin();
for (; index < ACTION_BAR_INDEX_END; ++iter, ++index)
auto iter = tokens.begin();
for (uint8 index = ACTION_BAR_INDEX_START; index < ACTION_BAR_INDEX_END; ++index)
{
// use unsigned cast to avoid sign negative format use at long-> ActiveStates (int) conversion
ActiveStates type = ActiveStates(atol(*iter));
++iter;
uint32 action = atoul(*iter);
Optional<uint8> type = Trinity::StringTo<uint8>(*(iter++));
Optional<uint32> action = Trinity::StringTo<uint32>(*(iter++));
PetActionBar[index].SetActionAndType(action, type);
if (!type || !action)
continue;
PetActionBar[index].SetActionAndType(*action, static_cast<ActiveStates>(*type));
// check correctness
if (PetActionBar[index].IsActionBarForSpell())
{
SpellInfo const* spelInfo = sSpellMgr->GetSpellInfo(PetActionBar[index].GetAction());
if (!spelInfo)
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(PetActionBar[index].GetAction());
if (!spellInfo)
SetActionBar(index, 0, ACT_PASSIVE);
else if (!spelInfo->IsAutocastable())
else if (!spellInfo->IsAutocastable())
SetActionBar(index, PetActionBar[index].GetAction(), ACT_PASSIVE);
}
}
+41 -24
View File
@@ -55,6 +55,7 @@
#include "SpellAuras.h"
#include "SpellMgr.h"
#include "SpellScript.h"
#include "StringConvert.h"
#include "TemporarySummon.h"
#include "TerrainMgr.h"
#include "ThreadPool.h"
@@ -640,28 +641,36 @@ void ObjectMgr::LoadCreatureTemplateAddons()
creatureAddon.meleeAnimKit = fields[12].GetUInt16();
creatureAddon.visibilityDistanceType = VisibilityDistanceType(fields[13].GetUInt8());
Tokenizer tokens(fields[14].GetString(), ' ');
uint8 i = 0;
creatureAddon.auras.resize(tokens.size());
for (Tokenizer::const_iterator itr = tokens.begin(); itr != tokens.end(); ++itr)
for (std::string_view aura : Trinity::Tokenize(fields[14].GetStringView(), ' ', false))
{
SpellInfo const* AdditionalSpellInfo = sSpellMgr->GetSpellInfo(atoul(*itr));
if (!AdditionalSpellInfo)
SpellInfo const* spellInfo = nullptr;
if (Optional<uint32> spellId = Trinity::StringTo<uint32>(aura))
spellInfo = sSpellMgr->GetSpellInfo(*spellId);
if (!spellInfo)
{
TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) has wrong spell %lu defined in `auras` field in `creature_template_addon`.", entry, atoul(*itr));
TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) has wrong spell '%s' defined in `auras` field in `creature_template_addon`.", entry, std::string(aura).c_str());
continue;
}
if (AdditionalSpellInfo->HasAura(SPELL_AURA_CONTROL_VEHICLE))
TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) has SPELL_AURA_CONTROL_VEHICLE aura %lu defined in `auras` field in `creature_template_addon`.", entry, atoul(*itr));
if (spellInfo->HasAura(SPELL_AURA_CONTROL_VEHICLE))
TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) has SPELL_AURA_CONTROL_VEHICLE aura %u defined in `auras` field in `creature_template_addon`.", entry, spellInfo->Id);
if (std::find(creatureAddon.auras.begin(), creatureAddon.auras.end(), atoul(*itr)) != creatureAddon.auras.end())
if (std::find(creatureAddon.auras.begin(), creatureAddon.auras.end(), spellInfo->Id) != creatureAddon.auras.end())
{
TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) has duplicate aura (spell %lu) in `auras` field in `creature_template_addon`.", entry, atoul(*itr));
TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) has duplicate aura (spell %u) in `auras` field in `creature_template_addon`.", entry, spellInfo->Id);
continue;
}
creatureAddon.auras[i++] = atoul(*itr);
/*
if (spellInfo->GetDuration() > 0)
{
TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) has temporary aura (spell %u) in `auras` field in `creature_template_addon`.", entry, spellInfo->Id);
continue;
}
*/
creatureAddon.auras.push_back(spellInfo->Id);
}
if (creatureAddon.mount)
@@ -1198,28 +1207,36 @@ void ObjectMgr::LoadCreatureAddons()
creatureAddon.meleeAnimKit = fields[12].GetUInt16();
creatureAddon.visibilityDistanceType = VisibilityDistanceType(fields[13].GetUInt8());
Tokenizer tokens(fields[14].GetString(), ' ');
uint8 i = 0;
creatureAddon.auras.resize(tokens.size());
for (Tokenizer::const_iterator itr = tokens.begin(); itr != tokens.end(); ++itr)
for (std::string_view aura : Trinity::Tokenize(fields[14].GetStringView(), ' ', false))
{
SpellInfo const* AdditionalSpellInfo = sSpellMgr->GetSpellInfo(atoul(*itr));
if (!AdditionalSpellInfo)
SpellInfo const* spellInfo = nullptr;
if (Optional<uint32> spellId = Trinity::StringTo<uint32>(aura))
spellInfo = sSpellMgr->GetSpellInfo(*spellId);
if (!spellInfo)
{
TC_LOG_ERROR("sql.sql", "Creature (GUID: %u) has wrong spell %lu defined in `auras` field in `creature_addon`.", guid, atoul(*itr));
TC_LOG_ERROR("sql.sql", "Creature (GUID: %u) has wrong spell '%s' defined in `auras` field in `creature_addon`.", guid, std::string(aura).c_str());
continue;
}
if (AdditionalSpellInfo->HasAura(SPELL_AURA_CONTROL_VEHICLE))
TC_LOG_ERROR("sql.sql", "Creature (GUID: %u) has SPELL_AURA_CONTROL_VEHICLE aura %lu defined in `auras` field in `creature_addon`.", guid, atoul(*itr));
if (spellInfo->HasAura(SPELL_AURA_CONTROL_VEHICLE))
TC_LOG_ERROR("sql.sql", "Creature (GUID: %u) has SPELL_AURA_CONTROL_VEHICLE aura %u defined in `auras` field in `creature_addon`.", guid, spellInfo->Id);
if (std::find(creatureAddon.auras.begin(), creatureAddon.auras.end(), atoul(*itr)) != creatureAddon.auras.end())
if (std::find(creatureAddon.auras.begin(), creatureAddon.auras.end(), spellInfo->Id) != creatureAddon.auras.end())
{
TC_LOG_ERROR("sql.sql", "Creature (GUID: %u) has duplicate aura (spell %lu) in `auras` field in `creature_addon`.", guid, atoul(*itr));
TC_LOG_ERROR("sql.sql", "Creature (GUID: %u) has duplicate aura (spell %u) in `auras` field in `creature_addon`.", guid, spellInfo->Id);
continue;
}
creatureAddon.auras[i++] = atoul(*itr);
/*
if (spellInfo->GetDuration() > 0)
{
TC_LOG_ERROR("sql.sql", "Creature (GUID: %u) has temporary aura (spell %u) in `auras` field in `creature_addon`.", guid, spellInfo->Id);
continue;
}
*/
creatureAddon.auras.push_back(spellInfo->Id);
}
if (creatureAddon.mount)
+18 -11
View File
@@ -53,6 +53,7 @@
#include "ScriptMgr.h"
#include "SharedDefines.h"
#include "SocialMgr.h"
#include "StringConvert.h"
#include "SystemPackets.h"
#include "World.h"
#include "WorldPacket.h"
@@ -2167,18 +2168,24 @@ void WorldSession::HandleCharFactionOrRaceChangeCallback(std::shared_ptr<Charact
// Title conversion
if (!knownTitlesStr.empty())
{
uint32 const ktcount = KNOWN_TITLES_SIZE * 2;
uint32 knownTitles[ktcount];
Tokenizer tokens(knownTitlesStr, ' ', ktcount);
std::vector<std::string_view> tokens = Trinity::Tokenize(knownTitlesStr, ' ', false);
std::array<uint32, KNOWN_TITLES_SIZE * 2> knownTitles;
if (tokens.size() != ktcount)
for (uint32 index = 0; index < knownTitles.size(); ++index)
{
SendCharFactionChange(CHAR_CREATE_ERROR, factionChangeInfo.get());
return;
}
Optional<uint32> thisMask;
if (index < tokens.size())
thisMask = Trinity::StringTo<uint32>(tokens[index]);
for (uint32 index = 0; index < ktcount; ++index)
knownTitles[index] = atoul(tokens[index]);
if (thisMask)
knownTitles[index] = *thisMask;
else
{
TC_LOG_WARN("entities.player", "%s has invalid title data '%s' at index %u - skipped, this may result in titles being lost",
GetPlayerInfo().c_str(), (index < tokens.size()) ? std::string(tokens[index]).c_str() : "<none>", index);
knownTitles[index] = 0;
}
}
for (std::map<uint32, uint32>::const_iterator it = sObjectMgr->FactionChangeTitles.begin(); it != sObjectMgr->FactionChangeTitles.end(); ++it)
{
@@ -2216,8 +2223,8 @@ void WorldSession::HandleCharFactionOrRaceChangeCallback(std::shared_ptr<Charact
}
std::ostringstream ss;
for (uint32 index = 0; index < ktcount; ++index)
ss << knownTitles[index] << ' ';
for (uint32 mask : knownTitles)
ss << mask << ' ';
stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_TITLES_FACTION_CHANGE);
stmt->setString(0, ss.str());
@@ -18,8 +18,10 @@
#include "CharacterPackets.h"
#include "DBCStores.h"
#include "Field.h"
#include "Log.h"
#include "ObjectMgr.h"
#include "Player.h"
#include "StringConvert.h"
#include "World.h"
WorldPackets::Character::EnumCharactersResult::CharacterInfo::CharacterInfo(Field* fields)
@@ -95,23 +97,45 @@ WorldPackets::Character::EnumCharactersResult::CharacterInfo::CharacterInfo(Fiel
}
}
Tokenizer equipment(fields[22].GetString(), ' ');
std::vector<std::string_view> equipment = Trinity::Tokenize(fields[22].GetStringView(), ' ', false);
ListPosition = fields[24].GetUInt8();
for (uint8 slot = 0; slot < INVENTORY_SLOT_BAG_END; ++slot)
{
uint32 visualBase = slot * 2;
uint32 itemId = Player::GetUInt32ValueFromArray(equipment, visualBase);
ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId);
uint32 const visualBase = slot * 2;
Optional<uint32> itemId;
if (visualBase < equipment.size())
itemId = Trinity::StringTo<uint32>(equipment[visualBase]);
ItemTemplate const* proto = nullptr;
if (itemId)
proto = sObjectMgr->GetItemTemplate(*itemId);
if (!proto)
{
if (!itemId || *itemId)
{
TC_LOG_WARN("entities.player.loading", "Player %u has invalid equipment '%s' in `equipmentcache` at index %u. Skipped.",
Guid.GetCounter(), (visualBase < equipment.size()) ? std::string(equipment[visualBase]).c_str() : "<none>", visualBase);
}
continue;
}
SpellItemEnchantmentEntry const* enchant = nullptr;
uint32 enchants = Player::GetUInt32ValueFromArray(equipment, visualBase + 1);
Optional<uint32> enchants;
if ((visualBase+1) < equipment.size())
enchants = Trinity::StringTo<uint32>(equipment[visualBase + 1]);
if (!enchants)
{
TC_LOG_WARN("entities.player.loading", "Player %u has invalid enchantment info '%s' in `equipmentcache` at index %u. Skipped.",
Guid.GetCounter(), ((visualBase+1) < equipment.size()) ? std::string(equipment[visualBase + 1]).c_str() : "<none>", visualBase + 1);
enchants = 0;
}
for (uint8 enchantSlot = PERM_ENCHANTMENT_SLOT; enchantSlot <= TEMP_ENCHANTMENT_SLOT; ++enchantSlot)
{
// values stored in 2 uint16
uint32 enchantId = 0x0000FFFF & (enchants >> enchantSlot * 16);
uint32 enchantId = 0x0000FFFF & ((*enchants) >> enchantSlot * 16);
if (!enchantId)
continue;
@@ -23,6 +23,7 @@
#include "Map.h"
#include "ObjectMgr.h"
#include "ScriptMgr.h"
#include "StringConvert.h"
#include "World.h"
#include "WorldStatePackets.h"
@@ -52,78 +53,76 @@ void WorldStateMgr::LoadFromDB()
worldState.Id = id;
worldState.DefaultValue = fields[1].GetInt32();
Tokenizer tokens(fields[2].GetString(), ' ');
uint8 i = 0;
for (Tokenizer::const_iterator itr = tokens.begin(); itr != tokens.end(); ++itr, ++i)
std::string_view mapIds = fields[2].GetStringView();
for (std::string_view mapIdToken : Trinity::Tokenize(mapIds, ',', false))
{
int32 mapId = atoi(*itr);
Optional<int32> mapId = Trinity::StringTo<int32>(mapIdToken);
if (!mapId)
{
TC_LOG_ERROR("sql.sql", "Table `world_state` contains a world state %d with non-integer MapID (%s), map ignored",
id, *itr);
id, mapIdToken.data());
continue;
}
if (!sMapStore.LookupEntry(mapId) && mapId != WORLDSTATE_ANY_MAP)
if (!sMapStore.LookupEntry(*mapId) && mapId != WORLDSTATE_ANY_MAP)
{
TC_LOG_ERROR("sql.sql", "Table `world_state` contains a world state %d with invalid MapID (%u), map ignored",
id, mapId);
id, *mapId);
continue;
}
worldState.MapIds.insert(mapId);
worldState.MapIds.insert(*mapId);
}
if (i > 0 && worldState.MapIds.empty())
if (!mapIds.empty() && worldState.MapIds.empty())
{
TC_LOG_ERROR("sql.sql", "Table `world_state` contains a world state %d with nonempty MapIDs but no valid map id was found, ignored",
id);
TC_LOG_ERROR("sql.sql", "Table `world_state` contains a world state %i with nonempty MapIDs (%s) but no valid map id was found, ignored",
id, mapIds.data());
continue;
}
Tokenizer tokens2(fields[3].GetString(), ' ');
i = 0;
std::string_view areaIds = fields[3].GetStringView();
if (!worldState.MapIds.empty())
{
for (Tokenizer::const_iterator itr = tokens2.begin(); itr != tokens2.end(); ++itr, ++i)
for (std::string_view areaIdToken : Trinity::Tokenize(areaIds, ',', false))
{
uint32 areaId = atoul(*itr);
Optional<uint32> areaId = Trinity::StringTo<uint32>(areaIdToken);
if (!areaId)
{
TC_LOG_ERROR("sql.sql", "Table `world_state` contains a world state %d with non-integer AreaID, area ignored",
id);
TC_LOG_ERROR("sql.sql", "Table `world_state` contains a world state %i with non-integer AreaID (%s), area ignored",
id, areaIdToken.data());
continue;
}
AreaTableEntry const* areaTableEntry = sAreaTableStore.LookupEntry(areaId);
AreaTableEntry const* areaTableEntry = sAreaTableStore.LookupEntry(*areaId);
if (!areaTableEntry)
{
TC_LOG_ERROR("sql.sql", "Table `world_state` contains a world state %d with invalid AreaID (%u), area ignored",
id, areaId);
id, *areaId);
continue;
}
if (worldState.MapIds.find(areaTableEntry->ContinentID) == worldState.MapIds.end())
{
TC_LOG_ERROR("sql.sql", "Table `world_state` contains a world state %d with AreaID (%u) not on any of required maps, area ignored",
id, areaId);
id, *areaId);
continue;
}
worldState.AreaIds.insert(areaId);
worldState.AreaIds.insert(*areaId);
}
if (i > 0 && worldState.AreaIds.empty())
if (!areaIds.empty() && worldState.AreaIds.empty())
{
TC_LOG_ERROR("sql.sql", "Table `world_state` contains a world state %d with nonempty AreaIDs but no valid area id was found, ignored",
id);
TC_LOG_ERROR("sql.sql", "Table `world_state` contains a world state %i with nonempty AreaIDs (%s) but no valid area id was found, ignored",
id, areaIds.data());
continue;
}
}
else if (tokens2.size() > 0)
else if (!areaIds.empty())
{
TC_LOG_ERROR("sql.sql", "Table `world_state` contains a world state %u with nonempty AreaIDs but is a realm wide world state, area requirement ignored",
id);
TC_LOG_ERROR("sql.sql", "Table `world_state` contains a world state %i with nonempty AreaIDs (%s) but is a realm wide world state, area requirement ignored",
id, areaIds.data());
}
worldState.ScriptId = sObjectMgr->GetScriptId(fields[4].GetString());
+9 -3
View File
@@ -33,6 +33,7 @@ EndScriptData */
#include "Player.h"
#include "RBAC.h"
#include "ReputationMgr.h"
#include "StringConvert.h"
#include "WorldSession.h"
class modify_commandscript : public CommandScript
@@ -558,11 +559,16 @@ public:
if (handler->HasLowerSecurity(target, ObjectGuid::Empty))
return false;
int64 moneyToAdd = 0;
Optional<int64> moneyToAddO = 0;
if (strchr(args, 'g') || strchr(args, 's') || strchr(args, 'c'))
moneyToAdd = MoneyStringToMoney(std::string(args));
moneyToAddO = MoneyStringToMoney(std::string(args));
else
moneyToAdd = atol(args);
moneyToAddO = Trinity::StringTo<int64>(args);
if (!moneyToAddO)
return false;
int64 moneyToAdd = *moneyToAddO;
uint64 targetMoney = target->GetMoney();
+5 -6
View File
@@ -42,6 +42,7 @@ EndScriptData */
#include "SkillExtraItems.h"
#include "SmartAI.h"
#include "SpellMgr.h"
#include "StringConvert.h"
#include "TicketMgr.h"
#include "WardenCheckMgr.h"
#include "WaypointManager.h"
@@ -196,7 +197,7 @@ public:
HandleReloadGameTeleCommand(handler, "");
HandleReloadCreatureMovementOverrideCommand(handler, "");
HandleReloadCreatureSummonGroupsCommand(handler, "");
HandleReloadCreatureSummonGroupsCommand(handler);
HandleReloadVehicleAccessoryCommand(handler, "");
HandleReloadVehicleTemplateAccessoryCommand(handler, "");
@@ -408,7 +409,7 @@ public:
return true;
}
static bool HandleReloadCreatureSummonGroupsCommand(ChatHandler* handler, char const* /*args*/)
static bool HandleReloadCreatureSummonGroupsCommand(ChatHandler* handler)
{
TC_LOG_INFO("misc", "Reloading creature summon groups...");
sObjectMgr->LoadTempSummons();
@@ -421,11 +422,9 @@ public:
if (!*args)
return false;
Tokenizer entries(std::string(args), ' ');
for (Tokenizer::const_iterator itr = entries.begin(); itr != entries.end(); ++itr)
for (std::string_view entryStr : Trinity::Tokenize(args, ' ', false))
{
uint32 entry = uint32(atoi(*itr));
uint32 entry = Trinity::StringTo<uint32>(entryStr).value_or(0);
WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_CREATURE_TEMPLATE);
stmt->setUInt32(0, entry);