開發筆記:遊戲中的好友系統

挺久沒更新文章了,這一年以來個人經歷了許多事情,去年下半年開始穩定下來了,但今年初始又趕上疫情,公司的項目進度也推遲了,現在好不容易復工,登錄了許久不上的博客,發現自己收到了很多新的關注和私信,也有很多網友表達了對自己文章的支持,在這裏先表達自己的感謝。其次對於一些網友詢問的問題,在這裏統一回復下:之前那一系列對於英雄遠征源碼分析的文章質量其實不高,各位隨便看看就行了...至於交流,本人工作經驗尚淺,不是什麼大神,就不打擾浪費大家時間了...至於上一篇英雄遠征的Erlang源碼,有時間會重新整理一遍,附加一些運行說明,確保都能跑起來。

閒話不多說了,最近在參與公司的新項目,對涉及到好友系統的部分有一些自己的理解和疑惑,在此隨手記錄一下

確認幾個前提:
    遊戲中每個玩家是一個語言級別的輕量級的進程,A進程要給B進程發送消息需要使用語言層面的RPC調用。
    玩家的好友數據保存在數據庫和內存緩存中。
    離線事件:有專門的離線事件管理進程,當給離線玩家派發一個事件(比如有人給其發送了好友申請),進程會將事件先進行保存(數據庫,緩存),玩家上線時通過離線事件管理進程取出,並執行其中的操作(收到該好友申請)。

保存的好友結構:
    好友列表
    臨時好友列表
    申請列表
    黑名單列表
    
先抽出一個最簡單的過程:
    添加好友:A向B申請好友,B收到A的申請,彈出“XXX請求添加你爲好友 確認 拒絕”,B點了確認,則A出現在了B的好友列表中,B自己也被添加到了A的好友列表
    刪除好友:A把B從好友列表刪除,則A自己也從B的好友列表消失了
    黑名單:不再贅述
    這些操作在對方離線的時候也是可執行的。
    
加好友過程:
    A申請B:A向B發送申請請求,B收到請求後將A放入申請列表
    B同意A:B向A發送同意信息,將A從申請列表中刪除,放入臨時好友列表
    B拒絕A:B向A發送拒絕信息,將A從申請列表中刪除
    A收到B的同意:A自動向B發送確認同意信息,將B放入好友正式列表
    B收到A的確認:B將A放入好友正式列表
    
    有點像TCP三次握手
    (1)A -> B:請求好友(請求建立連接)
    (2)A <- B:同意好友(同意建立連接)
    (3)A -> B:確認好友(確認建立連接)
    
    中間任一個階段條件檢查未通過都不能成功加好友
    條件檢查涉及幾個地方:目標玩家是否存在,自己的好友列表是否已滿,對方的好友列表是否已滿,是否已經建立關係,是否被拉黑
    
    需要進行條件檢查的地方:A給B發申請前;B收到申請時;B給A回覆同意時;A給B發送確認時;B收到A的確認時。
    
    其中每個階段,任一方都有可能離線,需要進行離線事件的處理
    
    在線的情況:
    A向B發出申請時,B將A放入申請列表。
    B選擇同意好友,將A從申請列表中刪除,同時加入自己的臨時好友列表(因爲A那邊沒確認),給A發出同意信息
    A給B發出確認添加好友的信息,B收到A的確認信息後不用再回復,只要把A從臨時列表刪除,加入到好友列表中即可。
    
    離線的情況:
    一個原則:任一玩家無法修改其他離線玩家的數據。
    A向B發出申請,B離線,給B發離線事件,A下線。
    B上線,取出離線事件,把A加入申請列表;同意A的申請,把A從申請列表刪除,加入自己的臨時列表。此時A離線,但又不能讓B等待A返回的確認結果(玩遊戲的時候確實沒等),於是決定讓離線進程代替A進行確認的判斷,把加好友的數據寫入離線進程,給B返回確認的結果。等A上線後從離線進程取出離線期間加好友的數據,再寫回給A。
    離線進程/A在線,返回了確認的結果但B離線(剛同意完以很快的速度下線了,或者網比較卡),給B發同意的離線事件。
    B上線,取出離線事件,把A從臨時列表刪除,加入正式的好友列表。
    
也有直接使用公共緩存保存好友數據的方式,每次好友關係的變動無論對方是否在線都只需要修改公共緩存,緩存定期同步到數據庫中。離線轉換爲在線狀態時,只需要從公共緩存中加載自己的好友數據。
    
刪除好友步驟(雙向):
    A想刪掉B,此時先把B從好友列表刪除。
    如果B在線,則把B列表中的A刪除;如果B離線,則給B派發離線事件,等B上線把A從B的好友列表中刪除
    
黑名單步驟(單向):
    A拉黑B,直接把B加入黑名單列表中。
    
推薦好友列表:
    隨便隨機幾個
    
極端情況考慮:
    現在我們有三個人:A,B和C,
    情況1:A和B同時向C發出申請,但C只有一個好友位置
        此時C首先同意了A的申請,將A加入自己的好友列表,同時C的好友列表已滿,則C無法再同意B的申請。需要在C同意B時對C的好友列表進行檢查。是需要在同意階段(2)檢查被申請方的好友列表長度。
        
    情況2:A向B發出申請,B向C發出申請,但B只有一個好友位置
        若B先同意了A發出的申請,則C無法再同意B的申請。是需要在確認階段(3)對申請方好友列表長度進行檢查。
        若C先同意了B的申請,則B無法同意A的申請。是需要在同意階段(2)檢查被申請方的好友列表長度。
        
    情況3:A申請B,B申請C,C申請A,此時每個人都是隻有一個好友列表
        其實也沒那麼複雜:若B同意了A,則C無法同意B,A無法同意C。需要在好友確認階段(3)檢查申請方好友列表長度,在同意階段(2)檢查被申請方好友列表長度。
        
    情況4:A向B申請了,B也向A申請了
        此時A和B都在相互的申請列表中,申請過程中只要做好是否已經是好友的檢查問題應該不大。
        
    要防止超出好友列表長度,只需要在同意階段(2)檢查被申請方好友列表長度,確認階段(3)檢查申請方好友列表長度即可。不過考慮實際需求變化和保險起見,最好能想到的地方都加上相關檢查。
    
幾個疑問:
    參考了一些網絡上的文章,好友系統的設計只有兩個步驟:請求好友(1)和同意好友(2),那麼本文中的第三個步驟確認好友(3)是否是多餘的,正如TCP的三次握手,如果涉及到“確認”這一步,可能會掉入A給B發送消息,B給A發送確認消息,A給B發送確認消息的確認...一種循環中,而如果將TCP三次握手中的第三次去掉的話,影響會和好友系統中去掉確認好友(3)步驟一樣嗎。說到底,拿添加好友的過程類比TCP三次握手是否恰當...
    
    ...

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章