diff --git a/src/server/database/Database/Implementation/CharacterDatabase.cpp b/src/server/database/Database/Implementation/CharacterDatabase.cpp index 3e537d2da..749f46056 100644 --- a/src/server/database/Database/Implementation/CharacterDatabase.cpp +++ b/src/server/database/Database/Implementation/CharacterDatabase.cpp @@ -240,7 +240,7 @@ void CharacterDatabaseConnection::DoPrepareStatements() "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC); // Account data - PrepareStatement(CHAR_SEL_ACCOUNT_DATA, "SELECT type, time, data FROM account_data WHERE accountId = ?", CONNECTION_SYNCH); + PrepareStatement(CHAR_SEL_ACCOUNT_DATA, "SELECT type, time, data FROM account_data WHERE accountId = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_REP_ACCOUNT_DATA, "REPLACE INTO account_data (accountId, type, time, data) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC); PrepareStatement(CHAR_DEL_ACCOUNT_DATA, "DELETE FROM account_data WHERE accountId = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_SEL_PLAYER_ACCOUNT_DATA, "SELECT type, time, data FROM character_account_data WHERE guid = ?", CONNECTION_ASYNC); @@ -248,7 +248,7 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_DEL_PLAYER_ACCOUNT_DATA, "DELETE FROM character_account_data WHERE guid = ?", CONNECTION_ASYNC); // Tutorials - PrepareStatement(CHAR_SEL_TUTORIALS, "SELECT tut0, tut1, tut2, tut3, tut4, tut5, tut6, tut7 FROM account_tutorial WHERE accountId = ?", CONNECTION_SYNCH); + PrepareStatement(CHAR_SEL_TUTORIALS, "SELECT tut0, tut1, tut2, tut3, tut4, tut5, tut6, tut7 FROM account_tutorial WHERE accountId = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_SEL_HAS_TUTORIALS, "SELECT 1 FROM account_tutorial WHERE accountId = ?", CONNECTION_SYNCH); PrepareStatement(CHAR_INS_TUTORIALS, "INSERT INTO account_tutorial(tut0, tut1, tut2, tut3, tut4, tut5, tut6, tut7, accountId) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC); PrepareStatement(CHAR_UPD_TUTORIALS, "UPDATE account_tutorial SET tut0 = ?, tut1 = ?, tut2 = ?, tut3 = ?, tut4 = ?, tut5 = ?, tut6 = ?, tut7 = ? WHERE accountId = ?", CONNECTION_ASYNC); diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index a4453e5e1..b0b0d7df7 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -842,13 +842,6 @@ void WorldSession::SendAuthWaitQueue(uint32 position) } } -void WorldSession::LoadGlobalAccountData() -{ - CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_ACCOUNT_DATA); - stmt->SetData(0, GetAccountId()); - LoadAccountData(CharacterDatabase.Query(stmt), GLOBAL_CACHE_MASK); -} - void WorldSession::LoadAccountData(PreparedQueryResult result, uint32 mask) { for (uint32 i = 0; i < NUM_ACCOUNT_DATA_TYPES; ++i) @@ -921,15 +914,17 @@ void WorldSession::SendAccountDataTimes(uint32 mask) SendPacket(&data); } -void WorldSession::LoadTutorialsData() +void WorldSession::LoadTutorialsData(PreparedQueryResult result) { memset(m_Tutorials, 0, sizeof(uint32) * MAX_ACCOUNT_TUTORIAL_VALUES); - CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_TUTORIALS); - stmt->SetData(0, GetAccountId()); - if (PreparedQueryResult result = CharacterDatabase.Query(stmt)) + if (result) + { for (uint8 i = 0; i < MAX_ACCOUNT_TUTORIAL_VALUES; ++i) + { m_Tutorials[i] = (*result)[i].Get(); + } + } m_TutorialsChanged = false; } @@ -1627,3 +1622,72 @@ void WorldSession::SendTimeSync() _timeSyncTimer = _timeSyncNextCounter == 0 ? 5000 : 10000; _timeSyncNextCounter++; } + +class AccountInfoQueryHolderPerRealm : public CharacterDatabaseQueryHolder +{ +public: + enum + { + GLOBAL_ACCOUNT_DATA = 0, + TUTORIALS, + + MAX_QUERIES + }; + + AccountInfoQueryHolderPerRealm() { SetSize(MAX_QUERIES); } + + bool Initialize(uint32 accountId) + { + bool ok = true; + + CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_ACCOUNT_DATA); + stmt->SetData(0, accountId); + ok = SetPreparedQuery(GLOBAL_ACCOUNT_DATA, stmt) && ok; + + stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_TUTORIALS); + stmt->SetData(0, accountId); + ok = SetPreparedQuery(TUTORIALS, stmt) && ok; + + return ok; + } +}; + +void WorldSession::InitializeSession() +{ + uint32 cacheVersion = sWorld->getIntConfig(CONFIG_CLIENTCACHE_VERSION); + sScriptMgr->OnBeforeFinalizePlayerWorldSession(cacheVersion); + + std::shared_ptr realmHolder = std::make_shared(); + if (!realmHolder->Initialize(GetAccountId())) + { + SendAuthResponse(AUTH_SYSTEM_ERROR, false); + return; + } + + AddQueryHolderCallback(CharacterDatabase.DelayQueryHolder(realmHolder)).AfterComplete([this, cacheVersion](SQLQueryHolderBase const& holder) + { + InitializeSessionCallback(static_cast(holder), cacheVersion); + }); +} + +void WorldSession::InitializeSessionCallback(CharacterDatabaseQueryHolder const& realmHolder, uint32 clientCacheVersion) +{ + LoadAccountData(realmHolder.GetPreparedResult(AccountInfoQueryHolderPerRealm::GLOBAL_ACCOUNT_DATA), GLOBAL_CACHE_MASK); + LoadTutorialsData(realmHolder.GetPreparedResult(AccountInfoQueryHolderPerRealm::TUTORIALS)); + + if (!m_inQueue) + { + SendAuthResponse(AUTH_OK, true); + } + else + { + SendAuthWaitQueue(0); + } + + SetInQueue(false); + ResetTimeOutTime(false); + + SendAddonsInfo(); + SendClientCacheVersion(clientCacheVersion); + SendTutorialsData(); +} diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index 7aa9f6e12..d4a0478b1 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -447,10 +447,9 @@ public: AccountData* GetAccountData(AccountDataType type) { return &m_accountData[type]; } void SetAccountData(AccountDataType type, time_t tm, std::string const& data); void SendAccountDataTimes(uint32 mask); - void LoadGlobalAccountData(); void LoadAccountData(PreparedQueryResult result, uint32 mask); - void LoadTutorialsData(); + void LoadTutorialsData(PreparedQueryResult result); void SendTutorialsData(); void SaveTutorialsData(CharacterDatabaseTransaction trans); uint32 GetTutorialInt(uint8 index) const { return m_Tutorials[index]; } @@ -1077,6 +1076,9 @@ public: // opcodes handlers TransactionCallback& AddTransactionCallback(TransactionCallback&& callback); SQLQueryHolderCallback& AddQueryHolderCallback(SQLQueryHolderCallback&& callback); + void InitializeSession(); + void InitializeSessionCallback(CharacterDatabaseQueryHolder const& realmHolder, uint32 clientCacheVersion); + private: void ProcessQueryCallbacks(); diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 12630c7ac..cf9efa628 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -313,14 +313,12 @@ void World::AddSession_(WorldSession* s) if (pLimit > 0 && Sessions >= pLimit && AccountMgr::IsPlayerAccount(s->GetSecurity()) && !s->CanSkipQueue() && !HasRecentlyDisconnected(s)) { - AddQueuedPlayer (s); + AddQueuedPlayer(s); UpdateMaxSessionCounters(); return; } - s->SendAuthResponse(AUTH_OK, true); - - FinalizePlayerWorldSession(s); + s->InitializeSession(); UpdateMaxSessionCounters(); } @@ -400,13 +398,7 @@ bool World::RemoveQueuedPlayer(WorldSession* sess) if ((!GetPlayerAmountLimit() || sessions < GetPlayerAmountLimit()) && !m_QueuedPlayer.empty()) { WorldSession* pop_sess = m_QueuedPlayer.front(); - pop_sess->SetInQueue(false); - pop_sess->ResetTimeOutTime(false); - pop_sess->SendAuthWaitQueue(0); - pop_sess->SendAccountDataTimes(GLOBAL_CACHE_MASK); - - FinalizePlayerWorldSession(pop_sess); - + pop_sess->InitializeSession(); m_QueuedPlayer.pop_front(); // update iter to point first queued socket or end() if queue is empty now @@ -3390,16 +3382,6 @@ uint32 World::GetNextWhoListUpdateDelaySecs() return uint32(std::ceil(t / 1000.0f)); } -void World::FinalizePlayerWorldSession(WorldSession* session) -{ - uint32 cacheVersion = sWorld->getIntConfig(CONFIG_CLIENTCACHE_VERSION); - sScriptMgr->OnBeforeFinalizePlayerWorldSession(cacheVersion); - - session->SendAddonsInfo(); - session->SendClientCacheVersion(cacheVersion); - session->SendTutorialsData(); -} - CliCommandHolder::CliCommandHolder(void* callbackArg, char const* command, Print zprint, CommandFinished commandFinished) : m_callbackArg(callbackArg), m_command(strdup(command)), m_print(zprint), m_commandFinished(commandFinished) {