小退 void GameChannel::OnLogOut() { if(m_eGameState != eGameState_EnterMap)//小退玩家肯定是进入地图状态 return; ClearMapRcd();//清除地图相关记录,实现就是给相应地图 m_eGameState = eGameState_Login;//我在想这里设置成登录状态,不怕登下GS返回的时候不是登录状态 } { //... else if (gs2ms_del_player == pkt.cmd) //玩家下线 { OffLine(pkt.channelId); } //... } /** *相关删除工作和保存工作 */ void Map::OffLine(int mapChannelId) { PlayerChannel* pPlayerChannel = m_vecPlayerChannel[mapChannelId]; if (!pPlayerChannel) { ShuiHu::GetLogger()->Warning("下线函数%s:nChannelId = %d为空", __FUNCTION__, mapChannelId); return; } // 清除地图相关数据 DelPlayer(mapChannelId); // 下线清除玩家的临时罪恶 m_spSinMgr->ClearTmpSin(pPlayerChannel); // 下线通知ReleationShip m_pRelationOpt->ActorOffline(pPlayerChannel); m_pGuildOpt->ActorOffline(pPlayerChannel); m_pTeamOpt->ActorOffline(pPlayerChannel); // 数据操作 ShuiHu::ActorInfoEx* pInfoEx = pPlayerChannel->m_pActorInfoEx; pInfoEx->SetOnline(false); pInfoEx->m_bGaming = false; if(m_MapType == eMAPTYPE_ACTIVITY) //地宫地图下线传回新手村 { pInfoEx->SetPos(4080, 2720); pInfoEx->SetMapID(1001); } else { pInfoEx->SetPos(pPlayerChannel->tgtPos.x, pPlayerChannel->tgtPos.y); pInfoEx->SetMapID(pPlayerChannel->m_nMapId); } pInfoEx->SetCurHP(pPlayerChannel->stat.cur_hp); pInfoEx->SetCurMP(pPlayerChannel->stat.cur_mp); pInfoEx->SetCurXP(pPlayerChannel->stat.cur_exp); pPlayerChannel->m_PropOpt.SetPropsToActorinfoEx(pPlayerChannel->m_pActorInfoEx);//同步道具信息 pPlayerChannel->m_fnSendInfoEx2Gs();//将玩家的数据信息存入gs中的数据库中,向GS发送ms2gs_db_buff_info消息 ClearMem(mapChannelId);//不知道干啥的 } void SendCmd2Gs(int nCmd, int nChannelId, void* pData, int nLen) { MapPkt Pkt; Pkt.cmd = nCmd; Pkt.channelId = nChannelId; char* pszNewBuffer = new char[nLen]; memcpy(pszNewBuffer, pData, nLen); Pkt.data = pszNewBuffer; Pkt.len = nLen; PushData2GS(Pkt);//将数据放到MS->GS端的无锁队列中 }; 在Share_Recv文件中 void Share::ProcMapSendData() { for(auto itMap : m_mapMap)//遍历所有地图 { MapPkt Pkt; try { for (;;) { if(!itMap.second->RecvData(Pkt))//从相应map无锁队列中取数据 break; if(Pkt.cmd == ms2gs_转client_cmd) { OnTurnToClient(Pkt.channelId, Pkt.data, Pkt.len); } else if(Pkt.cmd == ms2gs_json) { OnJson(Pkt.channelId, Pkt.data, Pkt.len); } else if(ms2gs_db_buff_info == Pkt.cmd) { OnLeaveMap(Pkt.channelId, Pkt.data, Pkt.len); } else if(ms2gs_obj_leave == Pkt.cmd) //玩家切换地图 { OnEnterNewMap(Pkt.channelId, Pkt.data, Pkt.len); } else if(ms2gs_guild_opt == Pkt.cmd) { m_spGuildOpt->OnGuildOpt(Pkt.channelId, Pkt.data, Pkt.len); } else if (ms2gs_prop_mgr == Pkt.cmd) { m_spPropManager->OnPropMgrOpt(Pkt.channelId, Pkt.data, Pkt.len); } else if (ms2ms_cmd == Pkt.cmd) { OnTurnToMap(Pkt.mapId, Pkt.data, Pkt.len); } else if (ms2gs_mall_opt == Pkt.cmd) { m_spMallOpt->OnMallOpt(Pkt.channelId, Pkt.data, Pkt.len); } delete[] Pkt.data; Pkt.data = nullptr; } } catch(...) { char sErrMsg[256] = {0}; sprintf(sErrMsg, "【%s】ShareCenter:接收%d地图的 cmd = %d 指令时时出错!", __FUNCTION__, itMap.first, Pkt.cmd); ShuiHu::GetLogger()->Fatal(sErrMsg); safe::error_msg(sErrMsg); } } } //看看GS这边针对下线的处理 void Share::OnLeaveMap(int nChannelId, void* pData, int nLen) { //玩家一旦离开地图,保存数据到DB GameChannel* pGC = GetGcByChannelId(nChannelId); msg_assert(pGC); pGC->LeaveMap(pData, nLen); int nActorId = pGC->GetActorID(); std::string strActorName = pGC->GetActorName(); DelOnLinePlayer(nActorId, strActorName);//删除在线玩家的相关容器 if(pGC->IsDisconnect()) //玩家打退,直接关闭客户端 { //放入释放队列中,断开 //PushFreeQueue(pGC); AutoFreeGC(pGC);//放到自动释放队列中,等没有数据库返回时在将pGC删除 m_vecChannel[nChannelId] = nullptr; } } void GameChannel::LeaveMap(void* pData, int nLen) { // 数据保存到数据库 SaveData(pData, nLen);//包括修改下线时间,同步等级,帮会名,保存玩家信息,保存角色详细信息 if(m_eGameState == eGameState_Login) SendActorListSyn(); // 小退到登录界面,发送角色列表 }