aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2017-01-13 21:38:03 +0100
committerariel- <ariel-@users.noreply.github.com>2017-01-25 23:38:13 -0300
commit4c27203c8f36dd2a5df0a4ae69fbdc4c9140b29d (patch)
tree175c45945668243f86642b40cfadac92823f6c9f /src
parent8af3cccc83aa7fbda348a784e36f45331c091c9a (diff)
Core/DBLayer: Convert async queries to new query callbacks and remove old callback handling
(cherry picked from commit 8e2634b2b49eb814b8cc425a060b2f160dbb49b7) Conflicts: src/server/bnetserver/Server/Session.cpp src/server/bnetserver/Server/Session.h src/server/database/Database/QueryCallback.cpp src/server/game/Handlers/CharacterHandler.cpp src/server/game/Handlers/SocialHandler.cpp src/server/game/Server/WorldSession.cpp src/server/game/Server/WorldSession.h src/server/game/Server/WorldSocket.cpp src/server/game/Server/WorldSocket.h src/server/game/World/World.cpp src/server/game/World/World.h
Diffstat (limited to 'src')
-rw-r--r--src/server/authserver/Server/AuthSession.cpp20
-rw-r--r--src/server/authserver/Server/AuthSession.h3
-rw-r--r--src/server/database/Database/DatabaseWorkerPool.cpp9
-rw-r--r--src/server/database/Database/DatabaseWorkerPool.h9
-rw-r--r--src/server/database/Database/Implementation/CharacterDatabase.cpp10
-rw-r--r--src/server/database/Database/Implementation/CharacterDatabase.h6
-rw-r--r--src/server/database/Database/QueryCallback.cpp173
-rw-r--r--src/server/database/Database/QueryCallback.h218
-rw-r--r--src/server/database/Database/QueryCallbackProcessor.cpp15
-rw-r--r--src/server/database/Database/QueryCallbackProcessor.h6
-rw-r--r--src/server/game/Accounts/RBAC.cpp3
-rw-r--r--src/server/game/Accounts/RBAC.h2
-rw-r--r--src/server/game/Handlers/CharacterHandler.cpp684
-rw-r--r--src/server/game/Handlers/NPCHandler.cpp18
-rw-r--r--src/server/game/Handlers/SocialHandler.cpp9
-rw-r--r--src/server/game/Server/WorldSession.cpp91
-rw-r--r--src/server/game/Server/WorldSession.h46
-rw-r--r--src/server/game/Server/WorldSocket.cpp17
-rw-r--r--src/server/game/Server/WorldSocket.h3
-rw-r--r--src/server/game/World/World.cpp20
-rw-r--r--src/server/game/World/World.h4
21 files changed, 550 insertions, 816 deletions
diff --git a/src/server/authserver/Server/AuthSession.cpp b/src/server/authserver/Server/AuthSession.cpp
index 0dbf7841e07..5c3ed477ace 100644
--- a/src/server/authserver/Server/AuthSession.cpp
+++ b/src/server/authserver/Server/AuthSession.cpp
@@ -169,8 +169,7 @@ void AuthSession::Start()
stmt->setString(0, ip_address);
stmt->setUInt32(1, inet_addr(ip_address.c_str()));
- _queryCallback = std::bind(&AuthSession::CheckIpCallback, this, std::placeholders::_1);
- _queryFuture = LoginDatabase.AsyncQuery(stmt);
+ _queryCallback = std::move(LoginDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&AuthSession::CheckIpCallback, this, std::placeholders::_1)));
}
bool AuthSession::Update()
@@ -178,12 +177,8 @@ bool AuthSession::Update()
if (!AuthSocket::Update())
return false;
- if (_queryFuture.valid() && _queryFuture.wait_for(std::chrono::seconds(0)) == std::future_status::ready)
- {
- auto callback = _queryCallback;
- _queryCallback = nullptr;
- callback(_queryFuture.get());
- }
+ if (_queryCallback && _queryCallback->InvokeIfReady() == QueryCallback::Completed)
+ _queryCallback = boost::none;
return true;
}
@@ -323,8 +318,7 @@ bool AuthSession::HandleLogonChallenge()
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_LOGONCHALLENGE);
stmt->setString(0, login);
- _queryCallback = std::bind(&AuthSession::LogonChallengeCallback, this, std::placeholders::_1);
- _queryFuture = LoginDatabase.AsyncQuery(stmt);
+ _queryCallback = std::move(LoginDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&AuthSession::LogonChallengeCallback, this, std::placeholders::_1)));
return true;
}
@@ -737,8 +731,7 @@ bool AuthSession::HandleReconnectChallenge()
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_RECONNECTCHALLENGE);
stmt->setString(0, login);
- _queryCallback = std::bind(&AuthSession::ReconnectChallengeCallback, this, std::placeholders::_1);
- _queryFuture = LoginDatabase.AsyncQuery(stmt);
+ _queryCallback = std::move(LoginDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&AuthSession::ReconnectChallengeCallback, this, std::placeholders::_1)));
return true;
}
@@ -819,8 +812,7 @@ bool AuthSession::HandleRealmList()
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_REALM_CHARACTER_COUNTS);
stmt->setUInt32(0, _accountInfo.Id);
- _queryCallback = std::bind(&AuthSession::RealmListCallback, this, std::placeholders::_1);
- _queryFuture = LoginDatabase.AsyncQuery(stmt);
+ _queryCallback = std::move(LoginDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&AuthSession::RealmListCallback, this, std::placeholders::_1)));
return true;
}
diff --git a/src/server/authserver/Server/AuthSession.h b/src/server/authserver/Server/AuthSession.h
index 1bc349dde4d..6b7124038e8 100644
--- a/src/server/authserver/Server/AuthSession.h
+++ b/src/server/authserver/Server/AuthSession.h
@@ -102,8 +102,7 @@ private:
uint16 _build;
uint8 _expversion;
- PreparedQueryResultFuture _queryFuture;
- std::function<void(PreparedQueryResult)> _queryCallback;
+ Optional<QueryCallback> _queryCallback;
};
#pragma pack(push, 1)
diff --git a/src/server/database/Database/DatabaseWorkerPool.cpp b/src/server/database/Database/DatabaseWorkerPool.cpp
index b770e30fc8c..9a0acedb0fe 100644
--- a/src/server/database/Database/DatabaseWorkerPool.cpp
+++ b/src/server/database/Database/DatabaseWorkerPool.cpp
@@ -17,6 +17,7 @@
#include "DatabaseWorkerPool.h"
#include "DatabaseEnv.h"
+#include "QueryCallback.h"
#define MIN_MYSQL_SERVER_VERSION 50100u
#define MIN_MYSQL_CLIENT_VERSION 50100u
@@ -146,23 +147,23 @@ PreparedQueryResult DatabaseWorkerPool<T>::Query(PreparedStatement* stmt)
}
template <class T>
-QueryResultFuture DatabaseWorkerPool<T>::AsyncQuery(const char* sql)
+QueryCallback DatabaseWorkerPool<T>::AsyncQuery(const char* sql)
{
BasicStatementTask* task = new BasicStatementTask(sql, true);
// Store future result before enqueueing - task might get already processed and deleted before returning from this method
QueryResultFuture result = task->GetFuture();
Enqueue(task);
- return result;
+ return QueryCallback(std::move(result));
}
template <class T>
-PreparedQueryResultFuture DatabaseWorkerPool<T>::AsyncQuery(PreparedStatement* stmt)
+QueryCallback DatabaseWorkerPool<T>::AsyncQuery(PreparedStatement* stmt)
{
PreparedStatementTask* task = new PreparedStatementTask(stmt, true);
// Store future result before enqueueing - task might get already processed and deleted before returning from this method
PreparedQueryResultFuture result = task->GetFuture();
Enqueue(task);
- return result;
+ return QueryCallback(std::move(result));
}
template <class T>
diff --git a/src/server/database/Database/DatabaseWorkerPool.h b/src/server/database/Database/DatabaseWorkerPool.h
index a082a9b6b0e..b195d2d6a28 100644
--- a/src/server/database/Database/DatabaseWorkerPool.h
+++ b/src/server/database/Database/DatabaseWorkerPool.h
@@ -19,7 +19,6 @@
#define _DATABASEWORKERPOOL_H
#include "Common.h"
-#include "QueryCallback.h"
#include "MySQLConnection.h"
#include "Transaction.h"
#include "DatabaseWorker.h"
@@ -34,6 +33,8 @@
#include <memory>
#include <array>
+class QueryCallback;
+
class PingOperation : public SQLOperation
{
//! Operation for idle delaythreads
@@ -192,12 +193,12 @@ class DatabaseWorkerPool
//! Enqueues a query in string format that will set the value of the QueryResultFuture return object as soon as the query is executed.
//! The return value is then processed in ProcessQueryCallback methods.
- QueryResultFuture AsyncQuery(const char* sql);
+ QueryCallback AsyncQuery(const char* sql);
//! Enqueues a query in string format -with variable args- that will set the value of the QueryResultFuture return object as soon as the query is executed.
//! The return value is then processed in ProcessQueryCallback methods.
template<typename Format, typename... Args>
- QueryResultFuture AsyncPQuery(Format&& sql, Args&&... args)
+ QueryCallback AsyncPQuery(Format&& sql, Args&&... args)
{
return AsyncQuery(Trinity::StringFormat(std::forward<Format>(sql), std::forward<Args>(args)...).c_str());
}
@@ -205,7 +206,7 @@ class DatabaseWorkerPool
//! Enqueues a query in prepared format that will set the value of the PreparedQueryResultFuture return object as soon as the query is executed.
//! The return value is then processed in ProcessQueryCallback methods.
//! Statement must be prepared with CONNECTION_ASYNC flag.
- PreparedQueryResultFuture AsyncQuery(PreparedStatement* stmt);
+ QueryCallback AsyncQuery(PreparedStatement* stmt);
//! Enqueues a vector of SQL operations (can be both adhoc and prepared) that will set the value of the QueryResultHolderFuture
//! return object as soon as the query is executed.
diff --git a/src/server/database/Database/Implementation/CharacterDatabase.cpp b/src/server/database/Database/Implementation/CharacterDatabase.cpp
index 301f3cf7d67..ecf3b52e8d9 100644
--- a/src/server/database/Database/Implementation/CharacterDatabase.cpp
+++ b/src/server/database/Database/Implementation/CharacterDatabase.cpp
@@ -51,7 +51,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
"cb.guid, cd.genitive FROM characters AS c LEFT JOIN character_pet AS cp ON c.guid = cp.owner AND cp.slot = ? "
"LEFT JOIN character_declinedname AS cd ON c.guid = cd.guid LEFT JOIN guild_member AS gm ON c.guid = gm.guid "
"LEFT JOIN character_banned AS cb ON c.guid = cb.guid AND cb.active = 1 WHERE c.account = ? AND c.deleteInfos_Name IS NULL ORDER BY c.guid", CONNECTION_ASYNC);
- PrepareStatement(CHAR_SEL_FREE_NAME, "SELECT guid, name FROM characters WHERE guid = ? AND account = ? AND (at_login & ?) = ? AND NOT EXISTS (SELECT NULL FROM characters WHERE name = ?)", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_SEL_FREE_NAME, "SELECT guid, name, at_login FROM characters WHERE guid = ? AND account = ? AND NOT EXISTS (SELECT NULL FROM characters WHERE name = ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_GUID_RACE_ACC_BY_NAME, "SELECT guid, race, account FROM characters WHERE name = ?", CONNECTION_BOTH);
PrepareStatement(CHAR_SEL_CHAR_LEVEL, "SELECT level FROM characters WHERE guid = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_CHAR_ZONE, "SELECT zone FROM characters WHERE guid = ?", CONNECTION_SYNCH);
@@ -162,7 +162,6 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_SEL_CHARACTER_NAME_CLASS, "SELECT name, class FROM characters WHERE guid = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_MATCH_MAKER_RATING, "SELECT matchMakerRating FROM character_arena_stats WHERE guid = ? AND slot = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_CHARACTER_COUNT, "SELECT account, COUNT(guid) FROM characters WHERE account = ? GROUP BY account", CONNECTION_ASYNC);
- PrepareStatement(CHAR_UPD_NAME, "UPDATE characters set name = ?, at_login = at_login & ~ ? WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_NAME_BY_GUID, "UPDATE characters SET name = ? WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_DECLINED_NAME, "DELETE FROM character_declinedname WHERE guid = ?", CONNECTION_ASYNC);
@@ -399,7 +398,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_UPD_INSTANCE_RESETTIME, "UPDATE instance SET resettime = ? WHERE id = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_GLOBAL_INSTANCE_RESETTIME, "UPDATE instance_reset SET resettime = ? WHERE mapid = ? AND difficulty = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_CHAR_ONLINE, "UPDATE characters SET online = 1 WHERE guid = ?", CONNECTION_ASYNC);
- PrepareStatement(CHAR_UPD_CHAR_NAME_AT_LOGIN, "UPDATE characters set name = ?, at_login = at_login & ~ ? WHERE guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_UPD_CHAR_NAME_AT_LOGIN, "UPDATE characters set name = ?, at_login = ? WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_WORLDSTATE, "UPDATE worldstates SET value = ? WHERE entry = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_WORLDSTATE, "INSERT INTO worldstates (entry, value) VALUES (?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_INSTANCE_BY_INSTANCE_GUID, "DELETE FROM character_instance WHERE guid = ? AND instance = ?", CONNECTION_ASYNC);
@@ -429,7 +428,8 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_SEL_POOL_QUEST_SAVE, "SELECT quest_id FROM pool_quest_save WHERE pool_id = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_CHARACTER_AT_LOGIN, "SELECT at_login FROM characters WHERE guid = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_CHAR_CLASS_LVL_AT_LOGIN, "SELECT class, level, at_login, knownTitles FROM characters WHERE guid = ?", CONNECTION_SYNCH);
- PrepareStatement(CHAR_SEL_CHAR_AT_LOGIN_TITLES, "SELECT at_login, knownTitles FROM characters WHERE guid = ?", CONNECTION_SYNCH);
+ PrepareStatement(CHAR_SEL_CHAR_CUSTOMIZE_INFO, "SELECT name, race, class, gender, at_login FROM characters WHERE guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_SEL_CHAR_RACE_OR_FACTION_CHANGE_INFOS, "SELECT at_login, knownTitles FROM characters WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_INSTANCE, "SELECT data, completedEncounters FROM instance WHERE map = ? AND id = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_PERM_BIND_BY_INSTANCE, "SELECT guid FROM character_instance WHERE instance = ? and permanent = 1", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_CHAR_COD_ITEM_MAIL, "SELECT id, messageType, mailTemplateId, sender, subject, body, money, has_items FROM mail WHERE receiver = ? AND has_items <> 0 AND cod <> 0", CONNECTION_SYNCH);
@@ -477,7 +477,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_DEL_PETITION_SIGNATURE_BY_GUID, "DELETE FROM petition_sign WHERE petitionguid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_DECLINED_NAME, "DELETE FROM character_declinedname WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_CHAR_DECLINED_NAME, "INSERT INTO character_declinedname (guid, genitive, dative, accusative, instrumental, prepositional) VALUES (?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
- PrepareStatement(CHAR_UPD_FACTION_OR_RACE, "UPDATE characters SET name = ?, race = ?, at_login = at_login & ~ ? WHERE guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_UPD_CHAR_RACE, "UPDATE characters SET race = ? WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_SKILL_LANGUAGES, "DELETE FROM character_skills WHERE skill IN (98, 113, 759, 111, 313, 109, 115, 315, 673, 137) AND guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_CHAR_SKILL_LANGUAGE, "INSERT INTO `character_skills` (guid, skill, value, max) VALUES (?, ?, 300, 300)", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_CHAR_TAXI_PATH, "UPDATE characters SET taxi_path = '' WHERE guid = ?", CONNECTION_ASYNC);
diff --git a/src/server/database/Database/Implementation/CharacterDatabase.h b/src/server/database/Database/Implementation/CharacterDatabase.h
index 3373daea2f0..5998b5f584c 100644
--- a/src/server/database/Database/Implementation/CharacterDatabase.h
+++ b/src/server/database/Database/Implementation/CharacterDatabase.h
@@ -148,7 +148,6 @@ enum CharacterDatabaseStatements
CHAR_SEL_CHARACTER_NAME_CLASS,
CHAR_SEL_MATCH_MAKER_RATING,
CHAR_SEL_CHARACTER_COUNT,
- CHAR_UPD_NAME,
CHAR_UPD_NAME_BY_GUID,
CHAR_DEL_DECLINED_NAME,
@@ -360,7 +359,8 @@ enum CharacterDatabaseStatements
CHAR_SEL_POOL_QUEST_SAVE,
CHAR_SEL_CHARACTER_AT_LOGIN,
CHAR_SEL_CHAR_CLASS_LVL_AT_LOGIN,
- CHAR_SEL_CHAR_AT_LOGIN_TITLES,
+ CHAR_SEL_CHAR_CUSTOMIZE_INFO,
+ CHAR_SEL_CHAR_RACE_OR_FACTION_CHANGE_INFOS,
CHAR_SEL_INSTANCE,
CHAR_SEL_PERM_BIND_BY_INSTANCE,
CHAR_SEL_CHAR_COD_ITEM_MAIL,
@@ -403,7 +403,7 @@ enum CharacterDatabaseStatements
CHAR_DEL_PETITION_SIGNATURE_BY_GUID,
CHAR_DEL_CHAR_DECLINED_NAME,
CHAR_INS_CHAR_DECLINED_NAME,
- CHAR_UPD_FACTION_OR_RACE,
+ CHAR_UPD_CHAR_RACE,
CHAR_DEL_CHAR_SKILL_LANGUAGES,
CHAR_INS_CHAR_SKILL_LANGUAGE,
CHAR_UPD_CHAR_TAXI_PATH,
diff --git a/src/server/database/Database/QueryCallback.cpp b/src/server/database/Database/QueryCallback.cpp
index b77036b8e6a..8850f87b20a 100644
--- a/src/server/database/Database/QueryCallback.cpp
+++ b/src/server/database/Database/QueryCallback.cpp
@@ -18,115 +18,186 @@
#include "QueryCallback.h"
template<typename T>
+inline void Construct(T& t)
+{
+ new (&t) T();
+}
+
+template<typename T>
inline void Destroy(T& t)
{
t.~T();
}
template<typename T>
-void DestroyActiveMember(T& obj)
+void ConstructActiveMember(T* obj)
+{
+ if (!obj->_isPrepared)
+ Construct(obj->_string);
+ else
+ Construct(obj->_prepared);
+}
+
+template<typename T>
+void DestroyActiveMember(T* obj)
{
- if (!obj._isPrepared)
- Destroy(obj._string);
+ if (!obj->_isPrepared)
+ Destroy(obj->_string);
else
- Destroy(obj._prepared);
+ Destroy(obj->_prepared);
}
template<typename T>
-void MoveFrom(T& to, T&& from)
+void MoveFrom(T* to, T&& from)
{
- DestroyActiveMember(to);
- to._isPrepared = from._isPrepared;
- if (!to._isPrepared)
- to._string = std::move(from._string);
+ ASSERT(to->_isPrepared == from._isPrepared);
+
+ if (!to->_isPrepared)
+ to->_string = std::move(from._string);
else
- to._prepared = std::move(from._prepared);
+ to->_prepared = std::move(from._prepared);
}
-struct QueryCallbackNew::QueryCallbackData
+struct QueryCallback::QueryCallbackData
{
public:
- friend class QueryCallbackNew;
+ friend class QueryCallback;
- QueryCallbackData(std::function<void(QueryResult)>&& callback) : _string(std::move(callback)), _isPrepared(false) { }
- QueryCallbackData(std::function<void(PreparedQueryResult)>&& callback) : _prepared(std::move(callback)), _isPrepared(true) { }
- QueryCallbackData(QueryCallbackData&& right) { MoveFrom(*this, std::move(right)); }
- QueryCallbackData& operator=(QueryCallbackData&& right) { MoveFrom(*this, std::move(right)); }
- ~QueryCallbackData() { DestroyActiveMember(*this); }
+ QueryCallbackData(std::function<void(QueryCallback&, QueryResult)>&& callback) : _string(std::move(callback)), _isPrepared(false) { TC_LOG_ERROR(LOGGER_ROOT, "QueryCallbackData [%p]: Constructing from string query", (void*)this); }
+ QueryCallbackData(std::function<void(QueryCallback&, PreparedQueryResult)>&& callback) : _prepared(std::move(callback)), _isPrepared(true) { TC_LOG_ERROR(LOGGER_ROOT, "QueryCallbackData [%p]: Constructing from prepared query", (void*)this); }
+ QueryCallbackData(QueryCallbackData&& right)
+ {
+ _isPrepared = right._isPrepared;
+ ConstructActiveMember(this);
+ MoveFrom(this, std::move(right));
+ }
+ QueryCallbackData& operator=(QueryCallbackData&& right)
+ {
+ if (this != &right)
+ {
+ if (_isPrepared != right._isPrepared)
+ {
+ DestroyActiveMember(this);
+ _isPrepared = right._isPrepared;
+ ConstructActiveMember(this);
+ }
+ MoveFrom(this, std::move(right));
+ }
+ return *this;
+ }
+ ~QueryCallbackData() { DestroyActiveMember(this); }
private:
QueryCallbackData(QueryCallbackData const&) = delete;
QueryCallbackData& operator=(QueryCallbackData const&) = delete;
- template<typename T> friend void MoveFrom(T& to, T&& from);
- template<typename T> friend void DestroyActiveMember(T& obj);
+ template<typename T> friend void ConstructActiveMember(T* obj);
+ template<typename T> friend void DestroyActiveMember(T* obj);
+ template<typename T> friend void MoveFrom(T* to, T&& from);
union
{
- std::function<void(QueryResult)> _string;
- std::function<void(PreparedQueryResult)> _prepared;
+ std::function<void(QueryCallback&, QueryResult)> _string;
+ std::function<void(QueryCallback&, PreparedQueryResult)> _prepared;
};
bool _isPrepared;
};
-QueryCallbackNew::QueryCallbackNew(std::future<QueryResult>&& result) : _string(std::move(result)), _isPrepared(false)
+QueryCallback::QueryCallback(std::future<QueryResult>&& result) : _string(std::move(result)), _isPrepared(false)
{
}
-QueryCallbackNew::QueryCallbackNew(std::future<PreparedQueryResult>&& result) : _prepared(std::move(result)), _isPrepared(true)
+QueryCallback::QueryCallback(std::future<PreparedQueryResult>&& result) : _prepared(std::move(result)), _isPrepared(true)
{
}
-QueryCallbackNew::QueryCallbackNew(QueryCallbackNew&& right)
+QueryCallback::QueryCallback(QueryCallback&& right)
{
- MoveFrom(*this, std::move(right));
+ _isPrepared = right._isPrepared;
+ ConstructActiveMember(this);
+ MoveFrom(this, std::move(right));
_callbacks = std::move(right._callbacks);
}
-QueryCallbackNew& QueryCallbackNew::operator=(QueryCallbackNew&& right)
+QueryCallback& QueryCallback::operator=(QueryCallback&& right)
{
- MoveFrom(*this, std::move(right));
- _callbacks = std::move(right._callbacks);
+ if (this != &right)
+ {
+ if (_isPrepared != right._isPrepared)
+ {
+ DestroyActiveMember(this);
+ _isPrepared = right._isPrepared;
+ ConstructActiveMember(this);
+ }
+ MoveFrom(this, std::move(right));
+ _callbacks = std::move(right._callbacks);
+ }
return *this;
}
-QueryCallbackNew::~QueryCallbackNew()
+QueryCallback::~QueryCallback()
{
- DestroyActiveMember(*this);
+ DestroyActiveMember(this);
}
-QueryCallbackNew&& QueryCallbackNew::WithCallback(std::function<void(QueryResult)>&& callback)
+QueryCallback&& QueryCallback::WithCallback(std::function<void(QueryResult)>&& callback)
+{
+ return WithChainingCallback([callback](QueryCallback& /*this*/, QueryResult result) { callback(std::move(result)); });
+}
+
+QueryCallback&& QueryCallback::WithPreparedCallback(std::function<void(PreparedQueryResult)>&& callback)
+{
+ return WithChainingPreparedCallback([callback](QueryCallback& /*this*/, PreparedQueryResult result) { callback(std::move(result)); });
+}
+
+QueryCallback&& QueryCallback::WithChainingCallback(std::function<void(QueryCallback&, QueryResult)>&& callback)
{
ASSERT(!_callbacks.empty() || !_isPrepared, "Attempted to set callback function for string query on a prepared async query");
_callbacks.emplace(std::move(callback));
return std::move(*this);
}
-QueryCallbackNew&& QueryCallbackNew::WithPreparedCallback(std::function<void(PreparedQueryResult)>&& callback)
+QueryCallback&& QueryCallback::WithChainingPreparedCallback(std::function<void(QueryCallback&, PreparedQueryResult)>&& callback)
{
ASSERT(!_callbacks.empty() || _isPrepared, "Attempted to set callback function for prepared query on a string async query");
_callbacks.emplace(std::move(callback));
return std::move(*this);
}
-QueryCallbackNew::Status QueryCallbackNew::InvokeIfReady()
+void QueryCallback::SetNextQuery(QueryCallback&& next)
+{
+ MoveFrom(this, std::move(next));
+}
+
+QueryCallback::Status QueryCallback::InvokeIfReady()
{
QueryCallbackData& callback = _callbacks.front();
+ auto checkStateAndReturnCompletion = [this]()
+ {
+ _callbacks.pop();
+ bool hasNext = !_isPrepared ? _string.valid() : _prepared.valid();
+ if (_callbacks.empty())
+ {
+ ASSERT(!hasNext);
+ return Completed;
+ }
+
+ // abort chain
+ if (!hasNext)
+ return Completed;
+
+ ASSERT(_isPrepared == _callbacks.front()._isPrepared);
+ return NextStep;
+ };
+
if (!_isPrepared)
{
if (_string.valid() && _string.wait_for(std::chrono::seconds(0)) == std::future_status::ready)
{
- std::function<void(QueryResult)> cb(std::move(callback._string));
- cb(_string.get());
- _callbacks.pop();
- if (_callbacks.empty())
- {
- ASSERT(!_isPrepared ? !_string.valid() : !_prepared.valid());
- return Completed;
- }
-
- ASSERT(_isPrepared == _callbacks.front()._isPrepared);
- return NextStep;
+ std::future<QueryResult> f(std::move(_string));
+ std::function<void(QueryCallback&, QueryResult)> cb(std::move(callback._string));
+ cb(*this, f.get());
+ return checkStateAndReturnCompletion();
}
}
else
@@ -134,17 +205,9 @@ QueryCallbackNew::Status QueryCallbackNew::InvokeIfReady()
if (_prepared.valid() && _prepared.wait_for(std::chrono::seconds(0)) == std::future_status::ready)
{
std::future<PreparedQueryResult> f(std::move(_prepared));
- std::function<void(PreparedQueryResult)> cb(std::move(callback._prepared));
- cb(_prepared.get());
- _callbacks.pop();
- if (_callbacks.empty())
- {
- ASSERT(!_isPrepared ? !_string.valid() : !_prepared.valid());
- return Completed;
- }
-
- ASSERT(_isPrepared == _callbacks.front()._isPrepared);
- return NextStep;
+ std::function<void(QueryCallback&, PreparedQueryResult)> cb(std::move(callback._prepared));
+ cb(*this, f.get());
+ return checkStateAndReturnCompletion();
}
}
diff --git a/src/server/database/Database/QueryCallback.h b/src/server/database/Database/QueryCallback.h
index 6c4a8a81b4e..f9c93000da7 100644
--- a/src/server/database/Database/QueryCallback.h
+++ b/src/server/database/Database/QueryCallback.h
@@ -18,27 +18,26 @@
#ifndef _QUERY_CALLBACK_H
#define _QUERY_CALLBACK_H
-#include <future>
#include "QueryResult.h"
+#include <future>
-typedef std::future<QueryResult> QueryResultFuture;
-typedef std::promise<QueryResult> QueryResultPromise;
-typedef std::future<PreparedQueryResult> PreparedQueryResultFuture;
-typedef std::promise<PreparedQueryResult> PreparedQueryResultPromise;
-
-#define CALLBACK_STAGE_INVALID uint8(-1)
-
-class TC_DATABASE_API QueryCallbackNew
+class TC_DATABASE_API QueryCallback
{
public:
- explicit QueryCallbackNew(std::future<QueryResult>&& result);
- explicit QueryCallbackNew(std::future<PreparedQueryResult>&& result);
- QueryCallbackNew(QueryCallbackNew&& right);
- QueryCallbackNew& operator=(QueryCallbackNew&& right);
- ~QueryCallbackNew();
+ explicit QueryCallback(std::future<QueryResult>&& result);
+ explicit QueryCallback(std::future<PreparedQueryResult>&& result);
+ QueryCallback(QueryCallback&& right);
+ QueryCallback& operator=(QueryCallback&& right);
+ ~QueryCallback();
+
+ QueryCallback&& WithCallback(std::function<void(QueryResult)>&& callback);
+ QueryCallback&& WithPreparedCallback(std::function<void(PreparedQueryResult)>&& callback);
+
+ QueryCallback&& WithChainingCallback(std::function<void(QueryCallback&, QueryResult)>&& callback);
+ QueryCallback&& WithChainingPreparedCallback(std::function<void(QueryCallback&, PreparedQueryResult)>&& callback);
- QueryCallbackNew&& WithCallback(std::function<void(QueryResult)>&& callback);
- QueryCallbackNew&& WithPreparedCallback(std::function<void(PreparedQueryResult)>&& callback);
+ // Moves std::future from next to this object
+ void SetNextQuery(QueryCallback&& next);
enum Status
{
@@ -50,11 +49,12 @@ public:
Status InvokeIfReady();
private:
- QueryCallbackNew(QueryCallbackNew const& right) = delete;
- QueryCallbackNew& operator=(QueryCallbackNew const& right) = delete;
+ QueryCallback(QueryCallback const& right) = delete;
+ QueryCallback& operator=(QueryCallback const& right) = delete;
- template<typename T> friend void MoveFrom(T& to, T&& from);
- template<typename T> friend void DestroyActiveMember(T& obj);
+ template<typename T> friend void ConstructActiveMember(T* obj);
+ template<typename T> friend void DestroyActiveMember(T* obj);
+ template<typename T> friend void MoveFrom(T* to, T&& from);
union
{
@@ -67,182 +67,4 @@ private:
std::queue<QueryCallbackData, std::list<QueryCallbackData>> _callbacks;
};
-template <typename Result, typename ParamType, bool chain = false>
-class QueryCallback
-{
- public:
- QueryCallback() : _param(), _stage(chain ? 0 : CALLBACK_STAGE_INVALID) { }
-
- //! The parameter of this function should be a resultset returned from either .AsyncQuery or .AsyncPQuery
- void SetFutureResult(std::future<Result> value)
- {
- _result = std::move(value);
- }
-
- std::future<Result>& GetFutureResult()
- {
- return _result;
- }
-
- bool IsReady()
- {
- return _result.valid() && _result.wait_for(std::chrono::seconds(0)) == std::future_status::ready;
- }
-
- void GetResult(Result& res)
- {
- res = _result.get();
- }
-
- void FreeResult()
- {
- // Nothing to do here, the constructor of std::future will take care of the cleanup
- }
-
- void SetParam(ParamType value)
- {
- _param = value;
- }
-
- ParamType GetParam()
- {
- return _param;
- }
-
- //! Resets the stage of the callback chain
- void ResetStage()
- {
- if (!chain)
- return;
-
- _stage = 0;
- }
-
- //! Advances the callback chain to the next stage, so upper level code can act on its results accordingly
- void NextStage()
- {
- if (!chain)
- return;
-
- ++_stage;
- }
-
- //! Returns the callback stage (or CALLBACK_STAGE_INVALID if invalid)
- uint8 GetStage()
- {
- return _stage;
- }
-
- //! Resets all underlying variables (param, result and stage)
- void Reset()
- {
- SetParam(ParamType());
- FreeResult();
- ResetStage();
- }
-
- private:
- std::future<Result> _result;
- ParamType _param;
- uint8 _stage;
-
- QueryCallback(QueryCallback const& right) = delete;
- QueryCallback& operator=(QueryCallback const& right) = delete;
-};
-
-template <typename Result, typename ParamType1, typename ParamType2, bool chain = false>
-class QueryCallback_2
-{
- public:
- QueryCallback_2() : _stage(chain ? 0 : CALLBACK_STAGE_INVALID) { }
-
- //! The parameter of this function should be a resultset returned from either .AsyncQuery or .AsyncPQuery
- void SetFutureResult(std::future<Result> value)
- {
- _result = std::move(value);
- }
-
- std::future<Result>& GetFutureResult()
- {
- return _result;
- }
-
- bool IsReady()
- {
- return _result.valid() && _result.wait_for(std::chrono::seconds(0)) == std::future_status::ready;
- }
-
- void GetResult(Result& res)
- {
- res = _result.get();
- }
-
- void FreeResult()
- {
- // Nothing to do here, the constructor of std::future will take care of the cleanup
- }
-
- void SetFirstParam(ParamType1 value)
- {
- _param_1 = value;
- }
-
- void SetSecondParam(ParamType2 value)
- {
- _param_2 = value;
- }
-
- ParamType1 GetFirstParam()
- {
- return _param_1;
- }
-
- ParamType2 GetSecondParam()
- {
- return _param_2;
- }
-
- //! Resets the stage of the callback chain
- void ResetStage()
- {
- if (!chain)
- return;
-
- _stage = 0;
- }
-
- //! Advances the callback chain to the next stage, so upper level code can act on its results accordingly
- void NextStage()
- {
- if (!chain)
- return;
-
- ++_stage;
- }
-
- //! Returns the callback stage (or CALLBACK_STAGE_INVALID if invalid)
- uint8 GetStage()
- {
- return _stage;
- }
-
- //! Resets all underlying variables (param, result and stage)
- void Reset()
- {
- SetFirstParam(NULL);
- SetSecondParam(NULL);
- FreeResult();
- ResetStage();
- }
-
- private:
- std::future<Result> _result;
- ParamType1 _param_1;
- ParamType2 _param_2;
- uint8 _stage;
-
- QueryCallback_2(QueryCallback_2 const& right) = delete;
- QueryCallback_2& operator=(QueryCallback_2 const& right) = delete;
-};
-
#endif // _QUERY_CALLBACK_H
diff --git a/src/server/database/Database/QueryCallbackProcessor.cpp b/src/server/database/Database/QueryCallbackProcessor.cpp
index 0eaa1c2352c..9f8b8fc4ad9 100644
--- a/src/server/database/Database/QueryCallbackProcessor.cpp
+++ b/src/server/database/Database/QueryCallbackProcessor.cpp
@@ -27,15 +27,22 @@ QueryCallbackProcessor::~QueryCallbackProcessor()
{
}
-void QueryCallbackProcessor::AddQuery(QueryCallbackNew&& query)
+void QueryCallbackProcessor::AddQuery(QueryCallback&& query)
{
_callbacks.emplace_back(std::move(query));
}
void QueryCallbackProcessor::ProcessReadyQueries()
{
- _callbacks.erase(std::remove_if(_callbacks.begin(), _callbacks.end(), [](QueryCallbackNew& callback)
+ if (_callbacks.empty())
+ return;
+
+ std::vector<QueryCallback> updateCallbacks{ std::move(_callbacks) };
+
+ updateCallbacks.erase(std::remove_if(updateCallbacks.begin(), updateCallbacks.end(), [](QueryCallback& callback)
{
- return callback.InvokeIfReady() == QueryCallbackNew::Completed;
- }), _callbacks.end());
+ return callback.InvokeIfReady() == QueryCallback::Completed;
+ }), updateCallbacks.end());
+
+ _callbacks.insert(_callbacks.end(), std::make_move_iterator(updateCallbacks.begin()), std::make_move_iterator(updateCallbacks.end()));
}
diff --git a/src/server/database/Database/QueryCallbackProcessor.h b/src/server/database/Database/QueryCallbackProcessor.h
index 08ae3d15693..0b06fd8fc27 100644
--- a/src/server/database/Database/QueryCallbackProcessor.h
+++ b/src/server/database/Database/QueryCallbackProcessor.h
@@ -21,7 +21,7 @@
#include "Define.h"
#include <vector>
-class QueryCallbackNew;
+class QueryCallback;
class TC_DATABASE_API QueryCallbackProcessor
{
@@ -29,14 +29,14 @@ public:
QueryCallbackProcessor();
~QueryCallbackProcessor();
- void AddQuery(QueryCallbackNew&& query);
+ void AddQuery(QueryCallback&& query);
void ProcessReadyQueries();
private:
QueryCallbackProcessor(QueryCallbackProcessor const&) = delete;
QueryCallbackProcessor& operator=(QueryCallbackProcessor const&) = delete;
- std::vector<QueryCallbackNew> _callbacks;
+ std::vector<QueryCallback> _callbacks;
};
#endif // QueryCallbackProcessor_h__
diff --git a/src/server/game/Accounts/RBAC.cpp b/src/server/game/Accounts/RBAC.cpp
index 378a66aa989..951223a9257 100644
--- a/src/server/game/Accounts/RBAC.cpp
+++ b/src/server/game/Accounts/RBAC.cpp
@@ -18,6 +18,7 @@
#include "RBAC.h"
#include "AccountMgr.h"
#include "Log.h"
+#include "QueryCallback.h"
namespace rbac
{
@@ -182,7 +183,7 @@ void RBACData::LoadFromDB()
LoadFromDBCallback(LoginDatabase.Query(stmt));
}
-PreparedQueryResultFuture RBACData::LoadFromDBAsync()
+QueryCallback RBACData::LoadFromDBAsync()
{
ClearData();
diff --git a/src/server/game/Accounts/RBAC.h b/src/server/game/Accounts/RBAC.h
index c998fd4274a..9b83b6492ed 100644
--- a/src/server/game/Accounts/RBAC.h
+++ b/src/server/game/Accounts/RBAC.h
@@ -918,7 +918,7 @@ class TC_GAME_API RBACData
/// Loads all permissions assigned to current account
void LoadFromDB();
- PreparedQueryResultFuture LoadFromDBAsync();
+ QueryCallback LoadFromDBAsync();
void LoadFromDBCallback(PreparedQueryResult result);
/// Sets security level
diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp
index cab80d23cba..0d6d750c73f 100644
--- a/src/server/game/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Handlers/CharacterHandler.cpp
@@ -35,6 +35,7 @@
#include "Pet.h"
#include "PlayerDump.h"
#include "Player.h"
+#include "QueryCallback.h"
#include "ReputationMgr.h"
#include "GitRevision.h"
#include "ScriptMgr.h"
@@ -261,23 +262,23 @@ void WorldSession::HandleCharEnumOpcode(WorldPacket& /*recvData*/)
stmt->setUInt8(0, PET_SAVE_AS_CURRENT);
stmt->setUInt32(1, GetAccountId());
- _charEnumCallback = CharacterDatabase.AsyncQuery(stmt);
+ _queryProcessor.AddQuery(CharacterDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSession::HandleCharEnum, this, std::placeholders::_1)));
}
void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
{
- CharacterCreateInfo createInfo;
-
- recvData >> createInfo.Name
- >> createInfo.Race
- >> createInfo.Class
- >> createInfo.Gender
- >> createInfo.Skin
- >> createInfo.Face
- >> createInfo.HairStyle
- >> createInfo.HairColor
- >> createInfo.FacialHair
- >> createInfo.OutfitId;
+ std::shared_ptr<CharacterCreateInfo> createInfo = std::make_shared<CharacterCreateInfo>();
+
+ recvData >> createInfo->Name
+ >> createInfo->Race
+ >> createInfo->Class
+ >> createInfo->Gender
+ >> createInfo->Skin
+ >> createInfo->Face
+ >> createInfo->HairStyle
+ >> createInfo->HairColor
+ >> createInfo->FacialHair
+ >> createInfo->OutfitId;
if (!HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_TEAMMASK))
{
@@ -285,7 +286,7 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
{
bool disabled = false;
- switch (Player::TeamForRace(createInfo.Race))
+ switch (Player::TeamForRace(createInfo->Race))
{
case ALLIANCE:
disabled = (mask & (1 << 0)) != 0;
@@ -303,18 +304,18 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
}
}
- ChrClassesEntry const* classEntry = sChrClassesStore.LookupEntry(createInfo.Class);
+ ChrClassesEntry const* classEntry = sChrClassesStore.LookupEntry(createInfo->Class);
if (!classEntry)
{
- TC_LOG_ERROR("network", "Class (%u) not found in DBC while creating new char for account (ID: %u): wrong DBC files or cheater?", createInfo.Class, GetAccountId());
+ TC_LOG_ERROR("network", "Class (%u) not found in DBC while creating new char for account (ID: %u): wrong DBC files or cheater?", createInfo->Class, GetAccountId());
SendCharCreate(CHAR_CREATE_FAILED);
return;
}
- ChrRacesEntry const* raceEntry = sChrRacesStore.LookupEntry(createInfo.Race);
+ ChrRacesEntry const* raceEntry = sChrRacesStore.LookupEntry(createInfo->Race);
if (!raceEntry)
{
- TC_LOG_ERROR("network", "Race (%u) not found in DBC while creating new char for account (ID: %u): wrong DBC files or cheater?", createInfo.Race, GetAccountId());
+ TC_LOG_ERROR("network", "Race (%u) not found in DBC while creating new char for account (ID: %u): wrong DBC files or cheater?", createInfo->Race, GetAccountId());
SendCharCreate(CHAR_CREATE_FAILED);
return;
}
@@ -322,7 +323,7 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
// prevent character creating Expansion race without Expansion account
if (raceEntry->expansion > Expansion())
{
- TC_LOG_ERROR("entities.player.cheat", "Expansion %u account:[%d] tried to Create character with expansion %u race (%u)", Expansion(), GetAccountId(), raceEntry->expansion, createInfo.Race);
+ TC_LOG_ERROR("entities.player.cheat", "Expansion %u account:[%d] tried to Create character with expansion %u race (%u)", Expansion(), GetAccountId(), raceEntry->expansion, createInfo->Race);
SendCharCreate(CHAR_CREATE_EXPANSION);
return;
}
@@ -330,7 +331,7 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
// prevent character creating Expansion class without Expansion account
if (classEntry->expansion > Expansion())
{
- TC_LOG_ERROR("entities.player.cheat", "Expansion %u account:[%d] tried to Create character with expansion %u class (%u)", Expansion(), GetAccountId(), classEntry->expansion, createInfo.Class);
+ TC_LOG_ERROR("entities.player.cheat", "Expansion %u account:[%d] tried to Create character with expansion %u class (%u)", Expansion(), GetAccountId(), classEntry->expansion, createInfo->Class);
SendCharCreate(CHAR_CREATE_EXPANSION_CLASS);
return;
}
@@ -338,7 +339,7 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
if (!HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RACEMASK))
{
uint32 raceMaskDisabled = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_DISABLED_RACEMASK);
- if ((1 << (createInfo.Race - 1)) & raceMaskDisabled)
+ if ((1 << (createInfo->Race - 1)) & raceMaskDisabled)
{
SendCharCreate(CHAR_CREATE_DISABLED);
return;
@@ -348,7 +349,7 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
if (!HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_CLASSMASK))
{
uint32 classMaskDisabled = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_DISABLED_CLASSMASK);
- if ((1 << (createInfo.Class - 1)) & classMaskDisabled)
+ if ((1 << (createInfo->Class - 1)) & classMaskDisabled)
{
SendCharCreate(CHAR_CREATE_DISABLED);
return;
@@ -356,7 +357,7 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
}
// prevent character creating with invalid name
- if (!normalizePlayerName(createInfo.Name))
+ if (!normalizePlayerName(createInfo->Name))
{
TC_LOG_ERROR("entities.player.cheat", "Account:[%d] but tried to Create character with empty [name] ", GetAccountId());
SendCharCreate(CHAR_NAME_NO_NAME);
@@ -364,20 +365,20 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
}
// check name limitations
- ResponseCodes res = ObjectMgr::CheckPlayerName(createInfo.Name, GetSessionDbcLocale(), true);
+ ResponseCodes res = ObjectMgr::CheckPlayerName(createInfo->Name, GetSessionDbcLocale(), true);
if (res != CHAR_NAME_SUCCESS)
{
SendCharCreate(res);
return;
}
- if (!HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RESERVEDNAME) && sObjectMgr->IsReservedName(createInfo.Name))
+ if (!HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RESERVEDNAME) && sObjectMgr->IsReservedName(createInfo->Name))
{
SendCharCreate(CHAR_NAME_RESERVED);
return;
}
- if (createInfo.Class == CLASS_DEATH_KNIGHT && !HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_HEROIC_CHARACTER))
+ if (createInfo->Class == CLASS_DEATH_KNIGHT && !HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_HEROIC_CHARACTER))
{
// speedup check for heroic class disabled case
uint32 heroic_free_slots = sWorld->getIntConfig(CONFIG_HEROIC_CHARACTERS_PER_REALM);
@@ -397,104 +398,58 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
}
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHECK_NAME);
- stmt->setString(0, createInfo.Name);
+ stmt->setString(0, createInfo->Name);
- delete _charCreateCallback.GetParam(); // Delete existing if any, to make the callback chain reset to stage 0
- _charCreateCallback.SetParam(new CharacterCreateInfo(std::move(createInfo)));
- _charCreateCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt));
-}
-
-void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, CharacterCreateInfo* createInfo)
-{
- /** This is a series of callbacks executed consecutively as a result from the database becomes available.
- This is much more efficient than synchronous requests on packet handler, and much less DoS prone.
- It also prevents data syncrhonisation errors.
- */
- switch (_charCreateCallback.GetStage())
+ _queryProcessor.AddQuery(CharacterDatabase.AsyncQuery(stmt)
+ .WithChainingPreparedCallback([this](QueryCallback& queryCallback, PreparedQueryResult result)
{
- case 0:
+ if (result)
{
- if (result)
- {
- SendCharCreate(CHAR_CREATE_NAME_IN_USE);
- delete createInfo;
- _charCreateCallback.Reset();
- return;
- }
-
- ASSERT(_charCreateCallback.GetParam() == createInfo);
+ SendCharCreate(CHAR_CREATE_NAME_IN_USE);
+ return;
+ }
- PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_SUM_REALM_CHARACTERS);
- stmt->setUInt32(0, GetAccountId());
+ PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_SUM_REALM_CHARACTERS);
+ stmt->setUInt32(0, GetAccountId());
+ queryCallback.SetNextQuery(LoginDatabase.AsyncQuery(stmt));
+ })
+ .WithChainingPreparedCallback([this](QueryCallback& queryCallback, PreparedQueryResult result)
+ {
+ uint64 acctCharCount = 0;
+ if (result)
+ {
+ Field* fields = result->Fetch();
+ acctCharCount = uint64(fields[0].GetDouble());
+ }
- _charCreateCallback.FreeResult();
- _charCreateCallback.SetFutureResult(LoginDatabase.AsyncQuery(stmt));
- _charCreateCallback.NextStage();
- break;
+ if (acctCharCount >= sWorld->getIntConfig(CONFIG_CHARACTERS_PER_ACCOUNT))
+ {
+ SendCharCreate(CHAR_CREATE_ACCOUNT_LIMIT);
+ return;
}
- case 1:
+
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_SUM_CHARS);
+ stmt->setUInt32(0, GetAccountId());
+ queryCallback.SetNextQuery(LoginDatabase.AsyncQuery(stmt));
+ })
+ .WithChainingPreparedCallback([this, createInfo](QueryCallback& queryCallback, PreparedQueryResult result)
+ {
+ if (result)
{
- uint64 acctCharCount = 0;
- if (result)
- {
- Field* fields = result->Fetch();
- acctCharCount = uint64(fields[0].GetDouble());
- }
+ Field* fields = result->Fetch();
+ createInfo->CharCount = uint8(fields[0].GetUInt64()); // SQL's COUNT() returns uint64 but it will always be less than uint8.Max
- if (acctCharCount >= sWorld->getIntConfig(CONFIG_CHARACTERS_PER_ACCOUNT))
+ if (createInfo->CharCount >= sWorld->getIntConfig(CONFIG_CHARACTERS_PER_REALM))
{
- SendCharCreate(CHAR_CREATE_ACCOUNT_LIMIT);
- delete createInfo;
- _charCreateCallback.Reset();
+ SendCharCreate(CHAR_CREATE_SERVER_LIMIT);
return;
}
-
- ASSERT(_charCreateCallback.GetParam() == createInfo);
-
- PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_SUM_CHARS);
- stmt->setUInt32(0, GetAccountId());
-
- _charCreateCallback.FreeResult();
- _charCreateCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt));
- _charCreateCallback.NextStage();
- break;
}
- case 2:
- {
- if (result)
- {
- Field* fields = result->Fetch();
- createInfo->CharCount = uint8(fields[0].GetUInt64()); // SQL's COUNT() returns uint64 but it will always be less than uint8.Max
- if (createInfo->CharCount >= sWorld->getIntConfig(CONFIG_CHARACTERS_PER_REALM))
- {
- SendCharCreate(CHAR_CREATE_SERVER_LIMIT);
- delete createInfo;
- _charCreateCallback.Reset();
- return;
- }
- }
-
- bool allowTwoSideAccounts = !sWorld->IsPvPRealm() || HasPermission(rbac::RBAC_PERM_TWO_SIDE_CHARACTER_CREATION);
- uint32 skipCinematics = sWorld->getIntConfig(CONFIG_SKIP_CINEMATICS);
-
- _charCreateCallback.FreeResult();
+ bool allowTwoSideAccounts = !sWorld->IsPvPRealm() || HasPermission(rbac::RBAC_PERM_TWO_SIDE_CHARACTER_CREATION);
+ uint32 skipCinematics = sWorld->getIntConfig(CONFIG_SKIP_CINEMATICS);
- if (!allowTwoSideAccounts || skipCinematics == 1 || createInfo->Class == CLASS_DEATH_KNIGHT)
- {
- PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_CREATE_INFO);
- stmt->setUInt32(0, GetAccountId());
- stmt->setUInt32(1, (skipCinematics == 1 || createInfo->Class == CLASS_DEATH_KNIGHT) ? 10 : 1);
- _charCreateCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt));
- _charCreateCallback.NextStage();
- return;
- }
-
- _charCreateCallback.NextStage();
- HandleCharCreateCallback(PreparedQueryResult(NULL), createInfo); // Will jump to case 3
- break;
- }
- case 3:
+ std::function<void(PreparedQueryResult)> finalizeCharacterCreation = [this, createInfo](PreparedQueryResult result)
{
bool haveSameRace = false;
uint32 heroicReqLevel = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_MIN_LEVEL_FOR_HEROIC_CHARACTER);
@@ -509,7 +464,7 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte
uint32 freeHeroicSlots = sWorld->getIntConfig(CONFIG_HEROIC_CHARACTERS_PER_REALM);
Field* field = result->Fetch();
- uint8 accRace = field[1].GetUInt8();
+ uint8 accRace = field[1].GetUInt8();
if (checkHeroicReqs)
{
@@ -522,8 +477,6 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte
if (freeHeroicSlots == 0)
{
SendCharCreate(CHAR_CREATE_UNIQUE_CLASS_LIMIT);
- delete createInfo;
- _charCreateCallback.Reset();
return;
}
}
@@ -547,8 +500,6 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte
if (accTeam != team)
{
SendCharCreate(CHAR_CREATE_PVP_TEAMS_VIOLATION);
- delete createInfo;
- _charCreateCallback.Reset();
return;
}
}
@@ -577,8 +528,6 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte
if (freeHeroicSlots == 0)
{
SendCharCreate(CHAR_CREATE_UNIQUE_CLASS_LIMIT);
- delete createInfo;
- _charCreateCallback.Reset();
return;
}
}
@@ -596,22 +545,18 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte
if (checkHeroicReqs && !hasHeroicReqLevel)
{
SendCharCreate(CHAR_CREATE_LEVEL_REQUIREMENT);
- delete createInfo;
- _charCreateCallback.Reset();
return;
}
Player newChar(this);
newChar.GetMotionMaster()->Initialize();
- if (!newChar.Create(sObjectMgr->GetGenerator<HighGuid::Player>().Generate(), createInfo))
+ if (!newChar.Create(sObjectMgr->GetGenerator<HighGuid::Player>().Generate(), createInfo.get()))
{
// Player not create (race/class/etc problem?)
newChar.CleanupsBeforeDelete();
SendCharCreate(CHAR_CREATE_ERROR);
- delete createInfo;
- _charCreateCallback.Reset();
return;
}
@@ -620,7 +565,7 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte
newChar.SetAtLoginFlag(AT_LOGIN_FIRST); // First login
- // Player created, save it now
+ // Player created, save it now
newChar.SaveToDB(true);
createInfo->CharCount += 1;
@@ -646,11 +591,19 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte
sWorld->AddCharacterInfo(newChar.GetGUID(), GetAccountId(), newChar.GetName(), newChar.GetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_GENDER), newChar.getRace(), newChar.getClass(), newChar.getLevel());
newChar.CleanupsBeforeDelete();
- delete createInfo;
- _charCreateCallback.Reset();
- break;
+ };
+
+ if (allowTwoSideAccounts && !skipCinematics && createInfo->Class != CLASS_DEATH_KNIGHT)
+ {
+ finalizeCharacterCreation(PreparedQueryResult(nullptr));
+ return;
}
- }
+
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_CREATE_INFO);
+ stmt->setUInt32(0, GetAccountId());
+ stmt->setUInt32(1, (skipCinematics == 1 || createInfo->Class == CLASS_DEATH_KNIGHT) ? 10 : 1);
+ queryCallback.WithPreparedCallback(std::move(finalizeCharacterCreation)).SetNextQuery(CharacterDatabase.AsyncQuery(stmt));
+ }));
}
void WorldSession::HandleCharDeleteOpcode(WorldPacket& recvData)
@@ -1084,29 +1037,29 @@ void WorldSession::HandleShowingCloakOpcode(WorldPacket& recvData)
void WorldSession::HandleCharRenameOpcode(WorldPacket& recvData)
{
- CharacterRenameInfo renameInfo;
+ std::shared_ptr<CharacterRenameInfo> renameInfo = std::make_shared<CharacterRenameInfo>();
- recvData >> renameInfo.Guid
- >> renameInfo.Name;
+ recvData >> renameInfo->Guid
+ >> renameInfo->Name;
// prevent character rename to invalid name
- if (!normalizePlayerName(renameInfo.Name))
+ if (!normalizePlayerName(renameInfo->Name))
{
- SendCharRename(CHAR_NAME_NO_NAME, renameInfo);
+ SendCharRename(CHAR_NAME_NO_NAME, renameInfo.get());
return;
}
- ResponseCodes res = ObjectMgr::CheckPlayerName(renameInfo.Name, GetSessionDbcLocale(), true);
+ ResponseCodes res = ObjectMgr::CheckPlayerName(renameInfo->Name, GetSessionDbcLocale(), true);
if (res != CHAR_NAME_SUCCESS)
{
- SendCharRename(res, renameInfo);
+ SendCharRename(res, renameInfo.get());
return;
}
// check name limitations
- if (!HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RESERVEDNAME) && sObjectMgr->IsReservedName(renameInfo.Name))
+ if (!HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RESERVEDNAME) && sObjectMgr->IsReservedName(renameInfo->Name))
{
- SendCharRename(CHAR_NAME_RESERVED, renameInfo);
+ SendCharRename(CHAR_NAME_RESERVED, renameInfo.get());
return;
}
@@ -1114,35 +1067,43 @@ void WorldSession::HandleCharRenameOpcode(WorldPacket& recvData)
// and that there is no character with the desired new name
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_FREE_NAME);
- stmt->setUInt32(0, renameInfo.Guid.GetCounter());
+ stmt->setUInt32(0, renameInfo->Guid.GetCounter());
stmt->setUInt32(1, GetAccountId());
- stmt->setUInt16(2, AT_LOGIN_RENAME);
- stmt->setUInt16(3, AT_LOGIN_RENAME);
- stmt->setString(4, renameInfo.Name);
+ stmt->setString(2, renameInfo->Name);
- delete _charRenameCallback.GetParam();
- _charRenameCallback.SetParam(new CharacterRenameInfo(std::move(renameInfo)));
- _charRenameCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt));
+ _queryProcessor.AddQuery(CharacterDatabase.AsyncQuery(stmt)
+ .WithPreparedCallback(std::bind(&WorldSession::HandleCharRenameCallback, this, renameInfo, std::placeholders::_1)));
}
-void WorldSession::HandleChangePlayerNameOpcodeCallBack(PreparedQueryResult result, CharacterRenameInfo const* renameInfo)
+void WorldSession::HandleCharRenameCallback(std::shared_ptr<CharacterRenameInfo> renameInfo, PreparedQueryResult result)
{
if (!result)
{
- SendCharRename(CHAR_CREATE_ERROR, *renameInfo);
+ SendCharRename(CHAR_CREATE_ERROR, renameInfo.get());
return;
}
Field* fields = result->Fetch();
- ObjectGuid::LowType guidLow = fields[0].GetUInt32();
+ ObjectGuid::LowType guidLow = fields[0].GetUInt32();
std::string oldName = fields[1].GetString();
+ uint16 atLoginFlags = fields[2].GetUInt16();
+
+ if (!(atLoginFlags & AT_LOGIN_RENAME))
+ {
+ SendCharRename(CHAR_CREATE_ERROR, renameInfo.get());
+ return;
+ }
+
+ atLoginFlags &= ~AT_LOGIN_RENAME;
+
+ SQLTransaction trans = CharacterDatabase.BeginTransaction();
// Update name and at_login flag in the db
- PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_NAME);
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_NAME_AT_LOGIN);
stmt->setString(0, renameInfo->Name);
- stmt->setUInt16(1, AT_LOGIN_RENAME);
+ stmt->setUInt16(1, atLoginFlags);
stmt->setUInt32(2, guidLow);
CharacterDatabase.Execute(stmt);
@@ -1156,7 +1117,7 @@ void WorldSession::HandleChangePlayerNameOpcodeCallBack(PreparedQueryResult resu
TC_LOG_INFO("entities.player.character", "Account: %d (IP: %s) Character:[%s] (%s) Changed name to: %s", GetAccountId(), GetRemoteAddress().c_str(), oldName.c_str(), renameInfo->Guid.ToString().c_str(), renameInfo->Name.c_str());
- SendCharRename(RESPONSE_SUCCESS, *renameInfo);
+ SendCharRename(RESPONSE_SUCCESS, renameInfo.get());
sWorld->UpdateCharacterInfo(renameInfo->Guid, renameInfo->Name);
}
@@ -1331,131 +1292,131 @@ void WorldSession::HandleRemoveGlyph(WorldPacket& recvData)
void WorldSession::HandleCharCustomize(WorldPacket& recvData)
{
- CharacterCustomizeInfo customizeInfo;
+ std::shared_ptr<CharacterCustomizeInfo> customizeInfo = std::make_shared<CharacterCustomizeInfo>();
- recvData >> customizeInfo.Guid;
- if (!IsLegitCharacterForAccount(customizeInfo.Guid))
+ recvData >> customizeInfo->Guid;
+ if (!IsLegitCharacterForAccount(customizeInfo->Guid))
{
TC_LOG_ERROR("entities.player.cheat", "Account %u, IP: %s tried to customise %s, but it does not belong to their account!",
- GetAccountId(), GetRemoteAddress().c_str(), customizeInfo.Guid.ToString().c_str());
+ GetAccountId(), GetRemoteAddress().c_str(), customizeInfo->Guid.ToString().c_str());
recvData.rfinish();
KickPlayer();
return;
}
- recvData >> customizeInfo.Name
- >> customizeInfo.Gender
- >> customizeInfo.Skin
- >> customizeInfo.HairColor
- >> customizeInfo.HairStyle
- >> customizeInfo.FacialHair
- >> customizeInfo.Face;
+ recvData >> customizeInfo->Name
+ >> customizeInfo->Gender
+ >> customizeInfo->Skin
+ >> customizeInfo->HairColor
+ >> customizeInfo->HairStyle
+ >> customizeInfo->FacialHair
+ >> customizeInfo->Face;
+
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_CUSTOMIZE_INFO);
+ stmt->setUInt32(0, customizeInfo->Guid.GetCounter());
- PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_NAME_DATA);
- stmt->setUInt32(0, customizeInfo.Guid.GetCounter());
- PreparedQueryResult result = CharacterDatabase.Query(stmt);
+ _queryProcessor.AddQuery(CharacterDatabase.AsyncQuery(stmt)
+ .WithPreparedCallback(std::bind(&WorldSession::HandleCharCustomizeCallback, this, customizeInfo, std::placeholders::_1)));
+}
+void WorldSession::HandleCharCustomizeCallback(std::shared_ptr<CharacterCustomizeInfo> customizeInfo, PreparedQueryResult result)
+{
if (!result)
{
- SendCharCustomize(CHAR_CREATE_ERROR, customizeInfo);
+ SendCharCustomize(CHAR_CREATE_ERROR, customizeInfo.get());
return;
}
Field* fields = result->Fetch();
- uint8 plrRace = fields[0].GetUInt8();
- uint8 plrClass = fields[1].GetUInt8();
- uint8 plrGender = fields[2].GetUInt8();
- std::string oldName = fields[4].GetString();
+ std::string oldName = fields[0].GetString();
+ uint8 plrRace = fields[1].GetUInt8();
+ uint8 plrClass = fields[2].GetUInt8();
+ uint8 plrGender = fields[3].GetUInt8();
+ uint16 atLoginFlags = fields[4].GetUInt16();
- if (!Player::ValidateAppearance(plrRace, plrClass, plrGender, customizeInfo.HairStyle, customizeInfo.HairColor, customizeInfo.Face, customizeInfo.FacialHair, customizeInfo.Skin, true))
+ if (!Player::ValidateAppearance(plrRace, plrClass, plrGender, customizeInfo->HairStyle, customizeInfo->HairColor, customizeInfo->Face, customizeInfo->FacialHair, customizeInfo->Skin, true))
{
- SendCharCustomize(CHAR_CREATE_ERROR, customizeInfo);
+ SendCharCustomize(CHAR_CREATE_ERROR, customizeInfo.get());
return;
}
- stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_AT_LOGIN);
-
- stmt->setUInt32(0, customizeInfo.Guid.GetCounter());
- // TODO: Make async with callback
- result = CharacterDatabase.Query(stmt);
-
- if (!result)
+ if (!(atLoginFlags & AT_LOGIN_CUSTOMIZE))
{
- SendCharCustomize(CHAR_CREATE_ERROR, customizeInfo);
+ SendCharCustomize(CHAR_CREATE_ERROR, customizeInfo.get());
return;
}
- fields = result->Fetch();
- uint32 at_loginFlags = fields[0].GetUInt16();
-
- if (!(at_loginFlags & AT_LOGIN_CUSTOMIZE))
- {
- SendCharCustomize(CHAR_CREATE_ERROR, customizeInfo);
- return;
- }
+ atLoginFlags &= ~AT_LOGIN_CUSTOMIZE;
// prevent character rename
- if (sWorld->getBoolConfig(CONFIG_PREVENT_RENAME_CUSTOMIZATION) && (customizeInfo.Name != oldName))
+ if (sWorld->getBoolConfig(CONFIG_PREVENT_RENAME_CUSTOMIZATION) && (customizeInfo->Name != oldName))
{
- SendCharCustomize(CHAR_NAME_FAILURE, customizeInfo);
+ SendCharCustomize(CHAR_NAME_FAILURE, customizeInfo.get());
return;
}
// prevent character rename to invalid name
- if (!normalizePlayerName(customizeInfo.Name))
+ if (!normalizePlayerName(customizeInfo->Name))
{
- SendCharCustomize(CHAR_NAME_NO_NAME, customizeInfo);
+ SendCharCustomize(CHAR_NAME_NO_NAME, customizeInfo.get());
return;
}
- ResponseCodes res = ObjectMgr::CheckPlayerName(customizeInfo.Name, GetSessionDbcLocale(), true);
+ ResponseCodes res = ObjectMgr::CheckPlayerName(customizeInfo->Name, GetSessionDbcLocale(), true);
if (res != CHAR_NAME_SUCCESS)
{
- SendCharCustomize(res, customizeInfo);
+ SendCharCustomize(res, customizeInfo.get());
return;
}
// check name limitations
- if (!HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RESERVEDNAME) && sObjectMgr->IsReservedName(customizeInfo.Name))
+ if (!HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RESERVEDNAME) && sObjectMgr->IsReservedName(customizeInfo->Name))
{
- SendCharCustomize(CHAR_NAME_RESERVED, customizeInfo);
+ SendCharCustomize(CHAR_NAME_RESERVED, customizeInfo.get());
return;
}
// character with this name already exist
- if (ObjectGuid newGuid = sObjectMgr->GetPlayerGUIDByName(customizeInfo.Name))
+ if (ObjectGuid newGuid = sObjectMgr->GetPlayerGUIDByName(customizeInfo->Name))
{
- if (newGuid != customizeInfo.Guid)
+ if (newGuid != customizeInfo->Guid)
{
- SendCharCustomize(CHAR_CREATE_NAME_IN_USE, customizeInfo);
+ SendCharCustomize(CHAR_CREATE_NAME_IN_USE, customizeInfo.get());
return;
}
}
+ PreparedStatement* stmt = nullptr;
SQLTransaction trans = CharacterDatabase.BeginTransaction();
- Player::Customize(&customizeInfo, trans);
+ ObjectGuid::LowType lowGuid = customizeInfo->Guid.GetCounter();
- stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_NAME_AT_LOGIN);
- stmt->setString(0, customizeInfo.Name);
- stmt->setUInt16(1, uint16(AT_LOGIN_CUSTOMIZE));
- stmt->setUInt32(2, customizeInfo.Guid.GetCounter());
+ /// Customize
+ Player::Customize(customizeInfo.get(), trans);
- trans->Append(stmt);
+ /// Name Change and update atLogin flags
+ {
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_NAME_AT_LOGIN);
+ stmt->setString(0, customizeInfo->Name);
+ stmt->setUInt16(1, atLoginFlags);
+ stmt->setUInt32(2, lowGuid);
- stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_DECLINED_NAME);
- stmt->setUInt32(0, customizeInfo.Guid.GetCounter());
+ trans->Append(stmt);
- trans->Append(stmt);
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_DECLINED_NAME);
+ stmt->setUInt32(0, lowGuid);
+
+ trans->Append(stmt);
+ }
CharacterDatabase.CommitTransaction(trans);
- sWorld->UpdateCharacterInfo(customizeInfo.Guid, customizeInfo.Name, customizeInfo.Gender);
+ sWorld->UpdateCharacterInfo(customizeInfo->Guid, customizeInfo->Name, customizeInfo->Gender);
- SendCharCustomize(RESPONSE_SUCCESS, customizeInfo);
+ SendCharCustomize(RESPONSE_SUCCESS, customizeInfo.get());
TC_LOG_INFO("entities.player.character", "Account: %d (IP: %s), Character[%s] (%s) Customized to: %s",
- GetAccountId(), GetRemoteAddress().c_str(), oldName.c_str(), customizeInfo.Guid.ToString().c_str(), customizeInfo.Name.c_str());
+ GetAccountId(), GetRemoteAddress().c_str(), oldName.c_str(), customizeInfo->Guid.ToString().c_str(), customizeInfo->Name.c_str());
}
void WorldSession::HandleEquipmentSetSave(WorldPacket& recvData)
@@ -1585,157 +1546,174 @@ void WorldSession::HandleEquipmentSetUse(WorldPacket& recvData)
void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData)
{
- CharacterFactionChangeInfo factionChangeInfo;
- recvData >> factionChangeInfo.Guid;
+ std::shared_ptr<CharacterFactionChangeInfo> factionChangeInfo = std::make_shared<CharacterFactionChangeInfo>();
+ recvData >> factionChangeInfo->Guid;
- if (!IsLegitCharacterForAccount(factionChangeInfo.Guid))
+ if (!IsLegitCharacterForAccount(factionChangeInfo->Guid))
{
TC_LOG_ERROR("entities.player.cheat", "Account %u, IP: %s tried to factionchange character %s, but it does not belong to their account!",
- GetAccountId(), GetRemoteAddress().c_str(), factionChangeInfo.Guid.ToString().c_str());
+ GetAccountId(), GetRemoteAddress().c_str(), factionChangeInfo->Guid.ToString().c_str());
recvData.rfinish();
KickPlayer();
return;
}
- recvData >> factionChangeInfo.Name
- >> factionChangeInfo.Gender
- >> factionChangeInfo.Skin
- >> factionChangeInfo.HairColor
- >> factionChangeInfo.HairStyle
- >> factionChangeInfo.FacialHair
- >> factionChangeInfo.Face
- >> factionChangeInfo.Race;
+ recvData >> factionChangeInfo->Name
+ >> factionChangeInfo->Gender
+ >> factionChangeInfo->Skin
+ >> factionChangeInfo->HairColor
+ >> factionChangeInfo->HairStyle
+ >> factionChangeInfo->FacialHair
+ >> factionChangeInfo->Face
+ >> factionChangeInfo->Race;
- ObjectGuid::LowType lowGuid = factionChangeInfo.Guid.GetCounter();
+ factionChangeInfo->FactionChange = (recvData.GetOpcode() == CMSG_CHAR_FACTION_CHANGE);
- // get the players old (at this moment current) race
- CharacterInfo const* nameData = sWorld->GetCharacterInfo(factionChangeInfo.Guid);
- if (!nameData)
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_RACE_OR_FACTION_CHANGE_INFOS);
+ stmt->setUInt32(0, factionChangeInfo->Guid.GetCounter());
+
+ _queryProcessor.AddQuery(CharacterDatabase.AsyncQuery(stmt)
+ .WithPreparedCallback(std::bind(&WorldSession::HandleCharFactionOrRaceChangeCallback, this, factionChangeInfo, std::placeholders::_1)));
+}
+
+void WorldSession::HandleCharFactionOrRaceChangeCallback(std::shared_ptr<CharacterFactionChangeInfo> factionChangeInfo, PreparedQueryResult result)
+{
+ if (!result)
{
- SendCharFactionChange(CHAR_CREATE_ERROR, factionChangeInfo);
+ SendCharFactionChange(CHAR_CREATE_ERROR, factionChangeInfo.get());
return;
}
- std::string oldName = nameData->Name;
- uint8 oldRace = nameData->Race;
- uint8 playerClass = nameData->Class;
- uint8 level = nameData->Level;
+ // get the players old (at this moment current) race
+ CharacterInfo const* characterInfo = sWorld->GetCharacterInfo(factionChangeInfo->Guid);
+ if (!characterInfo)
+ {
+ SendCharFactionChange(CHAR_CREATE_ERROR, factionChangeInfo.get());
+ return;
+ }
- // TO Do: Make async
- PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_AT_LOGIN_TITLES);
- stmt->setUInt32(0, lowGuid);
- PreparedQueryResult result = CharacterDatabase.Query(stmt);
+ uint8 oldRace = characterInfo->Race;
+ uint8 playerClass = characterInfo->Class;
+ uint8 level = characterInfo->Level;
- if (!result)
+ if (!sObjectMgr->GetPlayerInfo(factionChangeInfo->Race, playerClass))
{
- SendCharFactionChange(CHAR_CREATE_ERROR, factionChangeInfo);
+ SendCharFactionChange(CHAR_CREATE_ERROR, factionChangeInfo.get());
return;
}
- Field* fields = result->Fetch();
- uint32 at_loginFlags = fields[0].GetUInt16();
+ Field* fields = result->Fetch();
+ uint32 atLoginFlags = fields[0].GetUInt16();
std::string knownTitlesStr = fields[1].GetString();
- uint32 used_loginFlag = ((recvData.GetOpcode() == CMSG_CHAR_RACE_CHANGE) ? AT_LOGIN_CHANGE_RACE : AT_LOGIN_CHANGE_FACTION);
- if (!sObjectMgr->GetPlayerInfo(factionChangeInfo.Race, playerClass))
+ uint32 usedLoginFlag = (factionChangeInfo->FactionChange ? AT_LOGIN_CHANGE_FACTION : AT_LOGIN_CHANGE_RACE);
+ if (!(atLoginFlags & usedLoginFlag))
{
- SendCharFactionChange(CHAR_CREATE_ERROR, factionChangeInfo);
+ SendCharFactionChange(CHAR_CREATE_ERROR, factionChangeInfo.get());
return;
}
- if (!(at_loginFlags & used_loginFlag))
+ uint32 newTeam = Player::TeamForRace(factionChangeInfo->Race);
+ if (factionChangeInfo->FactionChange == (Player::TeamForRace(oldRace) == newTeam))
{
- SendCharFactionChange(CHAR_CREATE_ERROR, factionChangeInfo);
+ SendCharFactionChange(factionChangeInfo->FactionChange ? CHAR_CREATE_CHARACTER_SWAP_FACTION : CHAR_CREATE_CHARACTER_RACE_ONLY, factionChangeInfo.get());
return;
}
if (!HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RACEMASK))
{
uint32 raceMaskDisabled = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_DISABLED_RACEMASK);
- if ((1 << (factionChangeInfo.Race - 1)) & raceMaskDisabled)
+ if ((1 << (factionChangeInfo->Race - 1)) & raceMaskDisabled)
{
- SendCharFactionChange(CHAR_CREATE_ERROR, factionChangeInfo);
+ SendCharFactionChange(CHAR_CREATE_ERROR, factionChangeInfo.get());
return;
}
}
// prevent character rename
- if (sWorld->getBoolConfig(CONFIG_PREVENT_RENAME_CUSTOMIZATION) && (factionChangeInfo.Name != oldName))
+ if (sWorld->getBoolConfig(CONFIG_PREVENT_RENAME_CUSTOMIZATION) && (factionChangeInfo->Name != characterInfo->Name))
{
- SendCharFactionChange(CHAR_NAME_FAILURE, factionChangeInfo);
+ SendCharFactionChange(CHAR_NAME_FAILURE, factionChangeInfo.get());
return;
}
// prevent character rename to invalid name
- if (!normalizePlayerName(factionChangeInfo.Name))
+ if (!normalizePlayerName(factionChangeInfo->Name))
{
- SendCharFactionChange(CHAR_NAME_NO_NAME, factionChangeInfo);
+ SendCharFactionChange(CHAR_NAME_NO_NAME, factionChangeInfo.get());
return;
}
- ResponseCodes res = ObjectMgr::CheckPlayerName(factionChangeInfo.Name, GetSessionDbcLocale(), true);
+ ResponseCodes res = ObjectMgr::CheckPlayerName(factionChangeInfo->Name, GetSessionDbcLocale(), true);
if (res != CHAR_NAME_SUCCESS)
{
- SendCharFactionChange(res, factionChangeInfo);
+ SendCharFactionChange(res, factionChangeInfo.get());
return;
}
// check name limitations
- if (!HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RESERVEDNAME) && sObjectMgr->IsReservedName(factionChangeInfo.Name))
+ if (!HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RESERVEDNAME) && sObjectMgr->IsReservedName(factionChangeInfo->Name))
{
- SendCharFactionChange(CHAR_NAME_RESERVED, factionChangeInfo);
+ SendCharFactionChange(CHAR_NAME_RESERVED, factionChangeInfo.get());
return;
}
// character with this name already exist
- if (ObjectGuid newGuid = sObjectMgr->GetPlayerGUIDByName(factionChangeInfo.Name))
+ ObjectGuid newGuid = sObjectMgr->GetPlayerGUIDByName(factionChangeInfo->Name);
+ if (!newGuid.IsEmpty())
{
- if (newGuid != factionChangeInfo.Guid)
+ if (newGuid != factionChangeInfo->Guid)
{
- SendCharFactionChange(CHAR_CREATE_NAME_IN_USE, factionChangeInfo);
+ SendCharFactionChange(CHAR_CREATE_NAME_IN_USE, factionChangeInfo.get());
return;
}
}
+ if (sArenaTeamMgr->GetArenaTeamByCaptain(factionChangeInfo->Guid))
+ {
+ SendCharFactionChange(CHAR_CREATE_CHARACTER_ARENA_LEADER, factionChangeInfo.get());
+ return;
+ }
+
+ // All checks are fine, deal with race change now
+ ObjectGuid::LowType lowGuid = factionChangeInfo->Guid.GetCounter();
+
+ PreparedStatement* stmt = nullptr;
SQLTransaction trans = CharacterDatabase.BeginTransaction();
// resurrect the character in case he's dead
- Player::OfflineResurrect(factionChangeInfo.Guid, trans);
+ Player::OfflineResurrect(factionChangeInfo->Guid, trans);
- CharacterDatabase.EscapeString(factionChangeInfo.Name);
- Player::Customize(&factionChangeInfo, trans);
+ // Name Change and update atLogin flags
+ {
+ CharacterDatabase.EscapeString(factionChangeInfo->Name);
- stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_FACTION_OR_RACE);
- stmt->setString(0, factionChangeInfo.Name);
- stmt->setUInt8(1, factionChangeInfo.Race);
- stmt->setUInt16(2, used_loginFlag);
- stmt->setUInt32(3, lowGuid);
- trans->Append(stmt);
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_NAME_AT_LOGIN);
+ stmt->setString(0, factionChangeInfo->Name);
+ stmt->setUInt16(1, uint16((atLoginFlags | AT_LOGIN_RESURRECT) & ~usedLoginFlag));
+ stmt->setUInt32(2, lowGuid);
+ trans->Append(stmt);
- stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_DECLINED_NAME);
- stmt->setUInt32(0, lowGuid);
- trans->Append(stmt);
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_DECLINED_NAME);
+ stmt->setUInt32(0, lowGuid);
+ trans->Append(stmt);
+ }
- sWorld->UpdateCharacterInfo(factionChangeInfo.Guid, factionChangeInfo.Name, factionChangeInfo.Gender, factionChangeInfo.Race);
+ // Customize
+ Player::Customize(factionChangeInfo.get(), trans);
- if (oldRace != factionChangeInfo.Race)
+ // Race Change
{
- TeamId team = TEAM_ALLIANCE;
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_RACE);
+ stmt->setUInt8(0, factionChangeInfo->Race);
+ stmt->setUInt32(1, lowGuid);
+ trans->Append(stmt);
+ }
- // Search each faction is targeted
- switch (factionChangeInfo.Race)
- {
- case RACE_ORC:
- case RACE_TAUREN:
- case RACE_UNDEAD_PLAYER:
- case RACE_TROLL:
- case RACE_BLOODELF:
- team = TEAM_HORDE;
- break;
- default:
- break;
- }
+ sWorld->UpdateCharacterInfo(factionChangeInfo->Guid, factionChangeInfo->Name, factionChangeInfo->Gender, factionChangeInfo->Race);
+ if (oldRace != factionChangeInfo->Race)
+ {
// Switch Languages
// delete all languages first
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_SKILL_LANGUAGES);
@@ -1747,7 +1725,7 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData)
stmt->setUInt32(0, lowGuid);
// Faction specific languages
- if (team == TEAM_HORDE)
+ if (newTeam == HORDE)
stmt->setUInt16(1, 109);
else
stmt->setUInt16(1, 98);
@@ -1755,12 +1733,12 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData)
trans->Append(stmt);
// Race specific languages
- if (factionChangeInfo.Race != RACE_ORC && factionChangeInfo.Race != RACE_HUMAN)
+ if (factionChangeInfo->Race != RACE_ORC && factionChangeInfo->Race != RACE_HUMAN)
{
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_SKILL_LANGUAGE);
stmt->setUInt32(0, lowGuid);
- switch (factionChangeInfo.Race)
+ switch (factionChangeInfo->Race)
{
case RACE_DWARF:
stmt->setUInt16(1, 111);
@@ -1791,7 +1769,7 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData)
trans->Append(stmt);
}
- if (recvData.GetOpcode() == CMSG_CHAR_FACTION_CHANGE)
+ if (factionChangeInfo->FactionChange)
{
// Delete all Flypaths
stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_TAXI_PATH);
@@ -1806,41 +1784,21 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData)
uint32 numFullTaximasks = level / 7;
if (numFullTaximasks > 11)
numFullTaximasks = 11;
- if (team == TEAM_ALLIANCE)
- {
- if (playerClass != CLASS_DEATH_KNIGHT)
- {
- for (uint8 i = 0; i < numFullTaximasks; ++i)
- taximaskstream << uint32(sAllianceTaxiNodesMask[i]) << ' ';
- }
- else
- {
- for (uint8 i = 0; i < numFullTaximasks; ++i)
- taximaskstream << uint32(sAllianceTaxiNodesMask[i] | sDeathKnightTaxiNodesMask[i]) << ' ';
- }
- }
- else
+
+ TaxiMask const& factionMask = newTeam == HORDE ? sHordeTaxiNodesMask : sAllianceTaxiNodesMask;
+ for (uint8 i = 0; i < numFullTaximasks; ++i)
{
- if (playerClass != CLASS_DEATH_KNIGHT)
- {
- for (uint8 i = 0; i < numFullTaximasks; ++i)
- taximaskstream << uint32(sHordeTaxiNodesMask[i]) << ' ';
- }
- else
- {
- for (uint8 i = 0; i < numFullTaximasks; ++i)
- taximaskstream << uint32(sHordeTaxiNodesMask[i] | sDeathKnightTaxiNodesMask[i]) << ' ';
- }
+ uint8 deathKnightExtraNode = (playerClass == CLASS_DEATH_KNIGHT) ? sDeathKnightTaxiNodesMask[i] : 0;
+ taximaskstream << uint32(factionMask[i] | deathKnightExtraNode) << ' ';
}
uint32 numEmptyTaximasks = 11 - numFullTaximasks;
for (uint8 i = 0; i < numEmptyTaximasks; ++i)
taximaskstream << "0 ";
taximaskstream << '0';
- std::string taximask = taximaskstream.str();
stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_TAXIMASK);
- stmt->setString(0, taximask);
+ stmt->setString(0, taximaskstream.str());
stmt->setUInt32(1, lowGuid);
trans->Append(stmt);
}
@@ -1853,9 +1811,9 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData)
stmt->setUInt32(0, lowGuid);
if (PreparedQueryResult result = CharacterDatabase.Query(stmt))
if (Guild* guild = sGuildMgr->GetGuildById((result->Fetch()[0]).GetUInt32()))
- guild->DeleteMember(trans, factionChangeInfo.Guid, false, false, true);
+ guild->DeleteMember(trans, factionChangeInfo->Guid, false, false, true);
- Player::LeaveAllArenaTeams(factionChangeInfo.Guid);
+ Player::LeaveAllArenaTeams(factionChangeInfo->Guid);
}
if (!HasPermission(rbac::RBAC_PERM_TWO_SIDE_ADD_FRIEND))
@@ -1880,7 +1838,7 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData)
WorldLocation loc;
uint16 zoneId = 0;
- if (team == TEAM_ALLIANCE)
+ if (newTeam == ALLIANCE)
{
loc.WorldRelocate(0, -8867.68f, 673.373f, 97.9034f, 0.0f);
zoneId = 1519;
@@ -1898,7 +1856,7 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData)
stmt->setFloat(5, loc.GetPositionZ());
trans->Append(stmt);
- Player::SavePositionInDB(loc, zoneId, factionChangeInfo.Guid, trans);
+ Player::SavePositionInDB(loc, zoneId, factionChangeInfo->Guid, trans);
// Achievement conversion
for (std::map<uint32, uint32>::const_iterator it = sObjectMgr->FactionChangeAchievements.begin(); it != sObjectMgr->FactionChangeAchievements.end(); ++it)
@@ -1907,13 +1865,13 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData)
uint32 achiev_horde = it->second;
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_ACHIEVEMENT_BY_ACHIEVEMENT);
- stmt->setUInt16(0, uint16(team == TEAM_ALLIANCE ? achiev_alliance : achiev_horde));
+ stmt->setUInt16(0, uint16(newTeam == ALLIANCE ? achiev_alliance : achiev_horde));
stmt->setUInt32(1, lowGuid);
trans->Append(stmt);
stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_ACHIEVEMENT);
- stmt->setUInt16(0, uint16(team == TEAM_ALLIANCE ? achiev_alliance : achiev_horde));
- stmt->setUInt16(1, uint16(team == TEAM_ALLIANCE ? achiev_horde : achiev_alliance));
+ stmt->setUInt16(0, uint16(newTeam == ALLIANCE ? achiev_alliance : achiev_horde));
+ stmt->setUInt16(1, uint16(newTeam == ALLIANCE ? achiev_horde : achiev_alliance));
stmt->setUInt32(2, lowGuid);
trans->Append(stmt);
}
@@ -1925,8 +1883,8 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData)
uint32 item_horde = it->second;
stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_INVENTORY_FACTION_CHANGE);
- stmt->setUInt32(0, (team == TEAM_ALLIANCE ? item_alliance : item_horde));
- stmt->setUInt32(1, (team == TEAM_ALLIANCE ? item_horde : item_alliance));
+ stmt->setUInt32(0, (newTeam == ALLIANCE ? item_alliance : item_horde));
+ stmt->setUInt32(1, (newTeam == ALLIANCE ? item_horde : item_alliance));
stmt->setUInt32(2, lowGuid);
trans->Append(stmt);
}
@@ -1944,12 +1902,12 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData)
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_QUESTSTATUS_REWARDED_BY_QUEST);
stmt->setUInt32(0, lowGuid);
- stmt->setUInt32(1, (team == TEAM_ALLIANCE ? quest_alliance : quest_horde));
+ stmt->setUInt32(1, (newTeam == ALLIANCE ? quest_alliance : quest_horde));
trans->Append(stmt);
stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_QUESTSTATUS_REWARDED_FACTION_CHANGE);
- stmt->setUInt32(0, (team == TEAM_ALLIANCE ? quest_alliance : quest_horde));
- stmt->setUInt32(1, (team == TEAM_ALLIANCE ? quest_horde : quest_alliance));
+ stmt->setUInt32(0, (newTeam == ALLIANCE ? quest_alliance : quest_horde));
+ stmt->setUInt32(1, (newTeam == ALLIANCE ? quest_horde : quest_alliance));
stmt->setUInt32(2, lowGuid);
trans->Append(stmt);
}
@@ -1965,7 +1923,7 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData)
for (ObjectMgr::QuestMap::const_iterator iter = questTemplates.begin(); iter != questTemplates.end(); ++iter)
{
Quest const* quest = iter->second;
- uint32 newRaceMask = (team == TEAM_ALLIANCE) ? RACEMASK_ALLIANCE : RACEMASK_HORDE;
+ uint32 newRaceMask = (newTeam == ALLIANCE) ? RACEMASK_ALLIANCE : RACEMASK_HORDE;
if (!(quest->GetAllowableRaces() & newRaceMask))
{
stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_QUESTSTATUS_REWARDED_ACTIVE_BY_QUEST);
@@ -1983,13 +1941,13 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData)
uint32 spell_horde = it->second;
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_SPELL_BY_SPELL);
- stmt->setUInt32(0, (team == TEAM_ALLIANCE ? spell_alliance : spell_horde));
+ stmt->setUInt32(0, (newTeam == ALLIANCE ? spell_alliance : spell_horde));
stmt->setUInt32(1, lowGuid);
trans->Append(stmt);
stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_SPELL_FACTION_CHANGE);
- stmt->setUInt32(0, (team == TEAM_ALLIANCE ? spell_alliance : spell_horde));
- stmt->setUInt32(1, (team == TEAM_ALLIANCE ? spell_horde : spell_alliance));
+ stmt->setUInt32(0, (newTeam == ALLIANCE ? spell_alliance : spell_horde));
+ stmt->setUInt32(1, (newTeam == ALLIANCE ? spell_horde : spell_alliance));
stmt->setUInt32(2, lowGuid);
trans->Append(stmt);
}
@@ -1999,8 +1957,8 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData)
{
uint32 reputation_alliance = it->first;
uint32 reputation_horde = it->second;
- uint32 newReputation = (team == TEAM_ALLIANCE) ? reputation_alliance : reputation_horde;
- uint32 oldReputation = (team == TEAM_ALLIANCE) ? reputation_horde : reputation_alliance;
+ uint32 newReputation = (newTeam == ALLIANCE) ? reputation_alliance : reputation_horde;
+ uint32 oldReputation = (newTeam == ALLIANCE) ? reputation_horde : reputation_alliance;
// select old standing set in db
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_REP_BY_FACTION);
@@ -2017,7 +1975,7 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData)
int32 oldBaseRep = sObjectMgr->GetBaseReputationOf(factionEntry, oldRace, playerClass);
// new base reputation
- int32 newBaseRep = sObjectMgr->GetBaseReputationOf(sFactionStore.LookupEntry(newReputation), factionChangeInfo.Race, playerClass);
+ int32 newBaseRep = sObjectMgr->GetBaseReputationOf(sFactionStore.LookupEntry(newReputation), factionChangeInfo->Race, playerClass);
// final reputation shouldnt change
int32 FinalRep = oldDBRep + oldBaseRep;
@@ -2040,13 +1998,13 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData)
// Title conversion
if (!knownTitlesStr.empty())
{
- const uint32 ktcount = KNOWN_TITLES_SIZE * 2;
+ uint32 const ktcount = KNOWN_TITLES_SIZE * 2;
uint32 knownTitles[ktcount];
Tokenizer tokens(knownTitlesStr, ' ', ktcount);
if (tokens.size() != ktcount)
{
- SendCharFactionChange(CHAR_CREATE_ERROR, factionChangeInfo);
+ SendCharFactionChange(CHAR_CREATE_ERROR, factionChangeInfo.get());
return;
}
@@ -2061,7 +2019,7 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData)
CharTitlesEntry const* atitleInfo = sCharTitlesStore.LookupEntry(title_alliance);
CharTitlesEntry const* htitleInfo = sCharTitlesStore.LookupEntry(title_horde);
// new team
- if (team == TEAM_ALLIANCE)
+ if (newTeam == ALLIANCE)
{
uint32 bitIndex = htitleInfo->bit_index;
uint32 index = bitIndex / 32;
@@ -2108,9 +2066,9 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData)
CharacterDatabase.CommitTransaction(trans);
- TC_LOG_DEBUG("entities.player", "%s (IP: %s) changed race from %u to %u", GetPlayerInfo().c_str(), GetRemoteAddress().c_str(), oldRace, factionChangeInfo.Race);
+ TC_LOG_DEBUG("entities.player", "%s (IP: %s) changed race from %u to %u", GetPlayerInfo().c_str(), GetRemoteAddress().c_str(), oldRace, factionChangeInfo->Race);
- SendCharFactionChange(RESPONSE_SUCCESS, factionChangeInfo);
+ SendCharFactionChange(RESPONSE_SUCCESS, factionChangeInfo.get());
}
void WorldSession::SendCharCreate(ResponseCodes result)
@@ -2127,51 +2085,51 @@ void WorldSession::SendCharDelete(ResponseCodes result)
SendPacket(&data);
}
-void WorldSession::SendCharRename(ResponseCodes result, CharacterRenameInfo const& renameInfo)
+void WorldSession::SendCharRename(ResponseCodes result, CharacterRenameInfo const* renameInfo)
{
- WorldPacket data(SMSG_CHAR_RENAME, 1 + 8 + renameInfo.Name.size() + 1);
+ WorldPacket data(SMSG_CHAR_RENAME, 1 + 8 + renameInfo->Name.size() + 1);
data << uint8(result);
if (result == RESPONSE_SUCCESS)
{
- data << renameInfo.Guid;
- data << renameInfo.Name;
+ data << renameInfo->Guid;
+ data << renameInfo->Name;
}
SendPacket(&data);
}
-void WorldSession::SendCharCustomize(ResponseCodes result, CharacterCustomizeInfo const& customizeInfo)
+void WorldSession::SendCharCustomize(ResponseCodes result, CharacterCustomizeInfo const* customizeInfo)
{
- WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1 + 8 + customizeInfo.Name.size() + 1 + 6);
+ WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1 + 8 + customizeInfo->Name.size() + 1 + 6);
data << uint8(result);
if (result == RESPONSE_SUCCESS)
{
- data << customizeInfo.Guid;
- data << customizeInfo.Name;
- data << uint8(customizeInfo.Gender);
- data << uint8(customizeInfo.Skin);
- data << uint8(customizeInfo.Face);
- data << uint8(customizeInfo.HairStyle);
- data << uint8(customizeInfo.HairColor);
- data << uint8(customizeInfo.FacialHair);
+ data << customizeInfo->Guid;
+ data << customizeInfo->Name;
+ data << uint8(customizeInfo->Gender);
+ data << uint8(customizeInfo->Skin);
+ data << uint8(customizeInfo->Face);
+ data << uint8(customizeInfo->HairStyle);
+ data << uint8(customizeInfo->HairColor);
+ data << uint8(customizeInfo->FacialHair);
}
SendPacket(&data);
}
-void WorldSession::SendCharFactionChange(ResponseCodes result, CharacterFactionChangeInfo const& factionChangeInfo)
+void WorldSession::SendCharFactionChange(ResponseCodes result, CharacterFactionChangeInfo const* factionChangeInfo)
{
- WorldPacket data(SMSG_CHAR_FACTION_CHANGE, 1 + 8 + factionChangeInfo.Name.size() + 1 + 7);
+ WorldPacket data(SMSG_CHAR_FACTION_CHANGE, 1 + 8 + factionChangeInfo->Name.size() + 1 + 7);
data << uint8(result);
if (result == RESPONSE_SUCCESS)
{
- data << factionChangeInfo.Guid;
- data << factionChangeInfo.Name;
- data << uint8(factionChangeInfo.Gender);
- data << uint8(factionChangeInfo.Skin);
- data << uint8(factionChangeInfo.Face);
- data << uint8(factionChangeInfo.HairStyle);
- data << uint8(factionChangeInfo.HairColor);
- data << uint8(factionChangeInfo.FacialHair);
- data << uint8(factionChangeInfo.Race);
+ data << factionChangeInfo->Guid;
+ data << factionChangeInfo->Name;
+ data << uint8(factionChangeInfo->Gender);
+ data << uint8(factionChangeInfo->Skin);
+ data << uint8(factionChangeInfo->Face);
+ data << uint8(factionChangeInfo->HairStyle);
+ data << uint8(factionChangeInfo->HairColor);
+ data << uint8(factionChangeInfo->FacialHair);
+ data << uint8(factionChangeInfo->Race);
}
SendPacket(&data);
}
diff --git a/src/server/game/Handlers/NPCHandler.cpp b/src/server/game/Handlers/NPCHandler.cpp
index 7290acdbe43..055ad830f7b 100644
--- a/src/server/game/Handlers/NPCHandler.cpp
+++ b/src/server/game/Handlers/NPCHandler.cpp
@@ -19,6 +19,7 @@
#include "Common.h"
#include "Language.h"
#include "DatabaseEnv.h"
+#include "QueryCallback.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "Opcodes.h"
@@ -469,11 +470,10 @@ void WorldSession::SendStablePet(ObjectGuid guid)
stmt->setUInt8(1, PET_SAVE_FIRST_STABLE_SLOT);
stmt->setUInt8(2, PET_SAVE_LAST_STABLE_SLOT);
- _sendStabledPetCallback.SetParam(guid);
- _sendStabledPetCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt));
+ _queryProcessor.AddQuery(CharacterDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSession::SendStablePetCallback, this, guid, std::placeholders::_1)));
}
-void WorldSession::SendStablePetCallback(PreparedQueryResult result, ObjectGuid guid)
+void WorldSession::SendStablePetCallback(ObjectGuid guid, PreparedQueryResult result)
{
if (!GetPlayer())
return;
@@ -571,7 +571,7 @@ void WorldSession::HandleStablePet(WorldPacket& recvData)
stmt->setUInt8(1, PET_SAVE_FIRST_STABLE_SLOT);
stmt->setUInt8(2, PET_SAVE_LAST_STABLE_SLOT);
- _stablePetCallback = CharacterDatabase.AsyncQuery(stmt);
+ _queryProcessor.AddQuery(CharacterDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSession::HandleStablePetCallback, this, std::placeholders::_1)));
}
void WorldSession::HandleStablePetCallback(PreparedQueryResult result)
@@ -633,11 +633,10 @@ void WorldSession::HandleUnstablePet(WorldPacket& recvData)
stmt->setUInt8(2, PET_SAVE_FIRST_STABLE_SLOT);
stmt->setUInt8(3, PET_SAVE_LAST_STABLE_SLOT);
- _unstablePetCallback.SetParam(petnumber);
- _unstablePetCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt));
+ _queryProcessor.AddQuery(CharacterDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSession::HandleUnstablePetCallback, this, petnumber, std::placeholders::_1)));
}
-void WorldSession::HandleUnstablePetCallback(PreparedQueryResult result, uint32 petId)
+void WorldSession::HandleUnstablePetCallback(uint32 petId, PreparedQueryResult result)
{
if (!GetPlayer())
return;
@@ -760,11 +759,10 @@ void WorldSession::HandleStableSwapPet(WorldPacket& recvData)
stmt->setUInt32(0, _player->GetGUID().GetCounter());
stmt->setUInt32(1, petId);
- _stableSwapCallback.SetParam(petId);
- _stableSwapCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt));
+ _queryProcessor.AddQuery(CharacterDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSession::HandleStableSwapPetCallback, this, petId, std::placeholders::_1)));
}
-void WorldSession::HandleStableSwapPetCallback(PreparedQueryResult result, uint32 petId)
+void WorldSession::HandleStableSwapPetCallback(uint32 petId, PreparedQueryResult result)
{
if (!GetPlayer())
return;
diff --git a/src/server/game/Handlers/SocialHandler.cpp b/src/server/game/Handlers/SocialHandler.cpp
index cd9968bf84e..2b13cfdbd9b 100644
--- a/src/server/game/Handlers/SocialHandler.cpp
+++ b/src/server/game/Handlers/SocialHandler.cpp
@@ -18,6 +18,7 @@
#include "WorldSession.h"
#include "Player.h"
+#include "QueryCallback.h"
#include "SocialMgr.h"
#include "ObjectMgr.h"
@@ -42,11 +43,11 @@ void WorldSession::HandleAddFriendOpcode(WorldPacket& recvData)
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUID_RACE_ACC_BY_NAME);
stmt->setString(0, friendName);
- _addFriendCallback.SetParam(friendNote);
- _addFriendCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt));
+ _queryProcessor.AddQuery(CharacterDatabase.AsyncQuery(stmt)
+ .WithPreparedCallback(std::bind(&WorldSession::HandleAddFriendOpcodeCallback, this, std::move(friendNote), std::placeholders::_1)));
}
-void WorldSession::HandleAddFriendOpcodeCallback(PreparedQueryResult result, std::string const& friendNote)
+void WorldSession::HandleAddFriendOpcodeCallback(std::string const& friendNote, PreparedQueryResult result)
{
if (!GetPlayer())
return;
@@ -116,7 +117,7 @@ void WorldSession::HandleAddIgnoreOpcode(WorldPacket& recvData)
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUID_BY_NAME);
stmt->setString(0, ignoreName);
- _addIgnoreCallback = CharacterDatabase.AsyncQuery(stmt);
+ _queryProcessor.AddQuery(CharacterDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSession::HandleAddIgnoreOpcodeCallback, this, std::placeholders::_1)));
}
void WorldSession::HandleAddIgnoreOpcodeCallback(PreparedQueryResult result)
diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp
index a7dc3685171..4664d2efb8f 100644
--- a/src/server/game/Server/WorldSession.cpp
+++ b/src/server/game/Server/WorldSession.cpp
@@ -24,6 +24,7 @@
#include "Config.h"
#include "Common.h"
#include "DatabaseEnv.h"
+#include "QueryCallback.h"
#include "AccountMgr.h"
#include "Log.h"
#include "Opcodes.h"
@@ -137,7 +138,6 @@ WorldSession::WorldSession(uint32 id, std::string&& name, std::shared_ptr<WorldS
LoginDatabase.PExecute("UPDATE account SET online = 1 WHERE id = %u;", GetAccountId()); // One-time query
}
- InitializeQueryCallbackParameters();
}
/// WorldSession destructor
@@ -1085,99 +1085,16 @@ void WorldSession::SetPlayer(Player* player)
m_GUIDLow = _player->GetGUID().GetCounter();
}
-void WorldSession::InitializeQueryCallbackParameters()
-{
- // Callback parameters that have pointers in them should be properly
- // initialized to NULL here.
- _charCreateCallback.SetParam(NULL);
-}
-
void WorldSession::ProcessQueryCallbacks()
{
- PreparedQueryResult result;
+ _queryProcessor.ProcessReadyQueries();
if (_realmAccountLoginCallback.valid() && _realmAccountLoginCallback.wait_for(std::chrono::seconds(0)) == std::future_status::ready)
InitializeSessionCallback(_realmAccountLoginCallback.get());
- //! HandleCharEnumOpcode
- if (_charEnumCallback.valid() && _charEnumCallback.wait_for(std::chrono::seconds(0)) == std::future_status::ready)
- {
- result = _charEnumCallback.get();
- HandleCharEnum(result);
- }
-
- if (_charCreateCallback.IsReady())
- {
- _charCreateCallback.GetResult(result);
- HandleCharCreateCallback(result, _charCreateCallback.GetParam());
- }
-
//! HandlePlayerLoginOpcode
if (_charLoginCallback.valid() && _charLoginCallback.wait_for(std::chrono::seconds(0)) == std::future_status::ready)
- {
- SQLQueryHolder* param = _charLoginCallback.get();
- HandlePlayerLogin((LoginQueryHolder*)param);
- }
-
- //! HandleAddFriendOpcode
- if (_addFriendCallback.IsReady())
- {
- std::string param = _addFriendCallback.GetParam();
- _addFriendCallback.GetResult(result);
- HandleAddFriendOpcodeCallback(result, param);
- _addFriendCallback.FreeResult();
- }
-
- //- HandleCharRenameOpcode
- if (_charRenameCallback.IsReady())
- {
- _charRenameCallback.GetResult(result);
- CharacterRenameInfo* renameInfo = _charRenameCallback.GetParam();
- HandleChangePlayerNameOpcodeCallBack(result, renameInfo);
- delete renameInfo;
- _charRenameCallback.Reset();
- }
-
- //- HandleCharAddIgnoreOpcode
- if (_addIgnoreCallback.valid() && _addIgnoreCallback.wait_for(std::chrono::seconds(0)) == std::future_status::ready)
- {
- result = _addIgnoreCallback.get();
- HandleAddIgnoreOpcodeCallback(result);
- }
-
- //- SendStabledPet
- if (_sendStabledPetCallback.IsReady())
- {
- ObjectGuid param = _sendStabledPetCallback.GetParam();
- _sendStabledPetCallback.GetResult(result);
- SendStablePetCallback(result, param);
- _sendStabledPetCallback.FreeResult();
- }
-
- //- HandleStablePet
- if (_stablePetCallback.valid() && _stablePetCallback.wait_for(std::chrono::seconds(0)) == std::future_status::ready)
- {
- result = _stablePetCallback.get();
- HandleStablePetCallback(result);
- }
-
- //- HandleUnstablePet
- if (_unstablePetCallback.IsReady())
- {
- uint32 param = _unstablePetCallback.GetParam();
- _unstablePetCallback.GetResult(result);
- HandleUnstablePetCallback(result, param);
- _unstablePetCallback.FreeResult();
- }
-
- //- HandleStableSwapPet
- if (_stableSwapCallback.IsReady())
- {
- uint32 param = _stableSwapCallback.GetParam();
- _stableSwapCallback.GetResult(result);
- HandleStableSwapPetCallback(result, param);
- _stableSwapCallback.FreeResult();
- }
+ HandlePlayerLogin(reinterpret_cast<LoginQueryHolder*>(_charLoginCallback.get()));
}
void WorldSession::InitWarden(BigNumber* k, std::string const& os)
@@ -1204,7 +1121,7 @@ void WorldSession::LoadPermissions()
_RBACData->LoadFromDB();
}
-PreparedQueryResultFuture WorldSession::LoadPermissionsAsync()
+QueryCallback WorldSession::LoadPermissionsAsync()
{
uint32 id = GetAccountId();
uint8 secLevel = GetSecurity();
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index d4320923a59..a95aa75cccf 100644
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -239,6 +239,7 @@ struct CharacterFactionChangeInfo : public CharacterCustomizeInfo
protected:
uint8 Race = 0;
+ bool FactionChange = false;
};
struct PacketCounter
@@ -284,7 +285,7 @@ class TC_GAME_API WorldSession
rbac::RBACData* GetRBACData();
bool HasPermission(uint32 permissionId);
void LoadPermissions();
- PreparedQueryResultFuture LoadPermissionsAsync();
+ QueryCallback LoadPermissionsAsync();
void InvalidateRBACData(); // Used to force LoadPermissions at next HasPermission check
AccountTypes GetSecurity() const { return _security; }
@@ -356,7 +357,7 @@ class TC_GAME_API WorldSession
// Pet
void SendPetNameQuery(ObjectGuid guid, uint32 petnumber);
void SendStablePet(ObjectGuid guid);
- void SendStablePetCallback(PreparedQueryResult result, ObjectGuid guid);
+ void SendStablePetCallback(ObjectGuid guid, PreparedQueryResult result);
void SendStableResult(uint8 guid);
bool CheckStableMaster(ObjectGuid guid);
@@ -449,16 +450,23 @@ class TC_GAME_API WorldSession
void HandleCharEnumOpcode(WorldPacket& recvPacket);
void HandleCharDeleteOpcode(WorldPacket& recvPacket);
void HandleCharCreateOpcode(WorldPacket& recvPacket);
- void HandleCharCreateCallback(PreparedQueryResult result, CharacterCreateInfo* createInfo);
void HandlePlayerLoginOpcode(WorldPacket& recvPacket);
void HandleCharEnum(PreparedQueryResult result);
- void HandlePlayerLogin(LoginQueryHolder * holder);
+ void HandlePlayerLogin(LoginQueryHolder* holder);
void HandleCharFactionOrRaceChange(WorldPacket& recvData);
+ void HandleCharFactionOrRaceChangeCallback(std::shared_ptr<CharacterFactionChangeInfo> factionChangeInfo, PreparedQueryResult result);
+ void HandleCharRenameOpcode(WorldPacket& recvData);
+ void HandleCharRenameCallback(std::shared_ptr<CharacterRenameInfo> renameInfo, PreparedQueryResult result);
+ void HandleSetPlayerDeclinedNames(WorldPacket& recvData);
+ void HandleAlterAppearance(WorldPacket& recvData);
+ void HandleCharCustomize(WorldPacket& recvData);
+ void HandleCharCustomizeCallback(std::shared_ptr<CharacterCustomizeInfo> customizeInfo, PreparedQueryResult result);
+
void SendCharCreate(ResponseCodes result);
void SendCharDelete(ResponseCodes result);
- void SendCharRename(ResponseCodes result, CharacterRenameInfo const& renameInfo);
- void SendCharCustomize(ResponseCodes result, CharacterCustomizeInfo const& customizeInfo);
- void SendCharFactionChange(ResponseCodes result, CharacterFactionChangeInfo const& factionChangeInfo);
+ void SendCharRename(ResponseCodes result, CharacterRenameInfo const* renameInfo);
+ void SendCharCustomize(ResponseCodes result, CharacterCustomizeInfo const* customizeInfo);
+ void SendCharFactionChange(ResponseCodes result, CharacterFactionChangeInfo const* factionChangeInfo);
void SendSetPlayerDeclinedNamesResult(DeclinedNameResult result, ObjectGuid guid);
void SendBarberShopResult(BarberShopResult result);
@@ -528,7 +536,7 @@ class TC_GAME_API WorldSession
// Social
void HandleContactListOpcode(WorldPacket& recvPacket);
void HandleAddFriendOpcode(WorldPacket& recvPacket);
- void HandleAddFriendOpcodeCallback(PreparedQueryResult result, std::string const& friendNote);
+ void HandleAddFriendOpcodeCallback(std::string const& friendNote, PreparedQueryResult result);
void HandleDelFriendOpcode(WorldPacket& recvPacket);
void HandleAddIgnoreOpcode(WorldPacket& recvPacket);
void HandleAddIgnoreOpcodeCallback(PreparedQueryResult result);
@@ -651,11 +659,11 @@ class TC_GAME_API WorldSession
void HandleStablePet(WorldPacket& recvPacket);
void HandleStablePetCallback(PreparedQueryResult result);
void HandleUnstablePet(WorldPacket& recvPacket);
- void HandleUnstablePetCallback(PreparedQueryResult result, uint32 petId);
+ void HandleUnstablePetCallback(uint32 petId, PreparedQueryResult result);
void HandleBuyStableSlot(WorldPacket& recvPacket);
void HandleStableRevivePet(WorldPacket& recvPacket);
void HandleStableSwapPet(WorldPacket& recvPacket);
- void HandleStableSwapPetCallback(PreparedQueryResult result, uint32 petId);
+ void HandleStableSwapPetCallback(uint32 petId, PreparedQueryResult result);
void HandleDuelAcceptedOpcode(WorldPacket& recvPacket);
void HandleDuelCancelledOpcode(WorldPacket& recvPacket);
@@ -805,10 +813,6 @@ class TC_GAME_API WorldSession
void HandleSetActionBarToggles(WorldPacket& recvData);
- void HandleCharRenameOpcode(WorldPacket& recvData);
- void HandleChangePlayerNameOpcodeCallBack(PreparedQueryResult result, CharacterRenameInfo const* renameInfo);
- void HandleSetPlayerDeclinedNames(WorldPacket& recvData);
-
void HandleTotemDestroyed(WorldPacket& recvData);
void HandleDismissCritter(WorldPacket& recvData);
@@ -952,9 +956,7 @@ class TC_GAME_API WorldSession
void HandleSpellClick(WorldPacket& recvData);
void HandleMirrorImageDataRequest(WorldPacket& recvData);
- void HandleAlterAppearance(WorldPacket& recvData);
void HandleRemoveGlyph(WorldPacket& recvData);
- void HandleCharCustomize(WorldPacket& recvData);
void HandleQueryInspectAchievements(WorldPacket& recvData);
void HandleEquipmentSetSave(WorldPacket& recvData);
void HandleEquipmentSetDelete(WorldPacket& recvData);
@@ -969,21 +971,13 @@ class TC_GAME_API WorldSession
void HandleUpdateMissileTrajectory(WorldPacket& recvPacket);
private:
- void InitializeQueryCallbackParameters();
void ProcessQueryCallbacks();
QueryResultHolderFuture _realmAccountLoginCallback;
- PreparedQueryResultFuture _charEnumCallback;
- PreparedQueryResultFuture _addIgnoreCallback;
- PreparedQueryResultFuture _stablePetCallback;
- QueryCallback<PreparedQueryResult, CharacterRenameInfo*> _charRenameCallback;
- QueryCallback<PreparedQueryResult, std::string> _addFriendCallback;
- QueryCallback<PreparedQueryResult, uint32> _unstablePetCallback;
- QueryCallback<PreparedQueryResult, uint32> _stableSwapCallback;
- QueryCallback<PreparedQueryResult, ObjectGuid> _sendStabledPetCallback;
- QueryCallback<PreparedQueryResult, CharacterCreateInfo*, true> _charCreateCallback;
QueryResultHolderFuture _charLoginCallback;
+ QueryCallbackProcessor _queryProcessor;
+
friend class World;
protected:
class DosProtection
diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp
index fae31751358..08fb36dafb5 100644
--- a/src/server/game/Server/WorldSocket.cpp
+++ b/src/server/game/Server/WorldSocket.cpp
@@ -19,6 +19,7 @@
#include "WorldSocket.h"
#include "BigNumber.h"
#include "Opcodes.h"
+#include "QueryCallback.h"
#include "ScriptMgr.h"
#include "SHA1.h"
#include "PacketLog.h"
@@ -51,8 +52,7 @@ void WorldSocket::Start()
stmt->setString(0, ip_address);
stmt->setUInt32(1, inet_addr(ip_address.c_str()));
- _queryCallback = std::bind(&WorldSocket::CheckIpCallback, this, std::placeholders::_1);
- _queryFuture = LoginDatabase.AsyncQuery(stmt);
+ _queryProcessor.AddQuery(LoginDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSocket::CheckIpCallback, this, std::placeholders::_1)));
}
void WorldSocket::CheckIpCallback(PreparedQueryResult result)
@@ -125,12 +125,7 @@ bool WorldSocket::Update()
if (!BaseSocket::Update())
return false;
- if (_queryFuture.valid() && _queryFuture.wait_for(std::chrono::seconds(0)) == std::future_status::ready)
- {
- auto callback = _queryCallback;
- _queryCallback = nullptr;
- callback(_queryFuture.get());
- }
+ _queryProcessor.ProcessReadyQueries();
return true;
}
@@ -444,8 +439,7 @@ void WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
stmt->setInt32(0, int32(realm.Id.Realm));
stmt->setString(1, authSession->Account);
- _queryCallback = std::bind(&WorldSocket::HandleAuthSessionCallback, this, authSession, std::placeholders::_1);
- _queryFuture = LoginDatabase.AsyncQuery(stmt);
+ _queryProcessor.AddQuery(LoginDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSocket::HandleAuthSessionCallback, this, authSession, std::placeholders::_1)));
}
void WorldSocket::HandleAuthSessionCallback(std::shared_ptr<AuthSession> authSession, PreparedQueryResult result)
@@ -603,8 +597,7 @@ void WorldSocket::HandleAuthSessionCallback(std::shared_ptr<AuthSession> authSes
if (wardenActive)
_worldSession->InitWarden(&account.SessionKey, account.OS);
- _queryCallback = std::bind(&WorldSocket::LoadSessionPermissionsCallback, this, std::placeholders::_1);
- _queryFuture = _worldSession->LoadPermissionsAsync();
+ _queryProcessor.AddQuery(_worldSession->LoadPermissionsAsync().WithPreparedCallback(std::bind(&WorldSocket::LoadSessionPermissionsCallback, this, std::placeholders::_1)));
AsyncRead();
}
diff --git a/src/server/game/Server/WorldSocket.h b/src/server/game/Server/WorldSocket.h
index b5f2dee2006..36ce6528beb 100644
--- a/src/server/game/Server/WorldSocket.h
+++ b/src/server/game/Server/WorldSocket.h
@@ -111,8 +111,7 @@ private:
MessageBuffer _packetBuffer;
MPSCQueue<EncryptablePacket> _bufferQueue;
- PreparedQueryResultFuture _queryFuture;
- std::function<void(PreparedQueryResult&&)> _queryCallback;
+ QueryCallbackProcessor _queryProcessor;
std::string _ipCountry;
};
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index e4e09935970..363e0284632 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -39,6 +39,7 @@
#include "DisableMgr.h"
#include "GameEventMgr.h"
#include "GameObjectModel.h"
+#include "GitRevision.h"
#include "GridNotifiersImpl.h"
#include "GroupMgr.h"
#include "GuildMgr.h"
@@ -52,7 +53,7 @@
#include "OutdoorPvPMgr.h"
#include "Player.h"
#include "PoolMgr.h"
-#include "GitRevision.h"
+#include "QueryCallback.h"
#include "ScriptMgr.h"
#include "ScriptReloadMgr.h"
#include "SkillDiscovery.h"
@@ -2909,7 +2910,7 @@ void World::UpdateRealmCharCount(uint32 accountId)
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_COUNT);
stmt->setUInt32(0, accountId);
- m_realmCharCallbacks.push_back(CharacterDatabase.AsyncQuery(stmt));
+ _queryProcessor.AddQuery(CharacterDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&World::_UpdateRealmCharCount, this, std::placeholders::_1)));
}
void World::_UpdateRealmCharCount(PreparedQueryResult resultCharCount)
@@ -3271,20 +3272,7 @@ uint64 World::getWorldState(uint32 index) const
void World::ProcessQueryCallbacks()
{
- PreparedQueryResult result;
-
- for (std::deque<std::future<PreparedQueryResult>>::iterator itr = m_realmCharCallbacks.begin(); itr != m_realmCharCallbacks.end(); )
- {
- if ((*itr).wait_for(std::chrono::seconds(0)) != std::future_status::ready)
- {
- ++itr;
- continue;
- }
-
- result = (*itr).get();
- _UpdateRealmCharCount(result);
- itr = m_realmCharCallbacks.erase(itr);
- }
+ _queryProcessor.ProcessReadyQueries();
}
CharacterInfo const* World::GetCharacterInfo(ObjectGuid const& guid) const
diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h
index 77e06f62a53..87f5c9415b8 100644
--- a/src/server/game/World/World.h
+++ b/src/server/game/World/World.h
@@ -28,7 +28,7 @@
#include "Timer.h"
#include "SharedDefines.h"
#include "QueryResult.h"
-#include "QueryCallback.h"
+#include "QueryCallbackProcessor.h"
#include "Realm/Realm.h"
#include <atomic>
@@ -882,7 +882,7 @@ class TC_GAME_API World
void LoadCharacterInfoStore();
void ProcessQueryCallbacks();
- std::deque<std::future<PreparedQueryResult>> m_realmCharCallbacks;
+ QueryCallbackProcessor _queryProcessor;
};
TC_GAME_API extern Realm realm;