diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp
index 69becaba8c..00ead6c63e 100644
--- a/src/server/game/DungeonFinding/LFGMgr.cpp
+++ b/src/server/game/DungeonFinding/LFGMgr.cpp
@@ -1782,7 +1782,7 @@ LfgLockMap const LFGMgr::GetLockedDungeons(ObjectGuid guid)
}
uint8 level = player->getLevel();
- uint8 expansion = player->GetSession()->Expansion();
+ uint8 expansion = player->GetSession()->GetExpansion();
LfgDungeonSet const& dungeons = GetDungeonsByRandom(0);
bool denyJoin = !player->GetSession()->HasPermission(rbac::RBAC_PERM_JOIN_DUNGEON_FINDER);
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 90cdfd0992..7626a51955 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -1464,7 +1464,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
return false;
// client without expansion support
- if (GetSession()->Expansion() < mEntry->Expansion())
+ if (GetSession()->GetExpansion() < mEntry->Expansion())
{
TC_LOG_DEBUG("maps", "Player '%s' (%s) using client without required expansion tried teleport to non accessible map (MapID: %u)",
GetName().c_str(), GetGUID().ToString().c_str(), mapid);
@@ -17565,7 +17565,7 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder* holder)
// client without expansion support
if (mapEntry)
{
- if (GetSession()->Expansion() < mapEntry->Expansion())
+ if (GetSession()->GetExpansion() < mapEntry->Expansion())
{
TC_LOG_DEBUG("entities.player.loading", "Player::LoadFromDB: Player '%s' (%s) using client without required expansion tried login at non accessible map %u",
GetName().c_str(), GetGUID().ToString().c_str(), mapId);
@@ -19602,7 +19602,7 @@ bool Player::_LoadHomeBind(PreparedQueryResult result)
// accept saved data only for valid position (and non instanceable), and accessable
if (MapManager::IsValidMapCoord(m_homebindMapId, m_homebindX, m_homebindY, m_homebindZ) &&
- !bindMapEntry->Instanceable() && GetSession()->Expansion() >= bindMapEntry->Expansion())
+ !bindMapEntry->Instanceable() && GetSession()->GetExpansion() >= bindMapEntry->Expansion())
ok = true;
else
{
diff --git a/src/server/game/Handlers/AuthHandler.cpp b/src/server/game/Handlers/AuthHandler.cpp
index 5de98a33d8..47bb10b455 100644
--- a/src/server/game/Handlers/AuthHandler.cpp
+++ b/src/server/game/Handlers/AuthHandler.cpp
@@ -15,34 +15,42 @@
* with this program. If not, see .
*/
-#include "Opcodes.h"
#include "WorldSession.h"
-#include "WorldPacket.h"
+#include "AuthenticationPackets.h"
void WorldSession::SendAuthResponse(uint8 code, bool queued, uint32 queuePos)
{
- WorldPacket packet(SMSG_AUTH_RESPONSE, 1 /*bits*/ + 4 + 1 + 4 + 1 + 4 + 1 + 1 + (queued ? 4 : 0));
- packet.WriteBit(queued);
+ WorldPackets::Auth::AuthResponse response;
+ response.Result = code;
+
+ if (code == AUTH_OK)
+ {
+ response.SuccessInfo = boost::in_place();
+
+ response.SuccessInfo->AccountExpansionLevel = GetAccountExpansion();
+ response.SuccessInfo->ActiveExpansionLevel = GetExpansion();
+ }
+
if (queued)
- packet.WriteBit(0);
+ {
+ response.WaitInfo = boost::in_place();
+ response.WaitInfo->WaitCount = queuePos;
+ }
- packet.WriteBit(1); // has account info
+ SendPacket(response.Write());
+}
- packet.FlushBits();
-
- // account info
- packet << uint32(0); // BillingTimeRemaining
- packet << uint8(Expansion()); // 0 - normal, 1 - TBC, 2 - WOTLK, 3 - CATA; must be set in database manually for each account
- packet << uint32(0);
- packet << uint8(Expansion()); // Unknown, these two show the same
- packet << uint32(0); // BillingTimeRested
- packet << uint8(0); // BillingPlanFlags
-
- packet << uint8(code);
- if (queued)
- packet << uint32(queuePos); // Queue position
-
- SendPacket(&packet);
+void WorldSession::SendAuthWaitQue(uint32 position)
+{
+ if (position)
+ {
+ WorldPackets::Auth::WaitQueueUpdate waitQueueUpdate;
+ waitQueueUpdate.WaitInfo.WaitCount = position;
+ waitQueueUpdate.WaitInfo.HasFCM = true;
+ SendPacket(waitQueueUpdate.Write());
+ }
+ else
+ SendPacket(WorldPackets::Auth::WaitQueueFinish().Write());
}
void WorldSession::SendClientCacheVersion(uint32 version)
diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp
index ccc2c020cf..bb6c021904 100644
--- a/src/server/game/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Handlers/CharacterHandler.cpp
@@ -367,17 +367,17 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
}
// prevent character creating Expansion race without Expansion account
- if (raceEntry->Race_related > Expansion())
+ if (raceEntry->Race_related > GetAccountExpansion())
{
- TC_LOG_ERROR("entities.player.cheat", "Expansion %u account:[%d] tried to Create character with expansion %u race (%u)", Expansion(), GetAccountId(), raceEntry->Race_related, createInfo->Race);
+ TC_LOG_ERROR("entities.player.cheat", "Expansion %u account:[%d] tried to Create character with expansion %u race (%u)", GetAccountExpansion(), GetAccountId(), raceEntry->Race_related, createInfo->Race);
SendCharCreate(CHAR_CREATE_EXPANSION);
return;
}
// prevent character creating Expansion class without Expansion account
- if (classEntry->Required_expansion > Expansion())
+ if (classEntry->Required_expansion > GetAccountExpansion())
{
- TC_LOG_ERROR("entities.player.cheat", "Expansion %u account:[%d] tried to Create character with expansion %u class (%u)", Expansion(), GetAccountId(), classEntry->Required_expansion, createInfo->Class);
+ TC_LOG_ERROR("entities.player.cheat", "Expansion %u account:[%d] tried to Create character with expansion %u class (%u)", GetAccountExpansion(), GetAccountId(), classEntry->Required_expansion, createInfo->Class);
SendCharCreate(CHAR_CREATE_EXPANSION_CLASS);
return;
}
@@ -768,7 +768,7 @@ void WorldSession::HandlePlayerLoginOpcode(WorldPacket& recvData)
return;
}
- SendConnectToInstance(WorldPackets::Auth::ConnectToSerial::Realm);
+ SendConnectToInstance(WorldPackets::Auth::ConnectToSerial::WorldAttempt1);
}
void WorldSession::HandleContinuePlayerLogin()
@@ -792,6 +792,18 @@ void WorldSession::HandleContinuePlayerLogin()
_charLoginCallback = CharacterDatabase.DelayQueryHolder(holder);
}
+void WorldSession::AbortLogin(WorldPackets::Character::LoginFailureReason reason)
+{
+ if (!PlayerLoading() || GetPlayer())
+ {
+ KickPlayer();
+ return;
+ }
+
+ m_playerLoading.Clear();
+ SendPacket(WorldPackets::Character::CharacterLoginFailed(reason).Write());
+}
+
void WorldSession::HandleLoadScreenOpcode(WorldPacket& recvPacket)
{
TC_LOG_INFO("misc", "WORLD: Recvd CMSG_LOAD_SCREEN");
diff --git a/src/server/game/Handlers/LFGHandler.cpp b/src/server/game/Handlers/LFGHandler.cpp
index b123f30f0e..0bb1729a99 100644
--- a/src/server/game/Handlers/LFGHandler.cpp
+++ b/src/server/game/Handlers/LFGHandler.cpp
@@ -133,7 +133,7 @@ void WorldSession::SendLfgPlayerLockInfo()
// Get Random dungeons that can be done at a certain level and expansion
uint8 level = _player->getLevel();
- lfg::LfgDungeonSet const& randomDungeons = sLFGMgr->GetRandomAndSeasonalDungeons(level, _player->GetSession()->Expansion());
+ lfg::LfgDungeonSet const& randomDungeons = sLFGMgr->GetRandomAndSeasonalDungeons(level, GetExpansion());
WorldPackets::LFG::LFGPlayerInfo lfgPlayerInfo;
diff --git a/src/server/game/Server/Packets/AuthenticationPackets.cpp b/src/server/game/Server/Packets/AuthenticationPackets.cpp
index 426ff84cb2..844eb5d6e5 100644
--- a/src/server/game/Server/Packets/AuthenticationPackets.cpp
+++ b/src/server/game/Server/Packets/AuthenticationPackets.cpp
@@ -18,6 +18,40 @@
#include "AuthenticationPackets.h"
#include "HmacHash.h"
+bool WorldPackets::Auth::EarlyProcessClientPacket::ReadNoThrow()
+{
+ try
+ {
+ Read();
+ return true;
+ }
+ catch (ByteBufferPositionException const& /*ex*/)
+ {
+ }
+
+ return false;
+}
+
+void WorldPackets::Auth::Ping::Read()
+{
+ _worldPacket >> Latency;
+ _worldPacket >> Serial;
+}
+
+WorldPacket const* WorldPackets::Auth::Pong::Write()
+{
+ _worldPacket << uint32(Serial);
+ return &_worldPacket;
+}
+
+WorldPacket const* WorldPackets::Auth::AuthChallenge::Write()
+{
+ _worldPacket.append(DosChallenge.data(), DosChallenge.size());
+ _worldPacket << uint32(Challenge);
+ _worldPacket << uint8(DosZeroBits);
+ return &_worldPacket;
+}
+
void WorldPackets::Auth::AuthSession::Read()
{
uint32 addonDataSize;
@@ -75,6 +109,41 @@ void WorldPackets::Auth::AuthSession::Read()
Account = _worldPacket.ReadString(accountNameLength);
}
+WorldPacket const* WorldPackets::Auth::AuthResponse::Write()
+{
+ _worldPacket.WriteBit(WaitInfo.is_initialized());
+
+ if (WaitInfo)
+ _worldPacket.WriteBit(WaitInfo->HasFCM);
+
+ _worldPacket.WriteBit(SuccessInfo.is_initialized());
+ _worldPacket.FlushBits();
+
+ if (SuccessInfo)
+ {
+ _worldPacket << uint32(SuccessInfo->TimeRemain);
+ _worldPacket << uint8(SuccessInfo->ActiveExpansionLevel);
+ _worldPacket << uint32(SuccessInfo->TimeSecondsUntilPCKick);
+ _worldPacket << uint8(SuccessInfo->AccountExpansionLevel);
+ _worldPacket << uint32(SuccessInfo->TimeRested);
+ _worldPacket << uint8(SuccessInfo->TimeOptions);
+ }
+
+ _worldPacket << uint8(Result);
+
+ if (WaitInfo)
+ _worldPacket << uint32(WaitInfo->WaitCount);
+
+ return &_worldPacket;
+}
+
+WorldPacket const* WorldPackets::Auth::WaitQueueUpdate::Write()
+{
+ _worldPacket << uint32(WaitInfo.WaitCount);
+ _worldPacket.WriteBit(WaitInfo.HasFCM);
+ return &_worldPacket;
+}
+
void WorldPackets::Auth::AuthContinuedSession::Read()
{
_worldPacket >> Key;
@@ -238,7 +307,7 @@ uint8 const WherePacketHmac[] =
0x83, 0x95, 0x81, 0x69, 0xB0, 0x5A, 0xB4, 0x9D, 0xA8, 0x55, 0xFF, 0xFC, 0xEE, 0x58, 0x0A, 0x2F
};
-WorldPackets::Auth::ConnectTo::ConnectTo() : ServerPacket(SMSG_REDIRECT_CLIENT, 8 + 4 + 256 + 1)
+WorldPackets::Auth::ConnectTo::ConnectTo() : ServerPacket(SMSG_CONNECT_TO, 8 + 4 + 256 + 1)
{
Payload.Adler32 = 0xA0A66C10;
@@ -551,3 +620,9 @@ WorldPacket const* WorldPackets::Auth::ConnectTo::Write()
_worldPacket << uint8(Con);
return &_worldPacket;
}
+
+void WorldPackets::Auth::ConnectToFailed::Read()
+{
+ Serial = _worldPacket.read();
+ _worldPacket >> Con;
+}
diff --git a/src/server/game/Server/Packets/AuthenticationPackets.h b/src/server/game/Server/Packets/AuthenticationPackets.h
index 04850caea1..712ea14358 100644
--- a/src/server/game/Server/Packets/AuthenticationPackets.h
+++ b/src/server/game/Server/Packets/AuthenticationPackets.h
@@ -23,6 +23,7 @@
#include "Util.h"
#include "BigNumber.h"
#include "SHA1.h"
+#include
#include
using boost::asio::ip::tcp;
@@ -31,15 +32,55 @@ namespace WorldPackets
{
namespace Auth
{
- class AuthSession final : public ClientPacket
+ class EarlyProcessClientPacket : public ClientPacket
{
public:
- AuthSession(WorldPacket&& packet) : ClientPacket(CMSG_AUTH_SESSION, std::move(packet))
- {
- memset(Digest, 0, SHA_DIGEST_LENGTH);
- }
+ EarlyProcessClientPacket(OpcodeClient opcode, WorldPacket&& packet) : ClientPacket(opcode, std::move(packet)) { }
- void Read() override;
+ bool ReadNoThrow();
+ };
+
+ class Ping final : public EarlyProcessClientPacket
+ {
+ public:
+ Ping(WorldPacket&& packet) : EarlyProcessClientPacket(CMSG_PING, std::move(packet)) { }
+
+ uint32 Latency = 0;
+ uint32 Serial = 0;
+
+ private:
+ void Read();
+ };
+
+ class Pong final : public ServerPacket
+ {
+ public:
+ Pong(uint32 serial) : ServerPacket(SMSG_PONG, 4), Serial(serial) { }
+
+ WorldPacket const* Write() override;
+
+ uint32 Serial = 0;
+ };
+
+ class AuthChallenge final : public ServerPacket
+ {
+ public:
+ AuthChallenge() : ServerPacket(SMSG_AUTH_CHALLENGE, 32 + 4 + 1) { }
+
+ WorldPacket const* Write() override;
+
+ std::array DosChallenge = { };
+ uint32 Challenge = 0;
+ uint8 DosZeroBits = 0;
+ };
+
+ class AuthSession final : public EarlyProcessClientPacket
+ {
+ public:
+ AuthSession(WorldPacket&& packet) : EarlyProcessClientPacket(CMSG_AUTH_SESSION, std::move(packet))
+ {
+ Digest.fill(0);
+ }
uint32 BattlegroupID = 0;
int8 LoginServerType = 0; ///< Auth type used - 0 GRUNT, 1 battle.net
@@ -50,25 +91,75 @@ namespace WorldPackets
int32 LoginServerID = 0;
uint32 RegionID = 0;
uint64 DosResponse = 0;
- uint8 Digest[SHA_DIGEST_LENGTH];
+ std::array Digest;
std::string Account;
bool UseIPv6 = false;
ByteBuffer AddonInfo;
+
+ private:
+ void Read() override;
};
- class AuthContinuedSession final : public ClientPacket
+ struct AuthWaitInfo
+ {
+ uint32 WaitCount = 0; ///< position of the account in the login queue
+ bool HasFCM = false; ///< true if the account has a forced character migration pending. @todo implement
+ };
+
+ class AuthResponse final : public ServerPacket
{
public:
- AuthContinuedSession(WorldPacket&& packet) : ClientPacket(CMSG_AUTH_CONTINUED_SESSION, std::move(packet))
+ struct AuthSuccessInfo
{
- memset(Digest, 0, SHA_DIGEST_LENGTH);
- }
+ uint32 TimeRemain = 0; ///< the remaining game time that the account has in seconds. It is not currently implemented and probably won't ever be.
+ uint32 TimeRested = 0; ///< affects the return value of the GetBillingTimeRested() client API call, it is the number of seconds you have left until the experience points and loot you receive from creatures and quests is reduced. It is only used in the Asia region in retail, it's not implemented in TC and will probably never be.
+ uint32 TimeSecondsUntilPCKick = 0; ///< @todo research
+ uint8 AccountExpansionLevel = 0; ///< the current expansion of this account, the possible values are in @ref Expansions
+ uint8 ActiveExpansionLevel = 0; ///< the current server expansion, the possible values are in @ref Expansions
+ uint8 TimeOptions = 0; ///< controls the behavior of the client regarding billing, used in Asia realms, as they don't have monthly subscriptions, possible values are in @ref BillingPlanFlags. It is not currently implemented and will probably never be.
+ };
- void Read() override;
+ AuthResponse() : ServerPacket(SMSG_AUTH_RESPONSE) { }
+
+ WorldPacket const* Write() override;
+
+ Optional SuccessInfo; ///< contains the packet data in case that it has account information, otherwise its contents are undefined.
+ Optional WaitInfo; ///< contains the queue wait information in case the account is in the login queue.
+ uint8 Result = 0; ///< the result of the authentication process, possible values are @ref ResponseCodes
+ };
+
+ class WaitQueueUpdate final : public ServerPacket
+ {
+ public:
+ WaitQueueUpdate() : ServerPacket(SMSG_WAIT_QUEUE_UPDATE, 4 + 1) { }
+
+ WorldPacket const* Write() override;
+
+ AuthWaitInfo WaitInfo;
+ };
+
+ class WaitQueueFinish final : public ServerPacket
+ {
+ public:
+ WaitQueueFinish() : ServerPacket(SMSG_WAIT_QUEUE_FINISH, 0) { }
+
+ WorldPacket const* Write() override { return &_worldPacket; }
+ };
+
+ class AuthContinuedSession final : public EarlyProcessClientPacket
+ {
+ public:
+ AuthContinuedSession(WorldPacket&& packet) : EarlyProcessClientPacket(CMSG_AUTH_CONTINUED_SESSION, std::move(packet))
+ {
+ Digest.fill(0);
+ }
uint64 DosResponse = 0;
uint64 Key = 0;
- uint8 Digest[SHA_DIGEST_LENGTH];
+ std::array Digest;
+
+ private:
+ void Read() override;
};
class ResumeComms final : public ServerPacket
@@ -119,6 +210,18 @@ namespace WorldPackets
BigNumber dmq1;
BigNumber iqmp;
};
+
+ class ConnectToFailed final : public EarlyProcessClientPacket
+ {
+ public:
+ ConnectToFailed(WorldPacket&& packet) : EarlyProcessClientPacket(CMSG_CONNECT_TO_FAILED, std::move(packet)) { }
+
+ ConnectToSerial Serial = ConnectToSerial::None;
+ uint8 Con = 0;
+
+ private:
+ void Read() override;
+ };
}
}
diff --git a/src/server/game/Server/Packets/CharacterPackets.cpp b/src/server/game/Server/Packets/CharacterPackets.cpp
index 4c897a55f9..0fdcfc62ac 100644
--- a/src/server/game/Server/Packets/CharacterPackets.cpp
+++ b/src/server/game/Server/Packets/CharacterPackets.cpp
@@ -209,3 +209,9 @@ WorldPacket const* WorldPackets::Character::EnumCharactersResult::Write()
return &_worldPacket;
}
+
+WorldPacket const* WorldPackets::Character::CharacterLoginFailed::Write()
+{
+ _worldPacket << uint8(Code);
+ return &_worldPacket;
+}
diff --git a/src/server/game/Server/Packets/CharacterPackets.h b/src/server/game/Server/Packets/CharacterPackets.h
index eddf37df32..2491ca21e0 100644
--- a/src/server/game/Server/Packets/CharacterPackets.h
+++ b/src/server/game/Server/Packets/CharacterPackets.h
@@ -101,6 +101,30 @@ namespace WorldPackets
std::vector Characters; ///< all characters on the list
std::vector FactionChangeRestrictions; ///< @todo: research
};
+
+ enum class LoginFailureReason : uint8
+ {
+ Failed = 0,
+ NoWorld = 1,
+ DuplicateCharacter = 2,
+ NoInstances = 3,
+ Disabled = 4,
+ NoCharacter = 5,
+ LockedForTransfer = 6,
+ LockedByBilling = 7,
+ LockedByMobileAH = 8,
+ TemporaryGMLock = 9
+ };
+
+ class CharacterLoginFailed final : public ServerPacket
+ {
+ public:
+ CharacterLoginFailed(LoginFailureReason code) : ServerPacket(SMSG_CHARACTER_LOGIN_FAILED, 1), Code(code) { }
+
+ WorldPacket const* Write() override;
+
+ LoginFailureReason Code = LoginFailureReason::Failed;
+ };
}
}
diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp
index 5fea98ee1e..fafc6d9a42 100644
--- a/src/server/game/Server/Protocol/Opcodes.cpp
+++ b/src/server/game/Server/Protocol/Opcodes.cpp
@@ -33,6 +33,7 @@ public:
PacketClass nicePacket(std::move(packet));
nicePacket.Read();
(session->*HandlerFunction)(nicePacket);
+ session->LogUnprocessedTail(nicePacket.GetRawPacket());
}
};
@@ -45,6 +46,7 @@ public:
void Call(WorldSession* session, WorldPacket& packet) const override
{
(session->*HandlerFunction)(packet);
+ session->LogUnprocessedTail(&packet);
}
};
@@ -276,7 +278,7 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_COMPLAIN, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleComplainOpcode );
DEFINE_HANDLER(CMSG_COMPLETE_CINEMATIC, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCompleteCinematic );
DEFINE_HANDLER(CMSG_COMPLETE_MOVIE, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleCompleteMovie );
- DEFINE_HANDLER(CMSG_CONNECT_TO_FAILED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_HANDLER(CMSG_CONNECT_TO_FAILED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_EarlyProccess );
DEFINE_HANDLER(CMSG_CONTACT_LIST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleContactListOpcode );
DEFINE_HANDLER(CMSG_CORPSE_MAP_POSITION_QUERY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCorpseMapPositionQuery );
DEFINE_HANDLER(CMSG_CREATURE_QUERY, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleCreatureQueryOpcode );
@@ -786,6 +788,7 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_COMSAT_CONNECT_FAIL, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_COMSAT_DISCONNECT, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_COMSAT_RECONNECT_TRY, STATUS_NEVER, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_CONNECT_TO, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CONTACT_LIST, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CONVERT_RUNE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_COOLDOWN_CHEAT, STATUS_NEVER, CONNECTION_TYPE_REALM);
@@ -1167,7 +1170,6 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_REALM_SPLIT, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_REAL_GROUP_UPDATE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_RECEIVED_MAIL, STATUS_NEVER, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_REDIRECT_CLIENT, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_REFER_A_FRIEND_EXPIRED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_REFER_A_FRIEND_FAILURE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_REFORGE_RESULT, STATUS_NEVER, CONNECTION_TYPE_REALM);
diff --git a/src/server/game/Server/Protocol/Opcodes.h b/src/server/game/Server/Protocol/Opcodes.h
index a12fc58083..d10a515fab 100644
--- a/src/server/game/Server/Protocol/Opcodes.h
+++ b/src/server/game/Server/Protocol/Opcodes.h
@@ -723,6 +723,7 @@ enum OpcodeServer
SMSG_COMSAT_CONNECT_FAIL = 0x6317,
SMSG_COMSAT_DISCONNECT = 0x0316,
SMSG_COMSAT_RECONNECT_TRY = 0x4D35,
+ SMSG_CONNECT_TO = 0x0942,
SMSG_CONTACT_LIST = 0x6017,
SMSG_CONVERT_RUNE = 0x4F14,
SMSG_COOLDOWN_CHEAT = 0x4537,
@@ -1127,7 +1128,6 @@ enum OpcodeServer
SMSG_REALM_SPLIT = 0x2714,
SMSG_REAL_GROUP_UPDATE = 0x0F34,
SMSG_RECEIVED_MAIL = 0x2924,
- SMSG_REDIRECT_CLIENT = 0x0942,
SMSG_REFER_A_FRIEND_EXPIRED = 0x4934,
SMSG_REFER_A_FRIEND_FAILURE = 0x2037,
SMSG_REFORGE_RESULT = 0x58A4,
diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp
index 622c4c0070..c6d2242e4f 100644
--- a/src/server/game/Server/WorldSession.cpp
+++ b/src/server/game/Server/WorldSession.cpp
@@ -115,7 +115,8 @@ WorldSession::WorldSession(uint32 id, std::string&& name, uint32 battlenetAccoun
_accountId(id),
_accountName(std::move(name)),
_battlenetAccountId(battlenetAccountId),
- m_expansion(expansion),
+ m_accountExpansion(expansion),
+ m_expansion(std::min(expansion, sWorld->getIntConfig(CONFIG_EXPANSION))),
_warden(nullptr),
_logoutTime(0),
m_inQueue(false),
@@ -197,7 +198,9 @@ std::string WorldSession::GetPlayerInfo() const
std::ostringstream ss;
ss << "[Player: ";
- if (!m_playerLoading && _player)
+ if (!m_playerLoading.IsEmpty())
+ ss << "Logging in: " << m_playerLoading.ToString() << ", ";
+ else if (_player)
ss << _player->GetName() << ' ' << _player->GetGUID().ToString() << ", ";
ss << "Account: " << GetAccountId() << "]";
@@ -318,7 +321,7 @@ void WorldSession::LogUnexpectedOpcode(WorldPacket* packet, char const* status,
}
/// Logging helper for unexpected opcodes
-void WorldSession::LogUnprocessedTail(WorldPacket* packet)
+void WorldSession::LogUnprocessedTail(WorldPacket const* packet)
{
if (!sLog->ShouldLog("network.opcode", LOG_LEVEL_TRACE) || packet->rpos() >= packet->wpos())
return;
@@ -373,7 +376,6 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
{
sScriptMgr->OnPacketReceive(this, *packet);
opHandle->Call(this, *packet);
- LogUnprocessedTail(packet);
}
// lag can cause STATUS_LOGGEDIN opcodes to arrive after the player started a transfer
break;
@@ -386,7 +388,6 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
// not expected _player or must checked in packet hanlder
sScriptMgr->OnPacketReceive(this, *packet);
opHandle->Call(this, *packet);
- LogUnprocessedTail(packet);
}
break;
case STATUS_TRANSFER:
@@ -398,7 +399,6 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
{
sScriptMgr->OnPacketReceive(this, *packet);
opHandle->Call(this, *packet);
- LogUnprocessedTail(packet);
}
break;
case STATUS_AUTHED:
@@ -418,7 +418,6 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
{
sScriptMgr->OnPacketReceive(this, *packet);
opHandle->Call(this, *packet);
- LogUnprocessedTail(packet);
}
break;
case STATUS_NEVER:
@@ -784,30 +783,6 @@ void WorldSession::SendConnectToInstance(WorldPackets::Auth::ConnectToSerial ser
SendPacket(connectTo.Write());
}
-void WorldSession::SendAuthWaitQue(uint32 position)
-{
- if (position == 0)
- {
- WorldPacket packet(SMSG_AUTH_RESPONSE, 1);
- packet.WriteBit(0); // has queue info
- packet.WriteBit(0); // has account info
- packet.FlushBits();
- packet << uint8(AUTH_OK);
- SendPacket(&packet);
- }
- else
- {
- WorldPacket packet(SMSG_AUTH_RESPONSE, 6);
- packet.WriteBit(1); // has queue info
- packet.WriteBit(0); // unk queue bool
- packet.WriteBit(0); // has account info
- packet.FlushBits();
- packet << uint8(AUTH_WAIT_QUEUE);
- packet << uint32(position);
- SendPacket(&packet);
- }
-}
-
void WorldSession::LoadAccountData(PreparedQueryResult result, uint32 mask)
{
for (uint32 i = 0; i < NUM_ACCOUNT_DATA_TYPES; ++i)
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index 4078cc6499..d15ecf7da6 100644
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -83,6 +83,8 @@ namespace WorldPackets
namespace Character
{
class EnumCharacters;
+
+ enum class LoginFailureReason : uint8;
}
namespace LFG
@@ -404,7 +406,8 @@ class TC_GAME_API WorldSession
void SetSecurity(AccountTypes security) { _security = security; }
std::string const& GetRemoteAddress() const { return m_Address; }
void SetPlayer(Player* player);
- uint8 Expansion() const { return m_expansion; }
+ uint8 GetAccountExpansion() const { return m_accountExpansion; }
+ uint8 GetExpansion() const { return m_expansion; }
void InitWarden(BigNumber* k, std::string const& os);
@@ -432,7 +435,6 @@ class TC_GAME_API WorldSession
void QueuePacket(WorldPacket* new_packet);
bool Update(uint32 diff, PacketFilter& updater);
- void SendConnectToInstance(WorldPackets::Auth::ConnectToSerial serial);
/// Handle the authentication waiting queue (to be completed)
void SendAuthWaitQue(uint32 position);
@@ -554,13 +556,17 @@ class TC_GAME_API WorldSession
void Handle_EarlyProccess(WorldPacket& recvPacket); // just mark packets processed in WorldSocket::OnRead
void Handle_ServerSide(WorldPacket& recvPacket); // sever side only, can't be accepted from client
void Handle_Deprecated(WorldPacket& recvPacket); // never used anymore by client
+ void LogUnprocessedTail(WorldPacket const* packet);
void HandleCharEnum(PreparedQueryResult result);
void HandleCharEnumOpcode(WorldPackets::Character::EnumCharacters& /*enumCharacters*/);
void HandleCharDeleteOpcode(WorldPacket& recvPacket);
void HandleCharCreateOpcode(WorldPacket& recvPacket);
void HandlePlayerLoginOpcode(WorldPacket& recvPacket);
+
+ void SendConnectToInstance(WorldPackets::Auth::ConnectToSerial serial);
void HandleContinuePlayerLogin();
+ void AbortLogin(WorldPackets::Character::LoginFailureReason reason);
void HandleLoadScreenOpcode(WorldPacket& recvPacket);
void HandlePlayerLogin(LoginQueryHolder* holder);
void HandleCharFactionOrRaceChange(WorldPacket& recvData);
@@ -1223,7 +1229,6 @@ class TC_GAME_API WorldSession
// logging helper
void LogUnexpectedOpcode(WorldPacket* packet, char const* status, const char *reason);
- void LogUnprocessedTail(WorldPacket* packet);
// EnumData helpers
bool IsLegitCharacterForAccount(ObjectGuid lowGUID)
@@ -1245,6 +1250,7 @@ class TC_GAME_API WorldSession
uint32 _accountId;
std::string _accountName;
uint32 _battlenetAccountId;
+ uint8 m_accountExpansion;
uint8 m_expansion;
// Warden
diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp
index 006dee67a8..0a74430d9b 100644
--- a/src/server/game/Server/WorldSocket.cpp
+++ b/src/server/game/Server/WorldSocket.cpp
@@ -15,10 +15,11 @@
* with this program. If not, see .
*/
-#include "AuthenticationPackets.h"
#include "WorldSocket.h"
+#include "AuthenticationPackets.h"
#include "BattlenetAccountMgr.h"
#include "BigNumber.h"
+#include "CharacterPackets.h"
#include "DatabaseEnv.h"
#include "GameTime.h"
#include "IPLocation.h"
@@ -160,16 +161,16 @@ bool WorldSocket::Update()
void WorldSocket::HandleSendAuthSession()
{
- WorldPacket packet(SMSG_AUTH_CHALLENGE, 37);
_encryptSeed.SetRand(16 * 8);
_decryptSeed.SetRand(16 * 8);
- packet.append(_encryptSeed.AsByteArray(16).get(), 16); // new encryption seeds
- packet.append(_decryptSeed.AsByteArray(16).get(), 16); // new encryption seeds
+ WorldPackets::Auth::AuthChallenge challenge;
+ challenge.Challenge = _authSeed;
+ memcpy(&challenge.DosChallenge[0], _encryptSeed.AsByteArray(16).get(), 16);
+ memcpy(&challenge.DosChallenge[4], _decryptSeed.AsByteArray(16).get(), 16);
+ challenge.DosZeroBits = 1;
- packet << uint32(_authSeed);
- packet << uint8(1);
- SendPacketAndLogOpcode(packet);
+ SendPacketAndLogOpcode(*challenge.Write());
}
void WorldSocket::OnClose()
@@ -274,17 +275,6 @@ bool WorldSocket::ReadHeaderHandler()
return true;
}
-struct AuthSession
-{
- uint8 LoginServerType = 0;
- uint32 RealmID = 0;
- uint16 Build = 0;
- uint32 LocalChallenge = 0;
- uint8 Digest[SHA_DIGEST_LENGTH] = {};
- std::string Account;
- ByteBuffer AddonInfo;
-};
-
struct AccountInfo
{
struct
@@ -367,15 +357,15 @@ WorldSocket::ReadDataHandlerResult WorldSocket::ReadDataHandler()
case CMSG_PING:
{
LogOpcodeText(opcode, sessionGuard);
- try
+ WorldPackets::Auth::Ping ping(std::move(packet));
+ if (!ping.ReadNoThrow())
{
- return HandlePing(packet) ? ReadDataHandlerResult::Ok : ReadDataHandlerResult::Error;
+ TC_LOG_ERROR("network", "WorldSocket::ReadDataHandler(): client %s sent malformed CMSG_PING", GetRemoteIpAddress().to_string().c_str());
+ return ReadDataHandlerResult::Error;
}
- catch (ByteBufferException const&)
- {
- }
- TC_LOG_ERROR("network", "WorldSocket::ReadDataHandler(): client %s sent malformed CMSG_PING", GetRemoteIpAddress().to_string().c_str());
- return ReadDataHandlerResult::Error;
+ if (!HandlePing(ping))
+ return ReadDataHandlerResult::Error;
+ return ReadDataHandlerResult::Ok;
}
case CMSG_AUTH_SESSION:
{
@@ -388,18 +378,14 @@ WorldSocket::ReadDataHandlerResult WorldSocket::ReadDataHandler()
return ReadDataHandlerResult::Error;
}
- try
+ std::shared_ptr authSession = std::make_shared(std::move(packet));
+ if (!authSession->ReadNoThrow())
{
- WorldPackets::Auth::AuthSession authSession(std::move(packet));
- authSession.Read();
- HandleAuthSession(authSession);
- return ReadDataHandlerResult::WaitingForQuery;
+ TC_LOG_ERROR("network", "WorldSocket::ReadDataHandler(): client %s sent malformed CMSG_AUTH_SESSION", GetRemoteIpAddress().to_string().c_str());
+ return ReadDataHandlerResult::Error;
}
- catch (ByteBufferException const&)
- {
- }
- TC_LOG_ERROR("network", "WorldSocket::ReadDataHandler(): client %s sent malformed CMSG_AUTH_SESSION", GetRemoteIpAddress().to_string().c_str());
- return ReadDataHandlerResult::Error;
+ HandleAuthSession(authSession);
+ return ReadDataHandlerResult::WaitingForQuery;
}
case CMSG_AUTH_CONTINUED_SESSION:
{
@@ -412,34 +398,41 @@ WorldSocket::ReadDataHandlerResult WorldSocket::ReadDataHandler()
return ReadDataHandlerResult::Error;
}
- try
+ std::shared_ptr authSession = std::make_shared(std::move(packet));
+ if (!authSession->ReadNoThrow())
{
- std::shared_ptr authSession = std::make_shared(std::move(packet));
- authSession->Read();
- HandleAuthContinuedSession(authSession);
- return ReadDataHandlerResult::WaitingForQuery;
+ TC_LOG_ERROR("network", "WorldSocket::ReadDataHandler(): client %s sent malformed CMSG_AUTH_CONTINUED_SESSION", GetRemoteIpAddress().to_string().c_str());
+ return ReadDataHandlerResult::Error;
}
- catch (ByteBufferException const&)
- {
- }
- TC_LOG_ERROR("network", "WorldSocket::ReadDataHandler(): client %s sent malformed CMSG_AUTH_CONTINUED_SESSION", GetRemoteIpAddress().to_string().c_str());
- return ReadDataHandlerResult::Error;
+ HandleAuthContinuedSession(authSession);
+ return ReadDataHandlerResult::WaitingForQuery;
}
case CMSG_LOG_DISCONNECT:
- packet.rfinish(); // contains uint32 disconnectReason;
LogOpcodeText(opcode, sessionGuard);
- sScriptMgr->OnPacketReceive(_worldSession, packet);
+ packet.rfinish(); // contains uint32 disconnectReason;
return ReadDataHandlerResult::Ok;
case CMSG_ENABLE_NAGLE:
LogOpcodeText(opcode, sessionGuard);
- sScriptMgr->OnPacketReceive(_worldSession, packet);
if (_worldSession)
_worldSession->HandleEnableNagleAlgorithm();
return ReadDataHandlerResult::Ok;
case CMSG_KEEP_ALIVE: // todo: handle this packet in the same way of CMSG_TIME_SYNC_RESP
LogOpcodeText(opcode, sessionGuard);
- sScriptMgr->OnPacketReceive(_worldSession, packet);
return ReadDataHandlerResult::Ok;
+ case CMSG_CONNECT_TO_FAILED:
+ {
+ sessionGuard.lock();
+
+ LogOpcodeText(opcode, sessionGuard);
+ WorldPackets::Auth::ConnectToFailed connectToFailed(std::move(packet));
+ if (!connectToFailed.ReadNoThrow())
+ {
+ TC_LOG_ERROR("network", "WorldSocket::ReadDataHandler(): client %s sent malformed CMSG_CONNECT_TO_FAILED", GetRemoteIpAddress().to_string().c_str());
+ return ReadDataHandlerResult::Error;
+ }
+ HandleConnectToFailed(connectToFailed);
+ return ReadDataHandlerResult::Ok;
+ }
case CMSG_TIME_SYNC_RESP:
packetToQueue = new WorldPacket(std::move(packet), std::chrono::steady_clock::now());
break;
@@ -524,7 +517,7 @@ void WorldSocket::LogOpcodeText(OpcodeClient opcode, std::unique_lockC: %s %s", GetRemoteIpAddress().to_string().c_str(), GetOpcodeNameForLogging(static_cast(packet.GetOpcode())).c_str());
SendPacket(packet);
@@ -541,25 +534,17 @@ void WorldSocket::SendPacket(WorldPacket const& packet)
_bufferQueue.Enqueue(new EncryptablePacket(packet, _authCrypt.IsInitialized()));
}
-void WorldSocket::HandleAuthSession(WorldPackets::Auth::AuthSession& authSession)
+void WorldSocket::HandleAuthSession(std::shared_ptr authSession)
{
- std::shared_ptr session = std::make_shared();
- session->AddonInfo = authSession.AddonInfo;
- session->Account = authSession.Account;
- session->Build = authSession.Build;
- memcpy(session->Digest, authSession.Digest, SHA_DIGEST_LENGTH);
- session->LocalChallenge = authSession.LocalChallenge;
- session->LoginServerType = authSession.LoginServerType;
- session->RealmID = authSession.RealmID;
-
+ // Get the account information from the auth database
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_INFO_BY_NAME);
stmt->setInt32(0, int32(realm.Id.Realm));
- stmt->setString(1, session->Account);
+ stmt->setString(1, authSession->Account);
- _queryProcessor.AddQuery(LoginDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSocket::HandleAuthSessionCallback, this, session, std::placeholders::_1)));
+ _queryProcessor.AddQuery(LoginDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSocket::HandleAuthSessionCallback, this, authSession, std::placeholders::_1)));
}
-void WorldSocket::HandleAuthSessionCallback(std::shared_ptr authSession, PreparedQueryResult result)
+void WorldSocket::HandleAuthSessionCallback(std::shared_ptr authSession, PreparedQueryResult result)
{
// Stop if the account is not found
if (!result)
@@ -625,7 +610,7 @@ void WorldSocket::HandleAuthSessionCallback(std::shared_ptr authSes
sha.UpdateBigNumbers(&account.Game.SessionKey, nullptr);
sha.Finalize();
- if (memcmp(sha.GetDigest(), authSession->Digest, SHA_DIGEST_LENGTH) != 0)
+ if (memcmp(sha.GetDigest(), authSession->Digest.data(), SHA_DIGEST_LENGTH) != 0)
{
SendAuthResponseError(AUTH_FAILED);
TC_LOG_ERROR("network", "WorldSocket::HandleAuthSession: Authentication failed for account: %u ('%s') address: %s", account.Game.Id, authSession->Account.c_str(), address.c_str());
@@ -776,7 +761,7 @@ void WorldSocket::HandleAuthContinuedSessionCallback(std::shared_ptrDigest, sha.GetLength()))
+ if (memcmp(sha.GetDigest(), authSession->Digest.data(), sha.GetLength()))
{
SendAuthResponseError(AUTH_UNKNOWN_ACCOUNT);
TC_LOG_ERROR("network", "WorldSocket::HandleAuthContinuedSession: Authentication failed for account: %u ('%s') address: %s", accountId, login.c_str(), GetRemoteIpAddress().to_string().c_str());
@@ -788,27 +773,55 @@ void WorldSocket::HandleAuthContinuedSessionCallback(std::shared_ptrPlayerLoading())
+ {
+ switch (connectToFailed.Serial)
+ {
+ case WorldPackets::Auth::ConnectToSerial::WorldAttempt1:
+ _worldSession->SendConnectToInstance(WorldPackets::Auth::ConnectToSerial::WorldAttempt2);
+ break;
+ case WorldPackets::Auth::ConnectToSerial::WorldAttempt2:
+ _worldSession->SendConnectToInstance(WorldPackets::Auth::ConnectToSerial::WorldAttempt3);
+ break;
+ case WorldPackets::Auth::ConnectToSerial::WorldAttempt3:
+ _worldSession->SendConnectToInstance(WorldPackets::Auth::ConnectToSerial::WorldAttempt4);
+ break;
+ case WorldPackets::Auth::ConnectToSerial::WorldAttempt4:
+ _worldSession->SendConnectToInstance(WorldPackets::Auth::ConnectToSerial::WorldAttempt5);
+ break;
+ case WorldPackets::Auth::ConnectToSerial::WorldAttempt5:
+ {
+ TC_LOG_ERROR("network", "%s failed to connect 5 times to world socket, aborting login", _worldSession->GetPlayerInfo().c_str());
+ _worldSession->AbortLogin(WorldPackets::Character::LoginFailureReason::NoWorld);
+ break;
+ }
+ default:
+ return;
+ }
+ }
+ //else
+ //{
+ // transfer_aborted when/if we get map node redirection
+ // SendPacketAndLogOpcode(*WorldPackets::Auth::ResumeComms().Write());
+ //}
+ }
}
-bool WorldSocket::HandlePing(WorldPacket& recvPacket)
+void WorldSocket::SendAuthResponseError(uint8 code)
+{
+ WorldPackets::Auth::AuthResponse response;
+ response.Result = code;
+ SendPacketAndLogOpcode(*response.Write());
+}
+
+bool WorldSocket::HandlePing(WorldPackets::Auth::Ping& ping)
{
using namespace std::chrono;
- uint32 ping;
- uint32 latency;
-
- // Get the ping packet content
- recvPacket >> latency;
- recvPacket >> ping;
-
if (_LastPingTime == steady_clock::time_point())
{
_LastPingTime = steady_clock::now();
@@ -848,7 +861,7 @@ bool WorldSocket::HandlePing(WorldPacket& recvPacket)
std::lock_guard sessionGuard(_worldSessionLock);
if (_worldSession)
- _worldSession->SetLatency(latency);
+ _worldSession->SetLatency(ping.Latency);
else
{
TC_LOG_ERROR("network", "WorldSocket::HandlePing: peer sent CMSG_PING, but is not authenticated or got recently kicked, address = %s", GetRemoteIpAddress().to_string().c_str());
@@ -856,8 +869,6 @@ bool WorldSocket::HandlePing(WorldPacket& recvPacket)
}
}
- WorldPacket packet(SMSG_PONG, 4);
- packet << ping;
- SendPacketAndLogOpcode(packet);
+ SendPacketAndLogOpcode(*WorldPackets::Auth::Pong(ping.Serial).Write());
return true;
}
diff --git a/src/server/game/Server/WorldSocket.h b/src/server/game/Server/WorldSocket.h
index 62275094ef..00cb3d23fe 100644
--- a/src/server/game/Server/WorldSocket.h
+++ b/src/server/game/Server/WorldSocket.h
@@ -43,6 +43,7 @@ namespace WorldPackets
class AuthSession;
class AuthContinuedSession;
class ConnectToFailed;
+ class Ping;
}
}
@@ -107,15 +108,15 @@ private:
/// accessing WorldSession is not threadsafe, only do it when holding _worldSessionLock
void LogOpcodeText(OpcodeClient opcode, std::unique_lock const& guard) const;
/// sends and logs network.opcode without accessing WorldSession
- void SendPacketAndLogOpcode(WorldPacket& packet);
+ void SendPacketAndLogOpcode(WorldPacket const& packet);
void HandleSendAuthSession();
- void HandleAuthSession(WorldPackets::Auth::AuthSession& authSession);
+ void HandleAuthSession(std::shared_ptr authSession);
+ void HandleAuthSessionCallback(std::shared_ptr authSession, PreparedQueryResult result);
void HandleAuthContinuedSession(std::shared_ptr authSession);
void HandleAuthContinuedSessionCallback(std::shared_ptr authSession, PreparedQueryResult result);
- void HandleAuthSessionCallback(std::shared_ptr authSession, PreparedQueryResult result);
void LoadSessionPermissionsCallback(PreparedQueryResult result);
-
- bool HandlePing(WorldPacket& recvPacket);
+ void HandleConnectToFailed(WorldPackets::Auth::ConnectToFailed& connectToFailed);
+ bool HandlePing(WorldPackets::Auth::Ping& ping);
ConnectionType _type;
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index 88d1fc75ba..cd2b75a5f9 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -436,7 +436,7 @@ void World::AddQueuedPlayer(WorldSession* sess)
m_QueuedPlayer.push_back(sess);
// The 1st SMSG_AUTH_RESPONSE needs to contain other info too.
- sess->SendAuthResponse(AUTH_WAIT_QUEUE, true, GetQueuePos(sess));
+ sess->SendAuthResponse(AUTH_OK, true, GetQueuePos(sess));
}
bool World::RemoveQueuedPlayer(WorldSession* sess)