/** * @file Player.h * @brief 定义玩家类 * Copyright(c) 2007,上海第九城市游戏研发部 * All rights reserved * 文件名称: Player.h * 摘 要: 定义玩家类; * 作 者: dzj * 完成日期: 2007.11.29 * */ #include #include #include "../../../Base/Utility.h" #include "../../../Base/BufQueue/BufQueue.h" #include "../../../Base/PkgProc/PacketBuild.h" #include "../DealPkg/DealPkg.h" #include "../DealPkg/DealShopSrvPkg.h" #include "../../../Base/PkgProc/RelationServiceProtocol.h" #include "../../../Base/dscontainer/dshashtb.h" #include "../SynchCliTime.h" #include "../LogManager.h" #ifdef DS_EPOLL #include "../../../Test/testthreadque_wait/lsocket.h" #else //DS_EPOLL #ifndef WIN32 unsigned long GetTickCount(); #endif //WIN32 #endif //DS_EPOLL #include "../../../Test/testthreadque_wait/sigexception/sigexception.h" #include #pragma once using namespace std; using namespace MUX_PROTO; #ifndef DS_EPOLL extern IBufQueue* g_pClientSender; #endif //DS_EPOLL extern vector g_vecKickMapSrvPlayer;//是否因为mapsrv断线而踢去对应该mapsrv的所有玩家;; extern unsigned short SELF_SRV_ID;//自身为第几个GateSrv; extern bool g_bTimeCheck; #ifdef USE_DSIOCP extern TCache< UniqueObj< CDsSocket > >* g_poolUniDssocket;//保存socket唯一对象的对象池; #endif //USE_DSIOCP #ifdef USE_DSIOCP #define CreatePlayerPkg( PKGTYPE, pPlayer, pPkg ) CPacketBuild::CreateClientPkg( pPlayer->GetHandleID(), pPlayer->GetSessionID(), pPlayer->GetUniqueDsSocket(), &pPkg ); #else //USE_DSIOCP #define CreatePlayerPkg( PKGTYPE, pPlayer, pPkg ) CPacketBuild::CreateClientPkg( pPlayer->GetHandleID(), pPlayer->GetSessionID(), &pPkg ); #endif //USE_DSIOCP #ifdef DS_EPOLL #define NewSendPlayerPkgCrypt( PKGTYPE, pPlayer, pPkg ) \ if ( NULL != pPlayer )\ {\ char* cryptedMsg = NULL; unsigned short cryptedLen = 0;\ bool isCryptPkgBuildOK = CNewPkgBuild::CreatePkgWithSeqID( &pPkg, cryptedMsg, cryptedLen );\ if ( isCryptPkgBuildOK && ( NULL != cryptedMsg ) && ( cryptedLen > 0 ) )\ {\ pPlayer->LSSendMsgCryptInnerCpy( cryptedMsg, cryptedLen );\ }\ } #define NewSendPlayerPkgNoCrypt( PKGTYPE, pPlayer, pPkg ) \ if ( NULL != pPlayer )\ {\ NewMsgToPut* pToSend = CNewPkgBuild::CreatePkg(&pPkg);\ if ( NULL != pToSend ) \ {\ pPlayer->LSSendMsg( &pToSend, 1 );\ }\ } #ifdef USE_CRYPT #define NewSendPlayerPkg( PKGTYPE, pPlayer, pPkg ) NewSendPlayerPkgCrypt( PKGTYPE, pPlayer, pPkg ) #else //USE_CRYPT #define NewSendPlayerPkg( PKGTYPE, pPlayer, pPkg ) NewSendPlayerPkgNoCrypt( PKGTYPE, pPlayer, pPkg ) #endif //USE_CRYPT /*对于广播消息,由于此处只是保存至底层,然后由底层各socket拷贝组装自身发送消息,因此与是否加密无关,具体加密与否在CrdInsSendMsg及其调用处处理*/ #define GatePlayerBrocast( PKGTYPE, pPkg ) \ {\ NewMsgToPut* pToSend = CNewPkgBuild::CreatePkg(&pPkg);\ if ( NULL != pToSend ) \ {\ CManPlayer::IssueBrocastMsg( pToSend );\ }\ } #else //DS_EPOLL #define NewSendPlayerPkg( PKGTYPE, pPlayer, pPkg ) \ if ( NULL != pPlayer )\ {\ MsgToPut* pToSend = CreatePlayerPkg( PKGTYPE, pPlayer, pPkg );\ if ( NULL != pToSend ) \ {\ pPlayer->SendPkgToPlayer( pToSend );\ SEND_TO_CLI_STAT( PKGTYPE::wCmd, sizeof(PKGTYPE) );\ }\ } //组建向本gatesrv所有玩家广播的广播包; #define CreateGateBrocastPkg( PKGTYPE, pPkg ) CPacketBuild::CreateInconnBrocastPkg( &pPkg ); #endif //DS_EPOLL #ifdef USE_DSIOCP #define CreateRelationPkg( PKGTYPE, pPlayer, pPkg ) CPacketBuild::CreateRelationPkg( pPlayer->GetHandleID(), pPlayer->GetSessionID(), pPlayer->GetUniqueDsSocket(), &pPkg ); #else //USE_DSIOCP #define CreateRelationPkg( PKGTYPE, pPlayer, pPkg ) CPacketBuild::CreateRelationPkg( pPlayer->GetHandleID(), pPlayer->GetSessionID(), &pPkg ); #endif //USE_DSIOCP #ifdef USE_DSIOCP #define CreateNewLoginSrvPkg( PKGTYPE, pPlayer, pPkg ) CPacketBuild::CreateNewLoginPkg( pPlayer->GetHandleID(), pPlayer->GetSessionID(), pPlayer->GetUniqueDsSocket(), &pPkg ); #else //USE_DSIOCP #define CreateNewLoginSrvPkg( PKGTYPE, pPlayer, pPkg ) CPacketBuild::CreateNewLoginPkg( pPlayer->GetHandleID(), pPlayer->GetSessionID(), &pPkg ); #endif //USE_DSIOCP #ifdef USE_DSIOCP #define CreateShopPkg( PKGTYPE, pPlayer, pPkg ) CPacketBuild::CreateShopPkg( pPlayer->GetHandleID(), pPlayer->GetSessionID(), pPlayer->GetUniqueDsSocket(), &pPkg ); #else //USE_DSIOCP #define CreateShopPkg( PKGTYPE, pPlayer, pPkg ) CPacketBuild::CreateShopPkg( pPlayer->GetHandleID(), pPlayer->GetSessionID(), &pPkg ); #endif //USE_DSIOCP #ifdef USE_DSIOCP #define CreateLogPkg( PKGTYPE, pPlayer, pPkg ) CPacketBuild::CreateLogPkg( pPlayer->GetHandleID(), pPlayer->GetSessionID(), pPlayer->GetUniqueDsSocket(), &pPkg ); #else //USE_DSIOCP #define CreateLogPkg( PKGTYPE, pPlayer, pPkg ) CPacketBuild::CreateLogPkg( pPlayer->GetHandleID(), pPlayer->GetSessionID(), &pPkg ); #endif //USE_DSIOCP class CSrvConn; class CManPlayer; class CMapSrv; ///玩家当前所处的状态(阶段) enum PLAYER_STAT { PS_INVALID = 0, //初始(无效状态) PS_CONN, //已连接 PS_LOGINING, //登录中 PS_LOGINED, //已登录 PS_CENTER_CHECKING, //centersrv检测中 PS_CENTER_CHECKED, //centersrv已检测 PS_DB_LOGIN_QUERYING, //查询DB玩家信息中 PS_DB_LOGIN_QUERYED, //DB玩家信息已返回 PS_ROLESELED, //角色已选 PS_QUERY_DETAIL_INFO, //向DB请求玩家所选角色详细信息; PS_DETAIL_INFO_GOT, //DB已返回玩家所选角色详细信息; #ifdef WAIT_QUEUE PS_DB_PRE, //已开始向map发送存盘消息 PS_QUEUEING, //排队中 #endif /*增加2种新状态*/ PS_MAPFIGHTING, //游戏世界战斗中 PS_MAP_SWITCHING //正在跳地图中 }; struct SwitchMapStat { SwitchMapStat() : isOrgMapLeave(false), isPlayerReady(false) {} ~SwitchMapStat() {}; bool IsEnterNewMapSrv() { return isOrgMapLeave && isPlayerReady; } bool IsOrgMapSrvLeft() { return isOrgMapLeave; } void GetSwitchMapTgtInfo( unsigned short& outMapID, unsigned short& outPosX, unsigned short& outPosY ) { outMapID = usMapID; outPosX = (unsigned short)nPosX; outPosY = (unsigned short)nPosY; return; } void ResetSwitchMapStat( unsigned short inMapID, int inPosX, int inPosY ) { usMapID = inMapID; nPosX = inPosX; nPosY = inPosY; isOrgMapLeave = false; isPlayerReady = false; } void OrgMapSrvLeft() { isOrgMapLeave = true; } void PlayerSwitchReady() { isPlayerReady = true; } unsigned short usMapID;//目标地图;保存目标点信息,防止离开原mapsrv时,本GS保存的新位置信息被覆盖; int nPosX;//目标点X; int nPosY;//目标点X; bool isOrgMapLeave;//是否已离开原地图; bool isPlayerReady;//玩家是否已准备好; }; typedef struct StrInviteInfo { ///////////////////////////////////////////申请入队////////////////////////// void SetReqTeamMember(const Member& member) { reqTeamPlayer = member; } PlayerID GetReqTeamPlayerID() { PlayerID tmpID; tmpID.dwPID = reqTeamPlayer.playerId; tmpID.wGID = reqTeamPlayer.gateId; return tmpID; } const Member& GetReqTeamMember() { return reqTeamPlayer; } //void ResetReqTeamMember() //{ // memset( &reqTeamPlayer, 0, sizeof( Member ) ); //} ///////////////////////////////////////////申请入队////////////////////////// ////////////////////////////邀请组队///////////////////////////////////////////// void SetInviteTeamInfo(const PlayerID& invitePlayerID) { inviteTeamPlayerID = invitePlayerID; bTeamInvited = true; inviteTeamTime = ACE_OS::gettimeofday(); } const PlayerID& GetInviteTeamPlayerID() { return inviteTeamPlayerID; } ACE_Time_Value& GetInviteTeamTime() { return inviteTeamTime; } bool IsBeTeamInvited() { return bTeamInvited; } //清除所有相关组队邀请信息 void ResetInviteTeamInfo() { bTeamInvited = false; inviteTeamPlayerID.dwPID = 0; inviteTeamPlayerID.wGID = 0; inviteTeamTime = ACE_Time_Value::zero; } ////////////////////////////邀请组队///////////////////////////////////////////// ////////////////////////////////邀请好友//////////////////////////////////////// void SetInviteFriendInfo( const PlayerID& inviteFriendID ) { bFriendInvited = true; inviteFriendTime = ACE_OS::gettimeofday(); inviteFriendPlayerID = inviteFriendID; } bool IsBeFriendInvited() { return bFriendInvited; } const PlayerID& GetInviteFriendPlayerID() { return inviteFriendPlayerID; } const ACE_Time_Value& GetInviteFriendTime() { return inviteFriendTime; } void ResetReqTeamPlayer() { /* MemberInd memberInd; // UINT gateId; // UINT playerId; // USHORT memberSeq; // MemberName memberName; // CHAR memberJob; // USHORT mapId; // USHORT avatarId; // USHORT memberLevel; // CHAR memberSex; // */ StructMemSet( reqTeamPlayer, 0, sizeof( reqTeamPlayer ) ); //reqTeamPlayer.avatarId = 0; //reqTeamPlayer.gateId = 0; //reqTeamPlayer.mapId = 0; //reqTeamPlayer.memberLevel = 0; //reqTeamPlayer.playerId = 0; //reqTeamPlayer.memberSeq = 0; } void ResetFriendInfo() { bFriendInvited = false; inviteFriendPlayerID.dwPID = 0; inviteFriendPlayerID.wGID = 0; inviteFriendTime = ACE_Time_Value::zero; } ////////////////////////////////邀请好友//////////////////////////////////////// StrInviteInfo() { ResetAllInfo(); } void ResetAllInfo() { ResetInviteTeamInfo(); ResetFriendInfo(); ResetReqTeamPlayer(); } private: bool bTeamInvited; //是否被邀请 PlayerID inviteTeamPlayerID; //邀请的玩家 ACE_Time_Value inviteTeamTime; //受邀的时间 Member reqTeamPlayer; //申请入队的玩家信息 bool bFriendInvited; //是否被邀请加好友 PlayerID inviteFriendPlayerID; //申请好友玩家的ID ACE_Time_Value inviteFriendTime; //收到好友邀请的时间 }InviteInfo; ///////////////组队的更改/////////////////// #ifdef NEW_INVITE_INFO typedef struct strTeamInvitePlayerInfo { PlayerID teamInvitePlayerID; ACE_Time_Value inviteTime; strTeamInvitePlayerInfo() { teamInvitePlayerID.wGID = 0; teamInvitePlayerID.dwPID = 0; inviteTime = ACE_Time_Value::zero; } strTeamInvitePlayerInfo( const PlayerID& invitePlayer, const ACE_Time_Value& currentTime):teamInvitePlayerID( invitePlayer ), inviteTime( currentTime ) { } }TeamInvitePlayerInfo; typedef struct strTeamReqPlayerInfo { PlayerID teamReqPlayerID; ACE_Time_Value reqTime; strTeamReqPlayerInfo() { teamReqPlayerID.wGID = 0; teamReqPlayerID.dwPID = 0; reqTime = ACE_Time_Value::zero; } strTeamReqPlayerInfo( const PlayerID& reqPlayer, const ACE_Time_Value& currentTime):teamReqPlayerID( reqPlayer ), reqTime( currentTime ) { } }TeamReqPlayerInfo; typedef struct strFriendInvitePlayerInfo { PlayerID friendInvitePlayerID; ACE_Time_Value inviteTime; strFriendInvitePlayerInfo() { friendInvitePlayerID.wGID = 0; friendInvitePlayerID.dwPID = 0; inviteTime = ACE_Time_Value::zero; } strFriendInvitePlayerInfo( const PlayerID& invitePlayer, const ACE_Time_Value& currentTime):friendInvitePlayerID( invitePlayer ), inviteTime( currentTime ) { } }FriendInvitePlayerInfo; typedef struct strNewInviteInfo { #define MAX_LAST_TIME 60 vector vecTeamInviteInfo; vector vecTeamReqInfo; vector vecFriendInviteInfo; void ClearTeamPlayerInfo() { vecTeamInviteInfo.clear(); vecTeamReqInfo.clear(); } bool IsInTeamInviteList( const PlayerID& answerID ) { TeamInviteListTimeCheck(); for( size_t i=0; i::iterator iter = vecTeamInviteInfo.begin(); iter != vecTeamInviteInfo.end(); ) { if( (currentTime - (*iter).inviteTime).sec() >= MAX_LAST_TIME ) { iter = vecTeamInviteInfo.erase( iter ); continue; } iter++; } } void TeamReqListTimeCheck() { ACE_Time_Value currentTime = ACE_OS::gettimeofday(); for( vector::iterator iter = vecTeamReqInfo.begin(); iter != vecTeamReqInfo.end(); ) { if( (currentTime - (*iter).reqTime).sec() >= MAX_LAST_TIME ) { iter = vecTeamReqInfo.erase( iter ); continue; } iter++; } } void FriendInviteListTimeCheck() { ACE_Time_Value currentTime = ACE_OS::gettimeofday(); for( vector::iterator iter = vecFriendInviteInfo.begin(); iter != vecFriendInviteInfo.end(); ) { if( (currentTime - (*iter).inviteTime).sec() >= MAX_LAST_TIME ) { iter = vecFriendInviteInfo.erase( iter ); continue; } iter++; } } bool AddTeamInvitePlayer( const PlayerID& invitePlayer ) { if( IsInTeamInviteList( invitePlayer ) ) { //D_WARNING("忽略重复发送\n"); return false; } //已经有人正忙 if( vecTeamInviteInfo.size() != 0 ) return false; TeamInvitePlayerInfo teamInvite( invitePlayer, ACE_OS::gettimeofday() ); vecTeamInviteInfo.push_back( teamInvite ); return true; } bool AddTeamReqPlayer( const PlayerID& reqPlayer ) { if( IsInTeamReqList( reqPlayer ) ) { return false; } if( vecTeamReqInfo.size() != 0 ) return false; TeamReqPlayerInfo teamReq( reqPlayer, ACE_OS::gettimeofday() ); vecTeamReqInfo.push_back( teamReq ); return true; } bool AddFriendInvitePlayer( const PlayerID& invitePlayer ) { if( IsInFriendInviteList( invitePlayer ) ) { return false; } if( vecFriendInviteInfo.size() != 0 ) return false; FriendInvitePlayerInfo friendInvite( invitePlayer, ACE_OS::gettimeofday() ); vecFriendInviteInfo.push_back( friendInvite ); return true; } bool RemoveTeamInvitePlayer( const PlayerID& invitePlayer ) { for( size_t i=0; i m_vecNetDetectPkgSendTime;//延时检测包的发出时刻; vector m_vecNetDetectPkgDateTime;//延时检测包的发出日期; bool m_bIsBiasAquired;//是否已经确定了时间基准; ACE_Time_Value m_timeBias;//与客户端通信的时间基准; CPlayer* m_pPlayer; int m_nRcvedNum; int m_nMinDelay; int m_nMinDelayPkgID; }; struct TargetInfo { public: TargetInfo() { ResetTargetInfo(); }; ~TargetInfo() {}; public: void SetTargetInfo( float inTargetX, float inTargetY ) { targetX = inTargetX; targetY = inTargetY; } void ResetTargetInfo() { targetX = -1; targetY = -1; } public: float GetTargetX() { return targetX; } float GetTargetY() { return targetY; } private: float targetX;//目标点浮点X坐标; float targetY;//目标点浮点Y坐标; }; struct PlayerTeamInfo { public: PlayerTeamInfo(): isInTeam(false), isTeamLeader(false), teamSwitch(true),teamNum( 0 ) {}; ~PlayerTeamInfo() {}; public: void InitPlayerTeamInfo( bool inIsTeamLeader, const TeamInd& inTeamID ) { isInTeam = true; isTeamLeader = inIsTeamLeader; teamID = inTeamID; } void ResetPlayerTeamInfo() { isInTeam = false; isTeamLeader = false; teamSwitch = true; teamNum = 0; } void DestoryTeam() { ResetPlayerTeamInfo(); StructMemSet( teamID, 0 ,sizeof( teamID ) ); } void EnableTeamSwitch() { teamSwitch = true; } void DisableTeamSwitch() { teamSwitch = false; } void JoinTeam() { isInTeam = true; } void LeaveTeam() { teamNum = 0; isInTeam = false; isTeamLeader = false; StructMemSet( teamID, 0, sizeof( TeamInd ) ); } void EnableTeamCaptain() { isTeamLeader = true; isInTeam = true; } void DisableTeamCaptain() { isTeamLeader = false; } void SetTeamNum( unsigned int num ) { teamNum = num; } unsigned int GetTeamNum() { return teamNum; } public: const TeamInd& GetTeamId() { return teamID; } bool IsTeamCaptain() { return isTeamLeader; } bool GetTeamSwitch() { return teamSwitch; } bool IsEnableTeamSwitch() { return teamSwitch; } bool IsInTeam() { return isInTeam; } private: bool isInTeam; bool isTeamLeader; TeamInd teamID; bool teamSwitch; unsigned int teamNum; }; struct PlayerCopyMapTeamInfo { public: PlayerCopyMapTeamInfo() { ResetCopyMapTeamInfo(); } void ResetCopyMapTeamInfo() { m_TeamID = m_playerflag = m_teamflag = 0; } void SetCopyMapTeamInfo( unsigned int teamID, unsigned int playerflag, unsigned int teamflag ) { m_TeamID = teamID; m_playerflag = playerflag; m_teamflag = teamflag; } unsigned int GetPlayerFlag() { return m_playerflag; } unsigned int GetTeamFlag() { return m_teamflag; } unsigned int GetTeamID() { return m_TeamID; } private: unsigned int m_TeamID;//玩家组队时的编号 unsigned int m_playerflag; unsigned int m_teamflag; }; struct PlayerRideTeamInfo { public: PlayerRideTeamInfo():m_rideState(E_RIDESTATE_MAX),rideAttachInfo1(0),rideAttachInfo2(0){} void ResetRideTeamInfo() { m_rideState = E_RIDESTATE_MAX; rideAttachInfo1 = rideAttachInfo2 = 0; } ERIDESTATE GetRideState(){ return m_rideState; } void SetRideState( ERIDESTATE state ) { m_rideState = state; } void SetRideAttachInfo( int attachinfo1, int attachinfo2 ) { rideAttachInfo1 = attachinfo1; rideAttachInfo2 = attachinfo2; } int GetRideAttachInfo1() { return rideAttachInfo1; } int GetRideAttachInfo2() { return rideAttachInfo2; } private: ERIDESTATE m_rideState;//玩家的骑乘状态 int rideAttachInfo1;//玩家骑乘的附属信息1 int rideAttachInfo2;//玩家骑乘的附属信息2 }; ///跟随玩家的怪物,玩家跳地图时该信息需要保存; typedef struct StrPlayerNoDbSwitchMapReserveInfo { public: StrPlayerNoDbSwitchMapReserveInfo() { ClearPlayerNDSMInfo(); } public: void ClearPlayerNDSMInfo() { anamorphicState = 0; battleMode = DEFAULT_MODE; followMonsterType = 0; #ifdef ANTI_ADDICTION gameState = 0; #endif //ANTI_ADDICTION rogueTime = 0; warTaskId = 0; storageLock = true; StructMemSet(petInfo, 0x0,sizeof(petInfo) ); StructMemSet(petTimer, 0x0, sizeof(petTimer) ); StructMemSet(punishTaskInfo,0x0,sizeof(punishTaskInfo) ); rookieBreakTime = 0; StructMemSet(tpBuffData, 0, sizeof(tpBuffData)); StructMemSet(killInfo, 0, sizeof(killInfo)); } public: unsigned int followMonsterType; //跟随玩家的怪物类型; BATTLE_MODE battleMode; //战斗模式 unsigned int rogueTime; //流氓状态的时间 unsigned int warTaskId; //攻城任务id #ifdef ANTI_ADDICTION UINT gameState; //防沉迷状态 #endif /*ANTI_ADDICTION*/ DbPetInfo petInfo; PunishTaskInfo punishTaskInfo; //天谴任务信息 PetTimer petTimer; //宠物计时 unsigned int anamorphicState;//变形状态 bool storageLock;//副本是否锁定 unsigned int rookieBreakTime; MGTempBuffData tpBuffData; //跳转地图时的BUFF信息 KillInfo killInfo; //杀人信息 }PlayerNoDbSwitchMapReserveInfo; //用于在玩家进副本时,保存玩家副本外位置,以便在异常情况下存盘时,不会存副本位置; struct OutMapInfo { OutMapInfo() : isOutMapInfoSet(false), usMapID(0), iPosX(0), iPosY(0) {} bool isOutMapInfoSet;//是否有outmapinfo; unsigned short usMapID; unsigned short iPosX; unsigned short iPosY; }; //每玩家应用广播相关信息; struct PlayerAppBroInfo { PlayerAppBroInfo() { mapBroCheckID = 0; unionBroCheckID = 0; } inline unsigned int GetMapCheckID() { return mapBroCheckID; }; inline unsigned int GetUnionCheckID() { return unionBroCheckID; }; inline bool SetMapCheckID( unsigned int inMapBroCheckID ) { mapBroCheckID = inMapBroCheckID; return true; } inline bool SetUnionCheckID( unsigned int inUnionBroCheckID ) { unionBroCheckID = inUnionBroCheckID; return true; } unsigned int mapBroCheckID; unsigned int unionBroCheckID; }; class CPlayer #ifdef DS_EPOLL : public CLSocket #endif //DS_EPOLL { ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //以下应用层广播相关; public: inline unsigned int GetMapBroCheckID() { return m_AppBroInfo.GetMapCheckID(); }; inline unsigned int GetUnionBroCheckID() { return m_AppBroInfo.GetUnionCheckID(); }; inline bool SetMapBroCheckID( unsigned int inMapBroCheckID ) { return m_AppBroInfo.SetMapCheckID(inMapBroCheckID); } inline bool SetUnionBroCheckID( unsigned int inUnionBroCheckID ) { return m_AppBroInfo.SetUnionCheckID(inUnionBroCheckID); } private: PlayerAppBroInfo m_AppBroInfo; //以上应用层广播相关; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// private: static unsigned int g_uniPlayerID; #ifndef DS_EPOLL unsigned int m_dwPID;//自身的唯一标识号,每次poolobjinit时重置; #endif //DS_EPOLL #ifdef USE_CRYPT public: inline void SetIsRobot() { m_bIsRobot = true; };//标示此玩家为机器人; inline bool IsPlayerRobot() { return m_bIsRobot; };//返回此玩家是否为机器人; private: bool m_bIsRobot; bool m_bIsCryptNormal;//是否已开始正常加密,若没有,则检测连接时间,连接过长时间,且没有开始加密者,断开; unsigned int m_PlayerConnTick; #endif //USE_CRYPT public: #ifdef DS_EPOLL //以下DS_EPOLL框架需要的定义 CPlayer() { TestPlayerInit(); }; virtual ~CPlayer() {}; ///获得一个自身的对象实例,与DestorySelfIns对应; static CPlayer* CreateSelfIns(); ///释放自身,与CreateSelfIns对应;; virtual void DestorySelfIns(); ///从LSocket继承者需要做的池对象初始化工作; virtual void SocketChildPoolInit() { TestPlayerInit(); } public: void TestPlayerInit() { CommonInit(); m_inittick = 0; ////测试代码 //m_lastsendid = 0; //以下原有的PoolObjInit(),应用相关初始化; m_wSrvID = 0; m_nHandleID = 0; m_nSessionID = 0; #ifdef USE_DSIOCP m_pUniqueSocket = NULL; #endif //USE_DSIOCP return; } public: ///被框架遍历; virtual bool OnBeExploredByFrame() { ST_SIG_CATCH { NewLog( LOG_LEV_INFO, "CPlayer::OnBeExploredByFrame()" ); if ( IsIssueKickAllPlayer() ) { //已标记发起断开所有连接,则响应之; IssueDestory(); } PlayerFastTimerProc(); } END_SIG_CATCH; return true; }; ///连接成功后,给对象一个初始化自身的机会,每连接只执行一次; virtual bool OnConnedInit() { m_inittick = GetTickCount(); //与原实现兼容,为了避免小于1000的ID号,加上100000,由于框架元素只有32000,因此可以很容易分辨出真正的frameID SetHandleInfo( 100000+GetSelfFrameID(), 100000+GetSelfFrameID() );//适应原代码,连接初始状态设置; NewLog( LOG_LEV_DEBUG, "CPlayer::OnConnedInit(),socket%d,frameid%d,framepos%d", GetInnerSocket(), GetSelfFrameID(), GetPosInfo() ); return true; }; public: static inline void SetIssueKickAllPlayer() { m_bIsIssueKickAllPlayer = true; } //发起断开所有玩家; static inline bool IsIssueKickAllPlayer() { return m_bIsIssueKickAllPlayer; } //是否发起断开所有玩家; private: static bool m_bIsIssueKickAllPlayer;//发起断开所有玩家; public: unsigned int m_inittick; #endif //DS_EPOLL //dsepoll与nodsepoll共同的调用函数,需加入PoolObjInit以及TestPlayerInit中的初始化代码,加入此处; void CommonInit() { SetIsLeaveNotiMapSrv( true ); #ifdef USE_CRYPT m_bIsRobot = false; m_bIsCryptNormal = false;//是否已开始正常加密,若没有,则检测连接时间,连接过长时间,且没有开始加密者,断开; m_PlayerConnTick = GetTickCount(); #endif //USE_CRYPT m_playerDisconnIssueTime = 0; ClearNDSMRInfo();//不存盘,跳地图需要保存的信息; StructMemSet( m_copyInfo, 0, sizeof(m_copyInfo) );//清副本相关信息; m_isCurInCopy = false;//当前还未离开原地图,因此还未真正进副本地图 m_wRole = 0; m_CurStat = PS_INVALID; m_DBGetInfo.ClearDbGetInfo(); StructMemSet( m_strAccount, 0, sizeof(m_strAccount) ); StructMemSet( m_strPwd, 0, sizeof(m_strPwd) ); m_NetDetectInfo.NetDetectInfoReset( this ); m_bIsFullInfoOk = false; m_SwitchMapStat.ResetSwitchMapStat( 0, 0, 0 ); m_rideTeamInfo.ResetRideTeamInfo(); m_TeamInfo.ResetPlayerTeamInfo(); m_copymapTeamInfo.ResetCopyMapTeamInfo(); SetBeatRcved();//初始化上次心跳包收到时刻; m_bReqTeamSwitch = true; InitBeatLastChckTime(); mSynchTimer.ResetSynchTime(); m_bIrcPlayer = false; m_bIsGMAccount = false; m_bIsVip = false; m_unionID = 0; } private: //只要玩家换地图,则必定到SetSwitchMapInfo,跳普通地图时,该函数会正确地清outmapinfo, // 如果是跳副本,则在更新fullplayerinfo(及其内部的mapid与x,y)时,mapsrv必定会同时发来outmapinfo,在那时会设置相应的outmapinfo, // 因此总能正确地设置OutMapInfo,并在SaveFullInfoToDB中将其作为玩家存DB依据; void SetOutMapInfo( unsigned short inmapid, unsigned short inposx, unsigned short inposy ) { m_outMapInfo.isOutMapInfoSet = true; m_outMapInfo.usMapID = inmapid; m_outMapInfo.iPosX = inposx; m_outMapInfo.iPosY = inposy; } void ClearOutMapInfo() { StructMemSet( m_outMapInfo, 0, sizeof(m_outMapInfo) ); m_outMapInfo.isOutMapInfoSet = false; } private: OutMapInfo m_outMapInfo; public: #ifndef DS_EPOLL CPlayer() { PoolObjInit(); }; ~CPlayer() {}; PoolFlagDefine() { CommonInit(); m_dwPID = ++g_uniPlayerID; m_wSrvID = 0; m_nHandleID = 0; m_nSessionID = 0; #ifdef USE_DSIOCP m_pUniqueSocket = NULL; #endif //USE_DSIOCP return; } #endif //DS_EPOLL #ifdef USE_DSIOCP public: void SetUniqueDsSocket( UniqueObj< CDsSocket >* pUniqueSocket ) { if ( NULL == pUniqueSocket ) { return; } if ( ( NULL == m_pUniqueSocket ) && ( NULL != pUniqueSocket->GetUniqueObj() ) ) { //自己保存一份,因为MsgToPut中的uniqueSocket在回收时会被删去; m_pUniqueSocket = g_poolUniDssocket->RetrieveOrCreate(); if ( NULL == m_pUniqueSocket ) { TRY_BEGIN; D_ERROR( "SetUniqueDsSocket时,g_poolUniDssocket,内存分配失败\n" ); TRY_END; return; } m_pUniqueSocket->Init( pUniqueSocket->GetUniqueObj() ); } } UniqueObj< CDsSocket>* GetUniqueDsSocket() { if ( ( NULL != m_pUniqueSocket ) //非空 && ( NULL != m_pUniqueSocket->GetUniqueObj() ) //且对应的句柄仍然有效; ) { //复制一份往外传,因为MsgToPut中的uniqueSocket在回收时会被删去; UniqueObj< CDsSocket >* pOutUniqueObj = g_poolUniDssocket->RetrieveOrCreate(); if ( NULL == pOutUniqueObj ) { TRY_BEGIN; D_ERROR( "GetUniqueDsSocket时,g_poolUniDssocket,内存分配失败\n" ); TRY_END; return NULL; } pOutUniqueObj->Init( m_pUniqueSocket->GetUniqueObj() ); return pOutUniqueObj; } else { return NULL; } } private: UniqueObj< CDsSocket >* m_pUniqueSocket; #endif //USE_DSIOCP public: ///置玩家的句柄信息,每次新建时必须调用; void SetHandleInfo( int nHandleID, int nSessionID ); unsigned int GetPlayerDwPID() { #ifdef DS_EPOLL return GetSelfFrameID(); #else //DS_EPOLL return m_dwPID; #endif //DS_EPOLL } PlayerID GetPlayerID() { PlayerID tmpID; tmpID.wGID = SELF_SRV_ID; #ifdef DS_EPOLL tmpID.dwPID = GetSelfFrameID(); #else //DS_EPOLL tmpID.dwPID = m_dwPID; #endif //DS_EPOLL return tmpID; }; public: //通知玩家排行榜信息时,同时告知其自身的相关值 bool FillSelfRankInfo( GCNewRankInfo& rankInfo ); public: void PlayerFastTimerProc() { //快时钟事件1:如果之前处于timecheck且还没有校验时间基准,则进行校验过程; SendNetDetectPkg(); ACE_Time_Value curTime = ACE_OS::gettimeofday(); ACE_Time_Value passTime = curTime - m_playerBeatLastCheckTime; if ( passTime.msec() >= 5*1000 )//每5秒检测一次; { m_playerBeatLastCheckTime = curTime; if ( !IsBeatCheckOK() ) { if( g_bTimeCheck ) { if ( !m_bIsDesSelf ) { //之前没有主动断此连接,发起主动断; D_WARNING( "无响应!%s(%d)长时间不发包,准备断开此连接\n", GetAccount(), GetSessionID() ); //ReqDestorySelf();//准备断开自身; //todo wcj 2010.12.29 暂时屏蔽 ExecDestorySelfReq();//此情况下不必经过3秒等待; } } } } ///////////////////////////////////////////////////////////////////////////// //检测加密是否已正常开始,若登录过后一定时间还未开始正常加密,或者登录验证未成功,则断开... #ifdef USE_CRYPT if ( !m_bIsCryptNormal ) { //还未开始正常加密; if ( !m_bIsRobot ) { //非机器人; if ( ( !IsCliStRcvCrypt() ) //还未开始接收加密 || (m_CurStat < PS_LOGINED) //还未成功登录 ) { //校验不通过; if ( GetTickCount() - m_PlayerConnTick > 5000/*linux下5秒*/ ) { //且连接建立已超过5秒; D_WARNING( "%s(%d)长时间未完成登录或密钥协商,当前状态%d,断开之\n", GetAccount(), GetSessionID(), m_CurStat ); m_PlayerConnTick = GetTickCount();//防止短时间连续发断开请求; ReqDestorySelf(); return; } } else { m_bIsCryptNormal = true;//已登录成功且已开始接收加密,以后无需再检测; } } } #endif //USE_CRYPT //...检测加密是否已正常开始,若登录过后一定时间还未开始正常加密,或者登录验证未成功,则断开 ///////////////////////////////////////////////////////////////////////////// if ( 0 != m_playerDisconnIssueTime ) { unsigned int passed = GetTickCount() - m_playerDisconnIssueTime; unsigned int bias = 3000;//3秒; if ( passed > bias ) { ExecDestorySelfReq(); } } return; } private: void InitBeatLastChckTime() { m_playerBeatLastCheckTime = ACE_OS::gettimeofday(); } ACE_Time_Value m_playerBeatLastCheckTime;//记录玩家上次心跳包收到的时间; private: unsigned int m_playerDisconnIssueTime;//玩家断开发起时间,从此时刻起n秒后真正发断连请求,以便在服务器主动断开的情形下,给客户端一定时间收最后的错误消息; public: #ifndef DS_EPOLL //新建立时的处理(连接建立) void OnCreated() { ResetInfo(); return; } #endif //DS_EPOLL ///销毁时的处理(连接断开) ///注意:在新建连接之前也会调用这里; void OnDestoryed(); ///玩家离开本gatesrv时是否要通知mapsrv,唯一置此标记为false的异常情况是,mapsrv上该玩家已不存在,且相关信息已通知到本gate; inline bool SetIsLeaveNotiMapSrv( bool isUpdate ) { m_bIsLeaveNotiMapSrv = isUpdate; return true; } private: bool m_bIsLeaveNotiMapSrv;//玩家离开本mapsrv时,是否要向DB(gate)更新自身fullinfo? public: ///执行ReqDestorySelf的请求 void ExecDestorySelfReq() { D_WARNING( "ExecDestorySelfReq,递送断开请求,玩家(其sessionID:%d)\n", m_nSessionID ); #ifdef DS_EPOLL IssueDestory(); #else //DS_EPOLL TRY_BEGIN; if ( m_bIsDesSelf ) { //D_DEBUG( "ReqDestorySelf, %s(%d),已经发过了断开请求,不再重发\n", GetAccount(), GetSessionID() ); return;//已经发过了请求断开消息,就不再发了; } //发送长度为0消息断开自身; MsgToPut* disconnectMsg = g_poolMsgToPut->RetrieveOrCreate(); if ( NULL == disconnectMsg ) { TRY_BEGIN; D_ERROR( "ReqDestorySelf时,g_poolMsgToPut,内存分配失败\n" ); TRY_END; return; } #ifdef USE_DSIOCP disconnectMsg->pUniqueSocket = GetUniqueDsSocket();//唯一需要主动设置unisocket者,其余都通过createsrvpkg的方式来生成; #endif //USE_DSIOCP disconnectMsg->nHandleID = m_nHandleID;//向断开执行者传递自身标识; disconnectMsg->nSessionID = m_nSessionID;//向断开执行者传递自身标识; disconnectMsg->nMsgLen = 0;//表明断开连接请求; SendPkgToPlayer( disconnectMsg ); m_bIsDesSelf = true;//这一句一定要在SendPkgToPlayer之后,否则置上m_bIsDesSelf之后,SendPkgToPlayer会忽略后续发送消息; return; TRY_END; return; #endif //DS_EPOLL } ///请求销毁自身(断开连接) void ReqDestorySelf() { if ( 0 == m_playerDisconnIssueTime ) { D_WARNING( "ReqDestorySelf,主动请求断开,玩家(其sessionID:%d)\n", m_nSessionID ); m_playerDisconnIssueTime = GetTickCount(); } else { //D_WARNING( "ReqDestorySelf,重复主动请求断开,玩家(其sessionID:%d)\n", m_nSessionID ); } } ///如果某连接上解析包错误,则断开此连接; void OnPkgError() { //解析包错误时断开连接; ReqDestorySelf(); } //收包处理; #ifdef DS_EPOLL virtual bool OnPkgRcved( unsigned int timeInfo, unsigned short wCmd, const char* pPkg, unsigned short wPkgLen ); #else //DS_EPOLL bool OnPkgRcved( unsigned short wCmd, const char* pPkg, unsigned short wPkgLen ); #endif //DS_EPOLL int GetHandleID() { return m_nHandleID; } int GetSessionID() { return m_nSessionID; } public: const char* GetAccount() { return (const char*) &m_strAccount; } const char* GetPwd() { return (const char*) &m_strPwd; } #ifndef DS_EPOLL ///向外发包; void SendPkgToPlayer( MsgToPut* pPkg ) { TRY_BEGIN; if ( NULL == pPkg ) { return; } if ( m_bIsDesSelf ) { //D_DEBUG( "往已发起主动断开的连接写新消息,忽略此次发送!\n" ); //已发起主动断开,不要再往此玩家写新消息,回收发送消息占用的内存; if ( NULL != g_poolMsgToPut ) { g_poolMsgToPut->Release( pPkg ); pPkg = NULL; } else { D_ERROR( "SendPkgToPlayer, g_poolMsgToPut空\n" ); } } if ( NULL != g_pClientSender ) { if ( g_pClientSender->PushMsg( pPkg ) < 0 ) { D_ERROR( "0926dbg, SendPkgToPlayer, PushMsg失败\n" ); } } return; TRY_END; return; } #endif //DS_EPOLL bool SetAccount( const char* strAccount) { TRY_BEGIN; if ( NULL == strAccount ) { return false; } #ifdef ACE_WIN32 if ( strlen(strAccount)+1 <= sizeof(m_strAccount) ) { strcpy_s( m_strAccount, sizeof(m_strAccount), strAccount); return true; } #else //ACE_WIN32 if ( strlen(strAccount)+1 <= sizeof(m_strAccount) ) { strcpy( m_strAccount, strAccount); return true; } #endif //ACE_WIN32 return false; TRY_END; return false; } bool SetPwd( const char* strPwd) { TRY_BEGIN; SafeStrCpy( m_strPwd, strPwd ); return true; TRY_END; return false; } ///选角色; bool SelRole( unsigned int uiRoleNo ) { TRY_BEGIN; int foundpos = -1; for ( vector::iterator iter=m_vecPlayerInfos.begin(); iter!=m_vecPlayerInfos.end(); ++iter ) { if ( iter->playerInfo.uiID == uiRoleNo ) { foundpos = (int) (iter - m_vecPlayerInfos.begin()); break; } } if ( foundpos >= 0 ) { m_wRole = foundpos; return true; } else { m_wRole = 0; return false; } return true; TRY_END; return false; } //返回当前所选角色的数据库标号; unsigned int GetSeledRole() { if ( IsRoleValid() ) { return m_vecPlayerInfos[m_wRole].playerInfo.uiID;//返回当前所选角色号; } else { D_ERROR( "取不存在的角色" ); return 0; } } ///得到玩家当前状态; const PLAYER_STAT GetCurStat() { return m_CurStat; } bool IsEnterWorlding() { return (m_CurStat == PS_DB_PRE) || (m_CurStat == PS_QUEUEING); } public: ///收到mapsrv发来NDSMR信息时的处理; void OnMapNDSMRInfo( const MGNDSMRInfo* pMGInfo ); ///向Gate发送NDSMR信息; void PlayerNDSMRInfoSend(); ///清本地NDSMR信息; inline void ClearNDSMRInfo() { m_ndsmrInfo.ClearPlayerNDSMInfo(); }; //玩家的副本信息发送 bool PlayerNDSMRCopyTeamInfoSend(); private: PlayerNoDbSwitchMapReserveInfo m_ndsmrInfo;//不存盘,但跳地图需要保存的信息,每次跳地图之前由map发来,跳地图完后清空; CommCopyInfo m_copyInfo; //副本相关信息,与m_ndsmrInfo中信息的不同之处在于m_copyInfo不是来自mapsrv,另外该信息需要在进map/copy之后继续保存,而不能被清; bool m_isCurInCopy;//当前是否在副本中,发进副本地图命令后设置; public: //是否已发过了DbPre,在发过此信息的情况下,不允许客户端再次选角角,或再次发进世界消息; bool IsDbPreSend() { return ( m_CurStat >= PS_QUERY_DETAIL_INFO ); } bool IsInFighting() { return m_CurStat == PS_MAPFIGHTING ; } inline bool IsInSwitching() { return m_CurStat == PS_MAP_SWITCHING; } ///置当前状态; bool SetCurStat( const PLAYER_STAT& curStat ); //清玩家相关信息; void ClearPlayerInfo() { m_vecPlayerInfos.clear(); } int GetRoleNum(void) { return (int)(m_vecPlayerInfos.size()); } //加玩家相关信息,玩家信息来自DbSrv; bool AddPlayerInfoLogin( const GCPlayerRole& playerInfo ) { m_vecPlayerInfos.push_back( playerInfo ); return true; } //删除玩家角色信息 bool DeletePlayerInfoLogin(unsigned int uiRoleID) { if ( !(m_vecPlayerInfos.empty()) ) { for(vector< GCPlayerRole >::iterator i = m_vecPlayerInfos.begin(); i != m_vecPlayerInfos.end(); i++) { if(i->playerInfo.uiID == uiRoleID) { m_vecPlayerInfos.erase(i); if(uiRoleID == m_wRole) { m_wRole = 0; } return true; } } } return false; } bool GetRoleInfoLogin( int roleID, GCPlayerRole& playerInfo ) { if ( ( roleID<0 ) || ( roleID>=(int)(m_vecPlayerInfos.size()) ) ) { return false; } playerInfo = m_vecPlayerInfos[roleID]; return true; } int GetRoleIndex(unsigned int roleID) { if ( !(m_vecPlayerInfos.empty()) ) { for(vector< GCPlayerRole >::iterator i = m_vecPlayerInfos.begin(); i != m_vecPlayerInfos.end(); i++) { if(i->playerInfo.uiID == roleID) return (int)(i - m_vecPlayerInfos.begin()); } } return -1; } private: bool IsRoleValid() { return ( m_wRole m_vecPlayerInfos; bool m_bIsDesSelf; PlayerTeamInfo m_TeamInfo;//玩家组队信息; PlayerCopyMapTeamInfo m_copymapTeamInfo;//与玩家副本相关的组队信息 bool m_bReqTeamSwitch; //入队申请屏蔽开关 unsigned int m_userRequestID; //请求的random string的ID unsigned int m_userMd5ID; //请求MD5的ID bool m_bIrcPlayer; bool m_bIsGMAccount;//是否GM账号 bool m_bIsVip;//商城消费vip unsigned int m_unionID;//工会成员购买时发送给shop,以便shop确定消耗的星钻是否累加. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///新信息获取/DB存盘相关协议以及玩家离开地图协议--理清相关逻辑与操作, by dzj, 09.05.12 struct DBGetInfo { void ClearDbGetInfo() { isValid = false; //以下memset者都是协议中使用的结构,可以直接memset,其它地方的memset要禁止,改用构造与初始化函数; StructMemSet( petInfo, 0, sizeof(petInfo) ); StructMemSet( suitInfo, 0, sizeof(suitInfo) ); StructMemSet( fashionInfo, 0, sizeof(fashionInfo) ); protectInfoVec.clear(); StructMemSet( taskRdInfo, 0, sizeof(taskRdInfo) ); copyStageInfos.ResetCopyStageInfos(); } bool isValid;//DBGet信息是否有效; DbPetInfo petInfo;//玩家宠物信息; PlayerInfo_Suits suitInfo;//套装信息 PlayerInfo_Fashions fashionInfo;//时装信息 std::vector protectInfoVec;//保护道具的信息 TaskRdInfo taskRdInfo;//任务记录信息 PlayerStageInfos copyStageInfos;//玩家副本阶段信息; }; public: ////DB取信息开始; Register( D_G_DBGET_PRE, &OnDbGetPre ); bool OnDbGetPre( const DGDbGetPre* pDbGetPre ); ////DB取信息结束(与M_G_DBSAVE_POST一一对应); Register( D_G_DBGET_POST, &OnDbGetPost ); bool OnDbGetPost( const DGDbGetPost* pDbGetPost ); ////DB保存信息; Register( D_G_DBGET_INFO, &OnDbGetInfo ); bool OnDbGetInfo( const DGDbGetInfo* pDbGetInfo ); ///自身取到的存盘信息送map; bool PlayerDBInfoSend( bool isNeedQueueCheck=true/*是否需要排队检查,初始需要,如果是因为map通知可进入,则不需要*/ ); ///玩家可能的副本信息通知对应mapsrv; bool PlayerCopyInfoSend(); //发送保护道具信息给MapSrv void PlayerProtectItemSend(); //玩家的任务信息发送 void PlayerTaskInfoSend(); //接受玩家的保护道具的更新 void RecvMGProtectItemInfo( const ProtectItemInfo& protectItem ); //接受玩家的任务存盘的更新 void RecvMGTaskRecordInfo( const TaskRdInfo& taskRdInfo ); //接受套装更新 void RecvMGSuitInfo(const PlayerInfo_Suits &suits); //接受时装更新 void RecvMGFashionInfo(const PlayerInfo_Fashions &fashion); ///在gatesrv上保存玩家副本阶段信息副本; void RecvMGCopyStageInfo( const PlayerStageInfos& playerStageInfos ); ///向centersrv发送离开副本请求 bool NotiCenterPlayerLeaveCopyQuest( unsigned int copyID/*副本id号*/, unsigned short copyMapID/*副本地图号*/, const char* playerAccount/*玩家帐号*/ ); ///向centersrv发送玩家结束单人组队标志 bool NotiPlayerEndSingleTeamCopyFlag(); //是否是副本的队长(单人情况 和 组队队长状态 返回true) bool IsTeamCopyInfoLeader(); private: DBGetInfo m_DBGetInfo; ///新信息获取/DB存盘相关协议以及玩家离开地图协议--理清相关逻辑与操作, by dzj, 09.05.12 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #ifdef ANTI_ADDICTION public: bool SendGameState(); //当游戏状态改变时向mapsrv发送防沉迷的状态 void SetGameState( UINT state ); //保存当前的游戏状态 UINT GetGameState(); #endif /*ANTI_ADDICTION*/ ///////////////////////////////////新交互接口///////////////////////////////// #ifdef NEW_INVITE_INFO private: NewInviteInfo m_newInviteInfo; //邀请信息(工会的在RelationSrv保存,GateSrv不负责) public: unsigned int GetReqTeamSize() { return (unsigned int)m_newInviteInfo.vecTeamReqInfo.size(); } unsigned int GetInviteTeamSize() { return (unsigned int)m_newInviteInfo.vecTeamInviteInfo.size(); } bool AddTeamInvitePlayer( const PlayerID& invitePlayer ) { return m_newInviteInfo.AddTeamInvitePlayer( invitePlayer ); } bool AddTeamReqPlayer( const PlayerID& reqPlayer ) { return m_newInviteInfo.AddTeamReqPlayer( reqPlayer ); } bool AddFriendInvitePlayer( const PlayerID& invitePlayer ) { return m_newInviteInfo.AddFriendInvitePlayer( invitePlayer ); } bool IsInTeamInviteList( const PlayerID& invitePlayer ) { return m_newInviteInfo.IsInTeamInviteList( invitePlayer ); } bool IsInTeamReqList( const PlayerID& reqPlayer ) { return m_newInviteInfo.IsInTeamReqList( reqPlayer ); } bool IsInFriendInviteList( const PlayerID& invitePlayer ) { return m_newInviteInfo.IsInFriendInviteList( invitePlayer ); } bool RemoveTeamInvitePlayer( const PlayerID& invitePlayer ) { return m_newInviteInfo.RemoveTeamInvitePlayer( invitePlayer ); } bool RemoveTeamReqPlayer( const PlayerID& reqPlayer ) { return m_newInviteInfo.RemoveTeamReqPlayer( reqPlayer ); } bool RemoveFriendInvitePlayer( const PlayerID& invitePlayer ) { return m_newInviteInfo.RemoveFriendInvitePlayer( invitePlayer ); } #endif //NEW_INVITE_INFO }; extern void OnDealPkgNoRegCmd( CPlayer* pPlayer, unsigned short wCmd ); #define PLAYER_FAST_TIMER 45 //50毫秒 #ifdef DS_EPOLL class CManPlayer { private: CManPlayer();//屏蔽此操作; public: static void InitManPlayer( CManFrame* pTestManFrame ) { m_pManFrame = pTestManFrame; }; static void ReleaseManPlayer() { m_pManFrame = NULL; } public: ///发起广播消息,该消息广播给框架中除监听端口外的所有元素 static void IssueBrocastMsg( NewMsgToPut* pToSendMsg ) { if ( NULL == m_pManFrame ) { return; } m_pManFrame->AddOneBrocastMsg( pToSendMsg ); return; } public: static int GetPlayerNum() { if ( NULL == m_pManFrame ) { return 0; } return m_pManFrame->GetInnerValidEleNum(); } static CPlayer* FindPlayer( unsigned int dwPID ) { if ( NULL == m_pManFrame ) { return NULL; } return (CPlayer*) ( m_pManFrame->FindFrameEle( dwPID ) ); } public: static void KickMapSrvPlayer( unsigned short mapsrvID ) { //待实现 NewLog( LOG_LEV_ERROR, "KickMapSrvPlayer(%d),转为新的epoll,此接口待实现", mapsrvID ); return; } static void NotifyWarTaskState( unsigned int taskId, ETaskStatType taskStat ) { GCPlayerTaskStatus cliMsg; cliMsg.taskID = taskId; cliMsg.taskStat = taskStat; cliMsg.failTime = 0;//初始无失败计时; GatePlayerBrocast( GCPlayerTaskStatus, cliMsg ); return; } //static void RaceGroupNotify( EGRaceGroupNotify* pMsg ) //{ // if ( NULL == pMsg ) // { // return; // } // GCChat cliMsg; // cliMsg.nType = pMsg->chatType; // SafeStrCpy( cliMsg.srcName, pMsg->chatPlayerName ); // cliMsg.srcNameSize = (UINT)strlen( cliMsg.srcName ) + 1; // SafeStrCpy( cliMsg.strChat, pMsg->chatContent ); // cliMsg.chatSize = (UINT)strlen( cliMsg.strChat ) + 1; // GatePlayerBrocast( GCChat, cliMsg ); // return; //} static void KickAllPlayer() { NewLog( LOG_LEV_ERROR, "KickAllPlayer..." ); CPlayer::SetIssueKickAllPlayer(); return; } static void SetWarTaskInfo( unsigned int warTaskId, ETaskStatType taskState ) { //待实现 NewLog( LOG_LEV_ERROR, "SetWarTaskInfo(%d:%d),转为新的epoll,此接口待实现", warTaskId, taskState ); return; } private: static CManFrame* m_pManFrame; }; #else //DS_EPOLL class CManPlayer { private: CManPlayer();//屏蔽此操作; public: static void InitManPlayer() { m_pHashPlayers = NEW DsHashTable< HashTbPtrEle, 3000, 2 >; }; static void ReleaseManPlayer() { if ( NULL != m_pHashPlayers ) { delete m_pHashPlayers; m_pHashPlayers = NULL; } } public: ///快时钟触发; static void ManPlayerFastTimer() { static ACE_Time_Value fastLastTime = ACE_OS::gettimeofday(); ACE_Time_Value curTime = ACE_OS::gettimeofday(); ACE_Time_Value fastPastTime = curTime - fastLastTime; if ( fastPastTime.msec() >= PLAYER_FAST_TIMER ) { fastLastTime = curTime; ManPlayerFastTimerProc(); } return; } static int GetPlayerNum() { #ifdef USE_SELF_HASH if ( NULL == m_pHashPlayers ) { D_ERROR( "GetPlayerNum,m_pHashPlayers指针空\n" ); return 0; } return m_pHashPlayers->GetEleNum(); #else //USE_SELF_HASH return (int) m_mapPlayers.size(); #endif //USE_SELF_HASH } static void KickMapSrvPlayer( unsigned short mapsrvID ) { TRY_BEGIN; D_WARNING( "踢去mapsrv:%d上的全部玩家\n", mapsrvID ); CPlayer* pPlayer = NULL; #ifdef USE_SELF_HASH if ( NULL == m_pHashPlayers ) { return; } HashTbPtrEle* pFound = NULL; m_pHashPlayers->InitExplore(); vector vecToDelPlayer; while ( NULL != (pFound=m_pHashPlayers->ExploreNext()) ) { pPlayer = pFound->GetInnerPtr(); if ( NULL == pPlayer ) { continue; } if ( pPlayer->GetMapSrvID() == mapsrvID )//普通玩家; { pPlayer->ReqDestorySelf(); vecToDelPlayer.push_back( pFound->GetKey() );//准备遍历完毕后删除; } } if ( !(vecToDelPlayer.empty()) ) { for ( vector::iterator iter=vecToDelPlayer.begin(); iter!=vecToDelPlayer.end(); ++iter ) { m_pHashPlayers->DelEle( *iter );//从hash表中删去对应玩家; } } #else //USE_SELF_HASH bool iscont = true; while (iscont) { iscont = false; for ( map::iterator tmpiter=m_mapPlayers.begin(); tmpiter!=m_mapPlayers.end(); ++tmpiter ) { pPlayer = tmpiter->second; if ( NULL == pPlayer ) { continue; } if ( pPlayer->GetMapSrvID() == mapsrvID )//普通玩家; { pPlayer->ReqDestorySelf(); m_mapPlayers.erase( tmpiter ); iscont = true;//继续删; break; } } } #endif //USE_SELF_HASH return; TRY_END; return; } static void KickAllPlayer() { TRY_BEGIN; D_WARNING("踢去全部玩家\n"); CPlayer* pPlayer = NULL; #ifdef USE_SELF_HASH if( NULL == m_pHashPlayers ) { return; } HashTbPtrEle* pFound = NULL; m_pHashPlayers->InitExplore(); while( NULL != ( pFound = m_pHashPlayers->ExploreNext() ) ) { pPlayer = pFound->GetInnerPtr(); if( NULL == pPlayer ) { continue; } pPlayer->ReqDestorySelf(); } m_pHashPlayers->ClearAllEle(); #else for( map::iterator tmpiter = m_mapPlayers.begin(); tmpiter != m_mapPlayers.end(); ++tmpiter ) { pPlayer = tmpiter->second; if( NULL == pPlayer ) { continue; } pPlayer->ReqDestorySelf(); } m_mapPlayers.clear(); #endif ////USE_SELF_HASH return; TRY_END; } static void AddOnePlayer( CPlayer* pPlayer ) { #ifdef USE_SELF_HASH if ( NULL == m_pHashPlayers ) { return; } m_pHashPlayers->PushEle( HashTbPtrEle( pPlayer->GetPlayerDwPID(), pPlayer ) ); //,???,邓子建检查,D_WARNING( "将玩家加入全局列表时,发现对应的玩家指针%d已在列表中\n", (DWORD_PTR)pPlayer ); #else //USE_SELF_HASH map::iterator tmpIter = m_mapPlayers.find( pPlayer->GetPlayerDwPID() ); if ( tmpIter != m_mapPlayers.end() ) { D_WARNING( "将玩家加入全局列表时,发现对应的玩家%d已在列表中\n", pPlayer->GetPlayerDwPID() ); return; } m_mapPlayers.insert( pair( pPlayer->GetPlayerDwPID(), pPlayer ) ); #endif //USE_SELF_HASH } static void RemovePlayer( CPlayer* pPlayer ) { #ifdef USE_SELF_HASH if ( NULL == m_pHashPlayers ) { return; } m_pHashPlayers->DelEle( pPlayer->GetPlayerDwPID() ); return; #else //USE_SELF_HASH map::iterator tmpIter = m_mapPlayers.find( pPlayer->GetPlayerDwPID() ); if ( tmpIter != m_mapPlayers.end() ) { m_mapPlayers.erase( tmpIter ); return; } #endif //USE_SELF_HASH return; } static CPlayer* FindPlayer( unsigned int dwPID ) { #ifdef USE_SELF_HASH if ( NULL == m_pHashPlayers ) { return NULL; } HashTbPtrEle* pFound = NULL; bool isFound = m_pHashPlayers->FindEle( dwPID, pFound ); if ( isFound ) { if ( NULL != pFound ) { return pFound->GetInnerPtr(); } } return NULL; #else //USE_SELF_HASH map::iterator tmpIter = m_mapPlayers.find(dwPID); if ( tmpIter != m_mapPlayers.end() ) { return tmpIter->second; } else { return NULL; } #endif //USE_SELF_HASH } private: ///快时钟执行函数; static void ManPlayerFastTimerProc() { CPlayer* pPlayer = NULL; #ifdef USE_SELF_HASH if ( NULL == m_pHashPlayers ) { return; } HashTbPtrEle* pFound = NULL; m_pHashPlayers->InitExplore(); while ( NULL != (pFound=m_pHashPlayers->ExploreNext()) ) { pPlayer = pFound->GetInnerPtr(); if ( NULL == pPlayer ) { continue; } pPlayer->PlayerFastTimerProc(); } #else //USE_SELF_HASH for ( map::iterator tmpiter=m_mapPlayers.begin(); tmpiter!=m_mapPlayers.end(); ++tmpiter ) { pPlayer = tmpiter->second; if ( NULL == pPlayer ) { continue; } pPlayer->PlayerFastTimerProc(); } #endif //USE_SELF_HASH return; } private: #ifdef USE_SELF_HASH static DsHashTable< HashTbPtrEle, 3000, 2 >* m_pHashPlayers; #else //USE_SELF_HASH static map m_mapPlayers; #endif //USE_SELF_HASH }; #endif //DS_EPOLL ///无DB时,备份玩家存盘信息以便稍后恢复; bool NoDBPlayerInfoBackup( const char* playerAccount, const FullPlayerInfo& fullPlayerInfo ); ///恢复之前备份的玩家存盘信息; bool NoDBPlayerInfoRestore( const char* backFileName );