機器人的架構基於前面的游戲服務器架構設計展開,可以視為后者的附屬設計。
1、設計目標
1)機器人與游戲主流程耦合性盡量少,機器人即使有問題,不影響主流程;
2)機器人由桌子線程驅動,不單獨開新的線程
機器人和游戲邏輯是在一個進程里面運行的,所以機器人直接對table進行訪問可以簡化系統的設計,但原則上,機器人只能對table進行只讀操作。
2、消息機制
為了達成目標1),決定機器人和游戲table之間使用消息通訊,把機器人當做客戶端,tabe當做服務端。
於是乎,定義了兩類消息,一類是RobotClientMessage,代表機器人發給table的消息;一類是RobotServerMessage,代表table發給機器人的消息。
消息的處理全部異步化,降低相互影響。
由於有了消息機制,達成目標2)就比較方面了,只要將消息push進table線程,table線程做分發即可。
對於RobotClientMessage,table線程交由table的狀態機處理,和處理來自客戶端的消息類似;對於RobotServerMessage消息,table線程交由robot實例處理;
這一步驟在game-core庫里面支持,game-core還增加了對robot時鍾的支持。
3、機器人的分配和銷毀
我們的目標是降低機器人和table之間的耦合性,所以盡量不讓table對機器人進行區別對待,同時table也不需要維護機器人列表。
有一個叫RobotManager的類來提供機器人的分配、查找、銷毀功能;
1)分配
RobotManager分配了機器人實例以后,會在redis里面加鎖,然后會周期性地掃描機器人是否仍然被占用,以刷新鎖。
2)銷毀
當機器人離開table的時候(是現在捕魚的table基類中處理),就是機器人銷毀的時候,此時RobotManager會在內存中刪除機器人並刪掉redis鎖。
3)查找
RobotManager里面會維護該服務器所有存活的機器人,所以很容器查找某個桌子有哪些機器人。
4、機器人的狀態機
機器人的行為可能比較復雜,所以也用狀態機的形式來實現,這和table的狀態機如出一轍,這里不做贅述。
有所區別的是,捕魚的機器人基類,預置了幾個狀態,比如RobotJoinState和RobotLeaveState,分別代表機器人入桌狀態和離桌狀態。
有些情況下,機器人可能不需要這兩個狀態,比如一些匹配式的玩法,不需要入桌流程,忽略即可。
5、核心類介紹
GameRobotBase,機器人核心基類,在game-core庫里面,具體玩法要繼承這個類。
方法 |
含義 |
---|---|
GameRobotBase(PlayerInfo) |
構造函數,所有機器人必須有僅且有一個該簽名的構造函數 |
initialize(gameTable) |
初始化,子類一般要重寫,由於機器人在創建的時候,可能還沒有桌子,所以初始化要單獨一個方法 |
addState(RobotState<RobotType> state) |
增加一個狀態,一般在子類的構造函數或initialize中調用 |
setExceptionStateId(int exceptionStateId) |
設定異常狀態,機器人邏輯發生異常時進入,捕魚里已經預置為RobotLeaveState |
start(int stateId, Object param) |
機器人啟動狀態機,只有調用了這個方法,機器人才會開始工作 |
changeState(int initStateId, Object param) | 狀態機切換狀態 |
addTimer(int timerType, long delayMillis, Object param) | 設置一個定時器 |
sendClientMessage(int msg, Object param) |
發送消息給桌子 |
acceptServerMessage(int msg, Object param) |
接收消息,當外部邏輯給機器人發消息時,調用這個方法 |
RobotState, 機器人狀態類
方法 |
含義 |
---|---|
enter(RobotType e,Object param); |
狀態進入回調 |
handleTimerEvent(RobotType e ,int timerType,Object param) |
處理時鍾事件,參見GameRobotBase.addTimer |
handleServerMessage(RobotType e, RobotServerMessage t) |
處理接收的消息,參見GameRobotBase.acceptServerMessage
|
AbstractTableState(table狀態機的狀態基類),用以支持機器人的方法:
方法 | 含義 |
---|---|
handleRobotClientMessage |
處理機器人發送的消息,參見GameRobotBase. sendClientMessage |
6、關於GameRobotBase.start方法
機器人在完成初始化之后,如果不調用start方法是不會運作的,但是不同的玩法start的調用時機有所不同。
1)一般的入桌子式的玩法,機器人分配好了就立即初始化,然后立即start,然后進入RobotJoinState;
2)匹配式的玩法,比如斗地主,在匹配過程中需要創建機器人,但此時對應的GameTable還沒有,等匹配成功之后,table創建好,才能完成初始化,然后再start;
原則是機器人可以提前創建,有了table就初始化,游戲邏輯需要這個機器人開始運作的時候就調用start。
3)機器人創建好了不能長時間不用(暫定5分鍾),RobotManager里面有自動回收邏輯,如果發現一個機器人長時間不活動,會認為這是一個僵屍而回收掉。