/** * @file DealPkg.cpp * @brief 处理包实现文件 * Copyright(c) 2007,上海第九城市游戏研发部 * All rights reserved * 文件名称: DealPkg.cpp * 摘 要: 根据通信参与方以及消息中的命令字处理收到的网络消息 * 作 者: dzj * 完成日期: 2007.12.17 * */ #include "../../../Base/Utility.h" #include "../../../Base/LoadConfig/LoadSrvConfig.h" #include "DealPkg_Map.h" #include "../Player/Player.h" #include "../OtherServer/otherserver.h" #include "../AddictionPlayerList.h" #include "../PseudowireManager.h" #ifdef ACE_WIN32 #pragma warning( push ) #pragma warning( disable: 4819 ) //"type cast" pointer truncation from ??* to ?? #endif //ACE_WIN32 #include "../../../Base/PkgProc/RelationServiceProtocol.h" #ifdef ACE_WIN32 #pragma warning( pop ) #endif //ACE_WIN32 #include "../../../Base/PkgProc/ParserTool.h" #include "../mapteleport/MapTeleporterManager.h" #include "../toolmonitor/toolmonitor.h" #include "../LogManager.h" LoginServiceProtocol CDealNewLoginSrvPkg::m_loginProtocol; ///初始化(注册各命令字对应的处理函数); void CDealNewLoginSrvPkg::Init() { //Register( L_G_REPORT_USER_RESULT, &OnRandomStringReturn );//新登录服务器返回对应玩家帐号的随机字符串; Register( L_G_REPORT_USER_RESULT_WITH_KEY, &OnRandomNewStringReturn );//新登录服务器返回对应玩家帐号的随机字符串; //Register( L_G_CHECK_USER_MD5_RESULT, &OnMd5CheckReturn );//新登录服务器返回对应玩家帐号的md5验证结果; Register( L_G_CHECK_USER_MD5_RESULT_WITH_KEY, &OnMd5NewCheckReturn );//新登录服务器返回对应玩家帐号的md5验证结果; #ifdef ANTI_ADDICTION Register( L_G_USER_GAME_STATE_NOTIFY, &OnGameStateNotify ); //防沉迷 #endif //ANTI_ADDICTION } //对loginsrv密码验证结果的处理,新旧loginsrv共用; bool LoginPasswordCheckProcess( CPlayer* pPlayer, const char* playerAccount, bool isCheckOK, TYPE_ID sequenceID ) { if ( NULL == pPlayer ) { D_ERROR( "LoginPasswordCheckProcess,pOwner空\n" ); return false; } TRY_BEGIN; if ( isCheckOK ) { if ( !pPlayer->SetCurStat( PS_LOGINED ) ) { //登录成功,但置状态失败; D_WARNING( "玩家%s登录成功后置状态失败\n", pPlayer->GetAccount() ); pPlayer->ReqDestorySelf();//断开连接; return false; } //防止dbsrv不区分大小写(大小写不一样的帐号可以登录, //这样原来存的帐号就与PlayerInfo中的帐号不一致, //导致下线时centersrv找不到对应玩家从而在线管理出错之类的问题), //现在这样做,玩家的帐号经过验证之后将被存成与mysql中大小写一致的帐号; pPlayer->SetAccount( playerAccount ); pPlayer->SetGMAccount((0 != sequenceID)?true:false); //登录验证成功,向centersrv发在线唯一性验证; GEPlayerIsExist playerIsExist; playerIsExist.playerID = pPlayer->GetPlayerID(); SafeStrCpy( playerIsExist.szAccount, pPlayer->GetAccount() ); playerIsExist.accountLen = (int)strlen( playerIsExist.szAccount ) + 1; //SafeStrCpy( playerIsExist.szPlayerName, pPlayer->GetRoleName() ); //playerIsExist.nameLen = (int)strlen( playerIsExist.szPlayerName ) + 1; playerIsExist.sequenceID = sequenceID; //要把网络序列转发 CCenterSrv* pCenterSrv = CManCenterSrvs::GetCenterserver(); if ( NULL == pCenterSrv ) { GCSrvError srvError; srvError.errNO = 1001; NewSendPlayerPkg( GCSrvError, pPlayer, srvError ); //MsgToPut* pErrMsg = CreatePlayerPkg( GCSrvError, pPlayer, srvError ); //pPlayer->SendPkgToPlayer( pErrMsg );//通知玩家没有对应的mapsrv; D_WARNING( "玩家登录成功后,找不到CenterSrv,在线唯一性验证失败\n\n" ); return false; } if ( !pPlayer->SetCurStat( PS_CENTER_CHECKING ) ) { D_ERROR( "置玩家%s进入centerCheck状态失败\n", pPlayer->GetAccount() ); return false; } //D_DEBUG( "玩家%s登录验证成功,进行唯一性验证...\n", pPlayer->GetAccount() ); //MsgToPut* pPlayerIsExistQuery = CreateSrvPkg( GEPlayerIsExist, pCenterSrv, playerIsExist ); //pCenterSrv->SendPkgToSrv( pPlayerIsExistQuery );//向centersrv发查询消息; SendMsgToCenterSrv( GEPlayerIsExist, playerIsExist ); } else { //登录失败,通知玩家密码错误; D_DEBUG( "玩家%s登录验证失败,返回错误信息给玩家\n", pPlayer->GetAccount() ); GCPlayerLogin playerLogin; StructMemSet( playerLogin, 0, sizeof(playerLogin) ); playerLogin.byIsLoginOK = GCPlayerLogin::ISLOGINOK_FAILED_PWDWRONG; NewSendPlayerPkg( GCPlayerLogin, pPlayer, playerLogin ); //MsgToPut* pLoginSuc = CreatePlayerPkg( GCPlayerLogin, pPlayer, playerLogin ); //pPlayer->SendPkgToPlayer( pLoginSuc );//通知玩家登录失败; pPlayer->SetCurStat( PS_CONN );//重置玩家状态; pPlayer->ReqDestorySelf();//登录失败断开自身,防止恶意继续占用连接; } return true; TRY_END; return false; } ///新登录服务器返回对应玩家帐号的随机字符串以及密钥用随机字符串 bool CDealNewLoginSrvPkg::OnRandomNewStringReturn( CNewLoginSrv* pOwner, const char* pPkg, const unsigned short wPkgLen ) { TRY_BEGIN; if ( NULL == pOwner ) { D_ERROR( "OnRandomNewStringReturn,pOwner空\n" ); return false; } DealNewLoginPkgPre( LG_ReportUserResultWithKey, pNewRandomStrMsg, pPkg, wPkgLen ); //给玩家返回该随机字符串 CPlayer* pPlayer = CManPlayer::FindPlayer( pNewRandomStrMsg->playerId ); if ( NULL == pPlayer ) { D_WARNING( "OnRandomNewStringReturn,找不到玩家%s,ID:%x\n", pNewRandomStrMsg->userId.userId, pNewRandomStrMsg->playerId ); return false; } D_DEBUG( "收到NewLoginSrv给玩家%s的随机字符串new\n", pPlayer->GetAccount() ); GCRandomString gcRandomString;//组包,返回随机字符串给客户端; StructMemSet( gcRandomString, 0, sizeof(gcRandomString) ); gcRandomString.rdStrSize = pNewRandomStrMsg->randomString.randomStringLen; gcRandomString.rdStrSize2 = pNewRandomStrMsg->randomKey.randomStringLen; gcRandomString.sequenceID = pNewRandomStrMsg->requestSeq; if ( sizeof(gcRandomString.randomString) < gcRandomString.rdStrSize ) { D_WARNING( "OnRandomNewStringReturn,newloginsrv传来的随机字符串超长,玩家ID:%x\n", pNewRandomStrMsg->playerId ); return false; } if ( sizeof(gcRandomString.randomString2) < gcRandomString.rdStrSize2 ) { D_WARNING( "OnRandomNewStringReturn,newloginsrv传来的随机字符串2超长,玩家ID:%x\n", pNewRandomStrMsg->playerId ); return false; } //#ifdef ACE_WIN32 // memcpy_s( &(gcRandomString.randomString), sizeof(gcRandomString.randomString), pNewRandomStrMsg->randomString.randomString, gcRandomString.rdStrSize ); // memcpy_s( &(gcRandomString.randomString2), sizeof(gcRandomString.randomString2), pNewRandomStrMsg->randomKey.randomString, gcRandomString.rdStrSize2 ); //#else //ACE_WIN32 StructMemCpy( (gcRandomString.randomString), pNewRandomStrMsg->randomString.randomString, gcRandomString.rdStrSize ); StructMemCpy( (gcRandomString.randomString2), pNewRandomStrMsg->randomKey.randomString, gcRandomString.rdStrSize2 ); //#endif //ACE_WIN32 NewSendPlayerPkg( GCRandomString, pPlayer, gcRandomString ); return true; TRY_END; return false; } ///新登录服务器返回对应玩家帐号的md5验证结果; bool CDealNewLoginSrvPkg::OnMd5NewCheckReturn( CNewLoginSrv* pOwner, const char* pPkg, const unsigned short wPkgLen ) { TRY_BEGIN; if ( NULL == pOwner ) { D_ERROR( "OnMd5NewCheckReturn,pOwner空\n" ); return false; } DealNewLoginPkgPre( LG_CheckUserMD5dResultWithKey, pNewMd5CheckRstMsg, pPkg, wPkgLen ); //给玩家返回该随机字符串 CPlayer* pPlayer = CManPlayer::FindPlayer( pNewMd5CheckRstMsg->playerId ); if ( NULL == pPlayer ) { D_WARNING( "OnMd5NewCheckReturn,找不到玩家%s,ID:%x\n", pNewMd5CheckRstMsg->userId.userId, pNewMd5CheckRstMsg->playerId ); return false; } D_DEBUG( "收到NewLoginSrv给玩家%s的MD5校验结果new\n", pPlayer->GetAccount() ); bool isloginok = false; if ( L_G_RESULT_SUCCEED != pNewMd5CheckRstMsg->returnCode ) { D_WARNING( "OnMd5NewCheckReturn,NewLoginSrv 返回md5校验失败,错误码:%d\n", pNewMd5CheckRstMsg->returnCode ); } else { isloginok = true; } LoginPasswordCheckProcess( pPlayer, pNewMd5CheckRstMsg->userId.userId, isloginok, pNewMd5CheckRstMsg->requestSeq ); #ifdef USE_CRYPT //D_DEBUG( "设置密钥--" ); //for ( int i=0; ikey.randomStringLen; ++i ) //{ // D_DEBUG( "key%d:%d ", i, pNewMd5CheckRstMsg->key.randomString[i] ); //} //D_DEBUG( "\n" ); if ( !(pPlayer->IsPlayerRobot()) )//非机器人,开始加密通信 { pPlayer->CliSetSendRcvCryptKey( pNewMd5CheckRstMsg->key.randomString, pNewMd5CheckRstMsg->key.randomStringLen );//设置通信密钥; pPlayer->CliStSendCrypt();//开始通信加密; } #endif //USE_CRYPT return true; TRY_END; return false; } #ifdef ANTI_ADDICTION bool CDealNewLoginSrvPkg::OnGameStateNotify( CNewLoginSrv* pOwner, const char* pPkg, const unsigned short wPkgLen ) { TRY_BEGIN; if ( NULL == pOwner ) { D_ERROR( "OnGameStateNotify,pOwner空\n" ); return false; } DealNewLoginPkgPre( LG_UserGameStateNotify, pNewLoginSrvMsg, pPkg, wPkgLen ); CPlayer* pPlayer = CManPlayer::FindPlayer( pNewLoginSrvMsg->playerId ); if ( NULL == pPlayer ) { D_WARNING( "OnGameStateNotify,找不到玩家%s,ID:%x\n", pNewLoginSrvMsg->userId.userId, pNewLoginSrvMsg->playerId ); return false; } //先通知客户端 GCGameStateNotify climsg; climsg.state = pNewLoginSrvMsg->state; climsg.accOnlinePeriod = pNewLoginSrvMsg->accOnlinePeriod; climsg.accOfflinePeriod = pNewLoginSrvMsg->accOfflinePeriod; NewSendPlayerPkg( GCGameStateNotify, pPlayer, climsg ); //MsgToPut* pNewMsg = CreatePlayerPkg( GCGameStateNotify, pPlayer, climsg ); //pPlayer->SendPkgToPlayer( pNewMsg ); D_DEBUG( "收到NewLoginSrv给玩家%s疲劳状态state=%d通知\n", pPlayer->GetAccount(), pNewLoginSrvMsg->state); //根据当前Player的State,策略的向mapsrv发消息,因登陆时mapsrv还没有实例,需要等到进入世界时才能通知mapsrv pPlayer->SetGameState( pNewLoginSrvMsg->state ); if( pPlayer->GetCurStat() >= PS_MAPFIGHTING ) //在mapsrv中的话,直接发 { pPlayer->SendGameState(); } return true; TRY_END; return false; } #endif /*ANTI_ADDICTION*/