[传奇技术]LgendM2游戏消息流程
客户端OnIdle 执行QueryDynCode函数 发送加密信息与LoginGate验证 成功后 返回SM_QUERYDYNCODE 消息 客户端解密出key 用于账号加密 输入账号密码后发送CM_IDPASSWORD 至LoginGate并转发给LoginSrv 解析 并返回SM_PASSWD_FAIL(失败) SM_PASSOK_SELECTSERVER(成功) 返回DefMsg := MakeDefaultMsg(SM_PASSOK_SELECTSERVER, nIDCost, id充值时间 LoWord(nIPCost), ip天数 HiWord(nIPCost),ip小时 Config.ServerNameList.Count);服务器数量
客户端解析函数ClientGetPasswordOK 解析并显示服务器列表 点击事件TFrmDlg.DEngServer1Click 执行frmMain.SendSelectServer(svname); 发送 CM_SELECTSERVER =>LoginSrv => SS_OPENSESSION M2与DBS 两者同时添加SESSION 然后失败返回SM_STARTFAIL 成功返回 SM_SELECTSERVER_OK 执行 ClientGetPasswdSuccess 解析出选择网关的ip 与端口 并断开与登录网关的连接 切换场景g_ConnectionStep := cnsSelChr; 当然还有新建账号 找回密码 修改密码的 类似 ///////////////////////////////////////////////////////////////////////////////////////////////////////// 客户端OnIdle 继续执行QueryDynCode函数 发送CM_QUERYSELCHARCODE 给Sel网关 这只是预处理命令
SelChrWaitTimerTimer定时器 SendQueryChr CM_QUERYCHR 转发到DBS 的UsrSoc得到角色 成功返回SM_QUERYCHR ClientGetReceiveChrs客户端处理 失败SM_QUERYCHR_FAIL CM_NEWCHR CM_DELCHR CM_SELCHR 返回 SM_STARTPLAY 并给账号服务器发送 FrmIDSoc.SetGlobaSessionPlay(UserInfo.nSessionID); 客户端ClientGetStartPlay 解析出 7200 并g_ConnectionStep := cnsPlay; 发送sendrunlogin sSendMsg := Format(('**%s/%s/%d/%d/%d/%s'), [LoginID, m_sCharName, Certification, CLIENT_VERSION_NUMBER, RUNLOGINCODE, Dest]); 服务端返回SM_SENDNOTICE 客户端ClientGetSendNotice解析 CM_LOGINNOTICEOK 点击ok后 服务端设置m_boLoginNoticeOK:=true SM_CHECKCLIENT CM_CHECKCLIENT_RES
RUNGATECODE = $AA55AA55 + $00450045; RunGate处理第一登录 HandleLogin m_szAccount := szAccount; szTemp := GetValidStr3(szTemp, szCert, ['/']); szTemp := GetValidStr3(szTemp, szClientVerNO, ['/']); szTemp := GetValidStr3(szTemp, szCode, ['/']); szTemp := GetValidStr3(szTemp, szHarewareID, ['/']);
szTemp := Format('**%s/%s/%s/%s/%s/%s', [szAccount, szCharName, szCert, szClientVerNO, szCode, MD5Print(m_xHWID)]); pszLoginPacket[0] := '#'; pszLoginPacket[1] := '0'; pszLoginPacket[Len + 2] := '!'; m_fHandleLogin := 2; SendFirstPack(StrPas(pszLoginPacket));
最终交给ProcessDelayMsg 发送给m2 m_tLastGameSvr.SendBuffer(DelayMsg.pBuffer, DelayMsg.nBufLen);
m2 接受消息处理 ExecGateMsg GM_DATA:核心处理 首次登陆 DoClientCertification sData := Copy(sData, 3, Length(sData) - 2); sData := GetValidStr3(sData, sAccount, ['/']); sData := GetValidStr3(sData, sChrName, ['/']); sData := GetValidStr3(sData, sCodeStr, ['/']); sData := GetValidStr3(sData, sClientVersion, ['/']); sData := GetValidStr3(sData, sIdx, ['/']); sData := GetValidStr3(sData, sHWID, ['/']); 验证成功后 FrontEngine.AddToLoadRcdList 添加到m_LoadRcdList TFrontEngine.ProcessGameData() 与dbserver交互数据 具体的发包函数在 RunDB单元 SendDBSockMsg 执行发包操作 首次登陆后在线人物执行 ProcessUserMessage 处理来自客户端的 CM_类消息 交由ObjBase单元处理 游戏的逻辑 消息都是加入一个链表中排队处理 不然会导致数据混乱
TUserEngine。ProcessHumans UserOpenInfo人物信息保存到这个结构上
SendSocket(EncodeString(sSendMsg)); 服务端 发送SM_SENDNOTICE 客户端ClientGetSendNotice解析弹出公告 然后玩家发生CM_LOGINNOTICEOK
CM_QUERYDELCHR CM_GETBACKDELCHR//这几个都是主动触发
也就是说 同一账号的会话标识SessionID必须一致 (M2 LoginSrv DBS)
登录步骤 g_ConnectionStep cnsLogin 发送登录请求与LoginGate验证 cnsSelChr 发送角色请求与SelGate验证
|