void WorldSession::HandleMoveWorldportAckOpcode() { // ignore unexpected far teleports if (!GetPlayer()->IsBeingTeleportedFar()) return; GetPlayer()->SetSemaphoreTeleportFar(false); // get the teleport destination WorldLocation &loc = GetPlayer()->GetTeleportDest(); // possible errors in the coordinate validity check if (!MapManager::IsValidMapCoord(loc)) { LogoutPlayer(false); return; } // get the destination map entry, not the current one, this will fix homebind and reset greeting MapEntry const* mEntry = sMapStore.LookupEntry(loc.GetMapId()); InstanceTemplate const* mInstance = sObjectMgr->GetInstanceTemplate(loc.GetMapId()); // reset instance validity, except if going to an instance inside an instance if (GetPlayer()->m_InstanceValid == false && !mInstance) GetPlayer()->m_InstanceValid = true; Map* oldMap = GetPlayer()->GetMap(); ASSERT(oldMap); if (GetPlayer()->IsInWorld()) { sLog->outCrash("Player (Name %s) is still in world when teleported from map %u to new map %u", GetPlayer()->GetName(), oldMap->GetId(), loc.GetMapId()); oldMap->RemovePlayerFromMap(GetPlayer(), false); } // relocate the player to the teleport destination Map* newMap = sMapMgr->CreateMap(loc.GetMapId(), GetPlayer()); // the CanEnter checks are done in TeleporTo but conditions may change // while the player is in transit, for example the map may get full if (!newMap || !newMap->CanEnter(GetPlayer())) { sLog->outError("Map %d could not be created for player %d, porting player to homebind", loc.GetMapId(), GetPlayer()->GetGUIDLow()); GetPlayer()->TeleportTo(GetPlayer()->m_homebindMapId, GetPlayer()->m_homebindX, GetPlayer()->m_homebindY, GetPlayer()->m_homebindZ, GetPlayer()->GetOrientation()); return; } else GetPlayer()->Relocate(&loc); GetPlayer()->ResetMap(); GetPlayer()->SetMap(newMap); GetPlayer()->SendInitialPacketsBeforeAddToMap(); if (!GetPlayer()->GetMap()->AddPlayerToMap(GetPlayer())) { sLog->outError("WORLD: failed to teleport player %s (%d) to map %d because of unknown reason!", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow(), loc.GetMapId()); GetPlayer()->ResetMap(); GetPlayer()->SetMap(oldMap); GetPlayer()->TeleportTo(GetPlayer()->m_homebindMapId, GetPlayer()->m_homebindX, GetPlayer()->m_homebindY, GetPlayer()->m_homebindZ, GetPlayer()->GetOrientation()); return; } // battleground state prepare (in case join to BG), at relogin/tele player not invited // only add to bg group and object, if the player was invited (else he entered through command) if (_player->InBattleground()) { // cleanup setting if outdated if (!mEntry->IsBattlegroundOrArena()) { // We're not in BG _player->SetBattlegroundId(0, BATTLEGROUND_TYPE_NONE); // reset destination bg team _player->SetBGTeam(0); } // join to bg case else if (Battleground* bg = _player->GetBattleground()) { if (_player->IsInvitedForBattlegroundInstance(_player->GetBattlegroundId())) bg->AddPlayer(_player); } } GetPlayer()->SendInitialPacketsAfterAddToMap(); // flight fast teleport case if (GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE) { if (!_player->InBattleground()) { // short preparations to continue flight FlightPathMovementGenerator* flight = (FlightPathMovementGenerator*)(GetPlayer()->GetMotionMaster()->top()); flight->Initialize(*GetPlayer()); return; } // battleground state prepare, stop flight GetPlayer()->GetMotionMaster()->MovementExpired(); GetPlayer()->CleanupAfterTaxiFlight(); } // resurrect character at enter into instance where his corpse exist after add to map Corpse* corpse = GetPlayer()->GetCorpse(); if (corpse && corpse->GetType() != CORPSE_BONES && corpse->GetMapId() == GetPlayer()->GetMapId()) { if (mEntry->IsDungeon()) { GetPlayer()->ResurrectPlayer(0.5f, false); GetPlayer()->SpawnCorpseBones(); } } bool allowMount = !mEntry->IsDungeon() || mEntry->IsBattlegroundOrArena(); if (mInstance) { Difficulty diff = GetPlayer()->GetDifficulty(mEntry->IsRaid()); if (MapDifficulty const* mapDiff = GetMapDifficultyData(mEntry->MapID, diff)) { if (mapDiff->resetTime) { if (time_t timeReset = sInstanceSaveMgr->GetResetTimeFor(mEntry->MapID, diff)) { uint32 timeleft = uint32(timeReset - time(NULL)); GetPlayer()->SendInstanceResetWarning(mEntry->MapID, diff, timeleft); } } } allowMount = mInstance->AllowMount; } // mount allow check if (!allowMount) _player->RemoveAurasByType(SPELL_AURA_MOUNTED); // update zone immediately, otherwise leave channel will cause crash in mtmap uint32 newzone, newarea; GetPlayer()->GetZoneAndAreaId(newzone, newarea); GetPlayer()->UpdateZone(newzone, newarea); // honorless target if (GetPlayer()->pvpInfo.inHostileArea) GetPlayer()->CastSpell(GetPlayer(), 2479, true); // in friendly area else if (GetPlayer()->IsPvP() && !GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP)) GetPlayer()->UpdatePvP(false, false); // resummon pet GetPlayer()->ResummonPetTemporaryUnSummonedIfAny(); //lets process all delayed operations on successful teleport GetPlayer()->ProcessDelayedOperations(); }
/// Update the WorldSession (triggered by World update) bool WorldSession::Update(uint32 /*diff*/) { ///- Retrieve packets from the receive queue and call the appropriate handlers /// not proccess packets if socket already closed WorldPacket* packet; while (_recvQueue.next(packet) && m_Socket && !m_Socket->IsClosed ()) { /*#if 1 sLog.outError( "MOEP: %s (0x%.4X)", LookupOpcodeName(packet->GetOpcode()), packet->GetOpcode()); #endif*/ OpcodeHandler& opHandle = opcodeTable[packet->GetOpcode()]; try { switch (opHandle.status) { case STATUS_LOGGEDIN: if(!_player) { // skip STATUS_LOGGEDIN opcode unexpected errors if player logout sometime ago - this can be network lag delayed packets if(!m_playerRecentlyLogout) LogUnexpectedOpcode(packet, "the player has not logged in yet"); } else if(_player->IsInWorld()) { (this->*opHandle.handler)(*packet); if (sLog.IsOutDebug() && packet->rpos() < packet->wpos()) LogUnprocessedTail(packet); } // lag can cause STATUS_LOGGEDIN opcodes to arrive after the player started a transfer // playerbot mod if (_player && _player->GetPlayerbotMgr()) _player->GetPlayerbotMgr()->HandleMasterIncomingPacket(*packet); // playerbot mod end break; case STATUS_LOGGEDIN_OR_RECENTLY_LOGGEDOUT: if(!_player && !m_playerRecentlyLogout) { 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 (sLog.IsOutDebug() && packet->rpos() < packet->wpos()) LogUnprocessedTail(packet); } break; case STATUS_TRANSFER: if(!_player) LogUnexpectedOpcode(packet, "the player has not logged in yet"); else if(_player->IsInWorld()) LogUnexpectedOpcode(packet, "the player is still in world"); else { (this->*opHandle.handler)(*packet); if (sLog.IsOutDebug() && packet->rpos() < packet->wpos()) LogUnprocessedTail(packet); } break; case STATUS_AUTHED: // prevent cheating with skip queue wait if(m_inQueue) { LogUnexpectedOpcode(packet, "the player not pass queue yet"); break; } // single from authed time opcodes send in to after logout time // and before other STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT opcodes. if (packet->GetOpcode() != CMSG_SET_ACTIVE_VOICE_CHANNEL) m_playerRecentlyLogout = false; (this->*opHandle.handler)(*packet); if (sLog.IsOutDebug() && packet->rpos() < packet->wpos()) LogUnprocessedTail(packet); break; case STATUS_NEVER: sLog.outError( "SESSION: received not allowed opcode %s (0x%.4X)", LookupOpcodeName(packet->GetOpcode()), packet->GetOpcode()); break; case STATUS_UNHANDLED: sLog.outDebug("SESSION: received not handled opcode %s (0x%.4X)", LookupOpcodeName(packet->GetOpcode()), packet->GetOpcode()); break; default: sLog.outError("SESSION: received wrong-status-req opcode %s (0x%.4X)", LookupOpcodeName(packet->GetOpcode()), packet->GetOpcode()); break; } } 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()); if(sLog.IsOutDebug()) { sLog.outDebug("Dumping error causing packet:"); packet->hexlike(); } } delete packet; } // Playerbot mod - Process player bot packets // The PlayerbotAI class adds to the packet queue to simulate a real player // since Playerbots are known to the World obj only by its master's WorldSession object // we need to process all master's bot's packets. if (GetPlayer() && GetPlayer()->GetPlayerbotMgr()) { for (PlayerBotMap::const_iterator itr = GetPlayer()->GetPlayerbotMgr()->GetPlayerBotsBegin(); itr != GetPlayer()->GetPlayerbotMgr()->GetPlayerBotsEnd(); ++itr) { Player* const botPlayer = itr->second; WorldSession* const pBotWorldSession = botPlayer->GetSession(); if (botPlayer->IsBeingTeleported()) botPlayer->GetPlayerbotAI()->HandleTeleportAck(); else if (botPlayer->IsInWorld()) { WorldPacket* packet; while (pBotWorldSession->_recvQueue.next(packet)) { OpcodeHandler& opHandle = opcodeTable[packet->GetOpcode()]; (pBotWorldSession->*opHandle.handler)(*packet); delete packet; } } } } ///- Cleanup socket pointer if need if (m_Socket && m_Socket->IsClosed ()) { m_Socket->RemoveReference (); m_Socket = NULL; } ///- If necessary, log the player out time_t currTime = time(NULL); if (!m_Socket || (ShouldLogOut(currTime) && !m_playerLoading)) LogoutPlayer(true); if (!m_Socket) return false; //Will remove this session from the world session map return true; }
// Update the WorldSession (triggered by World update) bool WorldSession::Update(uint32 diff) { /// Update Timeout timer. UpdateTimeOutTime(diff); ///- Before we process anything: /// If necessary, kick the player from the character select screen if (IsConnectionIdle()) m_Socket->CloseSocket(); // Retrieve packets from the receive queue and call the appropriate handlers // not process packets if socket already closed WorldPacket* packet; while (m_Socket && !m_Socket->IsClosed() && _recvQueue.next(packet)) { /*#if 1 sLog.outError("MOEP: %s (0x%.4X)", LookupOpcodeName(packet->GetOpcode()), packet->GetOpcode()); #endif*/ if (packet->GetOpcode() >= NUM_MSG_TYPES) { sLog.outDebug("SESSION: received invalid opcode %s (0x%.4X)", LookupOpcodeName(packet->GetOpcode()), packet->GetOpcode()); } else { OpcodeHandler& opHandle = opcodeTable[packet->GetOpcode()]; try { switch (opHandle.status) { case STATUS_LOGGEDIN: if (!_player) { // skip STATUS_LOGGEDIN opcode unexpected errors if player logout sometime ago - this can be network lag delayed packets if (!m_playerRecentlyLogout) LogUnexpectedOpcode(packet, "the player has not logged in yet"); } else if (_player->IsInWorld()) ExecuteOpcode(opHandle, packet); // lag can cause STATUS_LOGGEDIN opcodes to arrive after the player started a transfer break; case STATUS_TRANSFER_PENDING: if (!_player) LogUnexpectedOpcode(packet, "the player has not logged in yet"); else if (_player->IsInWorld()) LogUnexpectedOpcode(packet, "the player is still in world"); else ExecuteOpcode(opHandle, packet); break; case STATUS_AUTHED: // prevent cheating with skip queue wait if (m_inQueue) { LogUnexpectedOpcode(packet, "the player not pass queue yet"); break; } m_playerRecentlyLogout = false; ExecuteOpcode(opHandle, packet); break; case STATUS_NEVER: sLog.outDebug("SESSION: received not allowed opcode %s (0x%.4X)", LookupOpcodeName(packet->GetOpcode()), packet->GetOpcode()); break; } } catch(ByteBufferException &) { sLog.outDebug("WorldSession::Update ByteBufferException occured while parsing a packet (opcode: %u) from client %s, accountid=%i. Skipped packet.", packet->GetOpcode(), GetRemoteAddress().c_str(), GetAccountId()); if (sLog.IsOutDebug()) { sLog.outDebug("Dumping error causing packet:"); packet->hexlike(); } } } delete packet; } ///- If necessary, log the player out time_t currTime = time(NULL); if (ShouldLogOut(currTime) && !m_playerLoading) LogoutPlayer(true); // Cleanup socket pointer if need if (m_Socket && m_Socket->IsClosed()) { m_Socket->RemoveReference(); m_Socket = NULL; } if (!m_Socket) return false; //Will remove this session from the world session map return true; }
/// Update the WorldSession (triggered by World update) bool WorldSession::Update(uint32 diff, PacketFilter& updater) { /// Update Timeout timer. UpdateTimeOutTime(diff); ///- Before we process anything: /// If necessary, kick the player from the character select screen if (IsConnectionIdle()) m_Socket->CloseSocket(); ///- 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; //! To prevent infinite loop WorldPacket* firstDelayedPacket = NULL; //! If _recvQueue.peek() == firstDelayedPacket it means that in this Update call, we've processed all //! *properly timed* packets, and we're now at the part of the queue where we find //! delayed packets that were re-enqueued due to improper timing. To prevent an infinite //! loop caused by re-enqueueing the same packets over and over again, we stop updating this session //! and continue updating others. The re-enqueued packets will be handled in the next Update call for this session. while (m_Socket && !m_Socket->IsClosed() && !_recvQueue.empty() && _recvQueue.peek(true) != firstDelayedPacket && _recvQueue.next(packet, updater)) { OpcodeHandler const* opHandle = opcodeTable[packet->GetOpcode()]; try { switch (opHandle->Status) { case STATUS_LOGGEDIN: 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) { //! Prevent infinite loop if (!firstDelayedPacket) firstDelayedPacket = packet; //! Because checking a bool is faster than reallocating memory deletePacket = false; QueuePacket(packet); //! Log sLog->outDebug(LOG_FILTER_NETWORKIO, "Re-enqueueing packet with opcode %s with with status STATUS_LOGGEDIN. " "Player is currently not in world yet.", GetOpcodeNameForLogging(packet->GetOpcode()).c_str()); } } else if (_player->IsInWorld()) { sScriptMgr->OnPacketReceive(m_Socket, WorldPacket(*packet)); (this->*opHandle->Handler)(*packet); if (sLog->ShouldLog(LOG_FILTER_NETWORKIO, LOG_LEVEL_TRACE) && packet->rpos() < packet->wpos()) LogUnprocessedTail(packet); } // lag can cause STATUS_LOGGEDIN opcodes to arrive after the player started a transfer break; case STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT: if (!_player && !m_playerRecentlyLogout && !m_playerLogout) // There's a short delay between _player = null and m_playerRecentlyLogout = true during logout LogUnexpectedOpcode(packet, "STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT", "the player has not logged in yet and not recently logout"); else { // not expected _player or must checked in packet hanlder sScriptMgr->OnPacketReceive(m_Socket, WorldPacket(*packet)); (this->*opHandle->Handler)(*packet); if (sLog->ShouldLog(LOG_FILTER_NETWORKIO, LOG_LEVEL_TRACE) && packet->rpos() < packet->wpos()) LogUnprocessedTail(packet); } break; case STATUS_TRANSFER: if (!_player) LogUnexpectedOpcode(packet, "STATUS_TRANSFER", "the player has not logged in yet"); else if (_player->IsInWorld()) LogUnexpectedOpcode(packet, "STATUS_TRANSFER", "the player is still in world"); else { sScriptMgr->OnPacketReceive(m_Socket, WorldPacket(*packet)); (this->*opHandle->Handler)(*packet); if (sLog->ShouldLog(LOG_FILTER_NETWORKIO, LOG_LEVEL_TRACE) && packet->rpos() < packet->wpos()) LogUnprocessedTail(packet); } break; case STATUS_AUTHED: // prevent cheating with skip queue wait if (m_inQueue) { LogUnexpectedOpcode(packet, "STATUS_AUTHED", "the player not pass queue yet"); break; } // some auth opcodes can be recieved before STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT opcodes // however when we recieve CMSG_CHAR_ENUM we are surely no longer during the logout process. if (packet->GetOpcode() == CMSG_CHAR_ENUM) m_playerRecentlyLogout = false; sScriptMgr->OnPacketReceive(m_Socket, WorldPacket(*packet)); (this->*opHandle->Handler)(*packet); if (sLog->ShouldLog(LOG_FILTER_NETWORKIO, LOG_LEVEL_TRACE) && packet->rpos() < packet->wpos()) LogUnprocessedTail(packet); break; case STATUS_NEVER: sLog->outError(LOG_FILTER_OPCODES, "Received not allowed opcode %s from %s", GetOpcodeNameForLogging(packet->GetOpcode()).c_str() , GetPlayerName(false).c_str()); break; case STATUS_UNHANDLED: sLog->outError(LOG_FILTER_OPCODES, "Received not handled opcode %s from %s", GetOpcodeNameForLogging(packet->GetOpcode()).c_str() , GetPlayerName(false).c_str()); break; } } catch(ByteBufferException &) { sLog->outError(LOG_FILTER_NETWORKIO, "WorldSession::Update ByteBufferException occured while parsing a packet (opcode: %u) from client %s, accountid=%i. Skipped packet.", packet->GetOpcode(), GetRemoteAddress().c_str(), GetAccountId()); packet->hexlike(); } if (deletePacket) delete packet; } if (m_Socket && !m_Socket->IsClosed() && _warden) _warden->Update(); ProcessQueryCallbacks(); //check if we are safe to proceed with logout //logout procedure should happen only in World::UpdateSessions() method!!! if (updater.ProcessLogout()) { time_t currTime = time(NULL); ///- If necessary, log the player out if (ShouldLogOut(currTime) && !m_playerLoading) LogoutPlayer(true); if (m_Socket && GetPlayer() && _warden) _warden->Update(); ///- Cleanup socket pointer if need if (m_Socket && m_Socket->IsClosed()) { m_Socket->RemoveReference(); m_Socket = NULL; } if (!m_Socket) return false; //Will remove this session from the world session map } return true; }
/// Update the WorldSession (triggered by World update) bool WorldSession::Update(PacketFilter& updater) { ///- Retrieve packets from the receive queue and call the appropriate handlers /// not process packets if socket already closed WorldPacket* packet = NULL; while (m_Socket && !m_Socket->IsClosed() && _recvQueue.next(packet, updater)) { /*#if 1 sLog.outError( "MOEP: %s (0x%.4X)", packet->GetOpcodeName(), packet->GetOpcode()); #endif*/ OpcodeHandler const& opHandle = opcodeTable[packet->GetOpcode()]; try { switch (opHandle.status) { case STATUS_LOGGEDIN: if (!_player) { // skip STATUS_LOGGEDIN opcode unexpected errors if player logout sometime ago - this can be network lag delayed packets if (!m_playerRecentlyLogout) LogUnexpectedOpcode(packet, "the player has not logged in yet"); } else if (_player->IsInWorld()) ExecuteOpcode(opHandle, packet); // lag can cause STATUS_LOGGEDIN opcodes to arrive after the player started a transfer break; case STATUS_LOGGEDIN_OR_RECENTLY_LOGGEDOUT: if (!_player && !m_playerRecentlyLogout) { LogUnexpectedOpcode(packet, "the player has not logged in yet and not recently logout"); } else // not expected _player or must checked in packet hanlder ExecuteOpcode(opHandle, packet); break; case STATUS_TRANSFER: if (!_player) LogUnexpectedOpcode(packet, "the player has not logged in yet"); else if (_player->IsInWorld()) LogUnexpectedOpcode(packet, "the player is still in world"); else ExecuteOpcode(opHandle, packet); break; case STATUS_AUTHED: // prevent cheating with skip queue wait if (m_inQueue) { LogUnexpectedOpcode(packet, "the player not pass queue yet"); break; } // single from authed time opcodes send in to after logout time // and before other STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT opcodes. if (packet->GetOpcode() != CMSG_SET_ACTIVE_VOICE_CHANNEL) m_playerRecentlyLogout = false; ExecuteOpcode(opHandle, packet); break; case STATUS_NEVER: sLog.outError("SESSION: received not allowed opcode %s (0x%.4X)", packet->GetOpcodeName(), packet->GetOpcode()); break; case STATUS_UNHANDLED: DEBUG_LOG("SESSION: received not handled opcode %s (0x%.4X)", packet->GetOpcodeName(), packet->GetOpcode()); break; default: sLog.outError("SESSION: received wrong-status-req opcode %s (0x%.4X)", packet->GetOpcodeName(), packet->GetOpcode()); break; } } catch (ByteBufferException&) { sLog.outError("WorldSession::Update ByteBufferException occured while parsing a packet (opcode: %u) from client %s, accountid=%i.", packet->GetOpcode(), GetRemoteAddress().c_str(), GetAccountId()); if (sLog.HasLogLevelOrHigher(LOG_LVL_DEBUG)) { DEBUG_LOG("Dumping error causing packet:"); packet->hexlike(); } if (sWorld.getConfig(CONFIG_BOOL_KICK_PLAYER_ON_BAD_PACKET)) { DETAIL_LOG("Disconnecting session [account id %u / address %s] for badly formatted packet.", GetAccountId(), GetRemoteAddress().c_str()); KickPlayer(); } } delete packet; } ///- Cleanup socket pointer if need if (m_Socket && m_Socket->IsClosed()) { m_Socket->RemoveReference(); m_Socket = NULL; } // check if we are safe to proceed with logout // logout procedure should happen only in World::UpdateSessions() method!!! if (updater.ProcessLogout()) { ///- If necessary, log the player out time_t currTime = time(NULL); if (!m_Socket || (ShouldLogOut(currTime) && !m_playerLoading)) LogoutPlayer(true); if (!m_Socket) return false; // Will remove this session from the world session map } return true; }
void WorldSession::HandleLogoutRequestOpcode(WorldPacket& /*recv_data*/) { DEBUG_LOG("WORLD: Received opcode CMSG_LOGOUT_REQUEST, security %u", GetSecurity()); if (ObjectGuid lootGuid = GetPlayer()->GetLootGuid()) { DoLootRelease(lootGuid); } uint8 reason = 0; if (GetPlayer()->IsInCombat()) { reason = 1; } else if (GetPlayer()->m_movementInfo.HasMovementFlag(MovementFlags(MOVEFLAG_FALLING | MOVEFLAG_FALLING_FAR))) { reason = 3; // is jumping or falling } else if (GetPlayer()->duel || GetPlayer()->HasAura(9454)) // is dueling or frozen by GM via freeze command { reason = 2; // FIXME - Need the correct value } if (reason) { WorldPacket data(SMSG_LOGOUT_RESPONSE, 1+4); data << uint8(reason); data << uint32(0); SendPacket(&data); LogoutRequest(0); return; } // instant logout in taverns/cities or on taxi or for admins, gm's, mod's if its enabled in mangosd.conf if (GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING) || GetPlayer()->IsTaxiFlying() || GetSecurity() >= (AccountTypes)sWorld.getConfig(CONFIG_UINT32_INSTANT_LOGOUT)) { WorldPacket data(SMSG_LOGOUT_RESPONSE, 1+4); data << uint8(0); data << uint32(16777216); SendPacket(&data); LogoutPlayer(true); return; } // not set flags if player can't free move to prevent lost state at logout cancel if (GetPlayer()->CanFreeMove()) { float height = GetPlayer()->GetMap()->GetHeight(GetPlayer()->GetPositionX(), GetPlayer()->GetPositionY(), GetPlayer()->GetPositionZ()); if ((GetPlayer()->GetPositionZ() < height + 0.1f) && !(GetPlayer()->IsInWater())) { GetPlayer()->SetStandState(UNIT_STAND_STATE_SIT); } GetPlayer()->SetRoot(true); GetPlayer()->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); } WorldPacket data(SMSG_LOGOUT_RESPONSE, 1 + 4); data << uint8(0); data << uint32(0); SendPacket(&data); LogoutRequest(time(NULL)); }
void WorldSession::HandleMoveWorldportAckOpcode() { // get the teleport destination WorldLocation &loc = GetPlayer()->GetTeleportDest(); // possible errors in the coordinate validity check if(!MapManager::IsValidMapCoord(loc.mapid,loc.x,loc.y,loc.z,loc.o)) { LogoutPlayer(false); return; } // get the destination map entry, not the current one, this will fix homebind and reset greeting MapEntry const* mEntry = sMapStore.LookupEntry(loc.mapid); InstanceTemplate const* mInstance = objmgr.GetInstanceTemplate(loc.mapid); // reset instance validity, except if going to an instance inside an instance if(GetPlayer()->m_InstanceValid == false && !mInstance) GetPlayer()->m_InstanceValid = true; GetPlayer()->SetSemaphoreTeleport(false); // relocate the player to the teleport destination GetPlayer()->SetMapId(loc.mapid); GetPlayer()->Relocate(loc.x, loc.y, loc.z, loc.o); // since the MapId is set before the GetInstance call, the InstanceId must be set to 0 // to let GetInstance() determine the proper InstanceId based on the player's binds GetPlayer()->SetInstanceId(0); // check this before Map::Add(player), because that will create the instance save! bool reset_notify = (GetPlayer()->GetBoundInstance(GetPlayer()->GetMapId(), GetPlayer()->GetDifficulty()) == NULL); GetPlayer()->SendInitialPacketsBeforeAddToMap(); // the CanEnter checks are done in TeleporTo but conditions may change // while the player is in transit, for example the map may get full if(!GetPlayer()->GetMap()->Add(GetPlayer())) { sLog.outDebug("WORLD: teleport of player %s (%d) to location %d,%f,%f,%f,%f failed", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow(), loc.mapid, loc.x, loc.y, loc.z, loc.o); // teleport the player home GetPlayer()->SetDontMove(false); if(!GetPlayer()->TeleportTo(GetPlayer()->m_homebindMapId, GetPlayer()->m_homebindX, GetPlayer()->m_homebindY, GetPlayer()->m_homebindZ, GetPlayer()->GetOrientation())) { // the player must always be able to teleport home sLog.outError("WORLD: failed to teleport player %s (%d) to homebind location %d,%f,%f,%f,%f!", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow(), GetPlayer()->m_homebindMapId, GetPlayer()->m_homebindX, GetPlayer()->m_homebindY, GetPlayer()->m_homebindZ, GetPlayer()->GetOrientation()); assert(false); } return; } GetPlayer()->SendInitialPacketsAfterAddToMap(); // flight fast teleport case if(GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType()==FLIGHT_MOTION_TYPE) { if(!_player->InBattleGround()) { // short preparations to continue flight GetPlayer()->SetDontMove(false); FlightPathMovementGenerator* flight = (FlightPathMovementGenerator*)(GetPlayer()->GetMotionMaster()->top()); flight->Initialize(*GetPlayer()); return; } // battleground state prepare, stop flight GetPlayer()->GetMotionMaster()->MovementExpired(); GetPlayer()->m_taxi.ClearTaxiDestinations(); } // resurrect character at enter into instance where his corpse exist after add to map Corpse *corpse = GetPlayer()->GetCorpse(); if (corpse && corpse->GetType() != CORPSE_BONES && corpse->GetMapId() == GetPlayer()->GetMapId()) { if( mEntry->IsDungeon() ) { GetPlayer()->ResurrectPlayer(0.5f); GetPlayer()->SpawnCorpseBones(); GetPlayer()->SaveToDB(); } } if(mEntry->IsRaid() && mInstance) { if(reset_notify) { uint32 timeleft = sInstanceSaveManager.GetResetTimeFor(GetPlayer()->GetMapId()) - time(NULL); GetPlayer()->SendInstanceResetWarning(GetPlayer()->GetMapId(), timeleft); // greeting at the entrance of the resort raid instance } } // mount allow check if(!mEntry->IsMountAllowed()) _player->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); // battleground state prepare if(_player->InBattleGround()) { BattleGround *bg = _player->GetBattleGround(); if(bg) { if(bg->GetMapId() == _player->GetMapId()) // we teleported to bg { if(!bg->GetBgRaid(_player->GetTeam())) // first player joined { Group *group = new Group; bg->SetBgRaid(_player->GetTeam(), group); group->Create(_player->GetGUIDLow(), _player->GetName()); } else // raid already exist { bg->GetBgRaid(_player->GetTeam())->AddMember(_player->GetGUID(), _player->GetName()); } } } } // honorless target if(GetPlayer()->pvpInfo.inHostileArea) GetPlayer()->CastSpell(GetPlayer(), 2479, true); // resummon pet if(GetPlayer()->m_temporaryUnsummonedPetNumber) { Pet* NewPet = new Pet; if(!NewPet->LoadPetFromDB(GetPlayer(), 0, GetPlayer()->m_temporaryUnsummonedPetNumber, true)) delete NewPet; GetPlayer()->m_temporaryUnsummonedPetNumber = 0; } GetPlayer()->SetDontMove(false); }