《棋牌游戏服务器》机器人设计

机器人的架构基于前面的游戏服务器架构设计展开,可以视为后者的附属设计。

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里面有自动回收逻辑,如果发现一个机器人长时间不活动,会认为这是一个僵尸而回收掉。

 

 

 
posted on 2019-02-23 18:26  longhuihu  阅读(2826)  评论(0编辑  收藏  举报