[10077] Add delayed far teleports for opcode handlers

Some opcode handlers have many code with possible deep calling
far teleports by some reason (death, quest script, etc).
This can be triggering unexpected lost Map context and crashs result.

Note: player login opcode still have disbled delayed teleports (old way work)
just becase Player object created in it and not have flag set.
Calling point look not 100% safe but at this commit this way not chnages for while.
This commit is contained in:
VladimirMangos 2010-06-19 05:52:17 +04:00
parent 3e210228f9
commit d6138f01a6
4 changed files with 35 additions and 19 deletions

View file

@ -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());

View file

@ -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);
}

View file

@ -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);

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "10076"
#define REVISION_NR "10077"
#endif // __REVISION_NR_H__