中心服CS:
作為遊戲的核心伺服器,中心服承擔着除戰鬥外的所有遊戲功能,包括房間比對,場景服(SS)戰鬥及玩家的管理控制,郵件系統,玩家實體建立和管理,Kernel核心管理,資料存儲與緩存,遊戲日志生成等。
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHL90zZNJnSzI2MGRVZy50MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL3MzNyMDN1cTMzEzNwkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
房間比對:
class CCSMatchMgr
{
public:
...
INT32 TeamStartMatch(IMatchPlayer* pPlayer);//開始比對
bool TeamStopMatch(IMatchPlayer* pPlayer);//結束比對
void Update(int64_t tUTCMilsec,int64_t tTickSpan);
...
private:
map<UINT32,ICSMatchList*> mAllMatchList[eMatchType_Total];//不同類型的比對清單
map<UINT32,CCSMatchTeam*> mAllTeamMap;//記錄所有正在比對的隊伍資訊
};
該類是CCSBattleMgr的成員變量,在伺服器啟動時建立,并在一個定時器中周期性的調用重新整理函數:
該重新整理函數中根據mAllMatchList數組中存儲的用戶端發來的不同類型的開始比對的玩家資料,調用各自類型的update函數進行比對。最終在比對函數:
中,根據函數
選取負載最小的SS,并根據該SS的id在CS上建立CCSBattle來管理本場戰鬥,然後将本次比對的玩家及機器人資料通過消息eMsgToSSFromCS_CreateBattle發送給該SS,SS接收到資訊後開始建立CSSBattle,加載地圖資訊,設定玩家和AI資訊,建立玩家CSSUser等,然後通知用戶端開啟戰鬥。
場景服(SS)戰鬥及玩家的管理控制:
//戰場資訊類
class CCSBattle
{
private:
...
BattleType m_Type; //戰場類型
EBattleMatchType m_MatchType;//比對類型
map<UINT64,CCSUser*> m_UserMap;//玩家資料
map<UINT32,SAIRobot*> m_AIRobots;//機器人資料
SMapLogicCfg* m_MapLogicCfg;//地圖配置
public:
...
//遊戲開始發送所有資料給場景服
INT32 Start();
//發送消息給用戶端
INT32 BroadcastMsgToAllUser(google::protobuf::Message& sMsg,int n32MsgID);
//向場景服發送消息
INT32 PostMsgToBattleSS(google::protobuf::Message& sMsg,int n32MsgID);
INT32 PostMsgToSS_NotifyUserIsOnline(CCSUser* pUser,bool IsOnline);
//向網關服發送消息
INT32 PostMsgToGS_NotifyCombineUserNetInfoToSS(CCSUser* piUser,ICSSSInfo* piSSInfo);
INT32 PostMsgToGS_NotifySplitUserNetInfoToSS(CCSUser* piUser,ICSSSInfo* piSSInfo);
...
};
typedef hash_map<UINT64,CCSBattle*> BattleMap;
//場景服戰場資訊管理類
class CCSBattleMgr
{
private:
UINT64 m_un64MaxBattleID;//目前最大戰場唯一id
BattleMap m_cAllBattleMap;//根據戰場id存儲目前存在的戰場資訊
CCSMatchMgr* m_pMatchMgr;//戰場比對管理資料
map<UINT32,CCSBattleRoom*> m_BattleRoomList;//遊戲房間清單
public:
...
//向場景服通知玩家線上資訊
INT32 NotifyBattleSSUserIsOnline(CCSUser* piUser,bool isOnline);
//向場景服發送資訊
INT32 PostMsgToBattleSS(UINT64 un64BattleID,google::protobuf::message& sMsg,int n32MsgID);
...
public://建立房間進入遊戲
...
//建立遊戲房間
INT32 AskCreateRoom(CCSUser* piUser,UINT32 un32mapId,const string& stPwd,bool isRestart,UINT32 rePostion=0);
//遊戲房間添加玩家
INT32 AskAddRoom(CCSUser* piUser,UINT32 un32mapId,const string& stPwd,bool isRestart,UINT32 rePostion=0);
//遊戲房間開始遊戲
INT32 OnBattleRoomStart(CCSBattleRoom* pRoom,CCSUserListMap& sList,map<UINT32,UINT32>* aiRobots,UINT32 mapID);
...
public://随機比對進入遊戲
INT32 RemoveMatchUser(CCSUser* piUser);//從準備比對隊列中移除該玩家
//對準備比對隊列中的玩家進行比對
void OnBattleMached(CCSUserListMap& pList,map<UINT32,UINT32>* aiRobots,...);
void OnBattleMached(EBattleMatchType type,UINT32 mapId,...);
private:
INT32 OnMsgFromRC_DO(ICSRCInfo* piRCInfo,...);//接收及處理來自遠端控制端的消息
INT32 OnMsgFromGC_DO(ICSRCInfo* piRCInfo,...);//接收及處理來自用戶端的消息
INT32 OnMsgFromSS_DO(ICSRCInfo* piRCInfo,...);//接收及處理來自場景服的消息
...
};
- 玩家進入遊戲比對分為自由比對,建立房間方式和引導方式,三種方式最終都是建立相應類型的CCSBattle,并将該戰場的玩家,機器人,地圖等資訊發送給場景服來建立戰場(具體見房間比對解析)。同時保持和用戶端(通過GS)及場景服的連接配接,同步及接收各種資料。
郵件系統:
struct MailDBData
{
INT64 objIdx; //郵件所屬玩家id
INT32 mailId; //郵件Id
...
INT64 n64CreateTime; //郵件建立時間
INT64 n64EndTime; //郵件過期時間
string mailTitle; //郵件主題
string mailContent;//郵件内容
string mailGift;//郵件贈送附件
...
};
class CCSMailMgr
{
INT32 m_curtMaxMailIdx;//目前的全服郵件id最大值,用于生成唯一郵件id
std::map<INT32,MailDBData> m_mapGameMail;//根據郵件id存儲全服郵件資料
std::map<INT64,std::map<INT32,bool>> m_IfHasSendMail;//臨時的延時郵件
//個人郵件資訊,根據個人id存儲郵件id清單,具體郵件資訊需根據郵件id在m_mapGameMail擷取
std::map<INT64,std::map<INT32,tagMailState>> m_mapPersonalMail;
public:
...
bool addGameMail(const MailDBData& mail);//添加郵件資料
...
bool closeOrGetMailGift(CCSUser* pUser,INT32 mailId);//領取贈送郵件附件并删除郵件
...
private:
void addPersonalMail(const MailDBData& mail);//添加個人郵件
};
- CCSMailMgr是玩家資料管理類CCSUserMgr的成員變量,用于管理玩家郵件的發送,提取,删除等操作。
- m_curtMaxMailIdx在伺服器開啟連接配接上資料庫時,會根據目前資料庫中的郵件id來設定該值,放置郵件id重複。
- 郵件主要資訊存儲在MailDBData,贈送附件mailGift根據EMerchType類型提取金币,鑽石,道具等不同附件。
玩家實體建立和管理:
class CCSUser
{
private:
EUserPlayingStatus m_eUserPlayingStatus; //玩家是否線上
SUserDBData m_sUserDBData;//玩家基本資料(存檔)
TIME_MILSEC m_OfflineTime;//下線時間
SUserNetInfo m_sUserNetInfo;//玩家網絡資料
TIME_MILSEC m_tGCLastPing;//用戶端最近一次ping時間
CCSUserBattleInfo m_sUserBattleInfoEx;//玩家戰鬥資料
IRoomPlayer m_tRoomPlayer;//建立房間進行遊戲時的個人房間資料
IMatchPlayer m_tMatchPlayer;//自由比對時的個人比對資料
CTaskMgr* m_cTaskMgr;//任務資料管理
map<UINT64, SUserRelationshipInfo> m_cAddFVec;//好友資料
int64_t m_TimerID;//個人資料定時儲存定時器id
...
stringstream m_RuneBagStream;//符文背包資料
stringstream m_RuneSlotStream;//符文位置資料
public:
//上線操作
void OnOnline(SUserNetInfo& netinfo,GCToCS::Login &pLogin,bool isFirstInDB,bool isFirstInMem,bool isReLogin=false);
//下線操作
void OnOffline();
//強制踢下線
INT32 KickOutOldUser();
//重置用戶端最後ping時間
INT32 ResetPingTimer();
//加載玩家基礎資料
INT32 LoadDBData(SUserDBData &crsDBData);
//加載玩家好友資料
void LoadUserSNSList(DBToCS::RSinfo msg_snslist);
//添加道具
void AddUserItems(DBToCS::ItemInfo& itemInfo);
...
};
class CCSUserMgr
{
private:
typedef map<UINT64, CCSUser*> UserMap;
UserMap m_cUserGUIDMap;//所有玩家資料管理
UserMap m_cUserOnlineMap;//線上玩家資料
typedef map<string, CCSUser*> UserNickNameMap;
UserNickNameMap m_cNickNameMap;//按綽号分類的玩家資料
map<SUserNetInfo, CCSUser*> m_cUserNetMap;//按網絡連接配接分類的玩家資料
Concurrency::concurrent_queue<Buffer*> m_DBCallbackQueue;//網絡線程與邏輯線程通訊消息隊列
CThreadSafeObejctPool<Buffer> m_DBCallbackQueuePool;//網絡Buffer池
DBActiveWrapper* m_UserCacheDBActiveWrapper;//用于系統對玩家資料存儲的資料庫線程
DBActiveWrapper* m_CdkeyWrapper;// 用于全局資料操作的資料庫線程
vector<DBActiveWrapper*> m_pUserAskDBActiveWrapperVec;//用于玩家主動請求操作的資料庫線程
INT64 m_MaxGuid;//目前伺服器最大GUID,但遊戲裡的GUID是合成的,以保證所有CS Server唯一
set<string> m_AllNickNameSet;//所有玩家昵稱集合,所有關于昵稱的操作可以通過此表來操作!
map<UserCombineKey, UINT64> m_AllUserName2GUIDMap;//所有玩家使用者名,guid表,如果玩家登陸 通過CS,SDK,Username查到對應guid
CCSMailMgr m_MailMgr;//郵件管理類
std::stringstream m_SaveUserStream;//玩家資料儲存資料流
DBActiveWrapper& GetNowWorkActor();// 擷取目前負載最小的DB線程
public:
//注冊消息處理回調
void RegisterMsgHandle(SSMsgHandlerMap& m_SSMsgHandlerMap, GSMsgHandlerMap& m_GSMsgHandlerMap, GCMsgHandlerMap& m_GCMsgHandlerMap, RCMsgHandlerMap& m_RCMsgHandlerMap);
//玩家存儲DB線程回調
void UserCacheDBAsynHandler(Buffer*& pBuffer);
//玩家請求回調
void UserAskDBAsynHandler(Buffer*& pBuffer);
//玩家線上處理
INT32 OnUserOnline(CCSUser *pcUser, const SUserNetInfo &crsUserNetInfo);
//玩家離線處理
void OnUserOffline(CCSUser *pcUser);
//處理玩家請求的資料庫操作
bool PostUserAskMsgToDBThread(google::protobuf::Message& sMsg, int n32MsgID);
//處理緩存資料請求的資料庫操作
bool PostUserCacheMsgToDBThread(INT64 guidIndex, const string& sqlStr);
private:
//添加玩家資料
INT32 AddUser(CCSUser *pcUser);
//移除玩家資料
INT32 RemoveUser(CCSUser*& pcUser);
//處理來自GateServer的消息
INT32 OnMsgFromGS_DO();
//處理來自用戶端的消息
INT32 OnMgrFromGC_DO();
//處理來自場景服的消息
INT32 OnMsgFromSS_DO();
//處理來自遠端控制端的消息
INT32 OnMsgFromRC_DO();
...
};
- 玩家實體CCSUser在玩家在中心服上線時建立,并加入到管理類CCSUserMgr,玩家資料在下線時會存檔,并從管理類中清除析構。
- 整體遊戲資料分為玩家資料和全局遊戲資料,通過兩個不同的資料庫線程進行自動存儲操作,玩家自身的對資料庫操作交由其他的自定義資料庫線程,這個資料庫線程數量根據配置決定,每次選取負載最小的線程處理資料。
- 中心服的玩家資料會根據來自用戶端,GateServer,場景服和遠端控制端的資料進行更新,并及時進行存檔。
Kernel核心管理:
class CCSKernel
{
public:
CCSSSInfo* m_pcSSInfoList;//連接配接的場景服清單
CCSGSInfo* m_pcGSInfoList;//連接配接的網關服清單
SSSNetInfo* m_psSSNetInfoList;//場景清單網絡連接配接資訊
SGSNetInfo* m_psGSNetInfoList;//網關清單網絡連接配接資訊
SRCNetInfo* m_psRCNetInfoList;//遠端控制端清單網絡連接配接資訊
CHAR m_szRemoteConsolekey[c_n32DefaultRemoveConsoleKeyLen];//遠端管理端密碼
CBattleTimer m_BattleTimer;//定時器管理類
SCSKernelCfg m_sCSKernelCfg;//配置資料
DWORD m_RunCounts;//用于記錄伺服器運作幀數情況
TIME_TICK m_LastReport;//伺服器運作日志最新記錄時間
SSMsgHandlerMap m_SSMsgHandlerMap;//場景服消息系統資料庫
GSMsgHandlerMap m_GSMsgHandlerMap;//網關服消息系統資料庫
GCMsgHandlerMap m_GCMsgHandlerMap;//用戶端消息系統資料庫
RCMsgHandlerMap m_RCMsgHandlerMap;//遠端控制端消息系統資料庫
private:
INT32 LoadCfg();//加載配置
INT32 UnloadCfg();//解除安裝配置
void ProfileReport(int64_t tUTCMilsec, int64_t tTickSpan);//記錄運作日志
public:
//主循環
void MainLoop();
//添加定時器
int64_t AddTimer(HeartbeatCallback pHeartbeatCallback, int64_t interval, bool ifPersist);
//移除定時器
void RemoveTimer(int64_t timerID){m_BattleTimer.RemoveTimer(timerID);}
};
CCSKernel主要用于
- 加載中心伺服器的配置,并負責監聽;
- 連接配接其他伺服器,注冊與其他伺服器的互動的消息;
- 記錄目前連接配接的網關服,場景服和遠端控制端網絡資訊;
- 提供定時器功能;
- 記錄伺服器運作日志;
資料存儲與緩存:
見資料存儲篇
遊戲日志生成:
見日志系統篇