小退

小退
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();    // 小退到登录界面,发送角色列表
}
原文地址:https://www.cnblogs.com/zzyoucan/p/4159669.html