小退
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(); // 小退到登录界面,发送角色列表
}