diff --git a/src/server/apps/worldserver/Main.cpp b/src/server/apps/worldserver/Main.cpp index 0f5a96208..26a13985f 100644 --- a/src/server/apps/worldserver/Main.cpp +++ b/src/server/apps/worldserver/Main.cpp @@ -49,6 +49,7 @@ #include "SharedDefines.h" #include "SteadyTimer.h" #include "World.h" +#include "WorldSessionMgr.h" #include "WorldSocket.h" #include "WorldSocketMgr.h" #include @@ -285,7 +286,7 @@ int main(int argc, char** argv) sMetric->Initialize(realm.Name, *ioContext, []() { - METRIC_VALUE("online_players", sWorld->GetPlayerCount()); + METRIC_VALUE("online_players", sWorldSessionMgr->GetPlayerCount()); METRIC_VALUE("db_queue_login", uint64(LoginDatabase.QueueSize())); METRIC_VALUE("db_queue_character", uint64(CharacterDatabase.QueueSize())); METRIC_VALUE("db_queue_world", uint64(WorldDatabase.QueueSize())); @@ -357,8 +358,8 @@ int main(int argc, char** argv) std::shared_ptr sWorldSocketMgrHandle(nullptr, [](void*) { - sWorld->KickAll(); // save and kick all players - sWorld->UpdateSessions(1); // real players unload required UpdateSessions call + sWorldSessionMgr->KickAll(); // save and kick all players + sWorldSessionMgr->UpdateSessions(1); // real players unload required UpdateSessions call sWorldSocketMgr.StopNetwork(); diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp index 13d989385..036621656 100644 --- a/src/server/game/Achievements/AchievementMgr.cpp +++ b/src/server/game/Achievements/AchievementMgr.cpp @@ -44,6 +44,7 @@ #include "SpellMgr.h" #include "World.h" #include "WorldPacket.h" +#include "WorldSessionMgr.h" bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria) { @@ -728,7 +729,7 @@ void AchievementMgr::SendAchievementEarned(AchievementEntry const* achievement) data << GetPlayer()->GetGUID(); data << uint32(achievement->ID); data << uint32(0); // display name as plain string in chat (always 0 for guild) - sWorld->SendGlobalMessage(&data); + sWorldSessionMgr->SendGlobalMessage(&data); } else { @@ -741,10 +742,10 @@ void AchievementMgr::SendAchievementEarned(AchievementEntry const* achievement) data << uint32(achievement->ID); std::size_t linkTypePos = data.wpos(); data << uint32(1); // display name as clickable link in chat - sWorld->SendGlobalMessage(&data, nullptr, teamId); + sWorldSessionMgr->SendGlobalMessage(&data, nullptr, teamId); data.put(linkTypePos, 0); // display name as plain string in chat - sWorld->SendGlobalMessage(&data, nullptr, teamId == TEAM_ALLIANCE ? TEAM_HORDE : TEAM_ALLIANCE); + sWorldSessionMgr->SendGlobalMessage(&data, nullptr, teamId == TEAM_ALLIANCE ? TEAM_HORDE : TEAM_ALLIANCE); } } // if player is in world he can tell his friends about new achievement diff --git a/src/server/game/Battlefield/Battlefield.cpp b/src/server/game/Battlefield/Battlefield.cpp index ae10a9f9d..0b25e18d1 100644 --- a/src/server/game/Battlefield/Battlefield.cpp +++ b/src/server/game/Battlefield/Battlefield.cpp @@ -31,6 +31,7 @@ #include "ObjectMgr.h" #include "Transport.h" #include "WorldPacket.h" +#include "WorldSessionMgr.h" /// @todo: this import is not necessary for compilation and marked as unused by the IDE // however, for some reasons removing it would cause a damn linking issue @@ -143,7 +144,7 @@ bool Battlefield::Update(uint32 diff) { if (m_Timer <= diff) { - if (!IsEnabled() || (!IsWarTime() && sWorld->GetActiveSessionCount() > 3500)) // if WG is disabled or there is more than 3500 connections, switch automaticly + if (!IsEnabled() || (!IsWarTime() && sWorldSessionMgr->GetActiveSessionCount() > 3500)) // if WG is disabled or there is more than 3500 connections, switch automaticly { m_isActive = true; EndBattle(false); diff --git a/src/server/game/Battlegrounds/Arena.cpp b/src/server/game/Battlegrounds/Arena.cpp index b0ecc3ab5..dc200abda 100644 --- a/src/server/game/Battlegrounds/Arena.cpp +++ b/src/server/game/Battlegrounds/Arena.cpp @@ -25,6 +25,7 @@ #include "ScriptMgr.h" #include "World.h" #include "WorldSession.h" +#include "WorldSessionMgr.h" //#include "WorldStatePackets.h" void ArenaScore::AppendToPacket(WorldPacket& data) @@ -224,7 +225,7 @@ void Arena::EndBattleground(TeamId winnerTeamId) { // pussywizard: arena logs in database uint32 fightId = sArenaTeamMgr->GetNextArenaLogId(); - uint32 currOnline = sWorld->GetActiveSessionCount(); + uint32 currOnline = sWorldSessionMgr->GetActiveSessionCount(); CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction(); CharacterDatabasePreparedStatement* stmt2 = CharacterDatabase.GetPreparedStatement(CHAR_INS_ARENA_LOG_FIGHT); diff --git a/src/server/game/Cache/WhoListCacheMgr.cpp b/src/server/game/Cache/WhoListCacheMgr.cpp index 8225627f6..c92ff7919 100644 --- a/src/server/game/Cache/WhoListCacheMgr.cpp +++ b/src/server/game/Cache/WhoListCacheMgr.cpp @@ -19,6 +19,7 @@ #include "GuildMgr.h" #include "ObjectAccessor.h" #include "World.h" +#include "WorldSessionMgr.h" WhoListCacheMgr* WhoListCacheMgr::instance() { @@ -30,7 +31,7 @@ void WhoListCacheMgr::Update() { // clear current list _whoListStorage.clear(); - _whoListStorage.reserve(sWorld->GetPlayerCount() + 1); + _whoListStorage.reserve(sWorldSessionMgr->GetPlayerCount() + 1); for (auto const& [guid, player] : ObjectAccessor::GetPlayers()) { diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp index d3de85c0d..26bfaf34c 100644 --- a/src/server/game/Chat/Chat.cpp +++ b/src/server/game/Chat/Chat.cpp @@ -30,6 +30,7 @@ #include "World.h" #include "WorldPacket.h" #include "WorldSession.h" +#include "WorldSessionMgr.h" #include Player* ChatHandler::GetPlayer() const @@ -188,7 +189,7 @@ void ChatHandler::SendGlobalSysMessage(const char* str) for (std::string_view line : Acore::Tokenize(str, '\n', true)) { BuildChatPacket(data, CHAT_MSG_SYSTEM, LANG_UNIVERSAL, nullptr, nullptr, line); - sWorld->SendGlobalMessage(&data); + sWorldSessionMgr->SendGlobalMessage(&data); } } @@ -198,7 +199,7 @@ void ChatHandler::SendGlobalGMSysMessage(const char* str) for (std::string_view line : Acore::Tokenize(str, '\n', true)) { BuildChatPacket(data, CHAT_MSG_SYSTEM, LANG_UNIVERSAL, nullptr, nullptr, line); - sWorld->SendGlobalGMMessage(&data); + sWorldSessionMgr->SendGlobalGMMessage(&data); } } @@ -442,8 +443,8 @@ bool ChatHandler::HasSession() const void ChatHandler::DoForAllValidSessions(std::function exec) { - SessionMap::const_iterator itr; - for (itr = sWorld->GetAllSessions().begin(); itr != sWorld->GetAllSessions().end(); ++itr) + WorldSessionMgr::SessionMap const& sessionMap = sWorldSessionMgr->GetAllSessions(); + for (WorldSessionMgr::SessionMap::const_iterator itr = sessionMap.begin(); itr != sessionMap.end(); ++itr) if (Player* player = itr->second->GetPlayer()) if (player->IsInWorld()) exec(player); diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index ad0cf07fe..6b60457a9 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -47,6 +47,7 @@ #include "WaypointMovementGenerator.h" #include "World.h" #include "WorldPacket.h" +#include "WorldSessionMgr.h" /// @todo: this import is not necessary for compilation and marked as unused by the IDE // however, for some reasons removing it would cause a damn linking issue @@ -2818,7 +2819,7 @@ void Creature::SendZoneUnderAttackMessage(Player* attacker) { WorldPacket data(SMSG_ZONE_UNDER_ATTACK, 4); data << (uint32)GetAreaId(); - sWorld->SendGlobalMessage(&data, nullptr, (attacker->GetTeamId() == TEAM_ALLIANCE ? TEAM_HORDE : TEAM_ALLIANCE)); + sWorldSessionMgr->SendGlobalMessage(&data, nullptr, (attacker->GetTeamId() == TEAM_ALLIANCE ? TEAM_HORDE : TEAM_ALLIANCE)); } /** diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 5a51b10a4..1787b8ccb 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -84,6 +84,7 @@ #include "World.h" #include "WorldPacket.h" #include "WorldSession.h" +#include "WorldSessionMgr.h" #include "WorldState.h" #include @@ -363,7 +364,7 @@ Player::Player(WorldSession* session): Unit(true), m_mover(this) m_ControlledByPlayer = true; - sWorld->IncreasePlayerCount(); + sWorldSessionMgr->IncreasePlayerCount(); m_ChampioningFaction = 0; @@ -447,7 +448,7 @@ Player::~Player() delete m_reputationMgr; delete _cinematicMgr; - sWorld->DecreasePlayerCount(); + sWorldSessionMgr->DecreasePlayerCount(); if (!m_isInSharedVisionOf.empty()) { diff --git a/src/server/game/Events/GameEventMgr.cpp b/src/server/game/Events/GameEventMgr.cpp index b380b8399..277d227e3 100644 --- a/src/server/game/Events/GameEventMgr.cpp +++ b/src/server/game/Events/GameEventMgr.cpp @@ -31,6 +31,7 @@ #include "Transport.h" #include "UnitAI.h" #include "World.h" +#include "WorldSessionMgr.h" #include "WorldStatePackets.h" #include @@ -1686,7 +1687,7 @@ void GameEventMgr::UpdateWorldStates(uint16 eventId, bool Activate) WorldPackets::WorldState::UpdateWorldState worldstate; worldstate.VariableID = bl->HolidayWorldStateId; worldstate.Value = Activate ? 1 : 0; - sWorld->SendGlobalMessage(worldstate.Write()); + sWorldSessionMgr->SendGlobalMessage(worldstate.Write()); } } } diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index b5d85760e..a6478b461 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -57,6 +57,7 @@ #include "World.h" #include "WorldPacket.h" #include "WorldSession.h" +#include "WorldSessionMgr.h" class LoginQueryHolder : public CharacterDatabaseQueryHolder { @@ -612,7 +613,7 @@ void WorldSession::HandleCharDeleteOpcode(WorldPacket& recvData) uint32 initAccountId = GetAccountId(); // can't delete loaded character - if (ObjectAccessor::FindConnectedPlayer(guid) || sWorld->FindOfflineSessionForCharacterGUID(guid.GetCounter())) + if (ObjectAccessor::FindConnectedPlayer(guid) || sWorldSessionMgr->FindOfflineSessionForCharacterGUID(guid.GetCounter())) { sScriptMgr->OnPlayerFailedDelete(guid, initAccountId); return; @@ -698,14 +699,14 @@ void WorldSession::HandlePlayerLoginOpcode(WorldPacket& recvData) }; // pussywizard: - if (WorldSession* sess = sWorld->FindOfflineSessionForCharacterGUID(playerGuid.GetCounter())) + if (WorldSession* sess = sWorldSessionMgr->FindOfflineSessionForCharacterGUID(playerGuid.GetCounter())) if (sess->GetAccountId() != GetAccountId()) { SendCharLogin(CHAR_LOGIN_DUPLICATE_CHARACTER); return; } // pussywizard: - if (WorldSession* sess = sWorld->FindOfflineSession(GetAccountId())) + if (WorldSession* sess = sWorldSessionMgr->FindOfflineSession(GetAccountId())) { Player* p = sess->GetPlayer(); if (!p || sess->IsKicked()) @@ -1101,7 +1102,7 @@ void WorldSession::HandlePlayerLoginFromDB(LoginQueryHolder const& holder) { bool isReferrer = pCurrChar->GetSession()->IsARecruiter(); - for (auto const& [accID, session] : sWorld->GetAllSessions()) + for (auto const& [accID, session] : sWorldSessionMgr->GetAllSessions()) { if (!session->GetRecruiterId() && !session->IsARecruiter()) continue; @@ -1390,7 +1391,7 @@ void WorldSession::HandleCharRenameCallBack(std::shared_ptr atLoginFlags &= ~AT_LOGIN_RENAME; // pussywizard: - if (ObjectAccessor::FindConnectedPlayer(ObjectGuid::Create(guidLow)) || sWorld->FindOfflineSessionForCharacterGUID(guidLow)) + if (ObjectAccessor::FindConnectedPlayer(ObjectGuid::Create(guidLow)) || sWorldSessionMgr->FindOfflineSessionForCharacterGUID(guidLow)) { SendCharRename(CHAR_CREATE_ERROR, renameInfo.get()); return; @@ -1626,7 +1627,7 @@ void WorldSession::HandleCharCustomize(WorldPacket& recvData) } // pussywizard: - if (ObjectAccessor::FindConnectedPlayer(customizeInfo->Guid) || sWorld->FindOfflineSessionForCharacterGUID(customizeInfo->Guid.GetCounter())) + if (ObjectAccessor::FindConnectedPlayer(customizeInfo->Guid) || sWorldSessionMgr->FindOfflineSessionForCharacterGUID(customizeInfo->Guid.GetCounter())) { recvData.rfinish(); WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1); @@ -1928,7 +1929,7 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData) >> factionChangeInfo->Race; // pussywizard: - if (ObjectAccessor::FindConnectedPlayer(factionChangeInfo->Guid) || sWorld->FindOfflineSessionForCharacterGUID(factionChangeInfo->Guid.GetCounter())) + if (ObjectAccessor::FindConnectedPlayer(factionChangeInfo->Guid) || sWorldSessionMgr->FindOfflineSessionForCharacterGUID(factionChangeInfo->Guid.GetCounter())) { SendCharFactionChange(CHAR_CREATE_ERROR, factionChangeInfo.get()); return; diff --git a/src/server/game/Instances/InstanceSaveMgr.cpp b/src/server/game/Instances/InstanceSaveMgr.cpp index cf9bd7967..5088742c8 100644 --- a/src/server/game/Instances/InstanceSaveMgr.cpp +++ b/src/server/game/Instances/InstanceSaveMgr.cpp @@ -32,6 +32,7 @@ #include "Timer.h" #include "Transport.h" #include "World.h" +#include "WorldSessionMgr.h" uint16 InstanceSaveMgr::ResetTimeDelay[] = {3600, 900, 300, 60, 0}; PlayerBindStorage InstanceSaveMgr::playerBindStorage; @@ -494,7 +495,9 @@ void InstanceSaveMgr::Update() { LOG_INFO("instance.save", "Instance ID reset occurred, sending updated calendar and raid info to all players!"); WorldPacket dummy; - for (SessionMap::const_iterator itr = sWorld->GetAllSessions().begin(); itr != sWorld->GetAllSessions().end(); ++itr) + + WorldSessionMgr::SessionMap const& sessionMap = sWorldSessionMgr->GetAllSessions(); + for (WorldSessionMgr::SessionMap::const_iterator itr = sessionMap.begin(); itr != sessionMap.end(); ++itr) if (Player* plr = itr->second->GetPlayer()) { itr->second->HandleCalendarGetCalendar(dummy); diff --git a/src/server/game/Misc/BanMgr.cpp b/src/server/game/Misc/BanMgr.cpp index e3102c67e..70fcf80d3 100644 --- a/src/server/game/Misc/BanMgr.cpp +++ b/src/server/game/Misc/BanMgr.cpp @@ -26,6 +26,7 @@ #include "ScriptMgr.h" #include "World.h" #include "WorldSession.h" +#include "WorldSessionMgr.h" BanMgr* BanMgr::instance() { @@ -69,11 +70,11 @@ BanReturn BanMgr::BanAccount(std::string const& AccountName, std::string const& stmt->SetData(3, Reason); trans->Append(stmt); - if (WorldSession* session = sWorld->FindSession(AccountID)) + if (WorldSession* session = sWorldSessionMgr->FindSession(AccountID)) if (session->GetPlayerName() != Author) session->KickPlayer("Ban Account at condition 'FindSession(account)->GetPlayerName() != author'"); - if (WorldSession* session = sWorld->FindOfflineSession(AccountID)) + if (WorldSession* session = sWorldSessionMgr->FindOfflineSession(AccountID)) if (session->GetPlayerName() != Author) session->KickPlayer("Ban Account at condition 'FindOfflineSession(account)->GetPlayerName() != author'"); @@ -131,11 +132,11 @@ BanReturn BanMgr::BanAccountByPlayerName(std::string const& CharacterName, std:: stmt->SetData(3, Reason); trans->Append(stmt); - if (WorldSession* session = sWorld->FindSession(AccountID)) + if (WorldSession* session = sWorldSessionMgr->FindSession(AccountID)) if (session->GetPlayerName() != Author) session->KickPlayer("Ban Account at condition 'FindSession(account)->GetPlayerName() != author'"); - if (WorldSession* session = sWorld->FindOfflineSession(AccountID)) + if (WorldSession* session = sWorldSessionMgr->FindOfflineSession(AccountID)) if (session->GetPlayerName() != Author) session->KickPlayer("Ban Account at condition 'FindOfflineSession(account)->GetPlayerName() != author'"); @@ -205,11 +206,11 @@ BanReturn BanMgr::BanIP(std::string const& IP, std::string const& Duration, std: Field* fields = resultAccounts->Fetch(); uint32 AccountID = fields[0].Get(); - if (WorldSession* session = sWorld->FindSession(AccountID)) + if (WorldSession* session = sWorldSessionMgr->FindSession(AccountID)) if (session->GetPlayerName() != Author) session->KickPlayer("Ban IP at condition 'FindSession(account)->GetPlayerName() != author'"); - if (WorldSession* session = sWorld->FindOfflineSession(AccountID)) + if (WorldSession* session = sWorldSessionMgr->FindOfflineSession(AccountID)) if (session->GetPlayerName() != Author) session->KickPlayer("Ban IP at condition 'FindOfflineSession(account)->GetPlayerName() != author'"); } while (resultAccounts->NextRow()); diff --git a/src/server/game/Server/WorldSessionMgr.cpp b/src/server/game/Server/WorldSessionMgr.cpp new file mode 100644 index 000000000..5bad2e10a --- /dev/null +++ b/src/server/game/Server/WorldSessionMgr.cpp @@ -0,0 +1,461 @@ +/* + * This file is part of the AzerothCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by the + * Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#include "Chat.h" +#include "ChatPackets.h" +#include "GameTime.h" +#include "Metric.h" +#include "Player.h" +#include "World.h" +#include "WorldSession.h" +#include "WorldSessionMgr.h" + +WorldSessionMgr* WorldSessionMgr::Instance() +{ + static WorldSessionMgr instance; + return &instance; +} + +WorldSessionMgr::WorldSessionMgr() +{ + _playerLimit = 0; + _maxActiveSessionCount = 0; + _maxQueuedSessionCount = 0; + _playerCount = 0; + _maxPlayerCount = 0; +} + +WorldSessionMgr::~WorldSessionMgr() +{ + ///- Empty the kicked session set + while (!_sessions.empty()) + { + // not remove from queue, prevent loading new sessions + delete _sessions.begin()->second; + _sessions.erase(_sessions.begin()); + } + + while (!_offlineSessions.empty()) + { + delete _offlineSessions.begin()->second; + _offlineSessions.erase(_offlineSessions.begin()); + } +} + +/// Find a session by its id +WorldSession* WorldSessionMgr::FindSession(uint32 id) const +{ + SessionMap::const_iterator itr = _sessions.find(id); + + if (itr != _sessions.end()) + return itr->second; // also can return nullptr for kicked session + else + return nullptr; +} + +WorldSession* WorldSessionMgr::FindOfflineSession(uint32 id) const +{ + SessionMap::const_iterator itr = _offlineSessions.find(id); + if (itr != _offlineSessions.end()) + return itr->second; + else + return nullptr; +} + +WorldSession* WorldSessionMgr::FindOfflineSessionForCharacterGUID(ObjectGuid::LowType guidLow) const +{ + if (_offlineSessions.empty()) + return nullptr; + + for (SessionMap::const_iterator itr = _offlineSessions.begin(); itr != _offlineSessions.end(); ++itr) + if (itr->second->GetGuidLow() == guidLow) + return itr->second; + + return nullptr; +} + +void WorldSessionMgr::UpdateSessions(uint32 const diff) +{ + { + METRIC_DETAILED_NO_THRESHOLD_TIMER("world_update_time", + METRIC_TAG("type", "Add sessions"), + METRIC_TAG("parent_type", "Update sessions")); + + ///- Add new sessions + WorldSession* sess = nullptr; + while (_addSessQueue.next(sess)) + { + AddSession_(sess); + } + } + + ///- Then send an update signal to remaining ones + for (SessionMap::iterator itr = _sessions.begin(), next; itr != _sessions.end(); itr = next) + { + next = itr; + ++next; + + ///- and remove not active sessions from the list + WorldSession* pSession = itr->second; + WorldSessionFilter updater(pSession); + + // pussywizard: + if (pSession->HandleSocketClosed()) + { + if (!RemoveQueuedPlayer(pSession) && sWorld->getIntConfig(CONFIG_INTERVAL_DISCONNECT_TOLERANCE)) + _disconnects[pSession->GetAccountId()] = GameTime::GetGameTime().count(); + _sessions.erase(itr); + // there should be no offline session if current one is logged onto a character + SessionMap::iterator iter; + if ((iter = _offlineSessions.find(pSession->GetAccountId())) != _offlineSessions.end()) + { + WorldSession* tmp = iter->second; + _offlineSessions.erase(iter); + delete tmp; + } + pSession->SetOfflineTime(GameTime::GetGameTime().count()); + _offlineSessions[pSession->GetAccountId()] = pSession; + continue; + } + + [[maybe_unused]] uint32 currentSessionId = itr->first; + METRIC_DETAILED_TIMER("world_update_sessions_time", METRIC_TAG("account_id", std::to_string(currentSessionId))); + + if (!pSession->Update(diff, updater)) + { + if (!RemoveQueuedPlayer(pSession) && sWorld->getIntConfig(CONFIG_INTERVAL_DISCONNECT_TOLERANCE)) + _disconnects[pSession->GetAccountId()] = GameTime::GetGameTime().count(); + _sessions.erase(itr); + delete pSession; + } + } + + // pussywizard: + if (_offlineSessions.empty()) + return; + uint32 currTime = GameTime::GetGameTime().count(); + for (SessionMap::iterator itr = _offlineSessions.begin(), next; itr != _offlineSessions.end(); itr = next) + { + next = itr; + ++next; + WorldSession* pSession = itr->second; + if (!pSession->GetPlayer() || pSession->GetOfflineTime() + 60 < currTime || pSession->IsKicked()) + { + _offlineSessions.erase(itr); + delete pSession; + } + } +} + +/// Remove a given session +bool WorldSessionMgr::KickSession(uint32 id) +{ + ///- Find the session, kick the user, but we can't delete session at this moment to prevent iterator invalidation + SessionMap::const_iterator itr = _sessions.find(id); + + if (itr != _sessions.end() && itr->second) + { + if (itr->second->PlayerLoading()) + return false; + + itr->second->KickPlayer("KickSession", false); + } + + return true; +} + +/// Kick (and save) all players +void WorldSessionMgr::KickAll() +{ + _queuedPlayer.clear(); // prevent send queue update packet and login queued sessions + + // session not removed at kick and will removed in next update tick + for (SessionMap::const_iterator itr = _sessions.begin(); itr != _sessions.end(); ++itr) + itr->second->KickPlayer("KickAll sessions"); + + // pussywizard: kick offline sessions + for (SessionMap::const_iterator itr = _offlineSessions.begin(); itr != _offlineSessions.end(); ++itr) + itr->second->KickPlayer("KickAll offline sessions"); +} + +/// Kick (and save) all players with security level less `sec` +void WorldSessionMgr::KickAllLess(AccountTypes sec) +{ + // session not removed at kick and will removed in next update tick + for (SessionMap::const_iterator itr = _sessions.begin(); itr != _sessions.end(); ++itr) + if (itr->second->GetSecurity() < sec) + itr->second->KickPlayer("KickAllLess"); +} + +void WorldSessionMgr::AddSession(WorldSession* session) +{ + _addSessQueue.add(session); +} + +void WorldSessionMgr::AddQueuedPlayer(WorldSession* session) +{ + session->SetInQueue(true); + _queuedPlayer.push_back(session); + + // The 1st SMSG_AUTH_RESPONSE needs to contain other info too. + session->SendAuthResponse(AUTH_WAIT_QUEUE, false, GetQueuePos(session)); +} + +bool WorldSessionMgr::RemoveQueuedPlayer(WorldSession* session) +{ + uint32 sessions = GetActiveSessionCount(); + + uint32 position = 1; + Queue::iterator iter = _queuedPlayer.begin(); + + // search to remove and count skipped positions + bool found = false; + + for (; iter != _queuedPlayer.end(); ++iter, ++position) + { + if (*iter == session) + { + session->SetInQueue(false); + session->ResetTimeOutTime(false); + iter = _queuedPlayer.erase(iter); + found = true; + break; + } + } + + // if session not queued then it was an active session + if (!found) + { + ASSERT(sessions > 0); + --sessions; + } + + // accept first in queue + if ((!GetPlayerAmountLimit() || sessions < GetPlayerAmountLimit()) && !_queuedPlayer.empty()) + { + WorldSession* pop_sess = _queuedPlayer.front(); + pop_sess->InitializeSession(); + _queuedPlayer.pop_front(); + + // update iter to point first queued socket or end() if queue is empty now + iter = _queuedPlayer.begin(); + position = 1; + } + + // update queue position from iter to end() + for (; iter != _queuedPlayer.end(); ++iter, ++position) + (*iter)->SendAuthWaitQueue(position); + + return found; +} + +int32 WorldSessionMgr::GetQueuePos(WorldSession* session) +{ + uint32 position = 1; + + for (Queue::const_iterator iter = _queuedPlayer.begin(); iter != _queuedPlayer.end(); ++iter, ++position) + if ((*iter) == session) + return position; + + return 0; +} + +void WorldSessionMgr::AddSession_(WorldSession* session) +{ + ASSERT(session); + + // kick existing session with same account (if any) + // if character on old session is being loaded, then return + if (!KickSession(session->GetAccountId())) + { + session->KickPlayer("kick existing session with same account"); + delete session; // session not added yet in session list, so not listed in queue + return; + } + + SessionMap::const_iterator old = _sessions.find(session->GetAccountId()); + if (old != _sessions.end()) + { + WorldSession* oldSession = old->second; + + if (!RemoveQueuedPlayer(oldSession) && sWorld->getIntConfig(CONFIG_INTERVAL_DISCONNECT_TOLERANCE)) + _disconnects[session->GetAccountId()] = GameTime::GetGameTime().count(); + + // pussywizard: + if (oldSession->HandleSocketClosed()) + { + // there should be no offline session if current one is logged onto a character + SessionMap::iterator iter; + if ((iter = _offlineSessions.find(oldSession->GetAccountId())) != _offlineSessions.end()) + { + WorldSession* tmp = iter->second; + _offlineSessions.erase(iter); + delete tmp; + } + oldSession->SetOfflineTime(GameTime::GetGameTime().count()); + _offlineSessions[oldSession->GetAccountId()] = oldSession; + } + else + { + delete oldSession; + } + } + + _sessions[session->GetAccountId()] = session; + + uint32 Sessions = GetActiveAndQueuedSessionCount(); + uint32 pLimit = GetPlayerAmountLimit(); + + // don't count this session when checking player limit + --Sessions; + + if (pLimit > 0 && Sessions >= pLimit && AccountMgr::IsPlayerAccount(session->GetSecurity()) && !session->CanSkipQueue() && !HasRecentlyDisconnected(session)) + { + AddQueuedPlayer(session); + UpdateMaxSessionCounters(); + return; + } + + session->InitializeSession(); + + UpdateMaxSessionCounters(); +} + +bool WorldSessionMgr::HasRecentlyDisconnected(WorldSession* session) +{ + if (!session) + return false; + + if (uint32 tolerance = sWorld->getIntConfig(CONFIG_INTERVAL_DISCONNECT_TOLERANCE)) + { + for (DisconnectMap::iterator i = _disconnects.begin(); i != _disconnects.end();) + { + if ((GameTime::GetGameTime().count() - i->second) < tolerance) + { + if (i->first == session->GetAccountId()) + return true; + ++i; + } + else + _disconnects.erase(i++); + } + } + return false; +} + +void WorldSessionMgr::UpdateMaxSessionCounters() +{ + _maxActiveSessionCount = std::max(_maxActiveSessionCount, uint32(_sessions.size() - _queuedPlayer.size())); + _maxQueuedSessionCount = std::max(_maxQueuedSessionCount, uint32(_queuedPlayer.size())); +} + +/// Send a packet to all players (except self if mentioned) +void WorldSessionMgr::SendGlobalMessage(WorldPacket const* packet, WorldSession* self, TeamId teamId) +{ + SessionMap::const_iterator itr; + for (itr = _sessions.begin(); itr != _sessions.end(); ++itr) + { + if (itr->second && + itr->second->GetPlayer() && + itr->second->GetPlayer()->IsInWorld() && + itr->second != self && + (teamId == TEAM_NEUTRAL || itr->second->GetPlayer()->GetTeamId() == teamId)) + { + itr->second->SendPacket(packet); + } + } +} + +/// Send a packet to all GMs (except self if mentioned) +void WorldSessionMgr::SendGlobalGMMessage(WorldPacket const* packet, WorldSession* self, TeamId teamId) +{ + SessionMap::iterator itr; + for (itr = _sessions.begin(); itr != _sessions.end(); ++itr) + { + if (itr->second && + itr->second->GetPlayer() && + itr->second->GetPlayer()->IsInWorld() && + itr->second != self && + !AccountMgr::IsPlayerAccount(itr->second->GetSecurity()) && + (teamId == TEAM_NEUTRAL || itr->second->GetPlayer()->GetTeamId() == teamId)) + { + itr->second->SendPacket(packet); + } + } +} + +/// Send a packet to all players (or players selected team) in the zone (except self if mentioned) +bool WorldSessionMgr::SendZoneMessage(uint32 zone, WorldPacket const* packet, WorldSession* self, TeamId teamId) +{ + bool foundPlayerToSend = false; + SessionMap::const_iterator itr; + + for (itr = _sessions.begin(); itr != _sessions.end(); ++itr) + { + if (itr->second && + itr->second->GetPlayer() && + itr->second->GetPlayer()->IsInWorld() && + itr->second->GetPlayer()->GetZoneId() == zone && + itr->second != self && + (teamId == TEAM_NEUTRAL || itr->second->GetPlayer()->GetTeamId() == teamId)) + { + itr->second->SendPacket(packet); + foundPlayerToSend = true; + } + } + + return foundPlayerToSend; +} + +/// Send a server message to the user(s) +void WorldSessionMgr::SendServerMessage(ServerMessageType messageID, std::string stringParam /*= ""*/, Player* player /*= nullptr*/) +{ + WorldPackets::Chat::ChatServerMessage chatServerMessage; + chatServerMessage.MessageID = int32(messageID); + if (messageID <= SERVER_MSG_STRING) + chatServerMessage.StringParam = stringParam; + + if (player) + player->SendDirectMessage(chatServerMessage.Write()); + else + SendGlobalMessage(chatServerMessage.Write()); +} + +/// Send a System Message to all players in the zone (except self if mentioned) +void WorldSessionMgr::SendZoneText(uint32 zone, std::string text, WorldSession* self, TeamId teamId) +{ + WorldPacket data; + ChatHandler::BuildChatPacket(data, CHAT_MSG_SYSTEM, LANG_UNIVERSAL, nullptr, nullptr, text.c_str()); + SendZoneMessage(zone, &data, self, teamId); +} + +void WorldSessionMgr::DoForAllOnlinePlayers(std::function exec) +{ + std::shared_lock lock(*HashMapHolder::GetLock()); + for (auto const& it : ObjectAccessor::GetPlayers()) + { + if (Player* player = it.second) + { + if (!player->IsInWorld()) + { + continue; + } + + exec(player); + } + } +} diff --git a/src/server/game/Server/WorldSessionMgr.h b/src/server/game/Server/WorldSessionMgr.h new file mode 100644 index 000000000..364dad1ed --- /dev/null +++ b/src/server/game/Server/WorldSessionMgr.h @@ -0,0 +1,112 @@ +/* + * This file is part of the AzerothCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by the + * Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#ifndef __WORLDSESSIONMGR_H +#define __WORLDSESSIONMGR_H + +#include "Common.h" +#include "IWorld.h" +#include "LockedQueue.h" +#include "ObjectGuid.h" +#include +#include + +class Player; +class WorldPacket; +class WorldSession; + +class WorldSessionMgr +{ +public: + static WorldSessionMgr* Instance(); + + WorldSessionMgr(); + ~WorldSessionMgr(); + + WorldSession* FindSession(uint32 id) const; + WorldSession* FindOfflineSession(uint32 id) const; + WorldSession* FindOfflineSessionForCharacterGUID(ObjectGuid::LowType guidLow) const; + + void UpdateSessions(uint32 const diff); + + bool KickSession(uint32 id); + void KickAll(); + void KickAllLess(AccountTypes sec); + void AddSession(WorldSession* session); + + void AddQueuedPlayer(WorldSession* session); + bool RemoveQueuedPlayer(WorldSession* session); + int32 GetQueuePos(WorldSession* session); + bool HasRecentlyDisconnected(WorldSession* session); + + typedef std::unordered_map SessionMap; + SessionMap const& GetAllSessions() const { return _sessions; } + + /// Get the number of current active sessions + void UpdateMaxSessionCounters(); + uint32 GetActiveAndQueuedSessionCount() const { return _sessions.size(); } + uint32 GetActiveSessionCount() const { return _sessions.size() - _queuedPlayer.size(); } + uint32 GetQueuedSessionCount() const { return _queuedPlayer.size(); } + /// Get the maximum number of parallel sessions on the server since last reboot + uint32 GetMaxQueuedSessionCount() const { return _maxQueuedSessionCount; } + uint32 GetMaxActiveSessionCount() const { return _maxActiveSessionCount; } + /// Get number of players + inline uint32 GetPlayerCount() const { return _playerCount; } + inline uint32 GetMaxPlayerCount() const { return _maxPlayerCount; } + /// Active session server limit + void SetPlayerAmountLimit(uint32 limit) { _playerLimit = limit; } + uint32 GetPlayerAmountLimit() const { return _playerLimit; } + + /// Increase/Decrease number of players + inline void IncreasePlayerCount() + { + _playerCount++; + _maxPlayerCount = std::max(_maxPlayerCount, _playerCount); + } + inline void DecreasePlayerCount() { _playerCount--; } + + void SendGlobalMessage(WorldPacket const* packet, WorldSession* self = nullptr, TeamId teamId = TEAM_NEUTRAL); + void SendGlobalGMMessage(WorldPacket const* packet, WorldSession* self = nullptr, TeamId teamId = TEAM_NEUTRAL); + bool SendZoneMessage(uint32 zone, WorldPacket const* packet, WorldSession* self = nullptr, TeamId teamId = TEAM_NEUTRAL); + void SendZoneText(uint32 zone, std::string text, WorldSession* self = nullptr, TeamId teamId = TEAM_NEUTRAL); + void SendServerMessage(ServerMessageType messageID, std::string stringParam = "", Player* player = nullptr); + + void DoForAllOnlinePlayers(std::function exec); + +private: + LockedQueue _addSessQueue; + void AddSession_(WorldSession* session); + + SessionMap _sessions; + SessionMap _offlineSessions; + + typedef std::unordered_map DisconnectMap; + DisconnectMap _disconnects; + + typedef std::list Queue; + Queue _queuedPlayer; + + uint32 _playerLimit; + uint32 _maxActiveSessionCount; + uint32 _maxQueuedSessionCount; + uint32 _playerCount; + uint32 _maxPlayerCount; +}; + +#define sWorldSessionMgr WorldSessionMgr::Instance() + +#endif diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp index fefe24949..a745ecc65 100644 --- a/src/server/game/Server/WorldSocket.cpp +++ b/src/server/game/Server/WorldSocket.cpp @@ -30,6 +30,7 @@ #include "ScriptMgr.h" #include "World.h" #include "WorldSession.h" +#include "WorldSessionMgr.h" #include "zlib.h" #include @@ -713,7 +714,7 @@ void WorldSocket::HandleAuthSessionCallback(std::shared_ptr authSes _worldSession->InitWarden(account.SessionKey, account.OS); } - sWorld->AddSession(_worldSession); + sWorldSessionMgr->AddSession(_worldSession); AsyncRead(); } diff --git a/src/server/game/Texts/CreatureTextMgr.cpp b/src/server/game/Texts/CreatureTextMgr.cpp index aad55356b..c471c7815 100644 --- a/src/server/game/Texts/CreatureTextMgr.cpp +++ b/src/server/game/Texts/CreatureTextMgr.cpp @@ -387,8 +387,8 @@ void CreatureTextMgr::SendNonChatPacket(WorldObject* source, WorldPacket const* } case TEXT_RANGE_WORLD: { - SessionMap const& smap = sWorld->GetAllSessions(); - for (SessionMap::const_iterator itr = smap.begin(); itr != smap.end(); ++itr) + WorldSessionMgr::SessionMap const& sessionMap = sWorldSessionMgr->GetAllSessions(); + for (WorldSessionMgr::SessionMap::const_iterator itr = sessionMap.begin(); itr != sessionMap.end(); ++itr) if (Player* player = itr->second->GetPlayer()) if ((teamId == TEAM_NEUTRAL || player->GetTeamId() == teamId) && (!gmOnly || player->IsGameMaster())) player->GetSession()->SendPacket(data); diff --git a/src/server/game/Texts/CreatureTextMgr.h b/src/server/game/Texts/CreatureTextMgr.h index 11b7c1569..f88179d45 100644 --- a/src/server/game/Texts/CreatureTextMgr.h +++ b/src/server/game/Texts/CreatureTextMgr.h @@ -23,6 +23,7 @@ #include "ObjectAccessor.h" #include "SharedDefines.h" #include "WorldSession.h" +#include "WorldSessionMgr.h" enum CreatureTextRange { @@ -232,8 +233,8 @@ void CreatureTextMgr::SendChatPacket(WorldObject* source, Builder const& builder } case TEXT_RANGE_WORLD: { - SessionMap const& smap = sWorld->GetAllSessions(); - for (SessionMap::const_iterator itr = smap.begin(); itr != smap.end(); ++itr) + WorldSessionMgr::SessionMap const& smap = sWorldSessionMgr->GetAllSessions(); + for (WorldSessionMgr::SessionMap::const_iterator itr = smap.begin(); itr != smap.end(); ++itr) if (Player* player = itr->second->GetPlayer()) if ((teamId == TEAM_NEUTRAL || player->GetTeamId() == teamId) && (!gmOnly || player->IsGameMaster())) localizer(player); diff --git a/src/server/game/Weather/Weather.cpp b/src/server/game/Weather/Weather.cpp index bfecc5c6a..bc22e7db6 100644 --- a/src/server/game/Weather/Weather.cpp +++ b/src/server/game/Weather/Weather.cpp @@ -25,6 +25,7 @@ #include "ScriptMgr.h" #include "Util.h" #include "World.h" +#include "WorldSessionMgr.h" /// Create the Weather object Weather::Weather(uint32 zone, WeatherData const* weatherChances) @@ -203,7 +204,7 @@ bool Weather::UpdateWeather() WorldPackets::Misc::Weather weather(state, m_grade); //- Returns false if there were no players found to update - if (!sWorld->SendZoneMessage(m_zone, weather.Write())) + if (!sWorldSessionMgr->SendZoneMessage(m_zone, weather.Write())) return false; ///- Log the event diff --git a/src/server/game/World/IWorld.h b/src/server/game/World/IWorld.h index 50e4dbfc3..10f69f30b 100644 --- a/src/server/game/World/IWorld.h +++ b/src/server/game/World/IWorld.h @@ -48,8 +48,6 @@ private: CliCommandHolder& operator=(CliCommandHolder const& right) = delete; }; -typedef std::unordered_map SessionMap; - // ServerMessages.dbc enum ServerMessageType { @@ -531,34 +529,11 @@ class IWorld { public: virtual ~IWorld() = default; - [[nodiscard]] virtual WorldSession* FindSession(uint32 id) const = 0; - [[nodiscard]] virtual WorldSession* FindOfflineSession(uint32 id) const = 0; - [[nodiscard]] virtual WorldSession* FindOfflineSessionForCharacterGUID(ObjectGuid::LowType guidLow) const = 0; - virtual void AddSession(WorldSession* s) = 0; - virtual bool KickSession(uint32 id) = 0; - virtual void UpdateMaxSessionCounters() = 0; - [[nodiscard]] virtual const SessionMap& GetAllSessions() const = 0; - [[nodiscard]] virtual uint32 GetActiveAndQueuedSessionCount() const = 0; - [[nodiscard]] virtual uint32 GetActiveSessionCount() const = 0; - [[nodiscard]] virtual uint32 GetQueuedSessionCount() const = 0; - [[nodiscard]] virtual uint32 GetMaxQueuedSessionCount() const = 0; - [[nodiscard]] virtual uint32 GetMaxActiveSessionCount() const = 0; - [[nodiscard]] virtual uint32 GetPlayerCount() const = 0; - [[nodiscard]] virtual uint32 GetMaxPlayerCount() const = 0; - virtual void IncreasePlayerCount() = 0; - virtual void DecreasePlayerCount() = 0; - virtual Player* FindPlayerInZone(uint32 zone) = 0; [[nodiscard]] virtual bool IsClosed() const = 0; virtual void SetClosed(bool val) = 0; [[nodiscard]] virtual AccountTypes GetPlayerSecurityLimit() const = 0; virtual void SetPlayerSecurityLimit(AccountTypes sec) = 0; virtual void LoadDBAllowedSecurityLevel() = 0; - virtual void SetPlayerAmountLimit(uint32 limit) = 0; - [[nodiscard]] virtual uint32 GetPlayerAmountLimit() const = 0; - virtual void AddQueuedPlayer(WorldSession*) = 0; - virtual bool RemoveQueuedPlayer(WorldSession* session) = 0; - virtual int32 GetQueuePos(WorldSession*) = 0; - virtual bool HasRecentlyDisconnected(WorldSession*) = 0; [[nodiscard]] virtual bool getAllowMovement() const = 0; virtual void SetAllowMovement(bool allow) = 0; virtual void SetNewCharString(std::string const& str) = 0; @@ -571,18 +546,12 @@ public: [[nodiscard]] virtual uint16 GetConfigMaxSkillValue() const = 0; virtual void SetInitialWorldSettings() = 0; virtual void LoadConfigSettings(bool reload = false) = 0; - virtual void SendGlobalMessage(WorldPacket const* packet, WorldSession* self = nullptr, TeamId teamId = TEAM_NEUTRAL) = 0; - virtual void SendGlobalGMMessage(WorldPacket const* packet, WorldSession* self = nullptr, TeamId teamId = TEAM_NEUTRAL) = 0; - virtual bool SendZoneMessage(uint32 zone, WorldPacket const* packet, WorldSession* self = nullptr, TeamId teamId = TEAM_NEUTRAL) = 0; - virtual void SendZoneText(uint32 zone, std::string text, WorldSession* self = nullptr, TeamId teamId = TEAM_NEUTRAL) = 0; - virtual void SendServerMessage(ServerMessageType messageID, std::string stringParam = "", Player* player = nullptr) = 0; [[nodiscard]] virtual bool IsShuttingDown() const = 0; [[nodiscard]] virtual uint32 GetShutDownTimeLeft() const = 0; virtual void ShutdownServ(uint32 time, uint32 options, uint8 exitcode, const std::string& reason = std::string()) = 0; virtual void ShutdownCancel() = 0; virtual void ShutdownMsg(bool show = false, Player* player = nullptr, const std::string& reason = std::string()) = 0; virtual void Update(uint32 diff) = 0; - virtual void UpdateSessions(uint32 diff) = 0; virtual void setRate(Rates rate, float value) = 0; [[nodiscard]] virtual float getRate(Rates rate) const = 0; virtual void setBoolConfig(WorldBoolConfigs index, bool value) = 0; @@ -596,8 +565,6 @@ public: virtual void LoadWorldStates() = 0; [[nodiscard]] virtual bool IsPvPRealm() const = 0; [[nodiscard]] virtual bool IsFFAPvPRealm() const = 0; - virtual void KickAll() = 0; - virtual void KickAllLess(AccountTypes sec) = 0; virtual uint32 GetNextWhoListUpdateDelaySecs() = 0; virtual void ProcessCliCommands() = 0; virtual void QueueCliCommand(CliCommandHolder* commandHolder) = 0; @@ -613,7 +580,6 @@ public: [[nodiscard]] virtual std::string const& GetRealmName() const = 0; virtual void SetRealmName(std::string name) = 0; virtual void RemoveOldCorpses() = 0; - virtual void DoForAllOnlinePlayers(std::function exec) = 0; }; #endif //AZEROTHCORE_IWORLD_H diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 76c2075b4..c4282b112 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -92,6 +92,7 @@ #include "WhoListCacheMgr.h" #include "WorldPacket.h" #include "WorldSession.h" +#include "WorldSessionMgr.h" #include "WorldState.h" #include #include @@ -109,15 +110,10 @@ Realm realm; /// World constructor World::World() { - _playerLimit = 0; _allowedSecurityLevel = SEC_PLAYER; _allowMovement = true; _shutdownMask = 0; _shutdownTimer = 0; - _maxActiveSessionCount = 0; - _maxQueuedSessionCount = 0; - _playerCount = 0; - _maxPlayerCount = 0; _nextDailyQuestReset = 0s; _nextWeeklyQuestReset = 0s; _nextMonthlyQuestReset = 0s; @@ -138,28 +134,12 @@ World::World() /// World destructor World::~World() { - ///- Empty the kicked session set - while (!_sessions.empty()) - { - // not remove from queue, prevent loading new sessions - delete _sessions.begin()->second; - _sessions.erase(_sessions.begin()); - } - - while (!_offlineSessions.empty()) - { - delete _offlineSessions.begin()->second; - _offlineSessions.erase(_offlineSessions.begin()); - } - CliCommandHolder* command = nullptr; while (_cliCmdQueue.next(command)) delete command; VMAP::VMapFactory::clear(); MMAP::MMapFactory::clear(); - - //TODO free addSessQueue } std::unique_ptr& getWorldInstance() @@ -168,26 +148,6 @@ std::unique_ptr& getWorldInstance() return instance; } -/// Find a player in a specified zone -Player* World::FindPlayerInZone(uint32 zone) -{ - ///- circle through active sessions and return the first player found in the zone - SessionMap::const_iterator itr; - for (itr = _sessions.begin(); itr != _sessions.end(); ++itr) - { - if (!itr->second) - continue; - - Player* player = itr->second->GetPlayer(); - if (!player) - continue; - - if (player->IsInWorld() && player->GetZoneId() == zone) - return player; - } - return nullptr; -} - bool World::IsClosed() const { return _isClosed; @@ -201,211 +161,6 @@ void World::SetClosed(bool val) sScriptMgr->OnOpenStateChange(!val); } -/// Find a session by its id -WorldSession* World::FindSession(uint32 id) const -{ - SessionMap::const_iterator itr = _sessions.find(id); - - if (itr != _sessions.end()) - return itr->second; // also can return nullptr for kicked session - else - return nullptr; -} - -WorldSession* World::FindOfflineSession(uint32 id) const -{ - SessionMap::const_iterator itr = _offlineSessions.find(id); - if (itr != _offlineSessions.end()) - return itr->second; - else - return nullptr; -} - -WorldSession* World::FindOfflineSessionForCharacterGUID(ObjectGuid::LowType guidLow) const -{ - if (_offlineSessions.empty()) - return nullptr; - - for (SessionMap::const_iterator itr = _offlineSessions.begin(); itr != _offlineSessions.end(); ++itr) - if (itr->second->GetGuidLow() == guidLow) - return itr->second; - - return nullptr; -} - -/// Remove a given session -bool World::KickSession(uint32 id) -{ - ///- Find the session, kick the user, but we can't delete session at this moment to prevent iterator invalidation - SessionMap::const_iterator itr = _sessions.find(id); - - if (itr != _sessions.end() && itr->second) - { - if (itr->second->PlayerLoading()) - return false; - - itr->second->KickPlayer("KickSession", false); - } - - return true; -} - -void World::AddSession(WorldSession* s) -{ - _addSessQueue.add(s); -} - -void World::AddSession_(WorldSession* s) -{ - ASSERT (s); - - // kick existing session with same account (if any) - // if character on old session is being loaded, then return - if (!KickSession(s->GetAccountId())) - { - s->KickPlayer("kick existing session with same account"); - delete s; // session not added yet in session list, so not listed in queue - return; - } - - SessionMap::const_iterator old = _sessions.find(s->GetAccountId()); - if (old != _sessions.end()) - { - WorldSession* oldSession = old->second; - - if (!RemoveQueuedPlayer(oldSession) && getIntConfig(CONFIG_INTERVAL_DISCONNECT_TOLERANCE)) - _disconnects[s->GetAccountId()] = GameTime::GetGameTime().count(); - - // pussywizard: - if (oldSession->HandleSocketClosed()) - { - // there should be no offline session if current one is logged onto a character - SessionMap::iterator iter; - if ((iter = _offlineSessions.find(oldSession->GetAccountId())) != _offlineSessions.end()) - { - WorldSession* tmp = iter->second; - _offlineSessions.erase(iter); - delete tmp; - } - oldSession->SetOfflineTime(GameTime::GetGameTime().count()); - _offlineSessions[oldSession->GetAccountId()] = oldSession; - } - else - { - delete oldSession; - } - } - - _sessions[s->GetAccountId()] = s; - - uint32 Sessions = GetActiveAndQueuedSessionCount(); - uint32 pLimit = GetPlayerAmountLimit(); - - // don't count this session when checking player limit - --Sessions; - - if (pLimit > 0 && Sessions >= pLimit && AccountMgr::IsPlayerAccount(s->GetSecurity()) && !s->CanSkipQueue() && !HasRecentlyDisconnected(s)) - { - AddQueuedPlayer(s); - UpdateMaxSessionCounters(); - return; - } - - s->InitializeSession(); - - UpdateMaxSessionCounters(); -} - -bool World::HasRecentlyDisconnected(WorldSession* session) -{ - if (!session) - return false; - - if (uint32 tolerance = getIntConfig(CONFIG_INTERVAL_DISCONNECT_TOLERANCE)) - { - for (DisconnectMap::iterator i = _disconnects.begin(); i != _disconnects.end();) - { - if ((GameTime::GetGameTime().count() - i->second) < tolerance) - { - if (i->first == session->GetAccountId()) - return true; - ++i; - } - else - _disconnects.erase(i++); - } - } - return false; -} - -int32 World::GetQueuePos(WorldSession* sess) -{ - uint32 position = 1; - - for (Queue::const_iterator iter = _queuedPlayer.begin(); iter != _queuedPlayer.end(); ++iter, ++position) - if ((*iter) == sess) - return position; - - return 0; -} - -void World::AddQueuedPlayer(WorldSession* sess) -{ - sess->SetInQueue(true); - _queuedPlayer.push_back(sess); - - // The 1st SMSG_AUTH_RESPONSE needs to contain other info too. - sess->SendAuthResponse(AUTH_WAIT_QUEUE, false, GetQueuePos(sess)); -} - -bool World::RemoveQueuedPlayer(WorldSession* sess) -{ - uint32 sessions = GetActiveSessionCount(); - - uint32 position = 1; - Queue::iterator iter = _queuedPlayer.begin(); - - // search to remove and count skipped positions - bool found = false; - - for (; iter != _queuedPlayer.end(); ++iter, ++position) - { - if (*iter == sess) - { - sess->SetInQueue(false); - sess->ResetTimeOutTime(false); - iter = _queuedPlayer.erase(iter); - found = true; - break; - } - } - - // if session not queued then it was an active session - if (!found) - { - ASSERT(sessions > 0); - --sessions; - } - - // accept first in queue - if ((!GetPlayerAmountLimit() || sessions < GetPlayerAmountLimit()) && !_queuedPlayer.empty()) - { - WorldSession* pop_sess = _queuedPlayer.front(); - pop_sess->InitializeSession(); - _queuedPlayer.pop_front(); - - // update iter to point first queued socket or end() if queue is empty now - iter = _queuedPlayer.begin(); - position = 1; - } - - // update queue position from iter to end() - for (; iter != _queuedPlayer.end(); ++iter, ++position) - (*iter)->SendAuthWaitQueue(position); - - return found; -} - /// Initialize config values void World::LoadConfigSettings(bool reload) { @@ -431,9 +186,7 @@ void World::LoadConfigSettings(bool reload) ///- Read the player limit and the Message of the day from the config file if (!reload) - { - SetPlayerAmountLimit(sConfigMgr->GetOption("PlayerLimit", 1000)); - } + sWorldSessionMgr->SetPlayerAmountLimit(sConfigMgr->GetOption("PlayerLimit", 1000)); ///- Read ticket system setting from the config file _bool_configs[CONFIG_ALLOW_TICKETS] = sConfigMgr->GetOption("AllowTickets", true); @@ -2293,9 +2046,9 @@ void World::Update(uint32 diff) sWorldUpdateTime.UpdateWithDiff(diff); // Record update if recording set in log and diff is greater then minimum set in log - sWorldUpdateTime.RecordUpdateTime(GameTime::GetGameTimeMS(), diff, GetActiveSessionCount()); + sWorldUpdateTime.RecordUpdateTime(GameTime::GetGameTimeMS(), diff, sWorldSessionMgr->GetActiveSessionCount()); - DynamicVisibilityMgr::Update(GetActiveSessionCount()); + DynamicVisibilityMgr::Update(sWorldSessionMgr->GetActiveSessionCount()); ///- Update the different timers for (int i = 0; i < WUPDATE_COUNT; ++i) @@ -2376,8 +2129,10 @@ void World::Update(uint32 diff) _mail_expire_check_timer = currentGameTime + 6h; } - METRIC_TIMER("world_update_time", METRIC_TAG("type", "Update sessions")); - UpdateSessions(diff); + { + METRIC_TIMER("world_update_time", METRIC_TAG("type", "Update sessions")); + sWorldSessionMgr->UpdateSessions(diff); + } ///
  • Handle weather updates when the timer has passed if (_timers[WUPDATE_WEATHERS].Passed()) @@ -2463,7 +2218,7 @@ void World::Update(uint32 diff) LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_UPTIME_PLAYERS); stmt->SetData(0, uint32(GameTime::GetUptime().count())); - stmt->SetData(1, uint16(GetMaxPlayerCount())); + stmt->SetData(1, uint16(sWorldSessionMgr->GetMaxPlayerCount())); stmt->SetData(2, realm.Id.Realm); stmt->SetData(3, uint32(GameTime::GetStartTime().count())); LoginDatabase.Execute(stmt); @@ -2535,41 +2290,6 @@ void World::ForceGameEventUpdate() _timers[WUPDATE_EVENTS].Reset(); } -/// Send a packet to all players (except self if mentioned) -void World::SendGlobalMessage(WorldPacket const* packet, WorldSession* self, TeamId teamId) -{ - SessionMap::const_iterator itr; - for (itr = _sessions.begin(); itr != _sessions.end(); ++itr) - { - if (itr->second && - itr->second->GetPlayer() && - itr->second->GetPlayer()->IsInWorld() && - itr->second != self && - (teamId == TEAM_NEUTRAL || itr->second->GetPlayer()->GetTeamId() == teamId)) - { - itr->second->SendPacket(packet); - } - } -} - -/// Send a packet to all GMs (except self if mentioned) -void World::SendGlobalGMMessage(WorldPacket const* packet, WorldSession* self, TeamId teamId) -{ - SessionMap::iterator itr; - for (itr = _sessions.begin(); itr != _sessions.end(); ++itr) - { - if (itr->second && - itr->second->GetPlayer() && - itr->second->GetPlayer()->IsInWorld() && - itr->second != self && - !AccountMgr::IsPlayerAccount(itr->second->GetSecurity()) && - (teamId == TEAM_NEUTRAL || itr->second->GetPlayer()->GetTeamId() == teamId)) - { - itr->second->SendPacket(packet); - } - } -} - namespace Acore { class WorldWorldTextBuilder @@ -2615,60 +2335,6 @@ namespace Acore }; } // namespace Acore -/// Send a packet to all players (or players selected team) in the zone (except self if mentioned) -bool World::SendZoneMessage(uint32 zone, WorldPacket const* packet, WorldSession* self, TeamId teamId) -{ - bool foundPlayerToSend = false; - SessionMap::const_iterator itr; - - for (itr = _sessions.begin(); itr != _sessions.end(); ++itr) - { - if (itr->second && - itr->second->GetPlayer() && - itr->second->GetPlayer()->IsInWorld() && - itr->second->GetPlayer()->GetZoneId() == zone && - itr->second != self && - (teamId == TEAM_NEUTRAL || itr->second->GetPlayer()->GetTeamId() == teamId)) - { - itr->second->SendPacket(packet); - foundPlayerToSend = true; - } - } - - return foundPlayerToSend; -} - -/// Send a System Message to all players in the zone (except self if mentioned) -void World::SendZoneText(uint32 zone, std::string text, WorldSession* self, TeamId teamId) -{ - WorldPacket data; - ChatHandler::BuildChatPacket(data, CHAT_MSG_SYSTEM, LANG_UNIVERSAL, nullptr, nullptr, text.c_str()); - SendZoneMessage(zone, &data, self, teamId); -} - -/// Kick (and save) all players -void World::KickAll() -{ - _queuedPlayer.clear(); // prevent send queue update packet and login queued sessions - - // session not removed at kick and will removed in next update tick - for (SessionMap::const_iterator itr = _sessions.begin(); itr != _sessions.end(); ++itr) - itr->second->KickPlayer("KickAll sessions"); - - // pussywizard: kick offline sessions - for (SessionMap::const_iterator itr = _offlineSessions.begin(); itr != _offlineSessions.end(); ++itr) - itr->second->KickPlayer("KickAll offline sessions"); -} - -/// Kick (and save) all players with security level less `sec` -void World::KickAllLess(AccountTypes sec) -{ - // session not removed at kick and will removed in next update tick - for (SessionMap::const_iterator itr = _sessions.begin(); itr != _sessions.end(); ++itr) - if (itr->second->GetSecurity() < sec) - itr->second->KickPlayer("KickAllLess"); -} - /// Update the game time void World::_UpdateGameTime() { @@ -2684,7 +2350,7 @@ void World::_UpdateGameTime() ///- ... and it is overdue, stop the world (set m_stopEvent) if (_shutdownTimer <= elapsed.count()) { - if (!(_shutdownMask & SHUTDOWN_MASK_IDLE) || GetActiveAndQueuedSessionCount() == 0) + if (!(_shutdownMask & SHUTDOWN_MASK_IDLE) || sWorldSessionMgr->GetActiveAndQueuedSessionCount() == 0) _stopEvent = true; // exist code already set else _shutdownTimer = 1; // minimum timer value to wait idle state @@ -2715,7 +2381,7 @@ void World::ShutdownServ(uint32 time, uint32 options, uint8 exitcode, std::strin ///- If the shutdown time is 0, set m_stopEvent (except if shutdown is 'idle' with remaining sessions) if (time == 0) { - if (!(options & SHUTDOWN_MASK_IDLE) || GetActiveAndQueuedSessionCount() == 0) + if (!(options & SHUTDOWN_MASK_IDLE) || sWorldSessionMgr->GetActiveAndQueuedSessionCount() == 0) _stopEvent = true; // exist code already set else _shutdownTimer = 1; //So that the session count is re-evaluated at next world tick @@ -2767,7 +2433,7 @@ void World::ShutdownMsg(bool show, Player* player, std::string const& reason) str += " - " + _shutdownReason; ServerMessageType msgid = (_shutdownMask & SHUTDOWN_MASK_RESTART) ? SERVER_MSG_RESTART_TIME : SERVER_MSG_SHUTDOWN_TIME; - SendServerMessage(msgid, str, player); + sWorldSessionMgr->SendServerMessage(msgid, str, player); LOG_WARN("server.worldserver", "Server {} in {}", (_shutdownMask & SHUTDOWN_MASK_RESTART ? "restarting" : "shutdown"), str); } } @@ -2784,100 +2450,13 @@ void World::ShutdownCancel() _shutdownMask = 0; _shutdownTimer = 0; _exitCode = SHUTDOWN_EXIT_CODE; // to default value - SendServerMessage(msgid); + sWorldSessionMgr->SendServerMessage(msgid); LOG_DEBUG("server.worldserver", "Server {} cancelled.", (_shutdownMask & SHUTDOWN_MASK_RESTART ? "restart" : "shuttingdown")); sScriptMgr->OnShutdownCancel(); } -/// Send a server message to the user(s) -void World::SendServerMessage(ServerMessageType messageID, std::string stringParam /*= ""*/, Player* player /*= nullptr*/) -{ - WorldPackets::Chat::ChatServerMessage chatServerMessage; - chatServerMessage.MessageID = int32(messageID); - if (messageID <= SERVER_MSG_STRING) - chatServerMessage.StringParam = stringParam; - - if (player) - player->SendDirectMessage(chatServerMessage.Write()); - else - SendGlobalMessage(chatServerMessage.Write()); -} - -void World::UpdateSessions(uint32 diff) -{ - { - METRIC_DETAILED_NO_THRESHOLD_TIMER("world_update_time", - METRIC_TAG("type", "Add sessions"), - METRIC_TAG("parent_type", "Update sessions")); - - ///- Add new sessions - WorldSession* sess = nullptr; - while (_addSessQueue.next(sess)) - { - AddSession_(sess); - } - } - - ///- Then send an update signal to remaining ones - for (SessionMap::iterator itr = _sessions.begin(), next; itr != _sessions.end(); itr = next) - { - next = itr; - ++next; - - ///- and remove not active sessions from the list - WorldSession* pSession = itr->second; - WorldSessionFilter updater(pSession); - - // pussywizard: - if (pSession->HandleSocketClosed()) - { - if (!RemoveQueuedPlayer(pSession) && getIntConfig(CONFIG_INTERVAL_DISCONNECT_TOLERANCE)) - _disconnects[pSession->GetAccountId()] = GameTime::GetGameTime().count(); - _sessions.erase(itr); - // there should be no offline session if current one is logged onto a character - SessionMap::iterator iter; - if ((iter = _offlineSessions.find(pSession->GetAccountId())) != _offlineSessions.end()) - { - WorldSession* tmp = iter->second; - _offlineSessions.erase(iter); - delete tmp; - } - pSession->SetOfflineTime(GameTime::GetGameTime().count()); - _offlineSessions[pSession->GetAccountId()] = pSession; - continue; - } - - [[maybe_unused]] uint32 currentSessionId = itr->first; - METRIC_DETAILED_TIMER("world_update_sessions_time", METRIC_TAG("account_id", std::to_string(currentSessionId))); - - if (!pSession->Update(diff, updater)) - { - if (!RemoveQueuedPlayer(pSession) && getIntConfig(CONFIG_INTERVAL_DISCONNECT_TOLERANCE)) - _disconnects[pSession->GetAccountId()] = GameTime::GetGameTime().count(); - _sessions.erase(itr); - delete pSession; - } - } - - // pussywizard: - if (_offlineSessions.empty()) - return; - uint32 currTime = GameTime::GetGameTime().count(); - for (SessionMap::iterator itr = _offlineSessions.begin(), next; itr != _offlineSessions.end(); itr = next) - { - next = itr; - ++next; - WorldSession* pSession = itr->second; - if (!pSession->GetPlayer() || pSession->GetOfflineTime() + 60 < currTime || pSession->IsKicked()) - { - _offlineSessions.erase(itr); - delete pSession; - } - } -} - // This handles the issued and queued CLI commands void World::ProcessCliCommands() { @@ -2995,7 +2574,8 @@ void World::ResetDailyQuests() CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_QUEST_STATUS_DAILY); CharacterDatabase.Execute(stmt); - for (SessionMap::const_iterator itr = _sessions.begin(); itr != _sessions.end(); ++itr) + WorldSessionMgr::SessionMap const& sessionMap = sWorldSessionMgr->GetAllSessions(); + for (WorldSessionMgr::SessionMap::const_iterator itr = sessionMap.begin(); itr != sessionMap.end(); ++itr) if (itr->second->GetPlayer()) itr->second->GetPlayer()->ResetDailyQuestStatus(); @@ -3022,7 +2602,7 @@ void World::SetPlayerSecurityLimit(AccountTypes _sec) bool update = sec > _allowedSecurityLevel; _allowedSecurityLevel = sec; if (update) - KickAllLess(_allowedSecurityLevel); + sWorldSessionMgr->KickAllLess(_allowedSecurityLevel); } void World::ResetWeeklyQuests() @@ -3030,7 +2610,8 @@ void World::ResetWeeklyQuests() CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_QUEST_STATUS_WEEKLY); CharacterDatabase.Execute(stmt); - for (SessionMap::const_iterator itr = _sessions.begin(); itr != _sessions.end(); ++itr) + WorldSessionMgr::SessionMap const& sessionMap = sWorldSessionMgr->GetAllSessions(); + for (WorldSessionMgr::SessionMap::const_iterator itr = sessionMap.begin(); itr != sessionMap.end(); ++itr) if (itr->second->GetPlayer()) itr->second->GetPlayer()->ResetWeeklyQuestStatus(); @@ -3048,7 +2629,8 @@ void World::ResetMonthlyQuests() CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_QUEST_STATUS_MONTHLY); CharacterDatabase.Execute(stmt); - for (SessionMap::const_iterator itr = _sessions.begin(); itr != _sessions.end(); ++itr) + WorldSessionMgr::SessionMap const& sessionMap = sWorldSessionMgr->GetAllSessions(); + for (WorldSessionMgr::SessionMap::const_iterator itr = sessionMap.begin(); itr != sessionMap.end(); ++itr) if (itr->second->GetPlayer()) itr->second->GetPlayer()->ResetMonthlyQuestStatus(); @@ -3062,7 +2644,8 @@ void World::ResetEventSeasonalQuests(uint16 event_id) stmt->SetData(0, event_id); CharacterDatabase.Execute(stmt); - for (SessionMap::const_iterator itr = _sessions.begin(); itr != _sessions.end(); ++itr) + WorldSessionMgr::SessionMap const& sessionMap = sWorldSessionMgr->GetAllSessions(); + for (WorldSessionMgr::SessionMap::const_iterator itr = sessionMap.begin(); itr != sessionMap.end(); ++itr) if (itr->second->GetPlayer()) itr->second->GetPlayer()->ResetSeasonalQuestStatus(event_id); } @@ -3074,7 +2657,8 @@ void World::ResetRandomBG() CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_BATTLEGROUND_RANDOM); CharacterDatabase.Execute(stmt); - for (SessionMap::const_iterator itr = _sessions.begin(); itr != _sessions.end(); ++itr) + WorldSessionMgr::SessionMap const& sessionMap = sWorldSessionMgr->GetAllSessions(); + for (WorldSessionMgr::SessionMap::const_iterator itr = sessionMap.begin(); itr != sessionMap.end(); ++itr) if (itr->second->GetPlayer()) itr->second->GetPlayer()->SetRandomWinner(false); @@ -3101,12 +2685,6 @@ void World::ResetGuildCap() sGuildMgr->ResetTimes(); } -void World::UpdateMaxSessionCounters() -{ - _maxActiveSessionCount = std::max(_maxActiveSessionCount, uint32(_sessions.size() - _queuedPlayer.size())); - _maxQueuedSessionCount = std::max(_maxQueuedSessionCount, uint32(_queuedPlayer.size())); -} - void World::LoadDBVersion() { QueryResult result = WorldDatabase.Query("SELECT db_version, cache_id FROM version LIMIT 1"); @@ -3126,8 +2704,8 @@ void World::LoadDBVersion() void World::UpdateAreaDependentAuras() { - SessionMap::const_iterator itr; - for (itr = _sessions.begin(); itr != _sessions.end(); ++itr) + WorldSessionMgr::SessionMap const& sessionMap = sWorldSessionMgr->GetAllSessions(); + for (WorldSessionMgr::SessionMap::const_iterator itr = sessionMap.begin(); itr != sessionMap.end(); ++itr) if (itr->second && itr->second->GetPlayer() && itr->second->GetPlayer()->IsInWorld()) { itr->second->GetPlayer()->UpdateAreaDependentAuras(itr->second->GetPlayer()->GetAreaId()); @@ -3196,23 +2774,6 @@ void World::RemoveOldCorpses() _timers[WUPDATE_CORPSES].SetCurrent(_timers[WUPDATE_CORPSES].GetInterval()); } -void World::DoForAllOnlinePlayers(std::function exec) -{ - std::shared_lock lock(*HashMapHolder::GetLock()); - for (auto const& it : ObjectAccessor::GetPlayers()) - { - if (Player* player = it.second) - { - if (!player->IsInWorld()) - { - continue; - } - - exec(player); - } - } -} - bool World::IsPvPRealm() const { return getIntConfig(CONFIG_GAME_TYPE) == REALM_TYPE_PVP || getIntConfig(CONFIG_GAME_TYPE) == REALM_TYPE_RPPVP || getIntConfig(CONFIG_GAME_TYPE) == REALM_TYPE_FFA_PVP; diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index 75f3bbdac..73ee81c4d 100644 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -155,34 +155,6 @@ public: static uint32 m_worldLoopCounter; - [[nodiscard]] WorldSession* FindSession(uint32 id) const override; - [[nodiscard]] WorldSession* FindOfflineSession(uint32 id) const override; - [[nodiscard]] WorldSession* FindOfflineSessionForCharacterGUID(ObjectGuid::LowType guidLow) const override; - void AddSession(WorldSession* s) override; - bool KickSession(uint32 id) override; - /// Get the number of current active sessions - void UpdateMaxSessionCounters() override; - [[nodiscard]] const SessionMap& GetAllSessions() const override { return _sessions; } - [[nodiscard]] uint32 GetActiveAndQueuedSessionCount() const override { return _sessions.size(); } - [[nodiscard]] uint32 GetActiveSessionCount() const override { return _sessions.size() - _queuedPlayer.size(); } - [[nodiscard]] uint32 GetQueuedSessionCount() const override { return _queuedPlayer.size(); } - /// Get the maximum number of parallel sessions on the server since last reboot - [[nodiscard]] uint32 GetMaxQueuedSessionCount() const override { return _maxQueuedSessionCount; } - [[nodiscard]] uint32 GetMaxActiveSessionCount() const override { return _maxActiveSessionCount; } - /// Get number of players - [[nodiscard]] inline uint32 GetPlayerCount() const override { return _playerCount; } - [[nodiscard]] inline uint32 GetMaxPlayerCount() const override { return _maxPlayerCount; } - - /// Increase/Decrease number of players - inline void IncreasePlayerCount() override - { - _playerCount++; - _maxPlayerCount = std::max(_maxPlayerCount, _playerCount); - } - inline void DecreasePlayerCount() override { _playerCount--; } - - Player* FindPlayerInZone(uint32 zone) override; - /// Deny clients? [[nodiscard]] bool IsClosed() const override; @@ -194,17 +166,6 @@ public: void SetPlayerSecurityLimit(AccountTypes sec) override; void LoadDBAllowedSecurityLevel() override; - /// Active session server limit - void SetPlayerAmountLimit(uint32 limit) override { _playerLimit = limit; } - [[nodiscard]] uint32 GetPlayerAmountLimit() const override { return _playerLimit; } - - //player Queue - typedef std::list Queue; - void AddQueuedPlayer(WorldSession*) override; - bool RemoveQueuedPlayer(WorldSession* session) override; - int32 GetQueuePos(WorldSession*) override; - bool HasRecentlyDisconnected(WorldSession*) override; - /// \todo Actions on m_allowMovement still to be implemented /// Is movement allowed? [[nodiscard]] bool getAllowMovement() const override { return _allowMovement; } @@ -236,12 +197,6 @@ public: void SetInitialWorldSettings() override; void LoadConfigSettings(bool reload = false) override; - void SendGlobalMessage(WorldPacket const* packet, WorldSession* self = nullptr, TeamId teamId = TEAM_NEUTRAL) override; - void SendGlobalGMMessage(WorldPacket const* packet, WorldSession* self = nullptr, TeamId teamId = TEAM_NEUTRAL) override; - bool SendZoneMessage(uint32 zone, WorldPacket const* packet, WorldSession* self = nullptr, TeamId teamId = TEAM_NEUTRAL) override; - void SendZoneText(uint32 zone, std::string text, WorldSession* self = nullptr, TeamId teamId = TEAM_NEUTRAL) override; - void SendServerMessage(ServerMessageType messageID, std::string stringParam = "", Player* player = nullptr) override; - /// Are we in the middle of a shutdown? [[nodiscard]] bool IsShuttingDown() const override { return _shutdownTimer > 0; } [[nodiscard]] uint32 GetShutDownTimeLeft() const override { return _shutdownTimer; } @@ -254,7 +209,6 @@ public: void Update(uint32 diff) override; - void UpdateSessions(uint32 diff) override; /// Set a server rate (see #Rates) void setRate(Rates rate, float value) override { _rate_values[rate] = value; } /// Get a server rate (see #Rates) @@ -307,9 +261,6 @@ public: [[nodiscard]] bool IsPvPRealm() const override; [[nodiscard]] bool IsFFAPvPRealm() const override; - void KickAll() override; - void KickAllLess(AccountTypes sec) override; - // for max speed access static float GetMaxVisibleDistanceOnContinents() { return _maxVisibleDistanceOnContinents; } static float GetMaxVisibleDistanceInInstances() { return _maxVisibleDistanceInInstances; } @@ -342,8 +293,6 @@ public: void RemoveOldCorpses() override; - void DoForAllOnlinePlayers(std::function exec) override; - protected: void _UpdateGameTime(); // callback for UpdateRealmCharacters @@ -375,15 +324,6 @@ private: IntervalTimer _timers[WUPDATE_COUNT]; Seconds _mail_expire_check_timer; - SessionMap _sessions; - SessionMap _offlineSessions; - typedef std::unordered_map DisconnectMap; - DisconnectMap _disconnects; - uint32 _maxActiveSessionCount; - uint32 _maxQueuedSessionCount; - uint32 _playerCount; - uint32 _maxPlayerCount; - std::string _newCharString; float _rate_values[MAX_RATES]; @@ -392,7 +332,6 @@ private: float _float_configs[FLOAT_CONFIG_VALUE_COUNT]; typedef std::map WorldStatesMap; WorldStatesMap _worldstates; - uint32 _playerLimit; AccountTypes _allowedSecurityLevel; LocaleConstant _defaultDbcLocale; // from config for one from loaded DBC locales uint32 _availableDbcLocaleMask; // by loaded DBC @@ -418,13 +357,6 @@ private: Seconds _nextCalendarOldEventsDeletionTime; Seconds _nextGuildReset; - //Player Queue - Queue _queuedPlayer; - - // sessions that are added async - void AddSession_(WorldSession* s); - LockedQueue _addSessQueue; - // used versions std::string _dbVersion; diff --git a/src/server/scripts/Commands/cs_message.cpp b/src/server/scripts/Commands/cs_message.cpp index 717e94ef7..1667034ec 100644 --- a/src/server/scripts/Commands/cs_message.cpp +++ b/src/server/scripts/Commands/cs_message.cpp @@ -32,6 +32,7 @@ EndScriptData */ #include "Player.h" #include "World.h" #include "WorldSession.h" +#include "WorldSessionMgr.h" using namespace Acore::ChatCommands; @@ -87,7 +88,7 @@ public: if (message.empty()) return false; - sWorld->SendServerMessage(SERVER_MSG_STRING, Acore::StringFormat(handler->GetAcoreString(LANG_SYSTEMMESSAGE), message.data())); + sWorldSessionMgr->SendServerMessage(SERVER_MSG_STRING, Acore::StringFormat(handler->GetAcoreString(LANG_SYSTEMMESSAGE), message.data())); return true; } @@ -112,7 +113,7 @@ public: WorldPacket data(SMSG_NOTIFICATION, (str.size() + 1)); data << str; - sWorld->SendGlobalMessage(&data); + sWorldSessionMgr->SendGlobalMessage(&data); return true; } @@ -128,7 +129,7 @@ public: WorldPacket data(SMSG_NOTIFICATION, (str.size() + 1)); data << str; - sWorld->SendGlobalGMMessage(&data); + sWorldSessionMgr->SendGlobalGMMessage(&data); return true; } diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index ce10a094b..cbfc4517c 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -45,6 +45,7 @@ #include "TargetedMovementGenerator.h" #include "Tokenize.h" #include "WeatherMgr.h" +#include "WorldSessionMgr.h" /// @todo: this import is not necessary for compilation and marked as unused by the IDE // however, for some reasons removing it would cause a damn linking issue @@ -2451,7 +2452,7 @@ public: // find only player from same account if any if (!target) - if (WorldSession* session = sWorld->FindSession(accountId)) + if (WorldSession* session = sWorldSessionMgr->FindSession(accountId)) { target = session->GetPlayer(); } @@ -2557,7 +2558,7 @@ public: // find only player from same account if any if (!playerTarget) { - if (WorldSession* session = sWorld->FindSession(accountId)) + if (WorldSession* session = sWorldSessionMgr->FindSession(accountId)) { playerTarget = session->GetPlayer(); } @@ -2946,7 +2947,7 @@ public: return false; } - sWorld->SendGlobalMessage(WorldPackets::Misc::Playsound(soundId).Write()); + sWorldSessionMgr->SendGlobalMessage(WorldPackets::Misc::Playsound(soundId).Write()); handler->PSendSysMessage(LANG_COMMAND_PLAYED_TO_ALL, soundId); return true; diff --git a/src/server/scripts/Commands/cs_reset.cpp b/src/server/scripts/Commands/cs_reset.cpp index e90da5af4..4b6328cb3 100644 --- a/src/server/scripts/Commands/cs_reset.cpp +++ b/src/server/scripts/Commands/cs_reset.cpp @@ -29,6 +29,7 @@ EndScriptData */ #include "Pet.h" #include "Player.h" #include "ScriptMgr.h" +#include "WorldSessionMgr.h" using namespace Acore::ChatCommands; @@ -302,7 +303,7 @@ public: stmt->SetData(0, uint16(atLogin)); CharacterDatabase.Execute(stmt); - sWorld->DoForAllOnlinePlayers([&] (Player* player){ + sWorldSessionMgr->DoForAllOnlinePlayers([&] (Player* player){ player->SetAtLoginFlag(atLogin); }); diff --git a/src/server/scripts/Commands/cs_server.cpp b/src/server/scripts/Commands/cs_server.cpp index a789420a4..088993244 100644 --- a/src/server/scripts/Commands/cs_server.cpp +++ b/src/server/scripts/Commands/cs_server.cpp @@ -36,6 +36,7 @@ #include "UpdateTime.h" #include "VMapFactory.h" #include "VMapMgr2.h" +#include "WorldSessionMgr.h" #include #include #include @@ -259,10 +260,10 @@ public: static bool HandleServerInfoCommand(ChatHandler* handler) { std::string realmName = sWorld->GetRealmName(); - uint32 playerCount = sWorld->GetPlayerCount(); - uint32 activeSessionCount = sWorld->GetActiveSessionCount(); - uint32 queuedSessionCount = sWorld->GetQueuedSessionCount(); - uint32 connPeak = sWorld->GetMaxActiveSessionCount(); + uint32 playerCount = sWorldSessionMgr->GetPlayerCount(); + uint32 activeSessionCount = sWorldSessionMgr->GetActiveSessionCount(); + uint32 queuedSessionCount = sWorldSessionMgr->GetQueuedSessionCount(); + uint32 connPeak = sWorldSessionMgr->GetMaxActiveSessionCount(); handler->PSendSysMessage("{}", GitRevision::GetFullVersion()); if (!queuedSessionCount) diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPEP.cpp b/src/server/scripts/OutdoorPvP/OutdoorPvPEP.cpp index 474f7306a..33a1e63ee 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPEP.cpp +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPEP.cpp @@ -27,6 +27,7 @@ #include "Player.h" #include "World.h" #include "WorldPacket.h" +#include "WorldSessionMgr.h" OPvPCapturePointEP_EWT::OPvPCapturePointEP_EWT(OutdoorPvP* pvp) : OPvPCapturePoint(pvp), m_TowerState(EP_TS_N), m_UnitsSummonedSideId(TEAM_NEUTRAL) @@ -40,12 +41,12 @@ void OPvPCapturePointEP_EWT::ChangeState() // if changing from controlling alliance to horde or vice versa if (_oldState == OBJECTIVESTATE_ALLIANCE && _oldState != _state) { - sWorld->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_LOSE_EWT_A)); + sWorldSessionMgr->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_LOSE_EWT_A)); ((OutdoorPvPEP*)_pvp)->SetControlledState(EP_EWT, TEAM_NEUTRAL); } else if (_oldState == OBJECTIVESTATE_HORDE && _oldState != _state) { - sWorld->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_LOSE_EWT_H)); + sWorldSessionMgr->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_LOSE_EWT_H)); ((OutdoorPvPEP*)_pvp)->SetControlledState(EP_EWT, TEAM_NEUTRAL); } @@ -58,14 +59,14 @@ void OPvPCapturePointEP_EWT::ChangeState() artkit = 2; SummonSupportUnitAtNorthpassTower(TEAM_ALLIANCE); ((OutdoorPvPEP*)_pvp)->SetControlledState(EP_EWT, TEAM_ALLIANCE); - if (_oldState != _state) sWorld->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_CAPTURE_EWT_A)); + if (_oldState != _state) sWorldSessionMgr->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_CAPTURE_EWT_A)); break; case OBJECTIVESTATE_HORDE: m_TowerState = EP_TS_H; artkit = 1; SummonSupportUnitAtNorthpassTower(TEAM_HORDE); ((OutdoorPvPEP*)_pvp)->SetControlledState(EP_EWT, TEAM_HORDE); - if (_oldState != _state) sWorld->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_CAPTURE_EWT_H)); + if (_oldState != _state) sWorldSessionMgr->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_CAPTURE_EWT_H)); break; case OBJECTIVESTATE_NEUTRAL: m_TowerState = EP_TS_N; @@ -172,12 +173,12 @@ void OPvPCapturePointEP_NPT::ChangeState() // if changing from controlling alliance to horde or vice versa if (_oldState == OBJECTIVESTATE_ALLIANCE && _oldState != _state) { - sWorld->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_LOSE_NPT_A)); + sWorldSessionMgr->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_LOSE_NPT_A)); ((OutdoorPvPEP*)_pvp)->SetControlledState(EP_NPT, TEAM_NEUTRAL); } else if (_oldState == OBJECTIVESTATE_HORDE && _oldState != _state) { - sWorld->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_LOSE_NPT_H)); + sWorldSessionMgr->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_LOSE_NPT_H)); ((OutdoorPvPEP*)_pvp)->SetControlledState(EP_NPT, TEAM_NEUTRAL); } @@ -190,14 +191,14 @@ void OPvPCapturePointEP_NPT::ChangeState() artkit = 2; SummonGO(TEAM_ALLIANCE); ((OutdoorPvPEP*)_pvp)->SetControlledState(EP_NPT, TEAM_ALLIANCE); - if (_oldState != _state) sWorld->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_CAPTURE_NPT_A)); + if (_oldState != _state) sWorldSessionMgr->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_CAPTURE_NPT_A)); break; case OBJECTIVESTATE_HORDE: m_TowerState = EP_TS_H; artkit = 1; SummonGO(TEAM_HORDE); ((OutdoorPvPEP*)_pvp)->SetControlledState(EP_NPT, TEAM_HORDE); - if (_oldState != _state) sWorld->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_CAPTURE_NPT_H)); + if (_oldState != _state) sWorldSessionMgr->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_CAPTURE_NPT_H)); break; case OBJECTIVESTATE_NEUTRAL: m_TowerState = EP_TS_N; @@ -314,12 +315,12 @@ void OPvPCapturePointEP_CGT::ChangeState() // if changing from controlling alliance to horde or vice versa if (_oldState == OBJECTIVESTATE_ALLIANCE && _oldState != _state) { - sWorld->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_LOSE_CGT_A)); + sWorldSessionMgr->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_LOSE_CGT_A)); ((OutdoorPvPEP*)_pvp)->SetControlledState(EP_CGT, TEAM_NEUTRAL); } else if (_oldState == OBJECTIVESTATE_HORDE && _oldState != _state) { - sWorld->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_LOSE_CGT_H)); + sWorldSessionMgr->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_LOSE_CGT_H)); ((OutdoorPvPEP*)_pvp)->SetControlledState(EP_CGT, TEAM_NEUTRAL); } @@ -332,14 +333,14 @@ void OPvPCapturePointEP_CGT::ChangeState() artkit = 2; LinkGraveyard(TEAM_ALLIANCE); ((OutdoorPvPEP*)_pvp)->SetControlledState(EP_CGT, TEAM_ALLIANCE); - if (_oldState != _state) sWorld->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_CAPTURE_CGT_A)); + if (_oldState != _state) sWorldSessionMgr->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_CAPTURE_CGT_A)); break; case OBJECTIVESTATE_HORDE: m_TowerState = EP_TS_H; artkit = 1; LinkGraveyard(TEAM_HORDE); ((OutdoorPvPEP*)_pvp)->SetControlledState(EP_CGT, TEAM_HORDE); - if (_oldState != _state) sWorld->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_CAPTURE_CGT_H)); + if (_oldState != _state) sWorldSessionMgr->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_CAPTURE_CGT_H)); break; case OBJECTIVESTATE_NEUTRAL: m_TowerState = EP_TS_N; @@ -441,12 +442,12 @@ void OPvPCapturePointEP_PWT::ChangeState() // if changing from controlling alliance to horde or vice versa if (_oldState == OBJECTIVESTATE_ALLIANCE && _oldState != _state) { - sWorld->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_LOSE_PWT_A)); + sWorldSessionMgr->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_LOSE_PWT_A)); ((OutdoorPvPEP*)_pvp)->SetControlledState(EP_PWT, TEAM_NEUTRAL); } else if (_oldState == OBJECTIVESTATE_HORDE && _oldState != _state) { - sWorld->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_LOSE_PWT_H)); + sWorldSessionMgr->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_LOSE_PWT_H)); ((OutdoorPvPEP*)_pvp)->SetControlledState(EP_PWT, TEAM_NEUTRAL); } @@ -459,14 +460,14 @@ void OPvPCapturePointEP_PWT::ChangeState() SummonFlightMaster(TEAM_ALLIANCE); artkit = 2; ((OutdoorPvPEP*)_pvp)->SetControlledState(EP_PWT, TEAM_ALLIANCE); - if (_oldState != _state) sWorld->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_CAPTURE_PWT_A)); + if (_oldState != _state) sWorldSessionMgr->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_CAPTURE_PWT_A)); break; case OBJECTIVESTATE_HORDE: m_TowerState = EP_TS_H; SummonFlightMaster(TEAM_HORDE); artkit = 1; ((OutdoorPvPEP*)_pvp)->SetControlledState(EP_PWT, TEAM_HORDE); - if (_oldState != _state) sWorld->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_CAPTURE_PWT_H)); + if (_oldState != _state) sWorldSessionMgr->SendZoneText(EP_GraveYardZone, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_EP_CAPTURE_PWT_H)); break; case OBJECTIVESTATE_NEUTRAL: m_TowerState = EP_TS_N; diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPHP.cpp b/src/server/scripts/OutdoorPvP/OutdoorPvPHP.cpp index efb85af37..b26af4d6f 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPHP.cpp +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPHP.cpp @@ -25,6 +25,7 @@ #include "Player.h" #include "World.h" #include "WorldPacket.h" +#include "WorldSessionMgr.h" const uint32 HP_LANG_LOSE_A[HP_TOWER_NUM] = {LANG_OPVP_HP_LOSE_BROKENHILL_A, LANG_OPVP_HP_LOSE_OVERLOOK_A, LANG_OPVP_HP_LOSE_STADIUM_A}; @@ -180,13 +181,13 @@ void OPvPCapturePointHP::ChangeState() field = HP_MAP_A[m_TowerType]; if (uint32 alliance_towers = ((OutdoorPvPHP*)_pvp)->GetAllianceTowersControlled()) ((OutdoorPvPHP*)_pvp)->SetAllianceTowersControlled(--alliance_towers); - sWorld->SendZoneText(OutdoorPvPHPBuffZones[0], sObjectMgr->GetAcoreStringForDBCLocale(HP_LANG_LOSE_A[m_TowerType])); + sWorldSessionMgr->SendZoneText(OutdoorPvPHPBuffZones[0], sObjectMgr->GetAcoreStringForDBCLocale(HP_LANG_LOSE_A[m_TowerType])); break; case OBJECTIVESTATE_HORDE: field = HP_MAP_H[m_TowerType]; if (uint32 horde_towers = ((OutdoorPvPHP*)_pvp)->GetHordeTowersControlled()) ((OutdoorPvPHP*)_pvp)->SetHordeTowersControlled(--horde_towers); - sWorld->SendZoneText(OutdoorPvPHPBuffZones[0], sObjectMgr->GetAcoreStringForDBCLocale(HP_LANG_LOSE_H[m_TowerType])); + sWorldSessionMgr->SendZoneText(OutdoorPvPHPBuffZones[0], sObjectMgr->GetAcoreStringForDBCLocale(HP_LANG_LOSE_H[m_TowerType])); break; case OBJECTIVESTATE_NEUTRAL_ALLIANCE_CHALLENGE: field = HP_MAP_N[m_TowerType]; @@ -223,7 +224,7 @@ void OPvPCapturePointHP::ChangeState() uint32 alliance_towers = ((OutdoorPvPHP*)_pvp)->GetAllianceTowersControlled(); if (alliance_towers < 3) ((OutdoorPvPHP*)_pvp)->SetAllianceTowersControlled(++alliance_towers); - sWorld->SendZoneText(OutdoorPvPHPBuffZones[0], sObjectMgr->GetAcoreStringForDBCLocale(HP_LANG_CAPTURE_A[m_TowerType])); + sWorldSessionMgr->SendZoneText(OutdoorPvPHPBuffZones[0], sObjectMgr->GetAcoreStringForDBCLocale(HP_LANG_CAPTURE_A[m_TowerType])); break; } case OBJECTIVESTATE_HORDE: @@ -234,7 +235,7 @@ void OPvPCapturePointHP::ChangeState() uint32 horde_towers = ((OutdoorPvPHP*)_pvp)->GetHordeTowersControlled(); if (horde_towers < 3) ((OutdoorPvPHP*)_pvp)->SetHordeTowersControlled(++horde_towers); - sWorld->SendZoneText(OutdoorPvPHPBuffZones[0], sObjectMgr->GetAcoreStringForDBCLocale(HP_LANG_CAPTURE_H[m_TowerType])); + sWorldSessionMgr->SendZoneText(OutdoorPvPHPBuffZones[0], sObjectMgr->GetAcoreStringForDBCLocale(HP_LANG_CAPTURE_H[m_TowerType])); break; } case OBJECTIVESTATE_NEUTRAL_ALLIANCE_CHALLENGE: diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPNA.cpp b/src/server/scripts/OutdoorPvP/OutdoorPvPNA.cpp index 23036977c..d59e2fb17 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPNA.cpp +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPNA.cpp @@ -28,6 +28,7 @@ #include "ScriptedCreature.h" #include "World.h" #include "WorldPacket.h" +#include "WorldSessionMgr.h" OutdoorPvPNA::OutdoorPvPNA() { @@ -193,9 +194,9 @@ void OPvPCapturePointNA::FactionTakeOver(TeamId teamId) if (m_ControllingFaction != TEAM_NEUTRAL) sGraveyard->RemoveGraveyardLink(NA_HALAA_GRAVEYARD, NA_HALAA_GRAVEYARD_ZONE, m_ControllingFaction, false); if (m_ControllingFaction == TEAM_ALLIANCE) - sWorld->SendZoneText(NA_HALAA_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_NA_LOSE_A)); + sWorldSessionMgr->SendZoneText(NA_HALAA_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_NA_LOSE_A)); else if (m_ControllingFaction == TEAM_HORDE) - sWorld->SendZoneText(NA_HALAA_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_NA_LOSE_H)); + sWorldSessionMgr->SendZoneText(NA_HALAA_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_NA_LOSE_H)); DespawnCreatures(GetControllingFaction() == TEAM_HORDE ? halaaNPCHorde : halaaNPCAlly); m_ControllingFaction = teamId; if (m_ControllingFaction != TEAM_NEUTRAL) @@ -217,7 +218,7 @@ void OPvPCapturePointNA::FactionTakeOver(TeamId teamId) _pvp->SendUpdateWorldState(NA_UI_HORDE_GUARDS_SHOW, 0); _pvp->SendUpdateWorldState(NA_UI_ALLIANCE_GUARDS_SHOW, 1); _pvp->SendUpdateWorldState(NA_UI_GUARDS_LEFT, m_GuardsAlive); - sWorld->SendZoneText(NA_HALAA_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_NA_CAPTURE_A)); + sWorldSessionMgr->SendZoneText(NA_HALAA_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_NA_CAPTURE_A)); } else { @@ -229,7 +230,7 @@ void OPvPCapturePointNA::FactionTakeOver(TeamId teamId) _pvp->SendUpdateWorldState(NA_UI_HORDE_GUARDS_SHOW, 1); _pvp->SendUpdateWorldState(NA_UI_ALLIANCE_GUARDS_SHOW, 0); _pvp->SendUpdateWorldState(NA_UI_GUARDS_LEFT, m_GuardsAlive); - sWorld->SendZoneText(NA_HALAA_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_NA_CAPTURE_H)); + sWorldSessionMgr->SendZoneText(NA_HALAA_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_NA_CAPTURE_H)); } UpdateWyvernRoostWorldState(NA_ROOST_S); UpdateWyvernRoostWorldState(NA_ROOST_N); @@ -641,7 +642,7 @@ bool OPvPCapturePointNA::Update(uint32 diff) { m_capturable = true; m_RespawnTimer = NA_RESPAWN_TIME; - sWorld->SendZoneText(NA_HALAA_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_NA_DEFENSELESS)); + sWorldSessionMgr->SendZoneText(NA_HALAA_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_NA_DEFENSELESS)); } else m_capturable = false; diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPSI.cpp b/src/server/scripts/OutdoorPvP/OutdoorPvPSI.cpp index 357f810ea..bde78c3aa 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPSI.cpp +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPSI.cpp @@ -28,6 +28,7 @@ #include "Transport.h" #include "World.h" #include "WorldPacket.h" +#include "WorldSessionMgr.h" OutdoorPvPSI::OutdoorPvPSI() { @@ -102,7 +103,7 @@ bool OutdoorPvPSI::HandleAreaTrigger(Player* player, uint32 trigger) if (m_Gathered_A >= SI_MAX_RESOURCES) { TeamApplyBuff(TEAM_ALLIANCE, SI_CENARION_FAVOR, 0, player); - sWorld->SendZoneText(OutdoorPvPSIBuffZones[0], sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_SI_CAPTURE_A)); + sWorldSessionMgr->SendZoneText(OutdoorPvPSIBuffZones[0], sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_SI_CAPTURE_A)); m_LastController = TEAM_ALLIANCE; m_Gathered_A = 0; m_Gathered_H = 0; @@ -128,7 +129,7 @@ bool OutdoorPvPSI::HandleAreaTrigger(Player* player, uint32 trigger) if (m_Gathered_H >= SI_MAX_RESOURCES) { TeamApplyBuff(TEAM_HORDE, SI_CENARION_FAVOR, 0, player); - sWorld->SendZoneText(OutdoorPvPSIBuffZones[0], sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_SI_CAPTURE_H)); + sWorldSessionMgr->SendZoneText(OutdoorPvPSIBuffZones[0], sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_SI_CAPTURE_H)); m_LastController = TEAM_HORDE; m_Gathered_A = 0; m_Gathered_H = 0; diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPTF.cpp b/src/server/scripts/OutdoorPvP/OutdoorPvPTF.cpp index 075ef17d8..d312b6abc 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPTF.cpp +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPTF.cpp @@ -26,6 +26,7 @@ #include "Player.h" #include "World.h" #include "WorldPacket.h" +#include "WorldSessionMgr.h" OutdoorPvPTF::OutdoorPvPTF() { @@ -397,14 +398,14 @@ void OPvPCapturePointTF::ChangeState() { if (uint32 alliance_towers = ((OutdoorPvPTF*)_pvp)->GetAllianceTowersControlled()) ((OutdoorPvPTF*)_pvp)->SetAllianceTowersControlled(--alliance_towers); - sWorld->SendZoneText(OutdoorPvPTFBuffZones[0], sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_TF_LOSE_A)); + sWorldSessionMgr->SendZoneText(OutdoorPvPTFBuffZones[0], sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_TF_LOSE_A)); } // if changing from controlling horde to alliance else if (_oldState == OBJECTIVESTATE_HORDE) { if (uint32 horde_towers = ((OutdoorPvPTF*)_pvp)->GetHordeTowersControlled()) ((OutdoorPvPTF*)_pvp)->SetHordeTowersControlled(--horde_towers); - sWorld->SendZoneText(OutdoorPvPTFBuffZones[0], sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_TF_LOSE_H)); + sWorldSessionMgr->SendZoneText(OutdoorPvPTFBuffZones[0], sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_TF_LOSE_H)); } uint32 artkit = 21; @@ -419,7 +420,7 @@ void OPvPCapturePointTF::ChangeState() if (alliance_towers < TF_TOWER_NUM) ((OutdoorPvPTF*)_pvp)->SetAllianceTowersControlled(++alliance_towers); - sWorld->SendZoneText(OutdoorPvPTFBuffZones[0], sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_TF_CAPTURE_A)); + sWorldSessionMgr->SendZoneText(OutdoorPvPTFBuffZones[0], sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_TF_CAPTURE_A)); for (PlayerSet::iterator itr = _activePlayers[0].begin(); itr != _activePlayers[0].end(); ++itr) if (Player* player = ObjectAccessor::FindPlayer(*itr)) @@ -434,7 +435,7 @@ void OPvPCapturePointTF::ChangeState() if (horde_towers < TF_TOWER_NUM) ((OutdoorPvPTF*)_pvp)->SetHordeTowersControlled(++horde_towers); - sWorld->SendZoneText(OutdoorPvPTFBuffZones[0], sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_TF_CAPTURE_H)); + sWorldSessionMgr->SendZoneText(OutdoorPvPTFBuffZones[0], sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_TF_CAPTURE_H)); for (PlayerSet::iterator itr = _activePlayers[1].begin(); itr != _activePlayers[1].end(); ++itr) if (Player* player = ObjectAccessor::FindPlayer(*itr)) diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPZM.cpp b/src/server/scripts/OutdoorPvP/OutdoorPvPZM.cpp index 3ecf6d9e7..b681c1604 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPZM.cpp +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPZM.cpp @@ -25,6 +25,7 @@ #include "Player.h" #include "World.h" #include "WorldPacket.h" +#include "WorldSessionMgr.h" OPvPCapturePointZM_Beacon::OPvPCapturePointZM_Beacon(OutdoorPvP* pvp, ZM_BeaconType type) : OPvPCapturePoint(pvp), m_TowerType(type), m_TowerState(ZM_TOWERSTATE_N) @@ -78,14 +79,14 @@ void OPvPCapturePointZM_Beacon::ChangeState() { if (uint32 alliance_towers = ((OutdoorPvPZM*)_pvp)->GetAllianceTowersControlled()) ((OutdoorPvPZM*)_pvp)->SetAllianceTowersControlled(--alliance_towers); - sWorld->SendZoneText(ZM_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(ZMBeaconLoseA[m_TowerType])); + sWorldSessionMgr->SendZoneText(ZM_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(ZMBeaconLoseA[m_TowerType])); } // if changing from controlling horde to alliance else if (_oldState == OBJECTIVESTATE_HORDE) { if (uint32 horde_towers = ((OutdoorPvPZM*)_pvp)->GetHordeTowersControlled()) ((OutdoorPvPZM*)_pvp)->SetHordeTowersControlled(--horde_towers); - sWorld->SendZoneText(ZM_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(ZMBeaconLoseH[m_TowerType])); + sWorldSessionMgr->SendZoneText(ZM_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(ZMBeaconLoseH[m_TowerType])); } switch (_state) @@ -96,7 +97,7 @@ void OPvPCapturePointZM_Beacon::ChangeState() uint32 alliance_towers = ((OutdoorPvPZM*)_pvp)->GetAllianceTowersControlled(); if (alliance_towers < ZM_NUM_BEACONS) ((OutdoorPvPZM*)_pvp)->SetAllianceTowersControlled(++alliance_towers); - sWorld->SendZoneText(ZM_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(ZMBeaconCaptureA[m_TowerType])); + sWorldSessionMgr->SendZoneText(ZM_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(ZMBeaconCaptureA[m_TowerType])); break; } case OBJECTIVESTATE_HORDE: @@ -105,7 +106,7 @@ void OPvPCapturePointZM_Beacon::ChangeState() uint32 horde_towers = ((OutdoorPvPZM*)_pvp)->GetHordeTowersControlled(); if (horde_towers < ZM_NUM_BEACONS) ((OutdoorPvPZM*)_pvp)->SetHordeTowersControlled(++horde_towers); - sWorld->SendZoneText(ZM_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(ZMBeaconCaptureH[m_TowerType])); + sWorldSessionMgr->SendZoneText(ZM_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(ZMBeaconCaptureH[m_TowerType])); break; } case OBJECTIVESTATE_NEUTRAL: @@ -223,7 +224,7 @@ int32 OPvPCapturePointZM_GraveYard::HandleOpenGo(Player* player, GameObject* go) if (player->HasAura(ZM_BATTLE_STANDARD_A) && m_GraveYardState != ZM_GRAVEYARD_A) { if (m_GraveYardState == ZM_GRAVEYARD_H) - sWorld->SendZoneText(ZM_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_ZM_LOSE_GY_H)); + sWorldSessionMgr->SendZoneText(ZM_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_ZM_LOSE_GY_H)); m_GraveYardState = ZM_GRAVEYARD_A; DelObject(0); // only one gotype is used in the whole outdoor pvp, no need to call it a constant AddObject(0, ZM_Banner_A.entry, ZM_Banner_A.map, ZM_Banner_A.x, ZM_Banner_A.y, ZM_Banner_A.z, ZM_Banner_A.o, ZM_Banner_A.rot0, ZM_Banner_A.rot1, ZM_Banner_A.rot2, ZM_Banner_A.rot3); @@ -231,12 +232,12 @@ int32 OPvPCapturePointZM_GraveYard::HandleOpenGo(Player* player, GameObject* go) sGraveyard->AddGraveyardLink(ZM_GRAVEYARD_ID, ZM_GRAVEYARD_ZONE, TEAM_ALLIANCE, false); // add gy _pvp->TeamApplyBuff(TEAM_ALLIANCE, ZM_CAPTURE_BUFF, 0, player); player->RemoveAurasDueToSpell(ZM_BATTLE_STANDARD_A); - sWorld->SendZoneText(ZM_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_ZM_CAPTURE_GY_A)); + sWorldSessionMgr->SendZoneText(ZM_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_ZM_CAPTURE_GY_A)); } else if (player->HasAura(ZM_BATTLE_STANDARD_H) && m_GraveYardState != ZM_GRAVEYARD_H) { if (m_GraveYardState == ZM_GRAVEYARD_A) - sWorld->SendZoneText(ZM_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_ZM_LOSE_GY_A)); + sWorldSessionMgr->SendZoneText(ZM_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_ZM_LOSE_GY_A)); m_GraveYardState = ZM_GRAVEYARD_H; DelObject(0); // only one gotype is used in the whole outdoor pvp, no need to call it a constant AddObject(0, ZM_Banner_H.entry, ZM_Banner_H.map, ZM_Banner_H.x, ZM_Banner_H.y, ZM_Banner_H.z, ZM_Banner_H.o, ZM_Banner_H.rot0, ZM_Banner_H.rot1, ZM_Banner_H.rot2, ZM_Banner_H.rot3); @@ -244,7 +245,7 @@ int32 OPvPCapturePointZM_GraveYard::HandleOpenGo(Player* player, GameObject* go) sGraveyard->AddGraveyardLink(ZM_GRAVEYARD_ID, ZM_GRAVEYARD_ZONE, TEAM_HORDE, false); // add gy _pvp->TeamApplyBuff(TEAM_HORDE, ZM_CAPTURE_BUFF, 0, player); player->RemoveAurasDueToSpell(ZM_BATTLE_STANDARD_H); - sWorld->SendZoneText(ZM_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_ZM_CAPTURE_GY_H)); + sWorldSessionMgr->SendZoneText(ZM_GRAVEYARD_ZONE, sObjectMgr->GetAcoreStringForDBCLocale(LANG_OPVP_ZM_CAPTURE_GY_H)); } UpdateTowerState(); } diff --git a/src/test/mocks/WorldMock.h b/src/test/mocks/WorldMock.h index 11823fcf3..fc095b4a6 100644 --- a/src/test/mocks/WorldMock.h +++ b/src/test/mocks/WorldMock.h @@ -32,34 +32,11 @@ class WorldMock: public IWorld { public: ~WorldMock() override { } - MOCK_METHOD(WorldSession*, FindSession, (uint32 id), (const)); - MOCK_METHOD(WorldSession*, FindOfflineSession, (uint32 id), (const)); - MOCK_METHOD(WorldSession*, FindOfflineSessionForCharacterGUID, (ObjectGuid::LowType guidLow),(const)); - MOCK_METHOD(void, AddSession, (WorldSession* s), ()); - MOCK_METHOD(bool, KickSession, (uint32 id), ()); - MOCK_METHOD(void, UpdateMaxSessionCounters, ()); - MOCK_METHOD(const SessionMap&, GetAllSessions, (), (const)); - MOCK_METHOD(uint32, GetActiveAndQueuedSessionCount, (), (const)); - MOCK_METHOD(uint32, GetActiveSessionCount, (), (const)); - MOCK_METHOD(uint32, GetQueuedSessionCount, (), (const)); - MOCK_METHOD(uint32, GetMaxQueuedSessionCount, (), (const)); - MOCK_METHOD(uint32, GetMaxActiveSessionCount, (), (const)); - MOCK_METHOD(uint32, GetPlayerCount, (), (const)); - MOCK_METHOD(uint32, GetMaxPlayerCount, (), (const)); - MOCK_METHOD(void, IncreasePlayerCount, ()); - MOCK_METHOD(void, DecreasePlayerCount, ()); - MOCK_METHOD(Player*, FindPlayerInZone, (uint32 zone), ()); MOCK_METHOD(bool, IsClosed, (), (const)); MOCK_METHOD(void, SetClosed, (bool val), ()); MOCK_METHOD(AccountTypes, GetPlayerSecurityLimit, (), (const)); MOCK_METHOD(void, SetPlayerSecurityLimit, (AccountTypes sec), ()); MOCK_METHOD(void, LoadDBAllowedSecurityLevel, ()); - MOCK_METHOD(void, SetPlayerAmountLimit, (uint32 limit), ()); - MOCK_METHOD(uint32, GetPlayerAmountLimit, (), (const)); - MOCK_METHOD(void, AddQueuedPlayer, (WorldSession*), ()); - MOCK_METHOD(bool, RemoveQueuedPlayer, (WorldSession* session), ()); - MOCK_METHOD(int32, GetQueuePos, (WorldSession*), ()); - MOCK_METHOD(bool, HasRecentlyDisconnected, (WorldSession*), ()); MOCK_METHOD(bool, getAllowMovement, (), (const)); MOCK_METHOD(void, SetAllowMovement, (bool allow), ()); MOCK_METHOD(void, SetNewCharString, (std::string const& str), ()); @@ -72,18 +49,12 @@ public: MOCK_METHOD(uint16, GetConfigMaxSkillValue, (), (const)); MOCK_METHOD(void, SetInitialWorldSettings, ()); MOCK_METHOD(void, LoadConfigSettings, (bool reload), ()); - MOCK_METHOD(void, SendGlobalMessage, (WorldPacket const* packet, WorldSession* self, TeamId teamId), ()); - MOCK_METHOD(void, SendGlobalGMMessage, (WorldPacket const* packet, WorldSession* self, TeamId teamId), ()); - MOCK_METHOD(bool, SendZoneMessage, (uint32 zone, WorldPacket const* packet, WorldSession* self, TeamId teamId), ()); - MOCK_METHOD(void, SendZoneText, (uint32 zone, std::string text, WorldSession* self, TeamId teamId), ()); - MOCK_METHOD(void, SendServerMessage, (ServerMessageType messageID, std::string stringParam, Player* player)); MOCK_METHOD(bool, IsShuttingDown, (), (const)); MOCK_METHOD(uint32, GetShutDownTimeLeft, (), (const)); MOCK_METHOD(void, ShutdownServ, (uint32 time, uint32 options, uint8 exitcode, const std::string& reason), ()); MOCK_METHOD(void, ShutdownCancel, ()); MOCK_METHOD(void, ShutdownMsg, (bool show, Player* player, const std::string& reason), ()); MOCK_METHOD(void, Update, (uint32 diff), ()); - MOCK_METHOD(void, UpdateSessions, (uint32 diff), ()); MOCK_METHOD(void, setRate, (Rates rate, float value), ()); MOCK_METHOD(float, getRate, (Rates rate), (const)); MOCK_METHOD(void, setBoolConfig, (WorldBoolConfigs index, bool value), ()); @@ -97,8 +68,6 @@ public: MOCK_METHOD(void, LoadWorldStates, ()); MOCK_METHOD(bool, IsPvPRealm, (), (const)); MOCK_METHOD(bool, IsFFAPvPRealm, (), (const)); - MOCK_METHOD(void, KickAll, ()); - MOCK_METHOD(void, KickAllLess, (AccountTypes sec), ()); MOCK_METHOD(uint32, GetNextWhoListUpdateDelaySecs, ()); MOCK_METHOD(void, ProcessCliCommands, ()); MOCK_METHOD(void, QueueCliCommand, (CliCommandHolder* commandHolder), ()); @@ -116,7 +85,6 @@ public: MOCK_METHOD(std::string const&, GetRealmName, (), (const)); MOCK_METHOD(void, SetRealmName, (std::string name), ()); MOCK_METHOD(void, RemoveOldCorpses, ()); - MOCK_METHOD(void, DoForAllOnlinePlayers, (std::function exec)); }; #pragma GCC diagnostic pop