/** * @file otherserver.cpp * @brief 定义服务器端的其它服务 * Copyright(c) 2007,上海第九城市游戏研发部 * All rights reserved * 文件名称: otherserver.h * 摘 要: 定义服务器端的其它服务 * 作 者: dzj * 完成日期: 2007.12.10 * */ #include "otherserver.h" #include "../Player/Player.h" #include "../../../Base/LoadConfig/LoadSrvConfig.h" //用于读srv字符串对应的数字标识; map CManLoginSrvs::m_mapLoginSrvs;//所有loginsrv; map CManCenterSrvs::m_mapCenterSrvs; map CManDbSrvs::m_mapDbSrvs;//所有dbsrv, pair(byID,CMapSrv*); map CManMapSrvs::m_mapMapSrvs;//所有mapsrv; map CManRelationSrvs::m_mapRelationSrvs;//所有Relationsrv; map CManNewLoginSrv::m_mapNewLoginSrvs;//所有NewLoginSrv; map CManRankSrv::m_mapRankSrvs;//所有的RankSrv map CManShopSrvs::m_mapShopSrvs;//所有ShopSrv map CManLogSrvs::m_mapLogSrvs;//所有LogSrv bool CFunctionSrv::m_isSomeHonorValid;//是否有有效的称号信息; GCHonorPlayer CFunctionSrv::m_arrHonorPlayer[TIANHOU+1]; ///置玩家的句柄信息,每次新建时必须调用; void CSrvConn::SetHandleInfo( int nHandleID, int nSessionID ) { TRY_BEGIN; m_bIsDesSelf = false; if ( ( nSessionID <=0 ) || ( nSessionID > SRV_SID_MAX ) ) { //错误,srv的nSessionID不应该大于SRV_SID_MAX; D_WARNING( "连接SRV:%d成功\n", nSessionID ); } m_nHandleID = nHandleID; m_nSessionID = nSessionID; if ( nSessionID <= SRV_SID_MAX ) { //本srv主动连接的其它srv; if ( ( nSessionID>=MAPSRV_SID_BASE ) && ( nSessionID=DBSRV_SID_BASE ) && ( nSessionID=CENTERSRV_SID_BASE ) && ( nSessionID=LOGINSRV_SID_BASE ) && ( nSessionID=NEWLOGINSRV_SID_BASE ) && ( nSessionID=RELATIONSRV_SID_BASE ) && ( nSessionID= RANKSRV_SID_BASE ) && (nSessionID < RANKSRV_SID_MAX ) ) { //ranksrv CLoadSrvConfig::GetNumType( "FunctionSrv", m_bySrvType ); unsigned short wID = nSessionID - RANKSRV_SID_BASE; m_pSrvBase = NEW CFunctionSrv( wID, this ); D_INFO("FunctionSrv:%d连接成功\n\n",wID ); }else if( (nSessionID >= SHOP_SID_BASE ) && (nSessionID < SHOP_SID_MAX ) ) { //shopsrv CLoadSrvConfig::GetNumType( "ShopSrv", m_bySrvType ); unsigned short wID = nSessionID - SHOP_SID_BASE; m_pSrvBase = NEW CShopSrv( wID, this ); D_INFO("ShopSrv:%d连接成功\n\n",wID ); }else if( (nSessionID >= LOG_SID_BASE ) && (nSessionID < LOG_SID_MAX ) ) { //logsrv CLoadSrvConfig::GetNumType( "LogSrv", m_bySrvType ); unsigned short wID = nSessionID - LOG_SID_BASE; m_pSrvBase = NEW CLogSrv( wID, this ); D_INFO("LogSrv:%d连接成功\n\n",wID ); } else { D_WARNING( "连上不可识别SRV,其sessionID:%d\n\n", nSessionID ); } } return; TRY_END; return; } ///销毁时的处理(连接断开) ///注意:在新建连接之前也会调用这里; void CSrvConn::OnDestoryed() { TRY_BEGIN; #ifdef USE_DSIOCP if ( NULL != m_pUniqueSocket ) { if ( NULL != g_poolUniDssocket ) { if ( NULL != g_poolUniDssocket ) { g_poolUniDssocket->Release( m_pUniqueSocket ); m_pUniqueSocket = NULL; } } } #endif //USE_DSIOCP if ( m_nHandleID != 0 ) { //确实为断开,区别于新建连接时的回调; if ( m_nSessionID <= SRV_SID_MAX ) { //本srv主动连接的其它srv; if ( ( m_nSessionID>=MAPSRV_SID_BASE ) && ( m_nSessionID=DBSRV_SID_BASE ) && ( m_nSessionID=CENTERSRV_SID_BASE ) && ( m_nSessionID=LOGINSRV_SID_BASE ) && ( m_nSessionID=NEWLOGINSRV_SID_BASE ) && ( m_nSessionID=RELATIONSRV_SID_BASE ) && ( m_nSessionID= RANKSRV_SID_BASE ) && ( m_nSessionID < RANKSRV_SID_MAX ) ) { unsigned short wID = m_nSessionID - RANKSRV_SID_BASE; CManRankSrv::RemoveSrv( wID ); D_WARNING("到FunctionSrv:%d连接断开\n", wID ); }else if( ( m_nSessionID >= SHOP_SID_BASE ) && ( m_nSessionID < SHOP_SID_MAX ) ) { unsigned short wID = m_nSessionID - SHOP_SID_BASE; CManShopSrvs::RemoveSrv( wID ); D_WARNING("到ShopSr:%d连接断开\n", wID ); } else { D_WARNING( "不可识别SRV连接断开,其sessionID:%d\n\n", m_nSessionID ); } } //以下断开处理; if ( NULL != m_pSrvBase ) { m_pSrvBase->OnDestory(); delete m_pSrvBase; m_pSrvBase = NULL; } } ResetInfo(); return; TRY_END; return; } ///loginsrv类; CLoginSrv::CLoginSrv( unsigned short byID, CSrvConn* pConn ) : CSrvBase(pConn) { TRY_BEGIN; m_wID = byID; CManLoginSrvs::AddOneSrv( this );//自身添加到服务管理器; TRY_END; }; CLoginSrv::~CLoginSrv() { TRY_BEGIN; CManLoginSrvs::RemoveSrv( GetID() ); TRY_END; }; ///centersrv类; CCenterSrv::CCenterSrv( unsigned short byID, CSrvConn* pConn ) : CSrvBase(pConn) { TRY_BEGIN; m_wID = byID; CManCenterSrvs::AddOneSrv( this );//自身添加到服务管理器; TRY_END; }; CCenterSrv::~CCenterSrv() { TRY_BEGIN; CManCenterSrvs::RemoveSrv( GetID() ); TRY_END; }; ///构造函数; CDbSrv::CDbSrv( unsigned short byID, CSrvConn* pConn ) : CSrvBase(pConn) { TRY_BEGIN; m_wID = byID; CManDbSrvs::AddOneSrv( this );//自身添加到服务管理器; TRY_END; }; CDbSrv::~CDbSrv() { TRY_BEGIN; CManDbSrvs::RemoveSrv(GetID()); TRY_END; }; ///构造函数; CMapSrv::CMapSrv( unsigned short byID, CSrvConn* pConn ) : CSrvBase(pConn) { TRY_BEGIN; m_bIsFull = false; m_bIsMapSrvReady = false;//初始总是不可进,除非收到mapsrv可进消息; m_wID = byID; m_bBroadFlag = false; m_bBroadToEveryOne = false; m_DbSaveInfo.isValid = false; CManMapSrvs::AddOneSrv( this );//自身添加到服务管理器; TRY_END; }; CMapSrv::~CMapSrv() { TRY_BEGIN; CManMapSrvs::RemoveSrv( GetID() ); TRY_END; }; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///新信息获取/DB存盘相关协议以及玩家离开地图协议--理清相关逻辑与操作, by dzj, 09.05.12 //新的存盘信息开始; bool CMapSrv::OnMGDbSavePre( const MGDbSavePre* pMGDbSavePre ) { TRY_BEGIN; if ( NULL == pMGDbSavePre ) { D_ERROR( "OnMGDbSavePre,输入信息空\n" ); return false; } if ( m_DbSaveInfo.isValid ) { //原来就是true,上次的存盘消息还未收完整; D_ERROR( "OnMGDbSavePre,m_DbSaveInfo.isValid连续两次SavePre,中间没有SavePost!!!\n" ); //上次的信息虽已丢失,但这次还是继续收; } m_DbSaveInfo.isValid = true; StructMemCpy( (m_DbSaveInfo.playerSavePre), pMGDbSavePre, sizeof(m_DbSaveInfo.playerSavePre) ); return true; TRY_END; return false; } //某条待存盘信息; bool CMapSrv::OnMGDbSaveInfo( const MGDbSaveInfo* pMGDbSaveInfo ) { TRY_BEGIN; if ( NULL == pMGDbSaveInfo ) { D_ERROR( "OnMGDbSavePre,输入信息空\n" ); return false; } CDbSrv* pDbSrv = NULL; GDDbSaveInfo dbSaveInfo; CPlayer* pPlayer = CManPlayer::FindPlayer( pMGDbSaveInfo->playerID.dwPID ); dbSaveInfo.infoType = pMGDbSaveInfo->infoType; if ( !(m_DbSaveInfo.isValid) ) { //没有SavePre,直接存DB信息,MapSrv必然以为此玩家仍在线; if ( NULL == pPlayer ) { D_WARNING( "CMapSrv::OnMGDbSaveInfo,直接存DB消息,玩家已下线" ); //由于之前gate肯定已通知了mapsrv,mapsrv会保存所有的玩家信息,因此本次保存可以忽略; return true; } //确实还在线 dbSaveInfo.playerID = pMGDbSaveInfo->playerID; dbSaveInfo.playerUID = pPlayer->GetRoleID(); SafeStrCpy( dbSaveInfo.roleName, pPlayer->GetRoleName() ); pDbSrv = CManDbSrvs::GetDbsrvByAccount( pPlayer->GetAccount() ); } else { //有SavePre,则需要获取该玩家的指针。如果为非NULL,修改GateSrv端的玩家数据。为NULL,则直接通知DB更新 //有SavePre,系列存盘消息,该玩家可能已不在线,从SavePre中取该玩家帐号与角色名; dbSaveInfo.playerID.wGID = 0; dbSaveInfo.playerID.dwPID = 0;//玩家已下线,对应ID号已无效; dbSaveInfo.playerUID = m_DbSaveInfo.playerSavePre.playerUID; SafeStrCpy( dbSaveInfo.roleName, m_DbSaveInfo.playerSavePre.roleName ); pDbSrv = CManDbSrvs::GetDbsrvByAccount( m_DbSaveInfo.playerSavePre.accountName ); } if ( NULL == pDbSrv ) { D_ERROR( "OnMGDbSavePre,找不到对应的DBSrv\n" ); return false; } switch ( pMGDbSaveInfo->infoType ) { case (DI_PET): { StructMemCpy( (dbSaveInfo.petInfo), &(pMGDbSaveInfo->petInfo), sizeof(dbSaveInfo.petInfo) ); break; } case (DI_SUIT): { StructMemCpy( (dbSaveInfo.suitInfo), &(pMGDbSaveInfo->suitInfo), sizeof(dbSaveInfo.suitInfo) ); if ( NULL != pPlayer ) { pPlayer->RecvMGSuitInfo(pMGDbSaveInfo->suitInfo); } break; } case (DI_FASHION): { StructMemCpy( (dbSaveInfo.fashionInfo), &(pMGDbSaveInfo->fashionInfo), sizeof(dbSaveInfo.fashionInfo) ); if ( NULL != pPlayer ) { pPlayer->RecvMGFashionInfo(pMGDbSaveInfo->fashionInfo); } break; } case (DI_PROTECTITEM): { StructMemCpy( dbSaveInfo.protectInfo, &pMGDbSaveInfo->protectitemInfo, sizeof(dbSaveInfo.protectInfo) ); if ( NULL != pPlayer ) { pPlayer->RecvMGProtectItemInfo( pMGDbSaveInfo->protectitemInfo ); } break; } case (DI_TASKRD): { StructMemCpy( dbSaveInfo.taskRdInfo, &pMGDbSaveInfo->taskRdInfo, sizeof(dbSaveInfo.taskRdInfo) ); if ( NULL != pPlayer ) { pPlayer->RecvMGTaskRecordInfo( pMGDbSaveInfo->taskRdInfo ); } break; } case (DI_SKILL): { StructMemCpy( dbSaveInfo.skillInfo, &pMGDbSaveInfo->skillInfo, sizeof(dbSaveInfo.skillInfo) ); break; } case (DI_COPYSTAGE): { StructMemCpy( dbSaveInfo.copyStageInfos, &pMGDbSaveInfo->copyStageInfos, sizeof(dbSaveInfo.copyStageInfos) ); if ( NULL != pPlayer ) { pPlayer->RecvMGCopyStageInfo( pMGDbSaveInfo->copyStageInfos ); } break; } default: { D_WARNING( "OnMGDbSaveInfo,不可识别的DB存盘信息类型%d", pMGDbSaveInfo->infoType ); } }; //MsgToPut* pDbSaveMsg = CreateSrvPkg( GDDbSaveInfo, pDbSrv, dbSaveInfo ); //pDbSrv->SendPkgToSrv( pDbSaveMsg ); SendMsgToSrv( GDDbSaveInfo, pDbSrv, dbSaveInfo ); return true; TRY_END; return false; } //最近一次存盘信息结束; bool CMapSrv::OnMGDbSavePost( const MGDbSavePost* pMGDbSavePost ) { TRY_BEGIN; if ( NULL == pMGDbSavePost ) { D_ERROR( "OnMGDbSavePost,输入信息空\n" ); return false; } if ( !(m_DbSaveInfo.isValid) ) { //原来就是true,上次的存盘消息还未收完整; D_ERROR( "OnMGDbSavePost,m_DbSaveInfo.isValid未收到SavePre的情况下直接收到SavePost!!!\n" ); //上次的信息虽已丢失,但这次还是继续收; } m_DbSaveInfo.isValid = false; return true; TRY_END; return false; }; ///新信息获取/DB存盘相关协议以及玩家离开地图协议--理清相关逻辑与操作, by dzj, 09.05.12 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///收包处理; void CLoginSrv::OnPkgRcved( unsigned short wCmd, const char* pBuf, unsigned short wPkgLen ) { TRY_BEGIN; CDealLoginSrvPkg::DealPkg( this, wCmd, pBuf, wPkgLen ); TRY_END; } ///收包处理; void CCenterSrv::OnPkgRcved( unsigned short wCmd, const char* pBuf, unsigned short wPkgLen ) { TRY_BEGIN; RECV_FROM_SRV_STAT( wCmd, wPkgLen ); CDealCenterSrvPkg::DealPkg( this, wCmd, pBuf, wPkgLen ); TRY_END; } ///收包处理; void CDbSrv::OnPkgRcved( unsigned short wCmd, const char* pBuf, unsigned short wPkgLen ) { TRY_BEGIN; RECV_FROM_SRV_STAT( wCmd, wPkgLen ); CDealDbSrvPkg::DealPkg( this, wCmd, pBuf, wPkgLen ); TRY_END; } ///收包处理; void CMapSrv::OnPkgRcved( unsigned short wCmd, const char* pBuf, unsigned short wPkgLen ) { TRY_BEGIN; RECV_FROM_SRV_STAT( wCmd, wPkgLen ); CDealMapSrvPkg::DealPkg( this, wCmd, pBuf, wPkgLen ); TRY_END; } ///构造函数; CRelationSrv::CRelationSrv( unsigned short byID, CSrvConn* pConn ) : CSrvBase(pConn) { TRY_BEGIN; m_wID = byID; CManRelationSrvs::AddOneSrv( this );//自身添加到服务管理器; TRY_END; }; CRelationSrv::~CRelationSrv() { TRY_BEGIN; CManRelationSrvs::RemoveSrv(GetID()); TRY_END; }; void CRelationSrv::OnPkgRcved( unsigned short wCmd, const char* pBuf, unsigned short wPkgLen ) { TRY_BEGIN; RECV_FROM_SRV_STAT( wCmd, wPkgLen ); CDealRelationSrvPkg::DealPkg( this, wCmd, pBuf, wPkgLen ); TRY_END; } ///构造函数; CNewLoginSrv::CNewLoginSrv( unsigned short byID, CSrvConn* pConn ) : CSrvBase(pConn) { TRY_BEGIN; m_wID = byID; CManNewLoginSrv::AddOneSrv( this );//自身添加到服务管理器; TRY_END; }; CNewLoginSrv::~CNewLoginSrv() { TRY_BEGIN; CManNewLoginSrv::RemoveSrv(GetID()); TRY_END; }; void CNewLoginSrv::OnPkgRcved( unsigned short wCmd, const char* pBuf, unsigned short wPkgLen ) { TRY_BEGIN; RECV_FROM_SRV_STAT( wCmd, wPkgLen ); CDealNewLoginSrvPkg::DealPkg( this, wCmd, pBuf, wPkgLen ); TRY_END; } //RankSrv的构造函数 CFunctionSrv::CFunctionSrv(unsigned short byID,CSrvConn* pConn ):CSrvBase( pConn ) { TRY_BEGIN; m_isSomeHonorValid = false;//初始称号信息无效; m_wID = byID; CManRankSrv::AddOneSrv( this );////自身添加到服务管理器; TRY_END; } CFunctionSrv::~CFunctionSrv() { TRY_BEGIN; CManRankSrv::RemoveSrv( GetID() ); TRY_END; } void CFunctionSrv::OnPkgRcved(unsigned short wCmd, const char* pBuf, unsigned short wPkgLen ) { TRY_BEGIN; RECV_FROM_SRV_STAT( wCmd, wPkgLen ); CDealRankSrvPkg::DealPkg( this, wCmd, pBuf, wPkgLen ); TRY_END; } //处理functionsrv发来的称号信息; bool CFunctionSrv::OnRcvHonorPlayer( const GCHonorPlayer& honorPlayer ) { EHonorMask honorMask = honorPlayer.honorType; if ( honorMask >= ARRAY_SIZE(m_arrHonorPlayer) ) { D_ERROR( "CFunctionSrv::OnRcvHonorPlayer, honorMask(%d) >= ARRAY_SIZE(m_arrHonorPlayer)\n", honorMask ); return false; } m_isSomeHonorValid = true; StructMemCpy( m_arrHonorPlayer[honorMask], &honorPlayer, sizeof(m_arrHonorPlayer[honorMask]) ); AllGateBroastHonorInfo();//每次收到functionsrv的称号消息就向所有人广播一次; return true; } //全gatesrv广播称号信息; bool CFunctionSrv::AllGateBroastHonorInfo() { for ( unsigned int i=0; iPushMsg( pBrocastMsg ) < 0 ) //直接压入client通信队列,因为到了底层会解析广播包发送给所有的连入连接,而不是特定人; { D_ERROR( "AllGateBroastHonorInfo, PushMsg失败\n" ); continue; } } #endif //DS_EPOLL //NewSendPlayerPkg( GCHonorPlayer, pPlayer, m_arrHonorPlayer[i] ); } return false; } //向某玩家通知称号信息(玩家进地图时); bool CFunctionSrv::NotifyHonorToOnePlayer( CPlayer* pPlayer ) { if ( NULL == pPlayer ) { D_ERROR( "CFunctionSrv::NotifyHonorToOnePlayer, NULL == pPlayer\n" ); return false; } for ( unsigned int i=0; i