TrinityCore
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
WorldSession.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
22#include "WorldSession.h"
23#include "AccountMgr.h"
25#include "BattlePetMgr.h"
26#include "BattlegroundMgr.h"
27#include "BattlenetPackets.h"
28#include "CharacterPackets.h"
29#include "ChatPackets.h"
30#include "ClientConfigPackets.h"
31#include "DatabaseEnv.h"
32#include "GameTime.h"
33#include "Group.h"
34#include "Guild.h"
35#include "GuildMgr.h"
36#include "Hyperlinks.h"
37#include "IpAddress.h"
38#include "Log.h"
39#include "Map.h"
40#include "Metric.h"
41#include "MiscPackets.h"
42#include "ObjectMgr.h"
43#include "OutdoorPvPMgr.h"
44#include "PacketUtilities.h"
45#include "Player.h"
46#include "QueryHolder.h"
47#include "Random.h"
48#include "RBAC.h"
49#include "RealmList.h"
50#include "ScriptMgr.h"
51#include "SocialMgr.h"
52#include "WardenWin.h"
53#include "World.h"
54#include "WorldSocket.h"
55#include <boost/circular_buffer.hpp>
56
57namespace {
58
59std::string const DefaultPlayerName = "<none>";
60
61} // namespace
62
64{
65 ClientOpcodeHandler const* opHandle = opcodeTable[static_cast<OpcodeClient>(packet->GetOpcode())];
66
67 //let's check if our opcode can be really processed in Map::Update()
68 if (opHandle->ProcessingPlace == PROCESS_INPLACE)
69 return true;
70
71 //we do not process thread-unsafe packets
73 return false;
74
75 Player* player = m_pSession->GetPlayer();
76 if (!player)
77 return false;
78
79 //in Map::Update() we do not process packets where player is not in world!
80 return player->IsInWorld();
81}
82
83//we should process ALL packets when player is not in world/logged in
84//OR packet handler is not thread-safe!
86{
87 ClientOpcodeHandler const* opHandle = opcodeTable[static_cast<OpcodeClient>(packet->GetOpcode())];
88
89 //check if packet handler is supposed to be safe
90 if (opHandle->ProcessingPlace == PROCESS_INPLACE)
91 return true;
92
93 //thread-unsafe packets should be processed in World::UpdateSessions()
95 return true;
96
97 //no player attached? -> our client! ^^
98 Player* player = m_pSession->GetPlayer();
99 if (!player)
100 return true;
101
102 //lets process all packets for non-in-the-world player
103 return (player->IsInWorld() == false);
104}
105
107WorldSession::WorldSession(uint32 id, std::string&& name, uint32 battlenetAccountId, std::shared_ptr<WorldSocket> sock, AccountTypes sec, uint8 expansion, time_t mute_time,
108 std::string os, Minutes timezoneOffset, uint32 build, ClientBuild::VariantId clientBuildVariant, LocaleConstant locale, uint32 recruiter, bool isARecruiter):
109 m_muteTime(mute_time),
110 m_timeOutTime(0),
111 AntiDOS(this),
112 m_GUIDLow(UI64LIT(0)),
113 _player(nullptr),
114 _security(sec),
115 _accountId(id),
116 _accountName(std::move(name)),
117 _battlenetAccountId(battlenetAccountId),
118 m_accountExpansion(expansion),
119 m_expansion(std::min<uint8>(expansion, sWorld->getIntConfig(CONFIG_EXPANSION))),
120 _os(std::move(os)),
121 _clientBuild(build),
122 _clientBuildVariant(clientBuildVariant),
123 _realmListSecret(),
124 _battlenetRequestToken(0),
125 _logoutTime(0),
126 m_inQueue(false),
127 m_playerLogout(false),
128 m_playerRecentlyLogout(false),
129 m_playerSave(false),
130 m_sessionDbcLocale(sWorld->GetAvailableDbcLocale(locale)),
131 m_sessionDbLocaleIndex(locale),
132 _timezoneOffset(timezoneOffset),
133 m_latency(0),
134 _tutorials(),
135 _tutorialsChanged(TUTORIALS_FLAG_NONE),
136 _filterAddonMessages(false),
137 recruiterId(recruiter),
138 isRecruiter(isARecruiter),
139 _RBACData(nullptr),
140 expireTime(60000), // 1 min after socket loss, session is deleted
141 forceExit(false),
142 _timeSyncClockDeltaQueue(std::make_unique<boost::circular_buffer<std::pair<int64, uint32>>>(6)),
143 _timeSyncClockDelta(0),
144 _pendingTimeSyncRequests(),
145 _timeSyncNextCounter(0),
146 _timeSyncTimer(0),
147 _calendarEventCreationCooldown(0),
148 _battlePetMgr(std::make_unique<BattlePets::BattlePetMgr>(this)),
149 _collectionMgr(std::make_unique<CollectionMgr>(this))
150{
151 if (sock)
152 {
153 m_Address = sock->GetRemoteIpAddress().to_string();
154 ResetTimeOutTime(false);
155 LoginDatabase.PExecute("UPDATE account SET online = 1 WHERE id = {};", GetAccountId()); // One-time query
156 }
157
158 m_Socket[CONNECTION_TYPE_REALM] = std::move(sock);
160}
161
164{
166 if (_player)
167 LogoutPlayer (true);
168
170 for (uint8 i = 0; i < 2; ++i)
171 {
172 if (m_Socket[i])
173 {
174 m_Socket[i]->CloseSocket();
175 m_Socket[i].reset();
176 }
177 }
178
179 delete _RBACData;
180
182 WorldPacket* packet = nullptr;
183 while (_recvQueue.next(packet))
184 delete packet;
185
186 LoginDatabase.PExecute("UPDATE account SET online = 0 WHERE id = {};", GetAccountId()); // One-time query
187}
188
190{
193}
194
195std::string const & WorldSession::GetPlayerName() const
196{
197 return _player != nullptr ? _player->GetName() : DefaultPlayerName;
198}
199
201{
202 if (_player)
203 return Trinity::StringFormat("[Player: {} {}, Account: {}]", _player->GetName(), _player->GetGUID(), GetAccountId());
204
206 return Trinity::StringFormat("[Player: Logging in: {}, Account: {}]", m_playerLoading, GetAccountId());
207
208 return Trinity::StringFormat("[Player: Account: {}]", GetAccountId());
209}
210
212void WorldSession::SendPacket(WorldPacket const* packet, bool forced /*= false*/)
213{
214 if (!opcodeTable.IsValid(static_cast<OpcodeServer>(packet->GetOpcode())))
215 {
216 char const* specialName = packet->GetOpcode() == UNKNOWN_OPCODE ? "UNKNOWN_OPCODE" : "INVALID_OPCODE";
217 TC_LOG_ERROR("network.opcode", "Prevented sending of {} (0x{:04X}) to {}", specialName, packet->GetOpcode(), GetPlayerInfo());
218 return;
219 }
220
221 ServerOpcodeHandler const* handler = opcodeTable[static_cast<OpcodeServer>(packet->GetOpcode())];
222 if (!handler)
223 {
224 TC_LOG_ERROR("network.opcode", "Prevented sending of opcode {} with non existing handler to {}", packet->GetOpcode(), GetPlayerInfo());
225 return;
226 }
227
228 // Default connection index defined in Opcodes.cpp table
229 ConnectionType conIdx = handler->ConnectionIndex;
230
231 // Override connection index
232 if (packet->GetConnection() != CONNECTION_TYPE_DEFAULT)
233 {
235 {
236 TC_LOG_ERROR("network.opcode", "Prevented sending of instance only opcode {} with connection type {} to {}", packet->GetOpcode(), uint32(packet->GetConnection()), GetPlayerInfo());
237 return;
238 }
239
240 conIdx = packet->GetConnection();
241 }
242
243 if (!m_Socket[conIdx])
244 {
245 TC_LOG_ERROR("network.opcode", "Prevented sending of {} to non existent socket {} to {}", GetOpcodeNameForLogging(static_cast<OpcodeServer>(packet->GetOpcode())), uint32(conIdx), GetPlayerInfo());
246 return;
247 }
248
249 if (!forced)
250 {
251 if (handler->Status == STATUS_UNHANDLED)
252 {
253 TC_LOG_ERROR("network.opcode", "Prevented sending disabled opcode {} to {}", GetOpcodeNameForLogging(static_cast<OpcodeServer>(packet->GetOpcode())), GetPlayerInfo());
254 return;
255 }
256 }
257
258#ifdef TRINITY_DEBUG
259 // Code for network use statistic
260 static uint64 sendPacketCount = 0;
261 static uint64 sendPacketBytes = 0;
262
263 static time_t firstTime = GameTime::GetGameTime();
264 static time_t lastTime = firstTime; // next 60 secs start time
265
266 static uint64 sendLastPacketCount = 0;
267 static uint64 sendLastPacketBytes = 0;
268
269 time_t cur_time = GameTime::GetGameTime();
270
271 if ((cur_time - lastTime) < 60)
272 {
273 sendPacketCount += 1;
274 sendPacketBytes += packet->size();
275
276 sendLastPacketCount += 1;
277 sendLastPacketBytes += packet->size();
278 }
279 else
280 {
281 uint64 minTime = uint64(cur_time - lastTime);
282 uint64 fullTime = uint64(lastTime - firstTime);
283 TC_LOG_DEBUG("misc", "Send all time packets count: {} bytes: {} avr.count/sec: {} avr.bytes/sec: {} time: {}", sendPacketCount, sendPacketBytes, float(sendPacketCount)/fullTime, float(sendPacketBytes)/fullTime, uint32(fullTime));
284 TC_LOG_DEBUG("misc", "Send last min packets count: {} bytes: {} avr.count/sec: {} avr.bytes/sec: {}", sendLastPacketCount, sendLastPacketBytes, float(sendLastPacketCount)/minTime, float(sendLastPacketBytes)/minTime);
285
286 lastTime = cur_time;
287 sendLastPacketCount = 1;
288 sendLastPacketBytes = packet->wpos(); // wpos is real written size
289 }
290#endif // !TRINITY_DEBUG
291
292 sScriptMgr->OnPacketSend(this, *packet);
293
294 TC_LOG_TRACE("network.opcode", "S->C: {} {}", GetPlayerInfo(), GetOpcodeNameForLogging(static_cast<OpcodeServer>(packet->GetOpcode())));
295 m_Socket[conIdx]->SendPacket(*packet);
296}
297
298void WorldSession::AddInstanceConnection(WorldSession* session, std::weak_ptr<WorldSocket> sockRef, ConnectToKey key)
299{
300 std::shared_ptr<WorldSocket> socket = sockRef.lock();
301 if (!socket || !socket->IsOpen())
302 return;
303
304 if (!session || session->GetConnectToInstanceKey() != key.Raw)
305 {
306 socket->SendAuthResponseError(ERROR_TIMED_OUT);
307 socket->DelayedCloseSocket();
308 return;
309 }
310
311 socket->SetWorldSession(session);
312 session->m_Socket[CONNECTION_TYPE_INSTANCE] = std::move(socket);
313 session->HandleContinuePlayerLogin();
314}
315
318{
319 _recvQueue.add(new_packet);
320}
321
323void WorldSession::LogUnexpectedOpcode(WorldPacket* packet, char const* status, const char *reason)
324{
325 TC_LOG_ERROR("network.opcode", "Received unexpected opcode {} Status: {} Reason: {} from {}",
326 GetOpcodeNameForLogging(static_cast<OpcodeClient>(packet->GetOpcode())), status, reason, GetPlayerInfo());
327}
328
331{
332 if (!sLog->ShouldLog("network.opcode", LOG_LEVEL_TRACE) || packet->rpos() >= packet->wpos())
333 return;
334
335 TC_LOG_TRACE("network.opcode", "Unprocessed tail data (read stop at {} from {}) Opcode {} from {}",
336 uint32(packet->rpos()), uint32(packet->wpos()), GetOpcodeNameForLogging(static_cast<OpcodeClient>(packet->GetOpcode())), GetPlayerInfo());
337 packet->print_storage();
338}
339
342{
347 m_Socket[CONNECTION_TYPE_REALM]->CloseSocket();
348
351 WorldPacket* packet = nullptr;
353 bool deletePacket = true;
354 std::vector<WorldPacket*> requeuePackets;
355 uint32 processedPackets = 0;
356 time_t currentTime = GameTime::GetGameTime();
357
358 constexpr uint32 MAX_PROCESSED_PACKETS_IN_SAME_WORLDSESSION_UPDATE = 100;
359
360 while (m_Socket[CONNECTION_TYPE_REALM] && _recvQueue.next(packet, updater))
361 {
362 OpcodeClient opcode = static_cast<OpcodeClient>(packet->GetOpcode());
363 ClientOpcodeHandler const* opHandle = opcodeTable[opcode];
364 TC_METRIC_DETAILED_TIMER("worldsession_update_opcode_time", TC_METRIC_TAG("opcode", opHandle->Name));
365
366 try
367 {
368 switch (opHandle->Status)
369 {
370 case STATUS_LOGGEDIN:
371 if (!_player)
372 {
373 // skip STATUS_LOGGEDIN opcode unexpected errors if player logout sometime ago - this can be network lag delayed packets
377 {
378 requeuePackets.push_back(packet);
379 deletePacket = false;
380 TC_LOG_DEBUG("network", "Re-enqueueing packet with opcode {} with with status STATUS_LOGGEDIN. "
381 "Player is currently not in world yet.", GetOpcodeNameForLogging(static_cast<OpcodeClient>(packet->GetOpcode())));
382 }
383 }
384 else if (_player->IsInWorld())
385 {
386 if(AntiDOS.EvaluateOpcode(*packet, currentTime))
387 {
388 sScriptMgr->OnPacketReceive(this, *packet);
389 opHandle->Call(this, *packet);
390 }
391 else
392 processedPackets = MAX_PROCESSED_PACKETS_IN_SAME_WORLDSESSION_UPDATE; // break out of packet processing loop
393 }
394 // lag can cause STATUS_LOGGEDIN opcodes to arrive after the player started a transfer
395 break;
397 if (!_player && !m_playerRecentlyLogout && !m_playerLogout) // There's a short delay between _player = null and m_playerRecentlyLogout = true during logout
398 LogUnexpectedOpcode(packet, "STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT",
399 "the player has not logged in yet and not recently logout");
400 else if (AntiDOS.EvaluateOpcode(*packet, currentTime))
401 {
402 // not expected _player or must checked in packet hanlder
403 sScriptMgr->OnPacketReceive(this, *packet);
404 opHandle->Call(this, *packet);
405 }
406 else
407 processedPackets = MAX_PROCESSED_PACKETS_IN_SAME_WORLDSESSION_UPDATE; // break out of packet processing loop
408 break;
409 case STATUS_TRANSFER:
410 if (!_player)
411 LogUnexpectedOpcode(packet, "STATUS_TRANSFER", "the player has not logged in yet");
412 else if (_player->IsInWorld())
413 LogUnexpectedOpcode(packet, "STATUS_TRANSFER", "the player is still in world");
414 else if (AntiDOS.EvaluateOpcode(*packet, currentTime))
415 {
416 sScriptMgr->OnPacketReceive(this, *packet);
417 opHandle->Call(this, *packet);
418 }
419 else
420 processedPackets = MAX_PROCESSED_PACKETS_IN_SAME_WORLDSESSION_UPDATE; // break out of packet processing loop
421 break;
422 case STATUS_AUTHED:
423 // prevent cheating with skip queue wait
424 if (m_inQueue)
425 {
426 LogUnexpectedOpcode(packet, "STATUS_AUTHED", "the player not pass queue yet");
427 break;
428 }
429
430 // some auth opcodes can be recieved before STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT opcodes
431 // however when we recieve CMSG_CHAR_ENUM we are surely no longer during the logout process.
432 if (packet->GetOpcode() == CMSG_ENUM_CHARACTERS)
434
435 if (AntiDOS.EvaluateOpcode(*packet, currentTime))
436 {
437 sScriptMgr->OnPacketReceive(this, *packet);
438 opHandle->Call(this, *packet);
439 }
440 else
441 processedPackets = MAX_PROCESSED_PACKETS_IN_SAME_WORLDSESSION_UPDATE; // break out of packet processing loop
442 break;
443 case STATUS_NEVER:
444 TC_LOG_ERROR("network.opcode", "Received not allowed opcode {} from {}", GetOpcodeNameForLogging(static_cast<OpcodeClient>(packet->GetOpcode()))
445 , GetPlayerInfo());
446 break;
447 case STATUS_UNHANDLED:
448 TC_LOG_ERROR("network.opcode", "Received not handled opcode {} from {}", GetOpcodeNameForLogging(static_cast<OpcodeClient>(packet->GetOpcode()))
449 , GetPlayerInfo());
450 break;
451 }
452 }
454 {
455 TC_LOG_ERROR("network", "{} sent {} with an invalid link:\n{}", GetPlayerInfo(),
456 GetOpcodeNameForLogging(static_cast<OpcodeClient>(packet->GetOpcode())), ihe.GetInvalidValue());
457
459 KickPlayer("WorldSession::Update Invalid chat link");
460 }
462 {
463 TC_LOG_ERROR("network", "{} sent {} which illegally contained a hyperlink:\n{}", GetPlayerInfo(),
464 GetOpcodeNameForLogging(static_cast<OpcodeClient>(packet->GetOpcode())), ihe.GetInvalidValue());
465
467 KickPlayer("WorldSession::Update Illegal chat link");
468 }
470 {
471 TC_LOG_ERROR("network", "PacketArrayMaxCapacityException: {} while parsing {} from {}.",
472 pamce.what(), GetOpcodeNameForLogging(static_cast<OpcodeClient>(packet->GetOpcode())), GetPlayerInfo());
473 }
474 catch (ByteBufferException const&)
475 {
476 TC_LOG_ERROR("network", "WorldSession::Update ByteBufferException occured while parsing a packet (opcode: {}) from client {}, accountid={}. Skipped packet.",
477 packet->GetOpcode(), GetRemoteAddress(), GetAccountId());
478 packet->hexlike();
479 }
480
481 if (deletePacket)
482 delete packet;
483
484 deletePacket = true;
485
486 processedPackets++;
487
488 //process only a max amout of packets in 1 Update() call.
489 //Any leftover will be processed in next update
490 if (processedPackets > MAX_PROCESSED_PACKETS_IN_SAME_WORLDSESSION_UPDATE)
491 break;
492 }
493
494 TC_METRIC_VALUE("processed_packets", processedPackets);
495
496 _recvQueue.readd(requeuePackets.begin(), requeuePackets.end());
497
498 if (!updater.ProcessUnsafe()) // <=> updater is of type MapSessionFilter
499 {
500 // Send time sync packet every 10s.
501 if (_timeSyncTimer > 0)
502 {
503 if (diff >= _timeSyncTimer)
504 SendTimeSync();
505 else
506 _timeSyncTimer -= diff;
507 }
508 }
509
511
512 //check if we are safe to proceed with logout
513 //logout procedure should happen only in World::UpdateSessions() method!!!
514 if (updater.ProcessUnsafe())
515 {
517 _warden->Update(diff);
518
520 if (ShouldLogOut(currentTime) && m_playerLoading.IsEmpty())
521 LogoutPlayer(true);
522
526 {
527 if (GetPlayer() && _warden)
528 _warden->Update(diff);
529
530 expireTime -= expireTime > diff ? diff : expireTime;
531 if (expireTime < diff || forceExit || !GetPlayer())
532 {
534 {
535 m_Socket[CONNECTION_TYPE_REALM]->CloseSocket();
537 }
539 {
540 m_Socket[CONNECTION_TYPE_INSTANCE]->CloseSocket();
542 }
543 }
544 }
545
547 return false; //Will remove this session from the world session map
548 }
549
550 return true;
551}
552
555{
556 // finish pending transfers before starting the logout
559
560 m_playerLogout = true;
561 m_playerSave = save;
562
563 if (_player)
564 {
565 if (!_player->GetLootGUID().IsEmpty())
567
569 if (_player->GetDeathTimer())
570 {
574 }
576 {
577 // this will kill character by SPELL_AURA_SPIRIT_OF_REDEMPTION
582 }
583 else if (_player->HasPendingBind())
584 {
586 _player->SetPendingBind(0, 0);
587 }
588
589 //drop a flag if player is carrying it
591 bg->EventPlayerLoggedOut(_player);
592
596
597 sOutdoorPvPMgr->HandlePlayerLeaveZone(_player, _player->GetZoneId());
598
599 for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i)
600 {
602 if (bgQueueTypeId != BATTLEGROUND_QUEUE_NONE)
603 {
604 _player->RemoveBattlegroundQueueId(bgQueueTypeId);
605 BattlegroundQueue& queue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId);
606 queue.RemovePlayer(_player->GetGUID(), true);
607 }
608 }
609
610 // Repop at Graveyard or other player far teleport will prevent saving player because of not present map
611 // Teleport player immediately for correct player save
614
616 if (Guild* guild = sGuildMgr->GetGuildById(_player->GetGuildId()))
617 guild->HandleMemberLogout(this);
618
620 _player->RemovePet(nullptr, PET_SAVE_AS_CURRENT, true);
621
623 if (_battlePetMgr->HasJournalLock())
624 _battlePetMgr->ToggleJournalLock(false);
625
628
630
632 // some save parts only correctly work in case player present in map/player_lists (pets, etc)
633 if (save)
634 {
635 uint32 eslot;
636 for (int j = BUYBACK_SLOT_START; j < BUYBACK_SLOT_END; ++j)
637 {
638 eslot = j - BUYBACK_SLOT_START;
640 _player->SetBuybackPrice(eslot, 0);
641 _player->SetBuybackTimestamp(eslot, 0);
642 }
643 _player->SaveToDB();
644 }
645
648
651
653 if (Group* group = _player->GetGroup())
654 {
655 group->SendUpdate();
656 if (group->GetLeaderGUID() == _player->GetGUID())
657 group->StartLeaderOfflineTimer();
658 }
659
661 sSocialMgr->SendFriendStatus(_player, FRIEND_OFFLINE, _player->GetGUID(), true);
663
665 sScriptMgr->OnPlayerLogout(_player);
666
667 TC_METRIC_EVENT("player_events", "Logout", _player->GetName());
668
670 // the player may not be in the world when logging out
671 // e.g if he got disconnected during a transfer to another map
672 // calls to GetMap in this case may cause crashes
675 TC_LOG_INFO("entities.player.character", "Account: {} (IP: {}) Logout Character:[{}] {} Level: {}, XP: {}/{} ({} left)",
678
679 if (Map* _map = _player->FindMap())
680 _map->RemovePlayerFromMap(_player, true);
681
682 SetPlayer(nullptr);
683
687 TC_LOG_DEBUG("network", "SESSION: Sent SMSG_LOGOUT_COMPLETE Message");
688
691 stmt->setUInt32(0, GetAccountId());
692 CharacterDatabase.Execute(stmt);
693 }
694
696 {
697 m_Socket[CONNECTION_TYPE_INSTANCE]->CloseSocket();
699 }
700
701 m_playerLogout = false;
702 m_playerSave = false;
705}
706
708void WorldSession::KickPlayer(std::string const& reason)
709{
710 TC_LOG_INFO("network.kick", "Account: {} Character: '{}' {} kicked with reason: {}", GetAccountId(), _player ? _player->GetName() : "<none>",
711 _player ? _player->GetGUID().ToString() : "", reason);
712
713 for (uint8 i = 0; i < 2; ++i)
714 {
715 if (m_Socket[i])
716 {
717 m_Socket[i]->CloseSocket();
718 forceExit = true;
719 }
720 }
721}
722
724{
726 return true;
727
728 TC_LOG_ERROR("network", "Player {}{} sent a message with an invalid link:\n{}", GetPlayer()->GetName(),
729 GetPlayer()->GetGUID().ToString(), str);
730
732 KickPlayer("WorldSession::ValidateHyperlinksAndMaybeKick Invalid chat link");
733
734 return false;
735}
736
738{
739 if (str.find('|') == std::string::npos)
740 return true;
741
742 TC_LOG_ERROR("network", "Player {} {} sent a message which illegally contained a hyperlink:\n{}", GetPlayer()->GetName(),
743 GetPlayer()->GetGUID().ToString(), str);
744
746 KickPlayer("WorldSession::DisallowHyperlinksAndMaybeKick Illegal chat link");
747
748 return false;
749}
750
751void WorldSession::SendNotification(char const* format, ...)
752{
753 if (format)
754 {
755 va_list ap;
756 char szStr[1024];
757 szStr[0] = '\0';
758 va_start(ap, format);
759 vsnprintf(szStr, 1024, format, ap);
760 va_end(ap);
761
763 }
764}
765
767{
768 char const* format = GetTrinityString(stringId);
769 if (format)
770 {
771 va_list ap;
772 char szStr[1024];
773 szStr[0] = '\0';
774 va_start(ap, stringId);
775 vsnprintf(szStr, 1024, format, ap);
776 va_end(ap);
777
779 }
780}
781
783{
785}
786
788{
789 return sObjectMgr->GetTrinityString(entry, GetSessionDbLocaleIndex());
790}
791
793{
794 if (GetPlayer())
796 else if (!onlyActive)
798}
799
801{
803}
804
806{
807 TC_LOG_ERROR("network.opcode", "Received unhandled opcode {} from {}", GetOpcodeNameForLogging(null.GetOpcode()), GetPlayerInfo());
808}
809
811{
812 TC_LOG_ERROR("network.opcode", "Received opcode {} that must be processed in WorldSocket::ReadDataHandler from {}"
814}
815
817{
818 boost::system::error_code ignored_error;
819 boost::asio::ip::address instanceAddress;
820 if (std::shared_ptr<Realm const> currentRealm = sRealmList->GetCurrentRealm())
821 instanceAddress = currentRealm->GetAddressForClient(Trinity::Net::make_address(GetRemoteAddress(), ignored_error));
822
825 _instanceConnectKey.Fields.Key = urand(0, 0x7FFFFFFF);
826
828 connectTo.Key = _instanceConnectKey.Raw;
829 connectTo.Serial = serial;
830 connectTo.Payload.Port = sWorld->getIntConfig(CONFIG_PORT_WORLD);
831 if (instanceAddress.is_v4())
832 {
833 memcpy(connectTo.Payload.Where.Address.V4.data(), instanceAddress.to_v4().to_bytes().data(), 4);
835 }
836 else
837 {
838 // client always uses v4 address for loopback and v4 mapped addresses
839 boost::asio::ip::address_v6 v6 = instanceAddress.to_v6();
840 if (v6.is_loopback())
841 {
842 memcpy(connectTo.Payload.Where.Address.V4.data(), boost::asio::ip::address_v4::loopback().to_bytes().data(), 4);
844 }
845 else if (v6.is_v4_mapped())
846 {
847 memcpy(connectTo.Payload.Where.Address.V4.data(), Trinity::Net::make_address_v4(Trinity::Net::v4_mapped, v6).to_bytes().data(), 4);
849 }
850 else
851 {
852 memcpy(connectTo.Payload.Where.Address.V6.data(), v6.to_bytes().data(), 16);
854 }
855 }
856 connectTo.Con = CONNECTION_TYPE_INSTANCE;
857
858 SendPacket(connectTo.Write());
859}
860
862{
863 for (uint32 i = 0; i < NUM_ACCOUNT_DATA_TYPES; ++i)
864 if (mask & (1 << i))
866
867 if (!result)
868 return;
869
870 do
871 {
872 Field* fields = result->Fetch();
873 uint32 type = fields[0].GetUInt8();
874 if (type >= NUM_ACCOUNT_DATA_TYPES)
875 {
876 TC_LOG_ERROR("misc", "Table `{}` have invalid account data type ({}), ignore.",
877 mask == GLOBAL_CACHE_MASK ? "account_data" : "character_account_data", type);
878 continue;
879 }
880
881 if ((mask & (1 << type)) == 0)
882 {
883 TC_LOG_ERROR("misc", "Table `{}` have non appropriate for table account data type ({}), ignore.",
884 mask == GLOBAL_CACHE_MASK ? "account_data" : "character_account_data", type);
885 continue;
886 }
887
888 _accountData[type].Time = fields[1].GetInt64();
889 _accountData[type].Data = fields[2].GetString();
890 }
891 while (result->NextRow());
892}
893
894void WorldSession::SetAccountData(AccountDataType type, time_t time, std::string const& data)
895{
896 if ((1 << type) & GLOBAL_CACHE_MASK)
897 {
899 stmt->setUInt32(0, GetAccountId());
900 stmt->setUInt8(1, type);
901 stmt->setInt64(2, time);
902 stmt->setString(3, data);
903 CharacterDatabase.Execute(stmt);
904 }
905 else
906 {
907 // _player can be NULL and packet received after logout but m_GUID still store correct guid
908 if (!m_GUIDLow)
909 return;
910
912 stmt->setUInt64(0, m_GUIDLow);
913 stmt->setUInt8(1, type);
914 stmt->setInt64(2, time);
915 stmt->setString(3, data);
916 CharacterDatabase.Execute(stmt);
917 }
918
919 _accountData[type].Time = time;
920 _accountData[type].Data = data;
921}
922
924{
926 accountDataTimes.PlayerGuid = playerGuid;
927 accountDataTimes.ServerTime = GameTime::GetSystemTime();
928 for (uint32 i = 0; i < NUM_ACCOUNT_DATA_TYPES; ++i)
929 if (mask & (1 << i))
930 accountDataTimes.AccountTimes[i] = GetAccountData(AccountDataType(i))->Time;
931
932 SendPacket(accountDataTimes.Write());
933}
934
936{
937 _tutorials = { };
938
939 if (result)
940 {
941 for (uint8 i = 0; i < MAX_ACCOUNT_TUTORIAL_VALUES; ++i)
942 _tutorials[i] = (*result)[i].GetUInt32();
944 }
945
946 _tutorialsChanged &= ~TUTORIALS_FLAG_CHANGED;
947}
948
950{
952 packet.TutorialData = _tutorials;
953 SendPacket(packet.Write());
954}
955
957{
959 return;
960
961 bool const hasTutorialsInDB = (_tutorialsChanged & TUTORIALS_FLAG_LOADED_FROM_DB) != 0;
962 CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(hasTutorialsInDB ? CHAR_UPD_TUTORIALS : CHAR_INS_TUTORIALS);
963 for (uint8 i = 0; i < MAX_ACCOUNT_TUTORIAL_VALUES; ++i)
964 stmt->setUInt32(i, _tutorials[i]);
966 trans->Append(stmt);
967
968 // now has, set flag so next save uses update query
969 if (!hasTutorialsInDB)
971
972 _tutorialsChanged &= ~TUTORIALS_FLAG_CHANGED;
973}
974
975bool WorldSession::IsAddonRegistered(std::string_view prefix) const
976{
977 if (!_filterAddonMessages) // if we have hit the softcap (64) nothing should be filtered
978 return true;
979
980 if (_registeredAddonPrefixes.empty())
981 return false;
982
983 std::vector<std::string>::const_iterator itr = std::find(_registeredAddonPrefixes.begin(), _registeredAddonPrefixes.end(), prefix);
984 return itr != _registeredAddonPrefixes.end();
985}
986
988{
990}
991
993{
994 // This is always sent after CMSG_CHAT_UNREGISTER_ALL_ADDON_PREFIXES
997 {
998 _filterAddonMessages = false;
999 return;
1000 }
1001
1002 _filterAddonMessages = true;
1003}
1004
1006{
1007 _player = player;
1008
1009 // set m_GUID that can be used while player loggined and later until m_playerRecentlyLogout not reset
1010 if (_player)
1012}
1013
1015{
1019}
1020
1022{
1023 return _transactionCallbacks.AddCallback(std::move(callback));
1024}
1025
1027{
1028 return _queryHolderProcessor.AddCallback(std::move(callback));
1029}
1030
1032{
1034}
1035
1037{
1038 if (_os == "Win")
1039 {
1040 _warden = std::make_unique<WardenWin>();
1041 _warden->Init(this, k);
1042 }
1043 else if (_os == "Wn64")
1044 {
1045 // Not implemented
1046 }
1047 else if (_os == "Mc64")
1048 {
1049 // Not implemented
1050 }
1051}
1052
1054{
1055 uint32 id = GetAccountId();
1056 uint8 secLevel = GetSecurity();
1057
1058 TC_LOG_DEBUG("rbac", "WorldSession::LoadPermissions [AccountId: {}, Name: {}, realmId: {}, secLevel: {}]",
1059 id, _accountName, sRealmList->GetCurrentRealmId().Realm, secLevel);
1060
1061 _RBACData = new rbac::RBACData(id, _accountName, sRealmList->GetCurrentRealmId().Realm, secLevel);
1063}
1064
1066{
1067 uint32 id = GetAccountId();
1068 uint8 secLevel = GetSecurity();
1069
1070 TC_LOG_DEBUG("rbac", "WorldSession::LoadPermissions [AccountId: {}, Name: {}, realmId: {}, secLevel: {}]",
1071 id, _accountName, sRealmList->GetCurrentRealmId().Realm, secLevel);
1072
1073 _RBACData = new rbac::RBACData(id, _accountName, sRealmList->GetCurrentRealmId().Realm, secLevel);
1074 return _RBACData->LoadFromDBAsync();
1075}
1076
1078{
1079public:
1080 enum
1081 {
1084
1087
1089
1090 bool Initialize(uint32 accountId, uint32 /*battlenetAccountId*/)
1091 {
1092 bool ok = true;
1093
1095 stmt->setUInt32(0, accountId);
1096 ok = SetPreparedQuery(GLOBAL_ACCOUNT_DATA, stmt) && ok;
1097
1098 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_TUTORIALS);
1099 stmt->setUInt32(0, accountId);
1100 ok = SetPreparedQuery(TUTORIALS, stmt) && ok;
1101
1102 return ok;
1103 }
1104};
1105
1107{
1108public:
1109 enum
1110 {
1121
1124
1126
1127 bool Initialize(uint32 accountId, uint32 battlenetAccountId)
1128 {
1129 bool ok = true;
1130
1132 stmt->setUInt32(0, battlenetAccountId);
1133 ok = SetPreparedQuery(GLOBAL_ACCOUNT_TOYS, stmt) && ok;
1134
1135 stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BATTLE_PETS);
1136 stmt->setUInt32(0, battlenetAccountId);
1137 stmt->setInt32(1, sRealmList->GetCurrentRealmId().Realm);
1138 ok = SetPreparedQuery(BATTLE_PETS, stmt) && ok;
1139
1140 stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BATTLE_PET_SLOTS);
1141 stmt->setUInt32(0, battlenetAccountId);
1142 ok = SetPreparedQuery(BATTLE_PET_SLOTS, stmt) && ok;
1143
1144 stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_HEIRLOOMS);
1145 stmt->setUInt32(0, battlenetAccountId);
1147
1148 stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_MOUNTS);
1149 stmt->setUInt32(0, battlenetAccountId);
1150 ok = SetPreparedQuery(MOUNTS, stmt) && ok;
1151
1153 stmt->setUInt32(0, accountId);
1155
1156 stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_ITEM_APPEARANCES);
1157 stmt->setUInt32(0, battlenetAccountId);
1158 ok = SetPreparedQuery(ITEM_APPEARANCES, stmt) && ok;
1159
1160 stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_ITEM_FAVORITE_APPEARANCES);
1161 stmt->setUInt32(0, battlenetAccountId);
1163
1164 stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_TRANSMOG_ILLUSIONS);
1165 stmt->setUInt32(0, battlenetAccountId);
1166 ok = SetPreparedQuery(TRANSMOG_ILLUSIONS, stmt) && ok;
1167
1168 stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_WARBAND_SCENES);
1169 stmt->setUInt32(0, battlenetAccountId);
1170 ok = SetPreparedQuery(WARBAND_SCENES, stmt) && ok;
1171
1172 return ok;
1173 }
1174};
1175
1177{
1178 std::shared_ptr<AccountInfoQueryHolderPerRealm> realmHolder = std::make_shared<AccountInfoQueryHolderPerRealm>();
1179 if (!realmHolder->Initialize(GetAccountId(), GetBattlenetAccountId()))
1180 {
1182 return;
1183 }
1184
1185 std::shared_ptr<AccountInfoQueryHolder> holder = std::make_shared<AccountInfoQueryHolder>();
1186 if (!holder->Initialize(GetAccountId(), GetBattlenetAccountId()))
1187 {
1189 return;
1190 }
1191
1192 struct ForkJoinState
1193 {
1194 std::shared_ptr<AccountInfoQueryHolderPerRealm> Character;
1195 std::shared_ptr<AccountInfoQueryHolder> Login;
1196 };
1197
1198 std::shared_ptr<ForkJoinState> state = std::make_shared<ForkJoinState>();
1199
1200 AddQueryHolderCallback(CharacterDatabase.DelayQueryHolder(realmHolder)).AfterComplete([this, state, realmHolder](SQLQueryHolderBase const& /*result*/)
1201 {
1202 state->Character = realmHolder;
1203 if (state->Login && state->Character)
1204 InitializeSessionCallback(*state->Login, *state->Character);
1205 });
1206
1207 AddQueryHolderCallback(LoginDatabase.DelayQueryHolder(holder)).AfterComplete([this, state, holder](SQLQueryHolderBase const& /*result*/)
1208 {
1209 state->Login = holder;
1210 if (state->Login && state->Character)
1211 InitializeSessionCallback(*state->Login, *state->Character);
1212 });
1213}
1214
1216{
1225
1226 if (!m_inQueue)
1227 SendAuthResponse(ERROR_OK, false);
1228 else
1230
1231 SetInQueue(false);
1232 ResetTimeOutTime(false);
1233
1240
1242 {
1243 do
1244 {
1245 Field* fields = characterCountsResult->Fetch();
1246 _realmCharacterCounts[Battlenet::RealmHandle{ fields[3].GetUInt8(), fields[4].GetUInt8(), fields[2].GetUInt32() }.GetAddress()] = fields[1].GetUInt8();
1247
1248 } while (characterCountsResult->NextRow());
1249 }
1250
1252 bnetConnected.State = 1;
1253 SendPacket(bnetConnected.Write());
1254
1257}
1258
1260{
1261 return _RBACData;
1262}
1263
1265{
1266 if (!_RBACData)
1268
1269 bool hasPermission = _RBACData->HasPermission(permission);
1270 TC_LOG_DEBUG("rbac", "WorldSession::HasPermission [AccountId: {}, Name: {}, realmId: {}]",
1271 _RBACData->GetId(), _RBACData->GetName(), sRealmList->GetCurrentRealmId().Realm);
1272
1273 return hasPermission;
1274}
1275
1277{
1278 TC_LOG_DEBUG("rbac", "WorldSession::Invalidaterbac::RBACData [AccountId: {}, Name: {}, realmId: {}]",
1279 _RBACData->GetId(), _RBACData->GetName(), sRealmList->GetCurrentRealmId().Realm);
1280 delete _RBACData;
1281 _RBACData = nullptr;
1282}
1283
1285{
1286 uint32 maxPacketCounterAllowed = GetMaxPacketCounterAllowed(p.GetOpcode());
1287
1288 // Return true if there no limit for the opcode
1289 if (!maxPacketCounterAllowed)
1290 return true;
1291
1292 PacketCounter& packetCounter = _PacketThrottlingMap[p.GetOpcode()];
1293 if (packetCounter.lastReceiveTime != time)
1294 {
1295 packetCounter.lastReceiveTime = time;
1296 packetCounter.amountCounter = 0;
1297 }
1298
1299 // Check if player is flooding some packets
1300 if (++packetCounter.amountCounter <= maxPacketCounterAllowed)
1301 return true;
1302
1303 TC_LOG_WARN("network", "AntiDOS: Account {}, IP: {}, Ping: {}, Character: {}, flooding packet (opc: {} (0x{:X}), count: {})",
1305 opcodeTable[static_cast<OpcodeClient>(p.GetOpcode())]->Name, p.GetOpcode(), packetCounter.amountCounter);
1306
1307 switch (_policy)
1308 {
1309 case POLICY_LOG:
1310 return true;
1311 case POLICY_KICK:
1312 {
1313 TC_LOG_WARN("network", "AntiDOS: Player kicked!");
1314 Session->KickPlayer("WorldSession::DosProtection::EvaluateOpcode AntiDOS");
1315 return false;
1316 }
1317 case POLICY_BAN:
1318 {
1320 uint32 duration = sWorld->getIntConfig(CONFIG_PACKET_SPOOF_BANDURATION); // in seconds
1321 std::string nameOrIp = "";
1322 switch (bm)
1323 {
1324 case BAN_CHARACTER: // not supported, ban account
1325 case BAN_ACCOUNT: (void)sAccountMgr->GetName(Session->GetAccountId(), nameOrIp); break;
1326 case BAN_IP: nameOrIp = Session->GetRemoteAddress(); break;
1327 }
1328 sWorld->BanAccount(bm, nameOrIp, duration, "DOS (Packet Flooding/Spoofing", "Server: AutoDOS");
1329 TC_LOG_WARN("network", "AntiDOS: Player automatically banned for {} seconds.", duration);
1330 Session->KickPlayer("WorldSession::DosProtection::EvaluateOpcode AntiDOS");
1331 return false;
1332 }
1333 default: // invalid policy
1334 return true;
1335 }
1336}
1337
1339{
1340 uint32 maxPacketCounterAllowed;
1341 switch (opcode)
1342 {
1343 // CPU usage sending 2000 packets/second on a 3.70 GHz 4 cores on Win x64
1344 // [% CPU mysqld] [%CPU worldserver RelWithDebInfo]
1345 case CMSG_PLAYER_LOGIN: // 0 0.5
1346 case CMSG_QUERY_PLAYER_NAMES: // 0 1
1347 case CMSG_QUERY_PET_NAME: // 0 1
1348 case CMSG_QUERY_NPC_TEXT: // 0 1
1349 case CMSG_ATTACK_STOP: // 0 1
1350 case CMSG_QUERY_TIME: // 0 1
1351 case CMSG_QUERY_CORPSE_TRANSPORT: // 0 1
1352 case CMSG_MOVE_TIME_SKIPPED: // 0 1
1353 case CMSG_QUERY_NEXT_MAIL_TIME: // 0 1
1354 case CMSG_SET_SHEATHED: // 0 1
1355 case CMSG_UPDATE_RAID_TARGET: // 0 1
1356 case CMSG_LOGOUT_REQUEST: // 0 1
1357 case CMSG_PET_RENAME: // 0 1
1359 case CMSG_COMPLETE_CINEMATIC: // 0 1
1360 case CMSG_BANKER_ACTIVATE: // 0 1
1361 case CMSG_BUY_BANK_SLOT: // 0 1
1362 case CMSG_OPT_OUT_OF_LOOT: // 0 1
1363 case CMSG_DUEL_RESPONSE: // 0 1
1364 case CMSG_CALENDAR_COMPLAIN: // 0 1
1365 case CMSG_QUERY_QUEST_INFO: // 0 1.5
1366 case CMSG_QUERY_GAME_OBJECT: // 0 1.5
1367 case CMSG_QUERY_CREATURE: // 0 1.5
1368 case CMSG_QUEST_GIVER_STATUS_QUERY: // 0 1.5
1369 case CMSG_QUERY_GUILD_INFO: // 0 1.5
1370 case CMSG_TAXI_NODE_STATUS_QUERY: // 0 1.5
1371 case CMSG_TAXI_QUERY_AVAILABLE_NODES: // 0 1.5
1372 case CMSG_QUEST_GIVER_QUERY_QUEST: // 0 1.5
1373 case CMSG_QUERY_PAGE_TEXT: // 0 1.5
1374 case CMSG_GUILD_BANK_TEXT_QUERY: // 0 1.5
1376 case CMSG_MOVE_SET_FACING: // 0 1.5
1377 case CMSG_MOVE_SET_FACING_HEARTBEAT: // 0 1.5
1378 case CMSG_MOVE_SET_PITCH: // 0 1.5
1379 case CMSG_REQUEST_PARTY_MEMBER_STATS: // 0 1.5
1380 case CMSG_QUEST_GIVER_COMPLETE_QUEST: // 0 1.5
1381 case CMSG_SET_ACTION_BUTTON: // 0 1.5
1382 case CMSG_SET_ACTION_BAR_TOGGLES: // not profiled
1383 case CMSG_RESET_INSTANCES: // 0 1.5
1384 case CMSG_HEARTH_AND_RESURRECT: // 0 1.5
1385 case CMSG_TOGGLE_PVP: // 0 1.5
1386 case CMSG_PET_ABANDON: // 0 1.5
1387 case CMSG_ACTIVATE_TAXI: // 0 1.5
1388 case CMSG_SELF_RES: // 0 1.5
1389 case CMSG_UNLEARN_SKILL: // 0 1.5
1390 case CMSG_SAVE_EQUIPMENT_SET: // 0 1.5
1391 case CMSG_DELETE_EQUIPMENT_SET: // 0 1.5
1392 case CMSG_DISMISS_CRITTER: // 0 1.5
1393 case CMSG_REPOP_REQUEST: // 0 1.5
1394 case CMSG_PARTY_INVITE: // 0 1.5
1395 case CMSG_PARTY_INVITE_RESPONSE: // 0 1.5
1396 case CMSG_PARTY_UNINVITE: // 0 1.5
1397 case CMSG_LEAVE_GROUP: // 0 1.5
1398 case CMSG_BATTLEMASTER_JOIN_ARENA: // 0 1.5
1399 case CMSG_BATTLEFIELD_LEAVE: // 0 1.5
1400 case CMSG_GUILD_BANK_LOG_QUERY: // 0 2
1401 case CMSG_LOGOUT_CANCEL: // 0 2
1402 case CMSG_ALTER_APPEARANCE: // 0 2
1403 case CMSG_QUEST_CONFIRM_ACCEPT: // 0 2
1404 case CMSG_GUILD_EVENT_LOG_QUERY: // 0 2.5
1406 case CMSG_BEGIN_TRADE: // 0 2.5
1407 case CMSG_INITIATE_TRADE: // 0 3
1408 case CMSG_CHAT_ADDON_MESSAGE: // 0 3.5
1410 case CMSG_CHAT_MESSAGE_AFK: // 0 3.5
1411 case CMSG_CHAT_MESSAGE_CHANNEL: // 0 3.5
1412 case CMSG_CHAT_MESSAGE_DND: // 0 3.5
1413 case CMSG_CHAT_MESSAGE_EMOTE: // 0 3.5
1414 case CMSG_CHAT_MESSAGE_GUILD: // 0 3.5
1415 case CMSG_CHAT_MESSAGE_OFFICER: // 0 3.5
1416 case CMSG_CHAT_MESSAGE_PARTY: // 0 3.5
1417 case CMSG_CHAT_MESSAGE_RAID: // 0 3.5
1418 case CMSG_CHAT_MESSAGE_RAID_WARNING: // 0 3.5
1419 case CMSG_CHAT_MESSAGE_SAY: // 0 3.5
1420 case CMSG_CHAT_MESSAGE_WHISPER: // 0 3.5
1421 case CMSG_CHAT_MESSAGE_YELL: // 0 3.5
1422 case CMSG_INSPECT: // 0 3.5
1423 case CMSG_AREA_SPIRIT_HEALER_QUERY: // not profiled
1424 case CMSG_STAND_STATE_CHANGE: // not profiled
1425 case CMSG_RANDOM_ROLL: // not profiled
1426 case CMSG_TIME_SYNC_RESPONSE: // not profiled
1427 case CMSG_MOVE_FORCE_RUN_SPEED_CHANGE_ACK: // not profiled
1428 case CMSG_MOVE_FORCE_SWIM_SPEED_CHANGE_ACK: // not profiled
1430 case CMSG_MOVE_FORCE_RUN_BACK_SPEED_CHANGE_ACK: // not profiled
1431 case CMSG_MOVE_FORCE_FLIGHT_SPEED_CHANGE_ACK: // not profiled
1433 case CMSG_MOVE_FORCE_WALK_SPEED_CHANGE_ACK: // not profiled
1434 case CMSG_MOVE_FORCE_TURN_RATE_CHANGE_ACK: // not profiled
1435 case CMSG_MOVE_FORCE_PITCH_RATE_CHANGE_ACK: // not profiled
1436 {
1437 // "0" is a magic number meaning there's no limit for the opcode.
1438 // All the opcodes above must cause little CPU usage and no sync/async database queries at all
1439 maxPacketCounterAllowed = 0;
1440 break;
1441 }
1442
1444 case CMSG_QUEST_LOG_REMOVE_QUEST: // 0 4
1446 case CMSG_SEND_CONTACT_LIST: // 0 5
1447 case CMSG_AUTOBANK_ITEM: // 0 6
1448 case CMSG_AUTOSTORE_BANK_ITEM: // 0 6
1449 case CMSG_WHO: // 0 7
1450 case CMSG_RIDE_VEHICLE_INTERACT: // 0 8
1452 {
1453 maxPacketCounterAllowed = 200;
1454 break;
1455 }
1456
1457 case CMSG_GUILD_SET_MEMBER_NOTE: // 1 2 1 async db query
1458 case CMSG_SET_CONTACT_NOTES: // 1 2.5 1 async db query
1459 case CMSG_CALENDAR_GET: // 0 1.5 medium upload bandwidth usage
1460 case CMSG_GUILD_BANK_QUERY_TAB: // 0 3.5 medium upload bandwidth usage
1461 case CMSG_QUERY_INSPECT_ACHIEVEMENTS: // 0 13 high upload bandwidth usage
1462 case CMSG_GAME_OBJ_REPORT_USE: // not profiled
1463 case CMSG_GAME_OBJ_USE: // not profiled
1464 case CMSG_DECLINE_PETITION: // not profiled
1465 {
1466 maxPacketCounterAllowed = 50;
1467 break;
1468 }
1469
1470 case CMSG_QUEST_POI_QUERY: // 0 25 very high upload bandwidth usage
1471 {
1472 maxPacketCounterAllowed = MAX_QUEST_LOG_SIZE;
1473 break;
1474 }
1475
1476 case CMSG_SPELL_CLICK: // not profiled
1477 case CMSG_MOVE_DISMISS_VEHICLE: // not profiled
1478 {
1479 maxPacketCounterAllowed = 20;
1480 break;
1481 }
1482
1483 case CMSG_SIGN_PETITION: // 9 4 2 sync 1 async db queries
1484 case CMSG_TURN_IN_PETITION: // 8 5.5 2 sync db query
1485 case CMSG_CHANGE_SUB_GROUP: // 6 5 1 sync 1 async db queries
1486 case CMSG_QUERY_PETITION: // 4 3.5 1 sync db query
1487 case CMSG_CHAR_CUSTOMIZE: // 5 5 1 sync db query
1488 case CMSG_CHAR_RACE_OR_FACTION_CHANGE: // 5 5 1 sync db query
1489 case CMSG_CHAR_DELETE: // 4 4 1 sync db query
1490 case CMSG_DEL_FRIEND: // 7 5 1 async db query
1491 case CMSG_ADD_FRIEND: // 6 4 1 async db query
1492 case CMSG_CHARACTER_RENAME_REQUEST: // 5 3 1 async db query
1493 case CMSG_BUG_REPORT: // 1 1 1 async db query
1494 case CMSG_SET_PARTY_LEADER: // 1 2 1 async db query
1495 case CMSG_CONVERT_RAID: // 1 5 1 async db query
1496 case CMSG_SET_ASSISTANT_LEADER: // 1 2 1 async db query
1497 case CMSG_MOVE_CHANGE_VEHICLE_SEATS: // not profiled
1498 case CMSG_PETITION_BUY: // not profiled 1 sync 1 async db queries
1499 case CMSG_REQUEST_VEHICLE_PREV_SEAT: // not profiled
1500 case CMSG_REQUEST_VEHICLE_NEXT_SEAT: // not profiled
1501 case CMSG_REQUEST_VEHICLE_SWITCH_SEAT: // not profiled
1502 case CMSG_REQUEST_VEHICLE_EXIT: // not profiled
1503 case CMSG_EJECT_PASSENGER: // not profiled
1504 case CMSG_ITEM_PURCHASE_REFUND: // not profiled
1505 case CMSG_SOCKET_GEMS: // not profiled
1506 case CMSG_WRAP_ITEM: // not profiled
1507 case CMSG_REPORT_PVP_PLAYER_AFK: // not profiled
1508 {
1509 maxPacketCounterAllowed = 10;
1510 break;
1511 }
1512
1513 case CMSG_CREATE_CHARACTER: // 7 5 3 async db queries
1514 case CMSG_ENUM_CHARACTERS: // 22 3 2 async db queries
1515 case CMSG_ENUM_CHARACTERS_DELETED_BY_CLIENT: // 22 3 2 async db queries
1516 case CMSG_SUBMIT_USER_FEEDBACK: // not profiled 1 async db query
1517 case CMSG_SUPPORT_TICKET_SUBMIT_COMPLAINT: // not profiled 1 async db query
1518 case CMSG_CALENDAR_ADD_EVENT: // 21 10 2 async db query
1519 case CMSG_CALENDAR_UPDATE_EVENT: // not profiled
1520 case CMSG_CALENDAR_REMOVE_EVENT: // not profiled
1521 case CMSG_CALENDAR_COPY_EVENT: // not profiled
1522 case CMSG_CALENDAR_INVITE: // not profiled
1523 case CMSG_CALENDAR_EVENT_SIGN_UP: // not profiled
1524 case CMSG_CALENDAR_RSVP: // not profiled
1525 case CMSG_CALENDAR_MODERATOR_STATUS: // not profiled
1526 case CMSG_CALENDAR_REMOVE_INVITE: // not profiled
1527 case CMSG_SET_LOOT_METHOD: // not profiled
1528 case CMSG_GUILD_INVITE_BY_NAME: // not profiled
1529 case CMSG_ACCEPT_GUILD_INVITE: // not profiled
1530 case CMSG_GUILD_DECLINE_INVITATION: // not profiled
1531 case CMSG_GUILD_LEAVE: // not profiled
1532 case CMSG_GUILD_DELETE: // not profiled
1533 case CMSG_GUILD_SET_GUILD_MASTER: // not profiled
1534 case CMSG_GUILD_UPDATE_MOTD_TEXT: // not profiled
1535 case CMSG_GUILD_SET_RANK_PERMISSIONS: // not profiled
1536 case CMSG_GUILD_ADD_RANK: // not profiled
1537 case CMSG_GUILD_DELETE_RANK: // not profiled
1538 case CMSG_GUILD_UPDATE_INFO_TEXT: // not profiled
1539 case CMSG_GUILD_BANK_DEPOSIT_MONEY: // not profiled
1540 case CMSG_GUILD_BANK_WITHDRAW_MONEY: // not profiled
1541 case CMSG_GUILD_BANK_BUY_TAB: // not profiled
1542 case CMSG_GUILD_BANK_UPDATE_TAB: // not profiled
1543 case CMSG_GUILD_BANK_SET_TAB_TEXT: // not profiled
1544 case CMSG_SAVE_GUILD_EMBLEM: // not profiled
1545 case CMSG_PETITION_RENAME_GUILD: // not profiled
1546 case CMSG_CONFIRM_RESPEC_WIPE: // not profiled
1547 case CMSG_SET_DUNGEON_DIFFICULTY: // not profiled
1548 case CMSG_SET_RAID_DIFFICULTY: // not profiled
1549 case CMSG_SET_PARTY_ASSIGNMENT: // not profiled
1550 case CMSG_DO_READY_CHECK: // not profiled
1551 {
1552 maxPacketCounterAllowed = 3;
1553 break;
1554 }
1555
1556 case CMSG_GET_ITEM_PURCHASE_DATA: // not profiled
1557 {
1558 maxPacketCounterAllowed = PLAYER_SLOTS_COUNT;
1559 break;
1560 }
1561 case CMSG_HOTFIX_REQUEST: // not profiled
1562 {
1563 maxPacketCounterAllowed = 1;
1564 break;
1565 }
1566 default:
1567 {
1568 maxPacketCounterAllowed = 100;
1569 break;
1570 }
1571 }
1572
1573 return maxPacketCounterAllowed;
1574}
1575
1577{
1578}
1579
1581{
1584}
1585
1587{
1589 timeSyncRequest.SequenceIndex = _timeSyncNextCounter;
1590 SendPacket(timeSyncRequest.Write());
1591
1593
1594 // Schedule next sync in 10 sec (except for the 2 first packets, which are spaced by only 5s)
1595 _timeSyncTimer = _timeSyncNextCounter == 0 ? 5000 : 10000;
1597}
1598
1600{
1602}
1603
1605{
1606 int64 movementTime = int64(time) + _timeSyncClockDelta;
1607 if (_timeSyncClockDelta == 0 || movementTime < 0 || movementTime > 0xFFFFFFFF)
1608 {
1609 TC_LOG_WARN("misc", "The computed movement time using clockDelta is erronous. Using fallback instead");
1610 return GameTime::GetGameTimeMS();
1611 }
1612 else
1613 return uint32(movementTime);
1614}
#define sAccountMgr
Definition: AccountMgr.h:104
std::array< uint8, SESSION_KEY_LENGTH > SessionKey
Definition: AuthDefines.h:25
#define sBattlegroundMgr
@ ERROR_INTERNAL
@ ERROR_TIMED_OUT
@ CHAR_INS_TUTORIALS
@ CHAR_UPD_TUTORIALS
@ CHAR_SEL_TUTORIALS
@ CHAR_SEL_ACCOUNT_DATA
@ CHAR_UPD_ACCOUNT_ONLINE
@ CHAR_REP_PLAYER_ACCOUNT_DATA
@ CHAR_REP_ACCOUNT_DATA
LocaleConstant
Definition: Common.h:51
AccountTypes
Definition: Common.h:42
SQLTransaction< CharacterDatabaseConnection > CharacterDatabaseTransaction
std::shared_ptr< PreparedResultSet > PreparedQueryResult
DatabaseWorkerPool< LoginDatabaseConnection > LoginDatabase
Accessor to the realm/login database.
Definition: DatabaseEnv.cpp:22
DatabaseWorkerPool< CharacterDatabaseConnection > CharacterDatabase
Accessor to the character database.
Definition: DatabaseEnv.cpp:21
uint8_t uint8
Definition: Define.h:150
int64_t int64
Definition: Define.h:143
int32_t int32
Definition: Define.h:144
uint64_t uint64
Definition: Define.h:147
#define UI64LIT(N)
Definition: Define.h:133
uint32_t uint32
Definition: Define.h:148
std::chrono::minutes Minutes
Minutes shorthand typedef.
Definition: Duration.h:32
#define sGuildMgr
Definition: GuildMgr.h:73
@ LOG_LEVEL_TRACE
Definition: LogCommon.h:27
#define TC_LOG_DEBUG(filterType__, message__,...)
Definition: Log.h:180
#define TC_LOG_ERROR(filterType__, message__,...)
Definition: Log.h:189
#define TC_LOG_INFO(filterType__, message__,...)
Definition: Log.h:183
#define sLog
Definition: Log.h:155
#define TC_LOG_WARN(filterType__, message__,...)
Definition: Log.h:186
#define TC_LOG_TRACE(filterType__, message__,...)
Definition: Log.h:177
@ LOGIN_SEL_BATTLE_PETS
@ LOGIN_SEL_BNET_ITEM_FAVORITE_APPEARANCES
@ LOGIN_SEL_ACCOUNT_TOYS
@ LOGIN_SEL_ACCOUNT_MOUNTS
@ LOGIN_SEL_BNET_CHARACTER_COUNTS_BY_ACCOUNT_ID
@ LOGIN_SEL_ACCOUNT_HEIRLOOMS
@ LOGIN_SEL_BNET_TRANSMOG_ILLUSIONS
@ LOGIN_SEL_BNET_WARBAND_SCENES
@ LOGIN_SEL_BATTLE_PET_SLOTS
@ LOGIN_SEL_BNET_ITEM_APPEARANCES
#define TC_METRIC_DETAILED_TIMER(category,...)
Definition: Metric.h:245
#define TC_METRIC_VALUE(category, value,...)
Definition: Metric.h:218
#define TC_METRIC_EVENT(category, title, description)
Definition: Metric.h:210
#define TC_METRIC_TAG(name, value)
Definition: Metric.h:184
#define sObjectMgr
Definition: ObjectMgr.h:1985
#define sOutdoorPvPMgr
@ PET_SAVE_AS_CURRENT
Definition: PetDefines.h:43
@ BUYBACK_SLOT_END
Definition: Player.h:739
@ BUYBACK_SLOT_START
Definition: Player.h:738
@ PLAYER_SLOTS_COUNT
Definition: Player.h:652
#define MAX_QUEST_LOG_SIZE
Definition: QuestDef.h:46
@ QUEST_FLAGS_FAIL_ON_LOGOUT
Definition: QuestDef.h:249
Role Based Access Control related classes definition.
uint32 urand(uint32 min, uint32 max)
Definition: Random.cpp:42
#define sRealmList
Definition: RealmList.h:93
#define sScriptMgr
Definition: ScriptMgr.h:1430
constexpr BattlegroundQueueTypeId BATTLEGROUND_QUEUE_NONE
static constexpr uint8 PLAYER_MAX_BATTLEGROUND_QUEUES
@ EXPANSION_BATTLE_FOR_AZEROTH
Definition: SharedDefines.h:97
#define MAX_ACCOUNT_TUTORIAL_VALUES
BanMode
Ban function modes.
@ BAN_ACCOUNT
@ BAN_IP
@ BAN_CHARACTER
@ FRIEND_OFFLINE
Definition: SocialMgr.h:72
#define sSocialMgr
Definition: SocialMgr.h:166
@ SPELL_AURA_MOD_SHAPESHIFT
@ SPELL_AURA_SPIRIT_OF_REDEMPTION
uint32 getMSTime()
Definition: Timer.h:33
bool Initialize(uint32 accountId, uint32)
bool Initialize(uint32 accountId, uint32 battlenetAccountId)
void RemovePlayer(ObjectGuid guid, bool decreaseInvitedCount)
char const * what() const noexcept override
Definition: ByteBuffer.h:36
size_t rpos() const
Definition: ByteBuffer.h:448
void hexlike() const
Definition: ByteBuffer.cpp:166
void print_storage() const
Definition: ByteBuffer.cpp:140
size_t wpos() const
Definition: ByteBuffer.h:461
size_t size() const
Definition: ByteBuffer.h:568
Class used to access individual fields of database query result.
Definition: Field.h:93
uint8 GetUInt8() const
Definition: Field.cpp:29
std::string GetString() const
Definition: Field.cpp:125
int64 GetInt64() const
Definition: Field.cpp:85
uint32 GetUInt32() const
Definition: Field.cpp:61
Definition: Group.h:205
Definition: Guild.h:329
void add(T const &item)
Adds an item to the queue.
Definition: LockedQueue.h:40
void readd(Iterator begin, Iterator end)
Adds items back to front of the queue.
Definition: LockedQueue.h:55
bool next(T &result)
Gets the next result in the queue, if any.
Definition: LockedQueue.h:62
virtual bool Process(WorldPacket *packet) override
Definition: Map.h:223
LowType GetCounter() const
Definition: ObjectGuid.h:296
static ObjectGuid const Empty
Definition: ObjectGuid.h:274
bool IsEmpty() const
Definition: ObjectGuid.h:322
std::string ToString() const
Definition: ObjectGuid.cpp:755
bool IsInWorld() const
Definition: Object.h:190
static ObjectGuid GetGUID(Object const *o)
Definition: Object.h:195
void SetDestroyedObject(bool destroyed)
Definition: Object.h:232
bool IsValid(OpcodeClient index) const
Definition: Opcodes.h:2302
virtual bool ProcessUnsafe() const
Definition: WorldSession.h:937
WorldSession *const m_pSession
Definition: WorldSession.h:940
void CleanupChannels()
Definition: Player.cpp:4866
uint32 GetXP() const
Definition: Player.h:1275
bool m_InstanceValid
Definition: Player.h:2684
bool IsBeingTeleportedFar() const
Definition: Player.h:2327
void KillPlayer()
Definition: Player.cpp:4453
void SetInvSlot(uint32 slot, ObjectGuid guid)
Definition: Player.h:1547
void FailQuestsWithFlag(QuestFlags flag)
Definition: Player.cpp:15395
void CleanupsBeforeDelete(bool finalCleanup=true) override
Definition: Player.cpp:381
uint32 GetDeathTimer() const
Definition: Player.h:2405
void RemoveSocial()
Definition: Player.cpp:30340
ObjectGuid const & GetLootGUID() const
Definition: Player.h:2197
bool HasPendingBind() const
Definition: Player.h:2700
WorldLocation m_homebind
Definition: Player.h:2616
void RemoveBattlegroundQueueId(BattlegroundQueueTypeId val)
Definition: Player.cpp:25429
void RepopAtGraveyard()
Definition: Player.cpp:4790
void ClearWhisperWhiteList()
Definition: Player.h:2790
void RemovePet(Pet *pet, PetSaveMode mode, bool returnreagent=false)
Definition: Player.cpp:21797
bool TeleportTo(uint32 mapid, float x, float y, float z, float orientation, TeleportToOptions options=TELE_TO_NONE, Optional< uint32 > instanceId={}, uint32 teleportSpellId=0)
Definition: Player.cpp:1225
Battleground * GetBattleground() const
Definition: Player.cpp:25344
ObjectGuid::LowType GetGuildId() const
Definition: Player.h:2099
bool IsGameMaster() const
Definition: Player.h:1257
void SetPendingBind(uint32 instanceId, uint32 bindTimer)
Definition: Player.cpp:19875
uint32 GetXPForNextLevel() const
Definition: Player.h:1276
void SaveToDB(bool create=false)
Definition: Player.cpp:20171
void SetBuybackTimestamp(uint32 slot, time_t timestamp)
Definition: Player.h:1569
Group * GetGroup(Optional< uint8 > partyIndex)
Definition: Player.h:2719
void BuildPlayerRepop()
Definition: Player.cpp:4314
void UninviteFromGroup()
Definition: Player.cpp:2155
void SetBuybackPrice(uint32 slot, uint32 price)
Definition: Player.h:1568
BattlegroundQueueTypeId GetBattlegroundQueueTypeId(uint32 index) const
Definition: Player.cpp:25369
void setString(uint8 index, std::string &&value)
void setUInt32(uint8 index, uint32 value)
void setInt64(uint8 index, int64 value)
void setUInt64(uint8 index, uint64 value)
void setInt32(uint8 index, int32 value)
void setUInt8(uint8 index, uint8 value)
void SetSize(size_t size)
Definition: QueryHolder.cpp:69
PreparedQueryResult GetPreparedResult(size_t index) const
Definition: QueryHolder.cpp:37
void AfterComplete(std::function< void(SQLQueryHolderBase const &)> callback) &
Definition: QueryHolder.h:70
bool SetPreparedQuery(size_t index, PreparedStatement< T > *stmt)
Definition: QueryHolder.h:48
void RemoveAurasByType(AuraType auraType, std::function< bool(AuraApplication const *)> const &check, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition: Unit.cpp:3902
void CombatStop(bool includingCast=false, bool mutualPvP=true, bool(*unitFilter)(Unit const *otherUnit)=nullptr)
Definition: Unit.cpp:5939
bool HasAuraType(AuraType auraType) const
Definition: Unit.cpp:4761
uint8 GetLevel() const
Definition: Unit.h:754
Map * FindMap() const
Definition: Object.h:774
std::string const & GetName() const
Definition: Object.h:704
uint32 GetZoneId() const
Definition: Object.h:694
ConnectionType GetConnection() const
Definition: WorldPacket.h:86
uint32 GetOpcode() const
Definition: WorldPacket.h:83
WorldPacket const * Write() override
WorldPacket const * Write() override
Array< std::string, MAX_PREFIXES > Prefixes
Definition: ChatPackets.h:287
std::array< Timestamp<>, NUM_ACCOUNT_DATA_TYPES > AccountTimes
OpcodeClient GetOpcode() const
Definition: Packet.h:68
std::string const & GetInvalidValue() const
WorldPacket const * Write() override
WorldPacket const * Write() override
std::array< uint32, MAX_ACCOUNT_TUTORIAL_VALUES > TutorialData
Definition: MiscPackets.h:239
bool Process(WorldPacket *packet) override
bool EvaluateOpcode(WorldPacket &p, time_t time) const
uint32 GetMaxPacketCounterAllowed(uint32 opcode) const
DosProtection(WorldSession *s)
PacketThrottlingMap _PacketThrottlingMap
Player session in the World.
Definition: WorldSession.h:979
void HandleUnregisterAllAddonPrefixesOpcode(WorldPackets::Chat::ChatUnregisterAllAddonPrefixes &packet)
void SetPlayer(Player *player)
bool m_playerRecentlyLogout
bool Update(uint32 diff, PacketFilter &updater)
Update the WorldSession (triggered by World update)
void LogoutPlayer(bool save)
Log the player out
uint8 _tutorialsChanged
AccountData _accountData[NUM_ACCOUNT_DATA_TYPES]
char const * GetTrinityString(uint32 entry) const
std::string m_Address
void LoadTutorialsData(PreparedQueryResult result)
void SendClientCacheVersion(uint32 version)
Definition: AuthHandler.cpp:86
void SendConnectToInstance(WorldPackets::Auth::ConnectToSerial serial)
void HandleMoveWorldportAck()
void SendNotification(char const *format,...) ATTR_PRINTF(2
bool CanAccessAlliedRaces() const
AsyncCallbackProcessor< SQLQueryHolderCallback > _queryHolderProcessor
void SendAuthResponse(uint32 code, bool queued, uint32 queuePos=0)
Definition: AuthHandler.cpp:32
QueryCallbackProcessor _queryProcessor
std::array< uint32, MAX_ACCOUNT_TUTORIAL_VALUES > _tutorials
AccountTypes GetSecurity() const
LocaleConstant GetSessionDbLocaleIndex() const
bool PlayerDisconnected() const
void LoadPermissions()
WorldSession(uint32 id, std::string &&name, uint32 battlenetAccountId, std::shared_ptr< WorldSocket > sock, AccountTypes sec, uint8 expansion, time_t mute_time, std::string os, Minutes timezoneOffset, uint32 build, ClientBuild::VariantId clientBuildVariant, LocaleConstant locale, uint32 recruiter, bool isARecruiter)
WorldSession constructor.
int64 _timeSyncClockDelta
bool DisallowHyperlinksAndMaybeKick(std::string const &str)
uint32 AdjustClientMovementTime(uint32 time) const
void QueuePacket(WorldPacket *new_packet)
Add an incoming packet to the queue.
class WorldSession::DosProtection AntiDOS
void LoadAccountData(PreparedQueryResult result, uint32 mask)
std::atomic< time_t > m_timeOutTime
uint64 GetConnectToInstanceKey() const
uint32 _timeSyncTimer
void InitWarden(SessionKey const &k)
std::unordered_map< uint32, uint8 > _realmCharacterCounts
std::string GetPlayerInfo() const
void KickPlayer(std::string const &reason)
Kick a player out of the World.
std::string _os
Player * GetPlayer() const
rbac::RBACData * _RBACData
std::unique_ptr< CollectionMgr > _collectionMgr
void SendAuthWaitQueue(uint32 position)
Handle the authentication waiting queue (to be completed)
Definition: AuthHandler.cpp:72
void Handle_EarlyProccess(WorldPackets::Null &null)
~WorldSession()
WorldSession destructor.
void SetLogoutStartTime(time_t requestTime)
Engage the logout process for the user.
void SendSetTimeZoneInformation()
Definition: AuthHandler.cpp:94
void LogUnexpectedOpcode(WorldPacket *packet, char const *status, const char *reason)
Logging helper for unexpected opcodes.
void RegisterTimeSync(uint32 counter)
std::string _accountName
AccountData const * GetAccountData(AccountDataType type) const
TransactionCallback & AddTransactionCallback(TransactionCallback &&callback)
bool CanSpeak() const
uint32 _timeSyncNextCounter
void Handle_NULL(WorldPackets::Null &null)
ObjectGuid m_playerLoading
SQLQueryHolderCallback & AddQueryHolderCallback(SQLQueryHolderCallback &&callback)
QueryCallback LoadPermissionsAsync()
std::string const & GetRemoteAddress() const
void SetInQueue(bool state)
Session in auth.queue currently.
ObjectGuid::LowType m_GUIDLow
void ResetTimeSync()
bool HasPermission(uint32 permissionId)
void SendPacket(WorldPacket const *packet, bool forced=false)
Send a packet to the client.
uint32 GetBattlenetAccountId() const
uint32 GetAccountId() const
uint8 GetAccountExpansion() const
ConnectToKey _instanceConnectKey
void SendTutorialsData()
Player * _player
uint32 GetLatency() const
void ProcessQueryCallbacks()
std::shared_ptr< WorldSocket > m_Socket[MAX_CONNECTION_TYPES]
void InitializeSessionCallback(LoginDatabaseQueryHolder const &holder, CharacterDatabaseQueryHolder const &realmHolder)
void HandleAddonRegisteredPrefixesOpcode(WorldPackets::Chat::ChatRegisterAddonPrefixes &packet)
void DoLootReleaseAll()
std::vector< std::string > _registeredAddonPrefixes
void SendAccountDataTimes(ObjectGuid playerGuid, uint32 mask)
bool IsAddonRegistered(std::string_view prefix) const
void HandleContinuePlayerLogin()
uint32 expireTime
void SaveTutorialsData(CharacterDatabaseTransaction trans)
LockedQueue< WorldPacket * > _recvQueue
std::string const & GetPlayerName() const
time_t m_muteTime
std::unique_ptr< Warden > _warden
void ResetTimeOutTime(bool onlyActive)
void InitializeSession()
void InvalidateRBACData()
static void AddInstanceConnection(WorldSession *session, std::weak_ptr< WorldSocket > sockRef, ConnectToKey key)
void SetAccountData(AccountDataType type, time_t time, std::string const &data)
void SendFeatureSystemStatusGlueScreen()
void LogUnprocessedTail(WorldPacket const *packet)
Logging helper for unexpected opcodes.
bool ShouldLogOut(time_t currTime) const
Is logout cooldown expired?
bool ValidateHyperlinksAndMaybeKick(std::string const &str)
AsyncCallbackProcessor< TransactionCallback > _transactionCallbacks
void SendAvailableHotfixes()
rbac::RBACData * GetRBACData()
bool IsConnectionIdle() const
std::unique_ptr< BattlePets::BattlePetMgr > _battlePetMgr
bool _filterAddonMessages
std::map< uint32, int64 > _pendingTimeSyncRequests
uint32 GetId() const
Gets the Id of the Object.
Definition: RBAC.h:823
QueryCallback LoadFromDBAsync()
Definition: RBAC.cpp:200
std::string const & GetName() const
Gets the Name of the Object.
Definition: RBAC.h:821
void LoadFromDB()
Loads all permissions assigned to current account.
Definition: RBAC.cpp:187
bool HasPermission(uint32 permission) const
Definition: RBAC.h:841
ConnectionType
Definition: Opcodes.h:31
constexpr bool IsInstanceOnlyOpcode(uint32 opcode)
Definition: Opcodes.h:2232
OpcodeServer
Definition: Opcodes.h:962
std::string GetOpcodeNameForLogging(OpcodeClient opcode)
Lookup opcode name for human understandable logging.
Definition: Opcodes.cpp:2307
OpcodeTable opcodeTable
Definition: Opcodes.cpp:35
#define GLOBAL_CACHE_MASK
Definition: WorldSession.h:889
constexpr uint16 UNKNOWN_OPCODE
Definition: Opcodes.h:39
AccountDataType
Definition: WorldSession.h:866
OpcodeClient
Definition: Opcodes.h:42
#define NUM_ACCOUNT_DATA_TYPES
Definition: WorldSession.h:886
@ CONNECTION_TYPE_INSTANCE
Definition: Opcodes.h:33
@ CONNECTION_TYPE_DEFAULT
Definition: Opcodes.h:36
@ CONNECTION_TYPE_REALM
Definition: Opcodes.h:32
@ TUTORIALS_FLAG_LOADED_FROM_DB
Definition: WorldSession.h:925
@ TUTORIALS_FLAG_CHANGED
Definition: WorldSession.h:924
@ TUTORIALS_FLAG_NONE
Definition: WorldSession.h:923
@ STATUS_LOGGEDIN
Definition: Opcodes.h:2256
@ STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT
Definition: Opcodes.h:2258
@ STATUS_TRANSFER
Definition: Opcodes.h:2257
@ STATUS_NEVER
Definition: Opcodes.h:2259
@ STATUS_AUTHED
Definition: Opcodes.h:2255
@ STATUS_UNHANDLED
Definition: Opcodes.h:2260
@ PROCESS_INPLACE
Definition: Opcodes.h:2265
@ PROCESS_THREADUNSAFE
Definition: Opcodes.h:2266
@ CMSG_TIME_SYNC_RESPONSE
Definition: Opcodes.h:885
@ CMSG_QUERY_PAGE_TEXT
Definition: Opcodes.h:680
@ CMSG_TURN_IN_PETITION
Definition: Opcodes.h:899
@ CMSG_CALENDAR_ADD_EVENT
Definition: Opcodes.h:156
@ CMSG_ATTACK_STOP
Definition: Opcodes.h:71
@ CMSG_SEND_CONTACT_LIST
Definition: Opcodes.h:790
@ CMSG_CALENDAR_RSVP
Definition: Opcodes.h:168
@ CMSG_ENUM_CHARACTERS
Definition: Opcodes.h:349
@ CMSG_CHAT_MESSAGE_YELL
Definition: Opcodes.h:234
@ CMSG_EJECT_PASSENGER
Definition: Opcodes.h:343
@ CMSG_QUERY_GAME_OBJECT
Definition: Opcodes.h:674
@ CMSG_LOGOUT_REQUEST
Definition: Opcodes.h:500
@ CMSG_CHAT_MESSAGE_WHISPER
Definition: Opcodes.h:233
@ CMSG_PET_RENAME
Definition: Opcodes.h:661
@ CMSG_GUILD_SET_RANK_PERMISSIONS
Definition: Opcodes.h:445
@ CMSG_CHAT_ADDON_MESSAGE_TARGETED
Definition: Opcodes.h:199
@ CMSG_CHAT_MESSAGE_EMOTE
Definition: Opcodes.h:225
@ CMSG_SET_SHEATHED
Definition: Opcodes.h:832
@ CMSG_REQUEST_VEHICLE_SWITCH_SEAT
Definition: Opcodes.h:766
@ CMSG_REPOP_REQUEST
Definition: Opcodes.h:731
@ CMSG_PET_ABANDON
Definition: Opcodes.h:646
@ CMSG_CHAT_MESSAGE_CHANNEL
Definition: Opcodes.h:223
@ CMSG_QUEST_CONFIRM_ACCEPT
Definition: Opcodes.h:696
@ CMSG_DELETE_EQUIPMENT_SET
Definition: Opcodes.h:321
@ CMSG_TOGGLE_PVP
Definition: Opcodes.h:889
@ CMSG_GUILD_BANK_DEPOSIT_MONEY
Definition: Opcodes.h:408
@ CMSG_SUBMIT_USER_FEEDBACK
Definition: Opcodes.h:866
@ CMSG_GUILD_LEAVE
Definition: Opcodes.h:427
@ CMSG_CHANGE_SUB_GROUP
Definition: Opcodes.h:190
@ CMSG_CHAT_MESSAGE_GUILD
Definition: Opcodes.h:226
@ CMSG_GUILD_SET_GUILD_MASTER
Definition: Opcodes.h:443
@ CMSG_CONVERT_RAID
Definition: Opcodes.h:303
@ CMSG_GUILD_BANK_WITHDRAW_MONEY
Definition: Opcodes.h:415
@ CMSG_SET_CONTACT_NOTES
Definition: Opcodes.h:805
@ CMSG_MOVE_FORCE_SWIM_SPEED_CHANGE_ACK
Definition: Opcodes.h:549
@ CMSG_CALENDAR_REMOVE_INVITE
Definition: Opcodes.h:167
@ CMSG_GUILD_DELETE_RANK
Definition: Opcodes.h:420
@ CMSG_SET_ACTION_BAR_TOGGLES
Definition: Opcodes.h:797
@ CMSG_CALENDAR_EVENT_SIGN_UP
Definition: Opcodes.h:160
@ CMSG_SAVE_EQUIPMENT_SET
Definition: Opcodes.h:778
@ CMSG_QUEST_POI_QUERY
Definition: Opcodes.h:707
@ CMSG_SIGN_PETITION
Definition: Opcodes.h:843
@ CMSG_SOCKET_GEMS
Definition: Opcodes.h:846
@ CMSG_QUERY_CREATURE
Definition: Opcodes.h:673
@ CMSG_MOVE_DISMISS_VEHICLE
Definition: Opcodes.h:534
@ CMSG_CALENDAR_INVITE
Definition: Opcodes.h:164
@ CMSG_SUPPORT_TICKET_SUBMIT_COMPLAINT
Definition: Opcodes.h:869
@ CMSG_MOVE_HEARTBEAT
Definition: Opcodes.h:556
@ CMSG_DUEL_RESPONSE
Definition: Opcodes.h:342
@ CMSG_MOVE_TIME_SKIPPED
Definition: Opcodes.h:615
@ CMSG_MOVE_FORCE_TURN_RATE_CHANGE_ACK
Definition: Opcodes.h:550
@ CMSG_QUEST_GIVER_QUERY_QUEST
Definition: Opcodes.h:702
@ CMSG_COMPLETE_CINEMATIC
Definition: Opcodes.h:285
@ CMSG_QUEST_GIVER_REQUEST_REWARD
Definition: Opcodes.h:703
@ CMSG_SELF_RES
Definition: Opcodes.h:786
@ CMSG_ACTIVATE_TAXI
Definition: Opcodes.h:54
@ CMSG_REQUEST_VEHICLE_NEXT_SEAT
Definition: Opcodes.h:764
@ CMSG_REQUEST_VEHICLE_PREV_SEAT
Definition: Opcodes.h:765
@ CMSG_RANDOM_ROLL
Definition: Opcodes.h:722
@ CMSG_DECLINE_PETITION
Definition: Opcodes.h:320
@ CMSG_REQUEST_VEHICLE_EXIT
Definition: Opcodes.h:763
@ CMSG_SET_ASSISTANT_LEADER
Definition: Opcodes.h:801
@ CMSG_CHAT_MESSAGE_RAID_WARNING
Definition: Opcodes.h:231
@ CMSG_MOVE_FORCE_WALK_SPEED_CHANGE_ACK
Definition: Opcodes.h:552
@ CMSG_ACCEPT_GUILD_INVITE
Definition: Opcodes.h:44
@ CMSG_OPT_OUT_OF_LOOT
Definition: Opcodes.h:629
@ CMSG_MOVE_FORCE_FLIGHT_SPEED_CHANGE_ACK
Definition: Opcodes.h:543
@ CMSG_DO_READY_CHECK
Definition: Opcodes.h:341
@ CMSG_CALENDAR_COMPLAIN
Definition: Opcodes.h:158
@ CMSG_CHAT_MESSAGE_SAY
Definition: Opcodes.h:232
@ CMSG_AUTOSTORE_BANK_ITEM
Definition: Opcodes.h:95
@ CMSG_CHAT_MESSAGE_AFK
Definition: Opcodes.h:222
@ CMSG_GUILD_ADD_RANK
Definition: Opcodes.h:404
@ CMSG_DISMISS_CRITTER
Definition: Opcodes.h:338
@ CMSG_BUG_REPORT
Definition: Opcodes.h:148
@ CMSG_QUEST_GIVER_COMPLETE_QUEST
Definition: Opcodes.h:700
@ CMSG_CHAR_DELETE
Definition: Opcodes.h:196
@ CMSG_CHAR_RACE_OR_FACTION_CHANGE
Definition: Opcodes.h:197
@ CMSG_STAND_STATE_CHANGE
Definition: Opcodes.h:861
@ CMSG_ENUM_CHARACTERS_DELETED_BY_CLIENT
Definition: Opcodes.h:350
@ CMSG_CONFIRM_RESPEC_WIPE
Definition: Opcodes.h:289
@ CMSG_AUTOBANK_ITEM
Definition: Opcodes.h:93
@ CMSG_CHAR_CUSTOMIZE
Definition: Opcodes.h:195
@ CMSG_SET_PARTY_LEADER
Definition: Opcodes.h:820
@ CMSG_CHAT_MESSAGE_RAID
Definition: Opcodes.h:230
@ CMSG_CHARACTER_RENAME_REQUEST
Definition: Opcodes.h:192
@ CMSG_BANKER_ACTIVATE
Definition: Opcodes.h:107
@ CMSG_MOVE_FORCE_RUN_SPEED_CHANGE_ACK
Definition: Opcodes.h:547
@ CMSG_LEAVE_GROUP
Definition: Opcodes.h:467
@ CMSG_CALENDAR_COPY_EVENT
Definition: Opcodes.h:159
@ CMSG_CHAT_MESSAGE_DND
Definition: Opcodes.h:224
@ CMSG_MOVE_FORCE_RUN_BACK_SPEED_CHANGE_ACK
Definition: Opcodes.h:546
@ CMSG_QUERY_INSPECT_ACHIEVEMENTS
Definition: Opcodes.h:677
@ CMSG_MOVE_SET_FACING
Definition: Opcodes.h:585
@ CMSG_MOVE_FORCE_SWIM_BACK_SPEED_CHANGE_ACK
Definition: Opcodes.h:548
@ CMSG_CALENDAR_MODERATOR_STATUS
Definition: Opcodes.h:165
@ CMSG_ALTER_APPEARANCE
Definition: Opcodes.h:64
@ CMSG_TAXI_NODE_STATUS_QUERY
Definition: Opcodes.h:881
@ CMSG_QUERY_QUEST_INFO
Definition: Opcodes.h:687
@ CMSG_QUEST_GIVER_CHOOSE_REWARD
Definition: Opcodes.h:698
@ CMSG_GUILD_UPDATE_MOTD_TEXT
Definition: Opcodes.h:448
@ CMSG_SET_ACTION_BUTTON
Definition: Opcodes.h:798
@ CMSG_WRAP_ITEM
Definition: Opcodes.h:937
@ CMSG_GUILD_DECLINE_INVITATION
Definition: Opcodes.h:418
@ CMSG_RIDE_VEHICLE_INTERACT
Definition: Opcodes.h:774
@ CMSG_MOVE_CHANGE_VEHICLE_SEATS
Definition: Opcodes.h:531
@ CMSG_GET_ITEM_PURCHASE_DATA
Definition: Opcodes.h:387
@ CMSG_QUEST_GIVER_ACCEPT_QUEST
Definition: Opcodes.h:697
@ CMSG_GAME_OBJ_REPORT_USE
Definition: Opcodes.h:354
@ CMSG_QUERY_PETITION
Definition: Opcodes.h:681
@ CMSG_SET_DUNGEON_DIFFICULTY
Definition: Opcodes.h:808
@ CMSG_GUILD_BANK_LOG_QUERY
Definition: Opcodes.h:409
@ CMSG_BEGIN_TRADE
Definition: Opcodes.h:142
@ CMSG_INSPECT
Definition: Opcodes.h:455
@ CMSG_MOVE_FORCE_PITCH_RATE_CHANGE_ACK
Definition: Opcodes.h:544
@ CMSG_QUERY_NPC_TEXT
Definition: Opcodes.h:679
@ CMSG_QUEST_GIVER_STATUS_QUERY
Definition: Opcodes.h:705
@ CMSG_AREA_SPIRIT_HEALER_QUERY
Definition: Opcodes.h:65
@ CMSG_SET_PARTY_ASSIGNMENT
Definition: Opcodes.h:819
@ CMSG_DEL_FRIEND
Definition: Opcodes.h:323
@ CMSG_GUILD_BANK_TEXT_QUERY
Definition: Opcodes.h:413
@ CMSG_TAXI_QUERY_AVAILABLE_NODES
Definition: Opcodes.h:882
@ CMSG_QUEST_LOG_REMOVE_QUEST
Definition: Opcodes.h:706
@ CMSG_MOVE_SET_PITCH
Definition: Opcodes.h:590
@ CMSG_QUERY_NEXT_MAIL_TIME
Definition: Opcodes.h:678
@ CMSG_QUEST_GIVER_STATUS_MULTIPLE_QUERY
Definition: Opcodes.h:704
@ CMSG_GUILD_EVENT_LOG_QUERY
Definition: Opcodes.h:422
@ CMSG_SAVE_GUILD_EMBLEM
Definition: Opcodes.h:779
@ CMSG_CHAT_ADDON_MESSAGE
Definition: Opcodes.h:198
@ CMSG_CHAT_MESSAGE_OFFICER
Definition: Opcodes.h:228
@ CMSG_PARTY_INVITE_RESPONSE
Definition: Opcodes.h:632
@ CMSG_QUERY_TIME
Definition: Opcodes.h:692
@ CMSG_ADD_FRIEND
Definition: Opcodes.h:58
@ CMSG_SET_RAID_DIFFICULTY
Definition: Opcodes.h:827
@ CMSG_MOVE_SET_FACING_HEARTBEAT
Definition: Opcodes.h:586
@ CMSG_GUILD_BANK_SET_TAB_TEXT
Definition: Opcodes.h:412
@ CMSG_CALENDAR_GET
Definition: Opcodes.h:161
@ CMSG_QUERY_PET_NAME
Definition: Opcodes.h:682
@ CMSG_LOGOUT_CANCEL
Definition: Opcodes.h:497
@ CMSG_PETITION_RENAME_GUILD
Definition: Opcodes.h:643
@ CMSG_BATTLEMASTER_JOIN_ARENA
Definition: Opcodes.h:113
@ CMSG_WHO
Definition: Opcodes.h:933
@ CMSG_GUILD_INVITE_BY_NAME
Definition: Opcodes.h:426
@ CMSG_HEARTH_AND_RESURRECT
Definition: Opcodes.h:449
@ CMSG_GUILD_UPDATE_INFO_TEXT
Definition: Opcodes.h:447
@ CMSG_PLAYER_LOGIN
Definition: Opcodes.h:666
@ CMSG_CREATE_CHARACTER
Definition: Opcodes.h:316
@ CMSG_CALENDAR_UPDATE_EVENT
Definition: Opcodes.h:170
@ CMSG_CHAT_MESSAGE_PARTY
Definition: Opcodes.h:229
@ CMSG_RESET_INSTANCES
Definition: Opcodes.h:771
@ CMSG_GUILD_DELETE
Definition: Opcodes.h:419
@ CMSG_HOTFIX_REQUEST
Definition: Opcodes.h:451
@ CMSG_PARTY_INVITE
Definition: Opcodes.h:631
@ CMSG_GUILD_SET_MEMBER_NOTE
Definition: Opcodes.h:444
@ CMSG_BATTLEFIELD_LEAVE
Definition: Opcodes.h:108
@ CMSG_PARTY_UNINVITE
Definition: Opcodes.h:633
@ CMSG_SET_LOOT_METHOD
Definition: Opcodes.h:817
@ CMSG_ITEM_PURCHASE_REFUND
Definition: Opcodes.h:458
@ CMSG_UNLEARN_SKILL
Definition: Opcodes.h:904
@ CMSG_INITIATE_TRADE
Definition: Opcodes.h:454
@ CMSG_QUERY_GUILD_INFO
Definition: Opcodes.h:676
@ CMSG_QUERY_CORPSE_LOCATION_FROM_CLIENT
Definition: Opcodes.h:670
@ CMSG_SPELL_CLICK
Definition: Opcodes.h:853
@ CMSG_QUERY_PLAYER_NAMES
Definition: Opcodes.h:683
@ CMSG_CALENDAR_REMOVE_EVENT
Definition: Opcodes.h:166
@ CMSG_UPDATE_RAID_TARGET
Definition: Opcodes.h:914
@ CMSG_REPORT_PVP_PLAYER_AFK
Definition: Opcodes.h:732
@ CMSG_GUILD_BANK_BUY_TAB
Definition: Opcodes.h:407
@ CMSG_QUERY_CORPSE_TRANSPORT
Definition: Opcodes.h:671
@ CMSG_PETITION_BUY
Definition: Opcodes.h:642
@ CMSG_GUILD_BANK_QUERY_TAB
Definition: Opcodes.h:410
@ CMSG_BUY_BANK_SLOT
Definition: Opcodes.h:152
@ CMSG_REQUEST_PARTY_MEMBER_STATS
Definition: Opcodes.h:752
@ CMSG_GUILD_BANK_UPDATE_TAB
Definition: Opcodes.h:414
@ CMSG_GAME_OBJ_USE
Definition: Opcodes.h:355
@ CMSG_MOVE_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK
Definition: Opcodes.h:542
#define sWorld
Definition: World.h:909
@ CONFIG_SOCKET_TIMEOUTTIME
Definition: World.h:243
@ CONFIG_CLIENTCACHE_VERSION
Definition: World.h:356
@ CONFIG_PACKET_SPOOF_BANDURATION
Definition: World.h:402
@ CONFIG_SOCKET_TIMEOUTTIME_ACTIVE
Definition: World.h:432
@ CONFIG_PACKET_SPOOF_POLICY
Definition: World.h:400
@ CONFIG_CHAT_STRICT_LINK_CHECKING_KICK
Definition: World.h:317
@ CONFIG_PACKET_SPOOF_BANMODE
Definition: World.h:401
@ CONFIG_EXPANSION
Definition: World.h:305
@ CONFIG_PORT_WORLD
Definition: World.h:242
TC_GAME_API bool GetName(uint32 accountId, std::string &name)
SystemTimePoint GetSystemTime()
Current chrono system_clock time point.
Definition: GameTime.cpp:54
time_t GetGameTime()
Definition: GameTime.cpp:44
uint32 GetGameTimeMS()
Definition: GameTime.cpp:49
std::string ToString(Type &&val, Params &&... params)
std::string StringFormat(FormatString< Args... > fmt, Args &&... args)
Default TC string format function.
Definition: StringFormat.h:39
@ RBAC_PERM_IGNORE_IDLE_CONNECTION
Definition: RBAC.h:60
STL namespace.
std::string Data
Definition: WorldSession.h:895
HandlerFunction Call
Definition: Opcodes.h:2279
SessionStatus Status
Definition: Opcodes.h:2278
char const * Name
Definition: Opcodes.h:2277
PacketProcessing ProcessingPlace
Definition: Opcodes.h:2280
uint32 amountCounter
Definition: WorldSession.h:974
time_t lastReceiveTime
Definition: WorldSession.h:973
SessionStatus Status
Definition: Opcodes.h:2286
ConnectionType ConnectionIndex
Definition: Opcodes.h:2287
union WorldPackets::Auth::ConnectTo::SocketAddress::@314 Address
struct WorldSession::ConnectToKey::@320 Fields