玩家游戏状态变化
enum GameState//玩家游戏状态
{
eGameState_OnlyConnect = 0, ///< 仅连接
eGameState_Login = 1, ///< 登录
eGameState_EnterMap = 2, ///< 进入地图
eGameState_Disconnect = 3, ///< 下线
};
1.当libevent收到连接事件的时候
GameChannel::GameChannel()
{
//...
m_eGameState = eGameState_OnlyConnect;//客户端仅仅连接
//...
}
2.客户端点击登录,然后数据库根据名字去查询userinfo,返回密码跟用户匹配,如果相同
void GameChannel::ProcessGetUserInfo(const ShuiHu::UserInfo& User)
{
if(0 == strncmp(User.m_szUserPwd, m_pUserInfo->m_szUserPwd, MAX_NAME_LEN))
{
m_eGameState = eGameState_Login;//玩家状态为登录状态
}
}
3.等用户登录成功之后服务器会想客户端发送角色表
用户选择角色点击开始,GS收到消息之后根据id从数据库查询角色的详细信息
void GameChannel::ProcessGetActorInfoEx(bool bRet, const ShuiHu::ActorInfoEx& crActorEx)
{
//...
//给客户端发送本地玩家信息
LocPlayerInfo info;
InitLocalPlayer(rActorEx, info);
SendCmd(s2c_local_player_info, &info, sizeof(info));
m_pShare->m_spLog->Logs(eLogLevel_Info, "s2c_local_player_info");
//放入ShareCenter中
m_strActorName = rActorEx.GetName();
m_pShare->AddOnLinePlayer(m_ActorId, m_strActorName, m_nChannelId);
// 标记已进入地图
//看来这个是在向客户端发送本地玩家信息,就直接标记成进入地图状态,个人觉得不对
//因为此时还没有进入地图,进入地图是在客户端发送激活包之后才算真正进入地图
m_eGameState = eGameState_EnterMap;
//序列化ActorInfoEx准备传入MS
rActorEx.m_nChannelId = m_nChannelId;
//...
}
4.libevent收到客户端连接断开事件
//...
void GameChannel::OnOffLine()
{
//未登录或者已离线
if(m_eGameState == eGameState_OnlyConnect || m_eGameState == eGameState_Disconnect)//此处为什么没有登录状态的判断
return;
//玩家断开时才真正删除角色
for(std::map<int, ShuiHu::ActorInfo>::iterator it = m_mapDelActors.begin(); it != m_mapDelActors.end(); ++it)
{
int actID = it->first;
m_pAsynDBC->DelActor(actID, m_UserId);
//帮会操作通知删除角色
m_pShare->m_spGuildOpt->OnActorDelete(actID, safe::mbstowcs(it->second.m_szGuildName));
}
//删除在线用户
m_pShare->DelOnLineUser(m_UserId);
if(m_eGameState != eGameState_EnterMap) //未登录游戏
return;
//通知Map玩家下线
m_pMap->Gs2MsData(gs2ms_del_player, m_nChannelId, NULL, 0);
m_eGameState = eGameState_Disconnect;//此时标记玩家下线状态,此时map玩家下线消息已经发送,GS这边还有很多需要处理
}