/** * 改变一个玩家的游戏房间 * * @param pPlayer 要改变游戏房间的玩家 */ bool RoomManager::ChangeGameRoom(Player *pPlayer) { if(pPlayer == NULL || m_RoomList.empty()) return false; // 首先检测玩家当前的状态,如果玩家处于准备,等待,游戏中,掉线等状态时说明玩家已经在房间中,不能进入新的房间 if(pPlayer->GetState() != PLAYERSTATE_NORAML) return false; // 得到原来玩家所在的房间 Room *pSrcRoom = GetRoomById(pPlayer->GetRoomId()); if(pSrcRoom == NULL || pSrcRoom->GetRoomState() != ROOMSTATE_WAITING) return false; // 向房间中其它用户发送用户离开消息 CMolMessageOut out(IDD_MESSAGE_FRAME); out.writeShort(IDD_MESSAGE_LEAVE_ROOM); out.writeShort(pPlayer->GetID()); ServerPlayerManager.SendMsgToEveryone(out); // 先处理用户在原来房间中离开消息 pSrcRoom->OnProcessLeaveRoomMsg(pPlayer->GetRoomIndex()); // 第一遍搜索当前房间中已经存在玩家在那里等待的房间 bool state = false; m_RoomLock.Acquire(); std::list<Room*>::iterator iter = m_RoomList.begin(); for(;iter != m_RoomList.end();iter++) { if((*iter)) { //(*iter)->UpdateAllPlayers(); // 如果玩家不能满足房间要求的最少金币值,就不能进入房间 if((*iter)->GetLastMoney() > pPlayer->GetMoney()) continue; if(!(*iter)->IsFull() && (*iter)->GetPlayerCount() > 0 && (*iter)->GetRoomState() != ROOMSTATE_GAMING) { // 找一个与原来不一样的房间 if(pSrcRoom->GetID() != (*iter)->GetID()) { //PlayerState oldstate = pPlayer->GetState(); // 设置玩家状态为改变房间状态,这样可以防止服务器将玩家强行掉线 //pPlayer->SetState(PLAYERSTATE_CHANGEROOM); // 先从原来的房间中删除这个玩家 pSrcRoom->ClearPlayer(pPlayer); // 更新一下房间中的用户 (*iter)->UpdateOnlinePlayers(); pPlayer->SetRoomId((*iter)->GetID()); //pPlayer->SetState(oldstate); int playerIndex = (*iter)->AddPlayer(pPlayer); pPlayer->SetRoomIndex(playerIndex); state = true; break; } } } } m_RoomLock.Release(); if(state) return state; // 第二遍搜索当前房间中没有坐满的房间或者空房间 state = false; m_RoomLock.Acquire(); iter = m_RoomList.begin(); for(;iter != m_RoomList.end();iter++) { if((*iter)) { //(*iter)->UpdateAllPlayers(); // 如果玩家不能满足房间要求的最少金币值,就不能进入房间 if((*iter)->GetLastMoney() > pPlayer->GetMoney()) continue; if(!(*iter)->IsFull() && (*iter)->GetRoomState() != ROOMSTATE_GAMING) { // 找一个与原来不一样的房间 if(pSrcRoom->GetID() != (*iter)->GetID()) { //PlayerState oldstate = pPlayer->GetState(); // 设置玩家状态为改变房间状态,这样可以防止服务器将玩家强行掉线 //pPlayer->SetState(PLAYERSTATE_CHANGEROOM); // 先从原来的房间中删除这个玩家 pSrcRoom->ClearPlayer(pPlayer); // 更新一下房间中的用户 (*iter)->UpdateOnlinePlayers(); if(pPlayer == NULL) { state = false; break; } pPlayer->SetRoomId((*iter)->GetID()); //pPlayer->SetState(oldstate); int playerIndex = (*iter)->AddPlayer(pPlayer); pPlayer->SetRoomIndex(playerIndex); state = true; break; } } } } m_RoomLock.Release(); return state; }
/** * 用于处理用于断开网络连接消息 * * @param connId 要断开网络连接的客户端连接ID */ void RoomManager::OnProcessDisconnectNetMes(int connId) { // 首先根据用户连接ID得到用户,然后根据用户信息得到房间信息,最后交给房间处理 Player *pPlayer = ServerPlayerManager.GetPlayer(connId); if(pPlayer == NULL) return; Room *pRoom = GetRoomById(pPlayer->GetRoomId()); if(pRoom == NULL) { // 如果用户没有进入任何房间的话,删除这个玩家 CMolMessageOut out(IDD_MESSAGE_FRAME); out.writeShort(IDD_MESSAGE_LEAVE_SERVER); out.writeShort(pPlayer->GetID()); ServerPlayerManager.SendMsgToEveryone(out); Disconnect(pPlayer->GetConnectID()); ServerPlayerManager.ClearPlayer(pPlayer); return; } //m_RoomLock.Acquire(); //int playerId = pRoom->GetPlayerIndex(pPlayer->GetConnectID()); if(pPlayer->GetState() == PLAYERSTATE_GAMING) { pPlayer->SetState(PLAYERSTATE_LOSTLINE); // 向房间所有玩家广播玩家离开房间消息 CMolMessageOut out(IDD_MESSAGE_FRAME); out.writeShort(IDD_MESSAGE_FALLLINE_ROOM); out.writeLong(pPlayer->GetID()); ServerPlayerManager.SendMsgToEveryone(out); } else { // 向房间所有玩家广播玩家离开服务器消息 CMolMessageOut out(IDD_MESSAGE_FRAME); out.writeShort(IDD_MESSAGE_LEAVE_SERVER); out.writeLong(pPlayer->GetID()); ServerPlayerManager.SendMsgToEveryone(out); pRoom->ClearPlayer(pPlayer); Disconnect(pPlayer->GetConnectID()); ServerPlayerManager.ClearPlayer(pPlayer); return; } pRoom->OnProcessDisconnectNetMes(pPlayer->GetRoomIndex()); // 如果当前处于游戏中状态下的话,用户就不用退出房间,否则退出房间 // if(pRoom->GetRoomState() == ROOMSTATE_GAMING) //pPlayer->SetState(PLAYERSTATE_LOSTLINE); if(pPlayer->GetState() != PLAYERSTATE_LOSTLINE) pRoom->ClearPlayer(pPlayer); // 如果房间中的用户全部掉线,就清空房间状态 if(pRoom->GetPlayerCount(PLAYERSTATE_LOSTLINE) == pRoom->GetMaxPlayer()/* || pRoom->GetLostPlayerCount() >= pRoom->GetMaxPlayer()-1*/) { pRoom->GameEnd(); pRoom->AllPlayerLeveaServer(); } //m_RoomLock.Release(); }