aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/server/game/Handlers/MiscHandler.cpp61
-rw-r--r--src/server/game/Server/Protocol/Opcodes.cpp2
-rw-r--r--src/server/game/Storages/WhoListStorage.cpp68
-rw-r--r--src/server/game/Storages/WhoListStorage.h86
-rw-r--r--src/server/game/World/World.cpp10
-rw-r--r--src/server/game/World/World.h1
6 files changed, 188 insertions, 40 deletions
diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp
index bdd7482c03b..65da0e6ff3f 100644
--- a/src/server/game/Handlers/MiscHandler.cpp
+++ b/src/server/game/Handlers/MiscHandler.cpp
@@ -49,6 +49,7 @@
#include "ScriptMgr.h"
#include "Spell.h"
#include "SpellPackets.h"
+#include "WhoListStorage.h"
#include "WhoPackets.h"
#include "World.h"
#include "WorldPacket.h"
@@ -140,64 +141,46 @@ void WorldSession::HandleWhoOpcode(WorldPackets::Who::WhoRequestPkt& whoRequest)
WorldPackets::Who::WhoResponsePkt response;
- boost::shared_lock<boost::shared_mutex> lock(*HashMapHolder<Player>::GetLock());
-
- HashMapHolder<Player>::MapType const& m = ObjectAccessor::GetPlayers();
- for (HashMapHolder<Player>::MapType::const_iterator itr = m.begin(); itr != m.end(); ++itr)
+ WhoListInfoVector const& whoList = sWhoListStorageMgr->GetWhoList();
+ for (WhoListPlayerInfo const& target : whoList)
{
- Player* target = itr->second;
// player can see member of other team only if has RBAC_PERM_TWO_SIDE_WHO_LIST
- if (target->GetTeam() != team && !HasPermission(rbac::RBAC_PERM_TWO_SIDE_WHO_LIST))
+ if (target.GetTeam() != team && !HasPermission(rbac::RBAC_PERM_TWO_SIDE_WHO_LIST))
continue;
// player can see MODERATOR, GAME MASTER, ADMINISTRATOR only if has RBAC_PERM_WHO_SEE_ALL_SEC_LEVELS
- if (target->GetSession()->GetSecurity() > AccountTypes(gmLevelInWhoList) && !HasPermission(rbac::RBAC_PERM_WHO_SEE_ALL_SEC_LEVELS))
- continue;
-
- // do not process players which are not in world
- if (!target->IsInWorld())
+ if (target.GetSecurity() > AccountTypes(gmLevelInWhoList) && !HasPermission(rbac::RBAC_PERM_WHO_SEE_ALL_SEC_LEVELS))
continue;
// check if target is globally visible for player
- if (!target->IsVisibleGloballyFor(_player))
- continue;
+ if (_player->GetGUID() != target.GetGuid() && !target.IsVisible())
+ if (AccountMgr::IsPlayerAccount(_player->GetSession()->GetSecurity()) || target.GetSecurity() > _player->GetSession()->GetSecurity())
+ continue;
// check if target's level is in level range
- uint8 lvl = target->getLevel();
+ uint8 lvl = target.GetLevel();
if (lvl < request.MinLevel || lvl > request.MaxLevel)
continue;
// check if class matches classmask
- if (request.ClassFilter >= 0 && !(request.ClassFilter & (1 << target->getClass())))
+ if (request.ClassFilter >= 0 && !(request.ClassFilter & (1 << target.GetClass())))
continue;
// check if race matches racemask
- if (request.RaceFilter >= 0 && !(request.RaceFilter & (SI64LIT(1) << target->getRace())))
+ if (request.RaceFilter >= 0 && !(request.RaceFilter & (SI64LIT(1) << target.GetRace())))
continue;
if (!whoRequest.Areas.empty())
{
- if (std::find(whoRequest.Areas.begin(), whoRequest.Areas.end(), target->GetZoneId()) == whoRequest.Areas.end())
+ if (std::find(whoRequest.Areas.begin(), whoRequest.Areas.end(), target.GetZoneId()) == whoRequest.Areas.end())
continue;
}
- std::wstring wTargetName;
-
- if (!Utf8toWStr(target->GetName(), wTargetName))
- continue;
-
- wstrToLower(wTargetName);
-
- if (!wPlayerName.empty() && wTargetName.find(wPlayerName) == std::wstring::npos)
- continue;
-
- Guild* targetGuild = target->GetGuild();
- std::wstring wTargetGuildName;
-
- if (!Utf8toWStr(targetGuild ? targetGuild->GetName() : "", wTargetGuildName))
+ std::wstring const& wTargetName = target.GetWidePlayerName();
+ if (!(wPlayerName.empty() || wTargetName.find(wPlayerName) != std::wstring::npos))
continue;
- wstrToLower(wTargetGuildName);
+ std::wstring const& wTargetGuildName = target.GetWideGuildName();
if (!wGuildName.empty() && wTargetGuildName.find(wGuildName) == std::wstring::npos)
continue;
@@ -205,7 +188,7 @@ void WorldSession::HandleWhoOpcode(WorldPackets::Who::WhoRequestPkt& whoRequest)
if (!wWords.empty())
{
std::string aName;
- if (AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(target->GetZoneId()))
+ if (AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(target.GetZoneId()))
aName = areaEntry->AreaName->Str[GetSessionDbcLocale()];
bool show = false;
@@ -228,18 +211,18 @@ void WorldSession::HandleWhoOpcode(WorldPackets::Who::WhoRequestPkt& whoRequest)
}
WorldPackets::Who::WhoEntry whoEntry;
- if (!whoEntry.PlayerData.Initialize(target->GetGUID(), target))
+ if (!whoEntry.PlayerData.Initialize(target.GetGuid(), nullptr))
continue;
- if (targetGuild)
+ if (!target.GetGuildGuid().IsEmpty())
{
- whoEntry.GuildGUID = targetGuild->GetGUID();
+ whoEntry.GuildGUID = target.GetGuildGuid();
whoEntry.GuildVirtualRealmAddress = GetVirtualRealmAddress();
- whoEntry.GuildName = targetGuild->GetName();
+ whoEntry.GuildName = target.GetGuildName();
}
- whoEntry.AreaID = target->GetZoneId();
- whoEntry.IsGM = target->IsGameMaster();
+ whoEntry.AreaID = target.GetZoneId();
+ whoEntry.IsGM = target.IsGameMaster();
response.Response.Entries.push_back(whoEntry);
diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp
index d5b2be6428b..13306152bcd 100644
--- a/src/server/game/Server/Protocol/Opcodes.cpp
+++ b/src/server/game/Server/Protocol/Opcodes.cpp
@@ -870,7 +870,7 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_VOICE_CHAT_LOGIN, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_VOID_STORAGE_TRANSFER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleVoidStorageTransfer);
DEFINE_HANDLER(CMSG_WARDEN_DATA, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleWardenData);
- DEFINE_HANDLER(CMSG_WHO, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleWhoOpcode);
+ DEFINE_HANDLER(CMSG_WHO, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleWhoOpcode);
DEFINE_HANDLER(CMSG_WHO_IS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleWhoIsOpcode);
DEFINE_HANDLER(CMSG_WORLD_PORT_RESPONSE, STATUS_TRANSFER, PROCESS_THREADUNSAFE, &WorldSession::HandleMoveWorldportAckOpcode);
DEFINE_HANDLER(CMSG_WRAP_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleWrapItem);
diff --git a/src/server/game/Storages/WhoListStorage.cpp b/src/server/game/Storages/WhoListStorage.cpp
new file mode 100644
index 00000000000..ea02853dc0d
--- /dev/null
+++ b/src/server/game/Storages/WhoListStorage.cpp
@@ -0,0 +1,68 @@
+/*
+* Copyright (C) 2008-2019 TrinityCore <http://www.trinitycore.org/>
+*
+* This program is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by the
+* Free Software Foundation; either version 2 of the License, or (at your
+* option) any later version.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "WhoListStorage.h"
+#include "World.h"
+#include "ObjectAccessor.h"
+#include "Player.h"
+#include "GuildMgr.h"
+#include "WorldSession.h"
+#include "Guild.h"
+
+WhoListStorageMgr* WhoListStorageMgr::instance()
+{
+ static WhoListStorageMgr instance;
+ return &instance;
+}
+
+void WhoListStorageMgr::Update()
+{
+ // clear current list
+ _whoListStorage.clear();
+ _whoListStorage.reserve(sWorld->GetPlayerCount()+1);
+
+ HashMapHolder<Player>::MapType const& m = ObjectAccessor::GetPlayers();
+ for (HashMapHolder<Player>::MapType::const_iterator itr = m.begin(); itr != m.end(); ++itr)
+ {
+ if (!itr->second->FindMap() || itr->second->GetSession()->PlayerLoading())
+ continue;
+
+ std::string playerName = itr->second->GetName();
+ std::wstring widePlayerName;
+ if (!Utf8toWStr(playerName, widePlayerName))
+ continue;
+
+ wstrToLower(widePlayerName);
+
+ std::string guildName = sGuildMgr->GetGuildNameById(itr->second->GetGuildId());
+ std::wstring wideGuildName;
+ if (!Utf8toWStr(guildName, wideGuildName))
+ continue;
+
+ wstrToLower(wideGuildName);
+
+ Guild* guild = itr->second->GetGuild();
+ ObjectGuid guildGuid;
+
+ if (guild)
+ guildGuid = guild->GetGUID();
+
+ _whoListStorage.emplace_back(itr->second->GetGUID(), itr->second->GetTeam(), itr->second->GetSession()->GetSecurity(), itr->second->getLevel(),
+ itr->second->getClass(), itr->second->getRace(), itr->second->GetZoneId(), itr->second->m_playerData->NativeSex, itr->second->IsVisible(),
+ itr->second->IsGameMaster(), widePlayerName, wideGuildName, playerName, guildName, guildGuid);
+ }
+}
diff --git a/src/server/game/Storages/WhoListStorage.h b/src/server/game/Storages/WhoListStorage.h
new file mode 100644
index 00000000000..d42e20cdc4c
--- /dev/null
+++ b/src/server/game/Storages/WhoListStorage.h
@@ -0,0 +1,86 @@
+/*
+* Copyright (C) 2008-2019 TrinityCore <http://www.trinitycore.org/>
+*
+* This program is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by the
+* Free Software Foundation; either version 2 of the License, or (at your
+* option) any later version.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _WHOLISTSTORAGE_H
+#define _WHOLISTSTORAGE_H
+
+#include "Common.h"
+#include "ObjectGuid.h"
+
+class WhoListPlayerInfo
+{
+public:
+ WhoListPlayerInfo(ObjectGuid guid, uint32 team, AccountTypes security, uint8 level, uint8 clss, uint8 race, uint32 zoneid, uint8 gender, bool visible, bool gamemaster, std::wstring const& widePlayerName,
+ std::wstring const& wideGuildName, std::string const& playerName, std::string const& guildName, ObjectGuid guildguid) :
+ _guid(guid), _team(team), _security(security), _level(level), _class(clss), _race(race), _zoneid(zoneid), _gender(gender), _visible(visible),
+ _gamemaster(gamemaster), _widePlayerName(widePlayerName), _wideGuildName(wideGuildName), _playerName(playerName), _guildName(guildName), _guildguid(guildguid) {}
+
+ ObjectGuid GetGuid() const { return _guid; }
+ uint32 GetTeam() const { return _team; }
+ AccountTypes GetSecurity() const { return _security; }
+ uint8 GetLevel() const { return _level; }
+ uint8 GetClass() const { return _class; }
+ uint8 GetRace() const { return _race; }
+ uint32 GetZoneId() const { return _zoneid; }
+ uint8 GetGender() const { return _gender; }
+ bool IsVisible() const { return _visible; }
+ bool IsGameMaster() const { return _gamemaster; }
+ std::wstring const& GetWidePlayerName() const { return _widePlayerName; }
+ std::wstring const& GetWideGuildName() const { return _wideGuildName; }
+ std::string const& GetPlayerName() const { return _playerName; }
+ std::string const& GetGuildName() const { return _guildName; }
+ ObjectGuid GetGuildGuid() const { return _guildguid; }
+
+private:
+ ObjectGuid _guid;
+ uint32 _team;
+ AccountTypes _security;
+ uint8 _level;
+ uint8 _class;
+ uint8 _race;
+ uint32 _zoneid;
+ uint8 _gender;
+ bool _visible;
+ bool _gamemaster;
+ std::wstring _widePlayerName;
+ std::wstring _wideGuildName;
+ std::string _playerName;
+ std::string _guildName;
+ ObjectGuid _guildguid;
+};
+
+typedef std::vector<WhoListPlayerInfo> WhoListInfoVector;
+
+class TC_GAME_API WhoListStorageMgr
+{
+private:
+ WhoListStorageMgr() { };
+ ~WhoListStorageMgr() { };
+
+public:
+ static WhoListStorageMgr* instance();
+
+ void Update();
+ WhoListInfoVector const& GetWhoList() const { return _whoListStorage; }
+
+protected:
+ WhoListInfoVector _whoListStorage;
+};
+
+#define sWhoListStorageMgr WhoListStorageMgr::instance()
+
+#endif // _WHOLISTSTORAGE_H
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index 7abaf15a857..bb0c517dbf4 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -91,6 +91,7 @@
#include "WaypointManager.h"
#include "WaypointMovementGenerator.h"
#include "WeatherMgr.h"
+#include "WhoListStorage.h"
#include "WorldSession.h"
#include "WorldSocket.h"
@@ -2102,6 +2103,8 @@ void World::SetInitialWorldSettings()
m_timers[WUPDATE_CHECK_FILECHANGES].SetInterval(500);
+ m_timers[WUPDATE_WHO_LIST].SetInterval(5 * IN_MILLISECONDS); // update who list cache every 5 seconds
+
//to set mailtimer to return mails every day between 4 and 5 am
//mailtimer is increased when updating auctions
//one second is 1000 -(tested on win system)
@@ -2305,6 +2308,13 @@ void World::Update(uint32 diff)
m_timers[i].SetCurrent(0);
}
+ ///- Update Who List Storage
+ if (m_timers[WUPDATE_WHO_LIST].Passed())
+ {
+ m_timers[WUPDATE_WHO_LIST].Reset();
+ sWhoListStorageMgr->Update();
+ }
+
///- Update the game time and check for shutdown time
_UpdateGameTime();
diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h
index 18c0770fece..9715cff322f 100644
--- a/src/server/game/World/World.h
+++ b/src/server/game/World/World.h
@@ -93,6 +93,7 @@ enum WorldTimers
WUPDATE_GUILDSAVE,
WUPDATE_BLACKMARKET,
WUPDATE_CHECK_FILECHANGES,
+ WUPDATE_WHO_LIST,
WUPDATE_COUNT
};