游戲匹配和結(jié)算實(shí)現(xiàn)

匹配

匹配.png
//請(qǐng)求匹配
message CM_Match {
  int type; //匹配房間類型
  String name; //玩家名稱
  long targetPlayerId; //加入他人比賽,目標(biāo)玩家id
}

//匹配成功
message L2RM_MatchSucc {
  int roomId;
  int roomType;
  boolean createRoomIfNotExist;  //場(chǎng)景中的第一個(gè)玩家為true
  RoomPlayerEnt ent;  //房間服需要的玩家信息
}

//業(yè)務(wù)服收到此消息創(chuàng)建房間
message R2LM_AddRoom {
  int id;
  int sign;  //房間簽名
  int type;
  Date createTime;
}

//業(yè)務(wù)服收到此消息,在房間銷毀前(R2LM_RemoveRoom),玩家都可以斷線重連房間服
message R2LM_AddPlayer {
  long playerId;
  int roomId;
  int roomSign;
  int roomType;
  int token;   //登錄令牌,斷線重連時(shí)下發(fā)給客戶端
}

//客戶端收到此消息后連接房間服
message SM_RoomServerPermission {
  String host;
  int port;
  String token;  //本次登錄的令牌
}

業(yè)務(wù)服房間管理

業(yè)務(wù)服維護(hù)了房間服的Room。房間服創(chuàng)建Room,業(yè)務(wù)服創(chuàng)建對(duì)應(yīng)Room,房間服銷毀Room,業(yè)務(wù)服銷毀對(duì)應(yīng)Room。其變化通過處理房間服的R2LM_AddRoom,R2LM_RemoveRoom等消息完成。
在匹配規(guī)則中另外維護(hù)了MatchRoom。匹配規(guī)則認(rèn)為需要?jiǎng)?chuàng)建一個(gè)新的房間時(shí),則馬上創(chuàng)建MatchRoom,當(dāng)一個(gè)玩家被匹配到某個(gè)MatchRoom中,MatchRoom中立即添加該玩家。新增過程不依賴房間服的消息。
Room的作用是用于統(tǒng)計(jì)房間服的信息,玩家的斷線重連。MatchRoom用于完成匹配邏輯。兩者的作用不同決定生命周期不同,Room的生命周期由房間服決定,MatchRoom在匹配時(shí)創(chuàng)建,在人滿時(shí)銷毀,在房間服的房間銷毀時(shí)也會(huì)銷毀。

class Room {
  int id;
  int sign;
  RoomType type;
  Date createTime;
  int playerNum;  //玩家數(shù)量
  int watcherNum;  //觀戰(zhàn)者數(shù)量
  RoomServer server;  //所屬房間服
}
class MatchRoom {
  int id;
  List<Long> playerIds;
  RoomServer server;  //所屬房間服
}

進(jìn)入房間服

進(jìn)入房間服.png
message CM_EnterRoom {
  long playerId;
  String token; //登錄令牌
}

//業(yè)務(wù)服收到此消息,將玩家加入房間服玩家集合
message R2LM_PlayerEnterRoom {
  long playerId;
  int roomId;
  int roomType;
  int status;  //狀態(tài) 0.游戲 1.觀戰(zhàn)
}

//場(chǎng)景快照
message SM_SceneSnapshot {
}

離開房間服

離開房間服.png
//業(yè)務(wù)服收到此消息,將玩家從房間服玩家集合中移除
message R2LM_PlayerLeaveRoom {
  long playerId;
  int roomId;
  String token; //登錄令牌相同才能移除玩家
}

玩家結(jié)算

玩家結(jié)算.png
//結(jié)算消息分成兩部分,第一部分在房間服計(jì)算,比如排行榜
message SM_RoomResult {
  根據(jù)結(jié)算面板確定...
}

//通知客戶端斷開房間服連接,返回業(yè)務(wù)服
message SM_DisconnectRoomServer {
  連接業(yè)務(wù)服的信息...
}

//將結(jié)算內(nèi)容發(fā)到業(yè)務(wù)服,由業(yè)務(wù)服計(jì)算獎(jiǎng)勵(lì)等數(shù)據(jù)
message R2LM_PlayerResult {
  
}

//業(yè)務(wù)服收到此消息,清理玩家斷線重連的相關(guān)信息。
//房間服再次收到R2LM_AddPlayer消息才允許玩家登陸。
message R2LM_RemovePlayer {
  long playerId;
  String token; //登錄令牌相同才能移除玩家
}

房間結(jié)算

房間結(jié)算.png
//房間結(jié)算,包含了所有需要結(jié)算的玩家
message R2LM_RoomResult {
  
}

//業(yè)務(wù)服收到此消息,清理房間服
message R2LM_RemoveRemove {
  long playerId;
  String token; //登錄令牌相同才能移除玩家
}

房間結(jié)算時(shí),所有玩家必須結(jié)算。

房間服消息作用

房間服發(fā)給業(yè)務(wù)服的消息主要有6個(gè)

  • R2LM_AddRoom
  • R2LM_RemoveRoom
  • R2LM_AddPlayer
  • R2LM_RemovePlayer
  • R2LM_PlayerEnterRoom
  • R2LM_PlayerLeaveRoom

R2LM_AddRoom/R2LM_RemoveRoom用于維護(hù)業(yè)務(wù)服的房間的創(chuàng)建和銷毀。
R2LM_AddPlayer/R2LM_RemovePlayer主要用于維護(hù)玩家能否斷線重連房間服。
R2LM_PlayerEnterRoom/R2LM_PlayerLeaveRoom用于維護(hù)哪些玩家在房間服,以及相關(guān)狀態(tài)的修改。
玩家離開房間服的行為會(huì)導(dǎo)致房間服發(fā)送R2LM_PlayerLeaveRoom給業(yè)務(wù)服,而玩家完成一局游戲才會(huì)導(dǎo)致房間服發(fā)送R2LM_RemovePlayer給業(yè)務(wù)服。

房間服線程模型

每個(gè)房間綁定到線程池中的一個(gè)線程,房間的所有業(yè)務(wù)都單線程處理。
房間支持消息隊(duì)列,可以向其投遞各種消息。玩家進(jìn)入房間,玩家離開房間,玩家結(jié)算,房間結(jié)算等任務(wù),都在房間線程中處理。
第一個(gè)玩家進(jìn)入房間時(shí),啟動(dòng)房間定時(shí)器,并處理房間消息。房間銷毀后停止定時(shí)器,不再處理房間消息。

class Room {
  ConcurrentLinkedQueue<IRoomTask> taskQueue;
}

<b>問題:</b>
當(dāng)房間服收到L2RM_MatchSucc時(shí),會(huì)創(chuàng)建新玩家,將玩家放入緩存,如果緩存中已存在玩家,則需要銷毀已存在的玩家。銷毀玩家的任務(wù)需要投遞到房間線程中執(zhí)行,可能會(huì)發(fā)生執(zhí)行順序錯(cuò)誤問題。

  • 代碼順序
Player oldPlayer = playerMap.put(playerId, player);
if(oldPlayer != null && oldPlayer.getScene() != null) {
    oldPlayer.getScene().removePlayerAsync(oldPlayer);
    ...
}
send R2LM_AddPlayer message
  • 執(zhí)行順序
thread 1: send R2LM_AddPlayer message
thread 2: send R2LM_RemovePlayer message  //removePlayer是異步執(zhí)行

<b>解決方法:</b>

并不糾正執(zhí)行順序,而是在R2LM_AddPlayer和R2LM_RemovePlayer消息中增加token字段。player和oldPlayer的玩家id相同,但是登錄token不同。業(yè)務(wù)服通過對(duì)比token,可以知道本次R2LM_RemovePlayer是否有效,如果在R2LM_RemovePlayer之前已經(jīng)收到了包含新的token的R2LM_AddPlayer消息,則忽略R2LM_RemovePlayer消息的處理。

由于執(zhí)行順序依然是異步的,在同一時(shí)間,房間服可能同時(shí)存在相同id的兩個(gè)Player。所以除了在全局維護(hù)Player集合,每個(gè)房間還維護(hù)了自己的Player集合,房間中需要獲取玩家通過內(nèi)部的Player集合獲取,不要通過全局的Player集合獲取,因?yàn)楂@取到的可能是新的Player。

異常情況

L2RM_MatchSucc問題

1.玩家匹配到一個(gè)已經(jīng)銷毀的房間
解決方案
1.盡可能在房間銷毀前停止匹配,比如持續(xù)12分鐘的房間,可以在最后30s停止匹配。
2.提示錯(cuò)誤。玩家手動(dòng)重新匹配。

CM_EnterRoom問題

1.玩家不存在,或登錄令牌錯(cuò)誤
解決方案:報(bào)錯(cuò)。
2.房間不存在
解決方案:報(bào)錯(cuò),重連業(yè)務(wù)服。
3.投遞消息時(shí)房間存在,(在房間線程)執(zhí)行消息時(shí)房間不存在
解決方案:報(bào)錯(cuò),重連業(yè)務(wù)服。

只匹配,但不登錄房間服的玩家如何清理

定時(shí)30分鐘檢查,Player關(guān)聯(lián)的房間銷毀則清理Player。

沒有啟動(dòng)定時(shí)器的房間如何銷毀

定時(shí)30分鐘檢查,30分鐘都沒有玩家進(jìn)入則銷毀房間。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,732評(píng)論 6 539
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,214評(píng)論 3 426
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,781評(píng)論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,588評(píng)論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,315評(píng)論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,699評(píng)論 1 327
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,698評(píng)論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,882評(píng)論 0 289
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,441評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,189評(píng)論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,388評(píng)論 1 372
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,933評(píng)論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,613評(píng)論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,023評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,310評(píng)論 1 293
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,112評(píng)論 3 398
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,334評(píng)論 2 377

推薦閱讀更多精彩內(nèi)容

  • 單區(qū)單服 游戲采用單區(qū)單服模式,職能上分成業(yè)務(wù)服和房間服。第一個(gè)版本的設(shè)計(jì),業(yè)務(wù)服為單點(diǎn)服務(wù)器,房間服可以無限拓展...
    瘋狂豬寶寶閱讀 3,712評(píng)論 3 7
  • 在開發(fā)球球游戲的過程中,為了解決事先沒有考慮到的問題,最終的實(shí)現(xiàn)和設(shè)計(jì)有所出入。其中有一部分是關(guān)于防御式編程的心得...
    瘋狂豬寶寶閱讀 505評(píng)論 0 3
  • 126.析構(gòu)器 在一個(gè)類實(shí)例銷毀前,一個(gè)析構(gòu)器會(huì)立即調(diào)用。使用deinit 關(guān)鍵字來表示析構(gòu)器, 跟構(gòu)造器寫法類似...
    無灃閱讀 826評(píng)論 0 4
  • 我之夜曲思路 因?yàn)殡娪啊朵撉偌摇罚又懒诵ぐ睿忠驗(yàn)楹⒆訉W(xué)琴我開始系統(tǒng)留意鋼琴曲子,肖邦在鋼琴音樂中的至...
    城邊書室閱讀 2,119評(píng)論 1 5
  • 1、穿壽衣 我叫李一兩,從小就沒有娘,聽說我娘是在生我的時(shí)候,難產(chǎn)走了,墳就埋在我們家后面。懂事之后,逢年過節(jié)我都...
    Smile_39ca閱讀 2,322評(píng)論 0 2