diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp index 8357ede9e..5e4e2421b 100644 --- a/src/game/CharacterHandler.cpp +++ b/src/game/CharacterHandler.cpp @@ -703,6 +703,7 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder *holder) if (!pCurrChar->GetMap()->Add(pCurrChar)) { + // normal delayed teleport protection not applied (and this correct) for this case (Player object just created) AreaTrigger const* at = sObjectMgr.GetGoBackTrigger(pCurrChar->GetMapId()); if(at) pCurrChar->TeleportTo(at->target_mapId, at->target_X, at->target_Y, at->target_Z, pCurrChar->GetOrientation()); diff --git a/src/game/WorldSession.cpp b/src/game/WorldSession.cpp index 273cf088e..491de312c 100644 --- a/src/game/WorldSession.cpp +++ b/src/game/WorldSession.cpp @@ -184,11 +184,8 @@ bool WorldSession::Update(uint32 /*diff*/) LogUnexpectedOpcode(packet, "the player has not logged in yet"); } else if(_player->IsInWorld()) - { - (this->*opHandle.handler)(*packet); - if (packet->rpos() < packet->wpos() && sLog.HasLogLevelOrHigher(LOG_LVL_DEBUG)) - LogUnprocessedTail(packet); - } + ExecuteOpcode(opHandle, packet); + // lag can cause STATUS_LOGGEDIN opcodes to arrive after the player started a transfer break; case STATUS_LOGGEDIN_OR_RECENTLY_LOGGEDOUT: @@ -197,12 +194,8 @@ bool WorldSession::Update(uint32 /*diff*/) LogUnexpectedOpcode(packet, "the player has not logged in yet and not recently logout"); } else - { // not expected _player or must checked in packet hanlder - (this->*opHandle.handler)(*packet); - if (packet->rpos() < packet->wpos() && sLog.HasLogLevelOrHigher(LOG_LVL_DEBUG)) - LogUnprocessedTail(packet); - } + ExecuteOpcode(opHandle, packet); break; case STATUS_TRANSFER: if(!_player) @@ -210,11 +203,7 @@ bool WorldSession::Update(uint32 /*diff*/) else if(_player->IsInWorld()) LogUnexpectedOpcode(packet, "the player is still in world"); else - { - (this->*opHandle.handler)(*packet); - if (packet->rpos() < packet->wpos() && sLog.HasLogLevelOrHigher(LOG_LVL_DEBUG)) - LogUnprocessedTail(packet); - } + ExecuteOpcode(opHandle, packet); break; case STATUS_AUTHED: // prevent cheating with skip queue wait @@ -229,9 +218,7 @@ bool WorldSession::Update(uint32 /*diff*/) if (packet->GetOpcode() != CMSG_SET_ACTIVE_VOICE_CHANNEL) m_playerRecentlyLogout = false; - (this->*opHandle.handler)(*packet); - if (packet->rpos() < packet->wpos() && sLog.HasLogLevelOrHigher(LOG_LVL_DEBUG)) - LogUnprocessedTail(packet); + ExecuteOpcode(opHandle, packet); break; case STATUS_NEVER: sLog.outError( "SESSION: received not allowed opcode %s (0x%.4X)", @@ -872,3 +859,27 @@ void WorldSession::SendRedirectClient(std::string& ip, uint16 port) SendPacket(&pkt); } + +void WorldSession::ExecuteOpcode( OpcodeHandler& opHandle, WorldPacket* packet ) +{ + // need prevent do internal far teleports in handlers because some handlers do lot steps + // or call code that can do far teleports in some conditions unexpectedly for generic way work code + if (_player) + _player->SetCanDelayTeleport(true); + + (this->*opHandle.handler)(*packet); + + if (_player) + { + // can be not set in fact for login opcode, but this not create porblems. + _player->SetCanDelayTeleport(false); + + //we should execute delayed teleports only for alive(!) players + //because we don't want player's ghost teleported from graveyard + if (_player->IsHasDelayedTeleport() && _player->isAlive()) + _player->TeleportTo(_player->m_teleport_dest, _player->m_teleport_options); + } + + if (packet->rpos() < packet->wpos() && sLog.HasLogLevelOrHigher(LOG_LVL_DEBUG)) + LogUnprocessedTail(packet); +} \ No newline at end of file diff --git a/src/game/WorldSession.h b/src/game/WorldSession.h index 8aa6ba959..23ae01646 100644 --- a/src/game/WorldSession.h +++ b/src/game/WorldSession.h @@ -43,6 +43,8 @@ class LoginQueryHolder; class CharacterHandler; class GMTicket; +struct OpcodeHandler; + enum AccountDataType { GLOBAL_CONFIG_CACHE = 0, // 0x01 g @@ -773,6 +775,8 @@ class MANGOS_DLL_SPEC WorldSession // private trade methods void moveItems(Item* myItems[], Item* hisItems[]); + void ExecuteOpcode( OpcodeHandler& opHandle, WorldPacket* packet ); + // logging helper void LogUnexpectedOpcode(WorldPacket *packet, const char * reason); void LogUnprocessedTail(WorldPacket *packet); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index c40f920e0..a6b664f8b 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "10076" + #define REVISION_NR "10077" #endif // __REVISION_NR_H__