aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Handlers/MiscHandler.cpp144
-rw-r--r--src/server/game/Server/Protocol/Opcodes.cpp2
-rw-r--r--src/server/game/Storages/WhoListStorage.cpp61
-rw-r--r--src/server/game/Storages/WhoListStorage.h82
-rw-r--r--src/server/game/World/World.cpp10
-rw-r--r--src/server/game/World/World.h1
6 files changed, 220 insertions, 80 deletions
diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp
index 4a80c2f07df..2f738b64910 100644
--- a/src/server/game/Handlers/MiscHandler.cpp
+++ b/src/server/game/Handlers/MiscHandler.cpp
@@ -44,6 +44,7 @@
#include "BattlegroundMgr.h"
#include "Battlefield.h"
#include "BattlefieldMgr.h"
+#include "WhoListStorage.h"
void WorldSession::HandleRepopRequestOpcode(WorldPacket& recvData)
{
@@ -176,45 +177,45 @@ void WorldSession::HandleWhoOpcode(WorldPacket& recvData)
{
TC_LOG_DEBUG("network", "WORLD: Recvd CMSG_WHO Message");
- uint32 matchcount = 0;
+ uint32 matchCount = 0;
- uint32 level_min, level_max, racemask, classmask, zones_count, str_count;
+ uint32 levelMin, levelMax, racemask, classmask, zonesCount, strCount;
uint32 zoneids[10]; // 10 is client limit
- std::string player_name, guild_name;
+ std::string packetPlayerName, packetGuildName;
- recvData >> level_min; // maximal player level, default 0
- recvData >> level_max; // minimal player level, default 100 (MAX_LEVEL)
- recvData >> player_name; // player name, case sensitive...
+ recvData >> levelMin; // maximal player level, default 0
+ recvData >> levelMax; // minimal player level, default 100 (MAX_LEVEL)
+ recvData >> packetPlayerName; // player name, case sensitive...
- recvData >> guild_name; // guild name, case sensitive...
+ recvData >> packetGuildName; // guild name, case sensitive...
- recvData >> racemask; // race mask
- recvData >> classmask; // class mask
- recvData >> zones_count; // zones count, client limit = 10 (2.0.10)
+ recvData >> racemask; // race mask
+ recvData >> classmask; // class mask
+ recvData >> zonesCount; // zones count, client limit = 10 (2.0.10)
- if (zones_count > 10)
+ if (zonesCount > 10)
return; // can't be received from real client or broken packet
- for (uint32 i = 0; i < zones_count; ++i)
+ for (uint32 i = 0; i < zonesCount; ++i)
{
uint32 temp;
- recvData >> temp; // zone id, 0 if zone is unknown...
+ recvData >> temp; // zone id, 0 if zone is unknown...
zoneids[i] = temp;
TC_LOG_DEBUG("network", "Zone %u: %u", i, zoneids[i]);
}
- recvData >> str_count; // user entered strings count, client limit=4 (checked on 2.0.10)
+ recvData >> strCount; // user entered strings count, client limit=4 (checked on 2.0.10)
- if (str_count > 4)
+ if (strCount > 4)
return; // can't be received from real client or broken packet
- TC_LOG_DEBUG("network", "Minlvl %u, maxlvl %u, name %s, guild %s, racemask %u, classmask %u, zones %u, strings %u", level_min, level_max, player_name.c_str(), guild_name.c_str(), racemask, classmask, zones_count, str_count);
+ TC_LOG_DEBUG("network", "Minlvl %u, maxlvl %u, name %s, guild %s, racemask %u, classmask %u, zones %u, strings %u", levelMin, levelMax, packetPlayerName.c_str(), packetGuildName.c_str(), racemask, classmask, zonesCount, strCount);
std::wstring str[4]; // 4 is client limit
- for (uint32 i = 0; i < str_count; ++i)
+ for (uint32 i = 0; i < strCount; ++i)
{
std::string temp;
- recvData >> temp; // user entered string, it used as universal search pattern(guild+player name)?
+ recvData >> temp; // user entered string, it used as universal search pattern(guild+player name)?
if (!Utf8toWStr(temp, str[i]))
continue;
@@ -224,110 +225,95 @@ void WorldSession::HandleWhoOpcode(WorldPacket& recvData)
TC_LOG_DEBUG("network", "String %u: %s", i, temp.c_str());
}
- std::wstring wplayer_name;
- std::wstring wguild_name;
- if (!(Utf8toWStr(player_name, wplayer_name) && Utf8toWStr(guild_name, wguild_name)))
+ std::wstring wpacketPlayerName;
+ std::wstring wpacketGuildName;
+ if (!(Utf8toWStr(packetPlayerName, wpacketPlayerName) && Utf8toWStr(packetGuildName, wpacketGuildName)))
return;
- wstrToLower(wplayer_name);
- wstrToLower(wguild_name);
+
+ wstrToLower(wpacketPlayerName);
+ wstrToLower(wpacketGuildName);
// client send in case not set max level value 100 but Trinity supports 255 max level,
// update it to show GMs with characters after 100 level
- if (level_max >= MAX_LEVEL)
- level_max = STRONG_MAX_LEVEL;
+ if (levelMax >= MAX_LEVEL)
+ levelMax = STRONG_MAX_LEVEL;
uint32 team = _player->GetTeam();
uint32 gmLevelInWhoList = sWorld->getIntConfig(CONFIG_GM_LEVEL_IN_WHO_LIST);
- uint32 displaycount = 0;
-
- WorldPacket data(SMSG_WHO, 50); // guess size
- data << uint32(matchcount); // placeholder, count of players matching criteria
- data << uint32(displaycount); // placeholder, count of players displayed
+ uint32 displayCount = 0;
- boost::shared_lock<boost::shared_mutex> lock(*HashMapHolder<Player>::GetLock());
+ WorldPacket data(SMSG_WHO, 500); // guess size
+ data << uint32(matchCount); // placeholder, count of players matching criteria
+ data << uint32(displayCount); // placeholder, count of players displayed
- 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 CONFIG_ALLOW_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 CONFIG_GM_IN_WHO_LIST
- if (!HasPermission(rbac::RBAC_PERM_WHO_SEE_ALL_SEC_LEVELS) && target->GetSession()->GetSecurity() > AccountTypes(gmLevelInWhoList))
- continue;
-
- // do not process players which are not in world
- if (!target->IsInWorld())
+ if (!HasPermission(rbac::RBAC_PERM_WHO_SEE_ALL_SEC_LEVELS) && target.GetSecurity() > AccountTypes(gmLevelInWhoList))
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();
- if (lvl < level_min || lvl > level_max)
+ uint8 lvl = target.GetLevel();
+ if (lvl < levelMin || lvl > levelMax)
continue;
// check if class matches classmask
- uint8 class_ = target->getClass();
+ uint8 class_ = target.GetClass();
if (!(classmask & (1 << class_)))
continue;
// check if race matches racemask
- uint32 race = target->getRace();
+ uint32 race = target.GetRace();
if (!(racemask & (1 << race)))
continue;
- uint32 pzoneid = target->GetZoneId();
- uint8 gender = target->GetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_GENDER);
+ uint32 playerZoneId = target.GetZoneId();
+ uint8 gender = target.GetGender();
- bool z_show = true;
- for (uint32 i = 0; i < zones_count; ++i)
+ bool showZones = true;
+ for (uint32 i = 0; i < zonesCount; ++i)
{
- if (zoneids[i] == pzoneid)
+ if (zoneids[i] == playerZoneId)
{
- z_show = true;
+ showZones = true;
break;
}
- z_show = false;
+ showZones = false;
}
- if (!z_show)
- continue;
-
- std::string pname = target->GetName();
- std::wstring wpname;
- if (!Utf8toWStr(pname, wpname))
- continue;
- wstrToLower(wpname);
-
- if (!(wplayer_name.empty() || wpname.find(wplayer_name) != std::wstring::npos))
+ if (!showZones)
continue;
- std::string gname = sGuildMgr->GetGuildNameById(target->GetGuildId());
- std::wstring wgname;
- if (!Utf8toWStr(gname, wgname))
+ std::wstring const& wideplayername = target.GetWidePlayerName();
+ if (!(wpacketPlayerName.empty() || wideplayername.find(wpacketPlayerName) != std::wstring::npos))
continue;
- wstrToLower(wgname);
- if (!(wguild_name.empty() || wgname.find(wguild_name) != std::wstring::npos))
+ std::wstring const& wideguildname = target.GetWideGuildName();
+ if (!(wpacketGuildName.empty() || wideguildname.find(wpacketGuildName) != std::wstring::npos))
continue;
std::string aname;
- if (AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(pzoneid))
+ if (AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(playerZoneId))
aname = areaEntry->area_name[GetSessionDbcLocale()];
bool s_show = true;
- for (uint32 i = 0; i < str_count; ++i)
+ for (uint32 i = 0; i < strCount; ++i)
{
if (!str[i].empty())
{
- if (wgname.find(str[i]) != std::wstring::npos ||
- wpname.find(str[i]) != std::wstring::npos ||
+ if (wideguildname.find(str[i]) != std::wstring::npos ||
+ wideplayername.find(str[i]) != std::wstring::npos ||
Utf8FitTo(aname, str[i]))
{
s_show = true;
@@ -341,22 +327,22 @@ void WorldSession::HandleWhoOpcode(WorldPacket& recvData)
// 49 is maximum player count sent to client - can be overridden
// through config, but is unstable
- if ((matchcount++) >= sWorld->getIntConfig(CONFIG_MAX_WHO))
+ if ((matchCount++) >= sWorld->getIntConfig(CONFIG_MAX_WHO))
continue;
- data << pname; // player name
- data << gname; // guild name
+ data << target.GetPlayerName(); // player name
+ data << target.GetGuildName(); // guild name
data << uint32(lvl); // player level
data << uint32(class_); // player class
data << uint32(race); // player race
data << uint8(gender); // player gender
- data << uint32(pzoneid); // player zone id
+ data << uint32(playerZoneId); // player zone id
- ++displaycount;
+ ++displayCount;
}
- data.put(0, displaycount); // insert right count, count displayed
- data.put(4, matchcount); // insert right count, count of matches
+ data.put(0, displayCount); // insert right count, count displayed
+ data.put(4, matchCount); // insert right count, count of matches
SendPacket(&data);
TC_LOG_DEBUG("network", "WORLD: Send SMSG_WHO Message");
diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp
index a591c568e8c..316335ffd47 100644
--- a/src/server/game/Server/Protocol/Opcodes.cpp
+++ b/src/server/game/Server/Protocol/Opcodes.cpp
@@ -213,7 +213,7 @@ void OpcodeTable::Initialize()
/*0x05F*/ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GAMEOBJECT_QUERY_RESPONSE, STATUS_NEVER);
/*0x060*/ DEFINE_HANDLER(CMSG_CREATURE_QUERY, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleCreatureQueryOpcode );
/*0x061*/ DEFINE_SERVER_OPCODE_HANDLER(SMSG_CREATURE_QUERY_RESPONSE, STATUS_NEVER);
- /*0x062*/ DEFINE_HANDLER(CMSG_WHO, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleWhoOpcode );
+ /*0x062*/ DEFINE_HANDLER(CMSG_WHO, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleWhoOpcode );
/*0x063*/ DEFINE_SERVER_OPCODE_HANDLER(SMSG_WHO, STATUS_NEVER);
/*0x064*/ DEFINE_HANDLER(CMSG_WHOIS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleWhoisOpcode );
/*0x065*/ DEFINE_SERVER_OPCODE_HANDLER(SMSG_WHOIS, STATUS_NEVER);
diff --git a/src/server/game/Storages/WhoListStorage.cpp b/src/server/game/Storages/WhoListStorage.cpp
new file mode 100644
index 00000000000..c213445c7bb
--- /dev/null
+++ b/src/server/game/Storages/WhoListStorage.cpp
@@ -0,0 +1,61 @@
+/*
+* Copyright (C) 2008-2016 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"
+
+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);
+
+ _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->GetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_GENDER), itr->second->IsVisible(),
+ widePlayerName, wideGuildName, playerName, guildName);
+ }
+}
diff --git a/src/server/game/Storages/WhoListStorage.h b/src/server/game/Storages/WhoListStorage.h
new file mode 100644
index 00000000000..7bcd43dc53b
--- /dev/null
+++ b/src/server/game/Storages/WhoListStorage.h
@@ -0,0 +1,82 @@
+/*
+* Copyright (C) 2008-2016 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, std::wstring const& widePlayerName,
+ std::wstring const& wideGuildName, std::string const& playerName, std::string const& guildName) :
+ _guid(guid), _team(team), _security(security), _level(level), _class(clss), _race(race), _zoneid(zoneid), _gender(gender), _visible(visible),
+ _widePlayerName(widePlayerName), _wideGuildName(wideGuildName), _playerName(playerName), _guildName(guildName) {}
+
+ 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; }
+ 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; }
+
+private:
+ ObjectGuid _guid;
+ uint32 _team;
+ AccountTypes _security;
+ uint8 _level;
+ uint8 _class;
+ uint8 _race;
+ uint32 _zoneid;
+ uint8 _gender;
+ bool _visible;
+ std::wstring _widePlayerName;
+ std::wstring _wideGuildName;
+ std::string _playerName;
+ std::string _guildName;
+};
+
+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 f4fcb36f995..77d5f57993b 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -69,6 +69,7 @@
#include "WeatherMgr.h"
#include "WorldSession.h"
#include "M2Stores.h"
+#include "WhoListStorage.h"
TC_GAME_API std::atomic<bool> World::m_stopEvent(false);
TC_GAME_API uint8 World::m_ExitCode = SHUTDOWN_EXIT_CODE;
@@ -1878,6 +1879,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)
@@ -2109,6 +2112,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 30e1283bc16..56896fa3644 100644
--- a/src/server/game/World/World.h
+++ b/src/server/game/World/World.h
@@ -83,6 +83,7 @@ enum WorldTimers
WUPDATE_AHBOT,
WUPDATE_PINGDB,
WUPDATE_CHECK_FILECHANGES,
+ WUPDATE_WHO_LIST,
WUPDATE_COUNT
};