Core/Netcode: Re-enqueue packets with STATUS_LOGGEDIN requirement that are sent before the server recognizes the player as logged in. They will be processed later.

Fixes #208
Fixes #1434
Fixes #2338
This commit is contained in:
Machiavelli
2011-12-16 15:36:03 +01:00
parent db8c10c7bf
commit 829be0b82b
2 changed files with 20 additions and 5 deletions

View File

@@ -791,7 +791,7 @@ void WorldSession::HandlePlayerLoginOpcode(WorldPacket & recv_data)
_charLoginCallback = CharacterDatabase.DelayQueryHolder((SQLQueryHolder*)holder);
}
void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder)
void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder)
{
uint64 playerGuid = holder->GetGuid();

View File

@@ -222,6 +222,8 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
///- Retrieve packets from the receive queue and call the appropriate handlers
/// not process packets if socket already closed
WorldPacket* packet = NULL;
//! Delete packet after processing by default
bool deletePacket = true;
while (m_Socket && !m_Socket->IsClosed() && _recvQueue.next(packet, updater))
{
if (packet->GetOpcode() >= NUM_MSG_TYPES)
@@ -240,8 +242,19 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
if (!_player)
{
// skip STATUS_LOGGEDIN opcode unexpected errors if player logout sometime ago - this can be network lag delayed packets
//! If player didn't log out a while ago, it means packets are being sent while the server does not recognize
//! the client to be in world yet. We will re-add the packets to the bottom of the queue and process them later.
if (!m_playerRecentlyLogout)
LogUnexpectedOpcode(packet, "STATUS_LOGGEDIN", "the player has not logged in yet");
{
//! Because checking a bool is faster than reallocating memory
deletePacket = false;
//! Re-enqueue
QueuePacket(packet);
//! Log
sLog->outDebug(LOG_FILTER_NETWORKIO, "Re-enqueueing packet with opcode %s (0x%.4X) with with status STATUS_LOGGEDIN. "
"Player is currently not in world yet.", opHandle.name, packet->GetOpcode());
}
}
else if (_player->IsInWorld())
{
@@ -258,7 +271,7 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
"the player has not logged in yet and not recently logout");
else
{
// not expected _player or must checked in packet hanlder
// not expected _player or must checked in packet handler
sScriptMgr->OnPacketReceive(m_Socket, WorldPacket(*packet));
(this->*opHandle.handler)(*packet);
if (sLog->IsOutDebug() && packet->rpos() < packet->wpos())
@@ -308,7 +321,7 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
break;
}
}
catch(ByteBufferException &)
catch (ByteBufferException &)
{
sLog->outError("WorldSession::Update ByteBufferException occured while parsing a packet (opcode: %u) from client %s, accountid=%i. Skipped packet.",
packet->GetOpcode(), GetRemoteAddress().c_str(), GetAccountId());
@@ -320,7 +333,8 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
}
}
delete packet;
if (deletePacket)
delete packet;
}
ProcessQueryCallbacks();
@@ -344,6 +358,7 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
if (!m_Socket)
return false; //Will remove this session from the world session map
}
return true;
}