void WorldSession::HandleChannelAnnouncementsOpcode(WorldPacket& recvPacket) { DEBUG_LOG("WORLD: Received opcode %s (%u, 0x%X)", recvPacket.GetOpcodeName(), recvPacket.GetOpcode(), recvPacket.GetOpcode()); //recvPacket.hexlike(); std::string channelname = recvPacket.ReadString(recvPacket.ReadBits(8)); if(ChannelMgr* cMgr = channelMgr(_player->GetTeam())) if(Channel *chn = cMgr->GetChannel(channelname, _player)) chn->Announce(_player->GetObjectGuid()); }
void WorldSession::HandleChannelDisplayListQueryOpcode(WorldPacket& recvPacket) { DEBUG_LOG("WORLD: Received opcode %s (%u, 0x%X)", recvPacket.GetOpcodeName(), recvPacket.GetOpcode(), recvPacket.GetOpcode()); // recvPacket.hexlike(); std::string channelname; recvPacket >> channelname; if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) if (Channel* chn = cMgr->GetChannel(channelname, _player)) chn->List(_player); }
void WorldSession::HandleSetChannelWatchOpcode(WorldPacket& recvPacket) { DEBUG_LOG("WORLD: Received opcode %s (%u, 0x%X)", recvPacket.GetOpcodeName(), recvPacket.GetOpcode(), recvPacket.GetOpcode()); // recvPacket.hexlike(); std::string channelname; recvPacket >> channelname; /*if(ChannelMgr* cMgr = channelMgr(_player->GetTeam())) if(Channel *chn = cMgr->GetChannel(channelname, _player)) chn->JoinNotify(_player->GetGUID());*/ }
void WorldSession::HandleGMResponseResolveOpcode(WorldPacket& recv_data) { // empty opcode DEBUG_LOG("WORLD: %s", recv_data.GetOpcodeName()); sTicketMgr.Delete(GetPlayer()->GetObjectGuid()); WorldPacket data(SMSG_GMTICKET_RESOLVE_RESPONSE, 1); data << uint8(0); // ask to fill out gm survey = 1 SendPacket(&data); }
void WorldSession::HandleChannelPasswordOpcode(WorldPacket& recvPacket) { DEBUG_LOG("WORLD: Received opcode %s (%u, 0x%X)", recvPacket.GetOpcodeName(), recvPacket.GetOpcode(), recvPacket.GetOpcode()); // recvPacket.hexlike(); std::string channelname, pass; recvPacket >> channelname; recvPacket >> pass; if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) if (Channel* chn = cMgr->GetChannel(channelname, _player)) chn->Password(_player->GetObjectGuid(), pass.c_str()); }
void WorldSession::HandleChannelKickOpcode(WorldPacket& recvPacket) { DEBUG_LOG("WORLD: Received opcode %s (%u, 0x%X)", recvPacket.GetOpcodeName(), recvPacket.GetOpcode(), recvPacket.GetOpcode()); // recvPacket.hexlike(); std::string channelname, otp; recvPacket >> channelname; recvPacket >> otp; if (!normalizePlayerName(otp)) return; if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) if (Channel* chn = cMgr->GetChannel(channelname, _player)) chn->Kick(_player->GetObjectGuid(), otp.c_str()); }
void WorldSession::HandleJoinChannelOpcode(WorldPacket& recvPacket) { DEBUG_LOG("WORLD: Received opcode %s (%u, 0x%X)", recvPacket.GetOpcodeName(), recvPacket.GetOpcode(), recvPacket.GetOpcode()); std::string channelname, pass; recvPacket >> channelname; if (channelname.empty()) return; recvPacket >> pass; if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) if (Channel* chn = cMgr->GetJoinChannel(channelname)) chn->Join(_player, pass.c_str()); }
void WorldSession::HandleChannelPasswordOpcode(WorldPacket& recvPacket) { DEBUG_LOG("WORLD: Received opcode %s (%u, 0x%X)", recvPacket.GetOpcodeName(), recvPacket.GetOpcode(), recvPacket.GetOpcode()); // recvPacket.hexlike(); uint32 nameLen, passLen; std::string channelname, pass; nameLen = recvPacket.ReadBits(8); passLen = recvPacket.ReadBits(7); channelname = recvPacket.ReadString(nameLen); pass = recvPacket.ReadString(passLen); if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) if (Channel* chn = cMgr->GetChannel(channelname, _player)) chn->Password(_player->GetObjectGuid(), pass.c_str()); }
void WorldSession::HandleGetChannelMemberCountOpcode(WorldPacket& recvPacket) { DEBUG_LOG("WORLD: Received opcode %s (%u, 0x%X)", recvPacket.GetOpcodeName(), recvPacket.GetOpcode(), recvPacket.GetOpcode()); // recvPacket.hexlike(); std::string channelname; recvPacket >> channelname; if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) { if (Channel* chn = cMgr->GetChannel(channelname, _player)) { WorldPacket data(SMSG_CHANNEL_MEMBER_COUNT, chn->GetName().size() + 1 + 1 + 4); data << chn->GetName(); data << uint8(chn->GetFlags()); data << uint32(chn->GetNumPlayers()); SendPacket(&data); } } }
void WorldSession::HandleLeaveChannelOpcode(WorldPacket& recvPacket) { DEBUG_LOG("WORLD: Received opcode %s (%u, 0x%X)", recvPacket.GetOpcodeName(), recvPacket.GetOpcode(), recvPacket.GetOpcode()); // recvPacket.hexlike(); uint32 unk; std::string channelname; recvPacket >> unk; // channel id? recvPacket >> channelname; if (channelname.empty()) return; if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) { if (Channel* chn = cMgr->GetChannel(channelname, _player)) chn->Leave(_player->GetObjectGuid(), true); cMgr->LeftChannel(channelname); } }
void WorldSession::HandleChannelSetOwnerOpcode(WorldPacket& recvPacket) { DEBUG_LOG("WORLD: Received opcode %s (%u, 0x%X)", recvPacket.GetOpcodeName(), recvPacket.GetOpcode(), recvPacket.GetOpcode()); // recvPacket.hexlike(); std::string channelname, newp; recvPacket >> channelname; recvPacket >> newp; if (!normalizePlayerName(newp)) { return; } if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) if (Channel* chn = cMgr->GetChannel(channelname, _player)) { chn->SetOwner(_player, newp.c_str()); } }
void WorldSession::HandleJoinChannelOpcode(WorldPacket& recvPacket) { DEBUG_LOG("WORLD: Received opcode %s (%u, 0x%X)", recvPacket.GetOpcodeName(), recvPacket.GetOpcode(), recvPacket.GetOpcode()); uint32 channel_id; uint8 unknown1, unknown2; std::string channelname, pass; recvPacket >> channel_id >> unknown1 >> unknown2; recvPacket >> channelname; if (channelname.empty()) return; recvPacket >> pass; if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) if (Channel* chn = cMgr->GetJoinChannel(channelname, channel_id)) // channel id seems to be useless but must be checked for LFG chn->Join(_player->GetObjectGuid(), pass.c_str()); }
void WorldSession::HandleChannelUnbanOpcode(WorldPacket& recvPacket) { DEBUG_LOG("WORLD: Received opcode %s (%u, 0x%X)", recvPacket.GetOpcodeName(), recvPacket.GetOpcode(), recvPacket.GetOpcode()); // recvPacket.hexlike(); uint32 channelLen, nameLen; std::string channelname, otp; nameLen = recvPacket.ReadBits(7); channelLen = recvPacket.ReadBits(8); otp = recvPacket.ReadString(nameLen); channelname = recvPacket.ReadString(channelLen); if (!normalizePlayerName(otp)) return; if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) if (Channel* chn = cMgr->GetChannel(channelname, _player)) chn->UnBan(_player->GetObjectGuid(), otp.c_str()); }
void WorldSession::HandleJoinChannelOpcode(WorldPacket& recvPacket) { DEBUG_LOG("WORLD: Received opcode %s (%u, 0x%X)", recvPacket.GetOpcodeName(), recvPacket.GetOpcode(), recvPacket.GetOpcode()); uint32 channel_id; std::string channelname, pass; recvPacket >> channel_id; recvPacket.ReadBit(); // has voice recvPacket.ReadBit(); // zone update uint8 channelLength = recvPacket.ReadBits(8); uint8 passwordLength = recvPacket.ReadBits(8); channelname = recvPacket.ReadString(channelLength); pass = recvPacket.ReadString(passwordLength); if (channelname.empty()) return; if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) if (Channel* chn = cMgr->GetJoinChannel(channelname, channel_id)) // channel id seems to be useless but must be checked for LFG chn->Join(_player->GetObjectGuid(), pass.c_str()); }
void WorldSession::HandleForceSpeedChangeAckOpcodes(WorldPacket& recv_data) { uint16 opcode = recv_data.GetOpcode(); DEBUG_LOG("WORLD: Received %s (%u, 0x%X) opcode", recv_data.GetOpcodeName(), opcode, opcode); /* extract packet */ ObjectGuid guid; MovementInfo movementInfo; float newspeed; recv_data >> guid; recv_data >> Unused<uint32>(); // counter or moveEvent recv_data >> movementInfo; recv_data >> newspeed; // now can skip not our packet if (_player->GetObjectGuid() != guid) return; /*----------------*/ // client ACK send one packet for mounted/run case and need skip all except last from its // in other cases anti-cheat check can be fail in false case UnitMoveType move_type; UnitMoveType force_move_type; static char const* move_type_name[MAX_MOVE_TYPE] = { "Walk", "Run", "RunBack", "Swim", "SwimBack", "TurnRate" }; switch (opcode) { case CMSG_FORCE_WALK_SPEED_CHANGE_ACK: move_type = MOVE_WALK; force_move_type = MOVE_WALK; break; case CMSG_FORCE_RUN_SPEED_CHANGE_ACK: move_type = MOVE_RUN; force_move_type = MOVE_RUN; break; case CMSG_FORCE_RUN_BACK_SPEED_CHANGE_ACK: move_type = MOVE_RUN_BACK; force_move_type = MOVE_RUN_BACK; break; case CMSG_FORCE_SWIM_SPEED_CHANGE_ACK: move_type = MOVE_SWIM; force_move_type = MOVE_SWIM; break; case CMSG_FORCE_SWIM_BACK_SPEED_CHANGE_ACK: move_type = MOVE_SWIM_BACK; force_move_type = MOVE_SWIM_BACK; break; case CMSG_FORCE_TURN_RATE_CHANGE_ACK: move_type = MOVE_TURN_RATE; force_move_type = MOVE_TURN_RATE; break; default: sLog.outError("WorldSession::HandleForceSpeedChangeAck: Unknown move type opcode: %u", opcode); return; } // skip all forced speed changes except last and unexpected // in run/mounted case used one ACK and it must be skipped.m_forced_speed_changes[MOVE_RUN} store both. if (_player->m_forced_speed_changes[force_move_type] > 0) { --_player->m_forced_speed_changes[force_move_type]; if (_player->m_forced_speed_changes[force_move_type] > 0) return; } if (!_player->GetTransport() && fabs(_player->GetSpeed(move_type) - newspeed) > 0.01f) { if (_player->GetSpeed(move_type) > newspeed) // must be greater - just correct { sLog.outError("%sSpeedChange player %s is NOT correct (must be %f instead %f), force set to correct value", move_type_name[move_type], _player->GetName(), _player->GetSpeed(move_type), newspeed); _player->SetSpeedRate(move_type, _player->GetSpeedRate(move_type), true); } else // must be lesser - cheating { BASIC_LOG("Player %s from account id %u kicked for incorrect speed (must be %f instead %f)", _player->GetName(), _player->GetSession()->GetAccountId(), _player->GetSpeed(move_type), newspeed); _player->GetSession()->KickPlayer(); } } }
void WorldSession::Handle_Deprecated(WorldPacket& recvPacket) { sLog.outError("SESSION: received deprecated opcode %s (0x%.4X)", recvPacket.GetOpcodeName(), recvPacket.GetOpcode()); }
void WorldSession::Handle_ServerSide(WorldPacket& recvPacket) { sLog.outError("SESSION: received server-side opcode %s (0x%.4X)", recvPacket.GetOpcodeName(), recvPacket.GetOpcode()); }
void WorldSession::Handle_EarlyProccess(WorldPacket& recvPacket) { sLog.outError("SESSION: received opcode %s (0x%.4X) that must be processed in WorldSocket::OnRead", recvPacket.GetOpcodeName(), recvPacket.GetOpcode()); }
void WorldSession::Handle_NULL(WorldPacket& recvPacket) { DEBUG_LOG("SESSION: received unimplemented opcode %s (0x%.4X)", recvPacket.GetOpcodeName(), recvPacket.GetOpcode()); }
/// 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::SizeError(WorldPacket const& packet, uint32 size) const { sLog.outError("Client (account %u) send packet %s (%u) with size " SIZEFMTD " but expected %u (attempt crash server?), skipped", GetAccountId(), packet.GetOpcodeName(), packet.GetOpcode(), packet.size(), size); }
void WorldSession::HandleJoinChannelOpcode(WorldPacket& recvPacket) { DEBUG_LOG("WORLD: Received opcode %s (%u, 0x%X)", recvPacket.GetOpcodeName(), recvPacket.GetOpcode(), recvPacket.GetOpcode()); std::string channelName, pass; recvPacket >> channelName; if (channelName.empty()) { return; } recvPacket >> pass; uint32 channelId = 0; char tmpStr[255]; // Current player area id const uint32 playerZoneId = _player->GetZoneId(); const uint32 stormwindZoneID = 1519; const uint32 ironforgeZoneID = 1537; const uint32 darnassusZoneID = 1657; const uint32 orgrimmarZoneID = 1637; const uint32 thunderbluffZoneID = 1638; const uint32 undercityZoneID = 1497; uint32 cityLookupAreaID = playerZoneId; // Used to lookup for channels which support cross-city-chat // Area id of "Cities" const uint32 citiesZoneID = 3459; // Channel ID of the trade channel since this only applies to it const uint32 tradeChannelID = 2; const uint32 guildRecruitmentChannelID = 25; // Check if we are inside of a city if (playerZoneId == stormwindZoneID || playerZoneId == ironforgeZoneID || playerZoneId == darnassusZoneID || playerZoneId == orgrimmarZoneID || playerZoneId == thunderbluffZoneID || playerZoneId == undercityZoneID) { // Use cities instead of the player id cityLookupAreaID = citiesZoneID; } //TODO: This doesn't seem like the right way to do it, but the client doesn't send any ID of the channel, and it's needed for (uint32 i = 0; i < sChatChannelsStore.GetNumRows(); ++i) { ChatChannelsEntry const* channel = sChatChannelsStore.LookupEntry(i); AreaTableEntry const* area = sAreaStore.LookupEntry( (channel->ChannelID == tradeChannelID || channel->ChannelID == guildRecruitmentChannelID) ? cityLookupAreaID : playerZoneId); if (area && channel) { snprintf(tmpStr, 255, channel->pattern[GetSessionDbcLocale()], area->area_name[GetSessionDbcLocale()]); //With a format string if (strcmp(tmpStr, channelName.c_str()) == 0 //Without one, used for ie: World Defense || strcmp(channel->pattern[0], channelName.c_str()) == 0) { channelId = channel->ChannelID; break; } } } if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) //the channel id needs to be checkd for lfg (explanation?) if (Channel* chn = cMgr->GetJoinChannel(channelName)) chn->Join(_player, pass.c_str()); }
/// Update the WorldSession (triggered by World update) bool WorldSession::Update(PacketFilter& updater) { std::lock_guard<std::mutex> guard(m_recvQueueLock); ///- Retrieve packets from the receive queue and call the appropriate handlers /// not process packets if socket already closed while (m_Socket && !m_Socket->IsClosed() && !m_recvQueue.empty()) { WorldPacket *packet = m_recvQueue.front(); m_recvQueue.pop_front(); /*#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 // 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 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; } // 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()) { std::for_each(pBotWorldSession->m_recvQueue.begin(), pBotWorldSession->m_recvQueue.end(), [&pBotWorldSession](WorldPacket* packet) { OpcodeHandler const& opHandle = opcodeTable[packet->GetOpcode()]; (pBotWorldSession->*opHandle.handler)(*packet); delete packet; }); pBotWorldSession->m_recvQueue.clear(); } } } // 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 const time_t currTime = time(nullptr); if (!m_Socket || m_Socket->IsClosed() || (ShouldLogOut(currTime) && !m_playerLoading)) LogoutPlayer(true); // finalize the session if disconnected. if (!m_Socket || m_Socket->IsClosed()) return false; } return true; }