《棋牌游戏服务器》玩法服务器架构
大体上我们的玩法有两种模式,一种是小桌,比如斗地主,一局游戏需要2~6个人;另一种是大桌,所有用户都可以在一桌来玩。
所以“桌”是一个比较核心的概念,玩法服务器的结构也是围绕这个核心来展开的。
以桌为核心的玩法架构
上图是这个架构设计的核心要素,GameTable类位于这个设计的核心;左侧GameTableManager是一个桌的集合类,里面逻辑并不多;table类包含桌的核心数据,包括玩家、当前局的状态等,这个类在具体玩法中一般需要派生。
GameStateMachine类是一个状态机,棋牌的游戏流程是一个状态在管理,由消息驱动,后面会细讲。GameTableThread是table的消息处理线程,保证了每个table的消息都是单线程处理,没有并发。
玩法状态机
GameStateMachine是一个状态机的管理器,其实就是一组状态实例的集合;这些状态全部都继承自AbstractTableState。玩法需要多少个状态,与玩法本身的规则相关,一个状态对应了一组当前可以处理的消息。为了简化状态的代码,我们抽取了GameRequestProcessor这样的工具类。
最后,建议每个玩法都包含一个异常状态和一个等待状态。异常状态用来处理状态机异常状况,清理数据,保证优雅退出;等待状态是牌局开始的第一个状态,检查牌局是否具备了开始的条件。
消息的处理流程
游戏的过程其实就是消息处理的过程,所有的消息会被封装成TableMessage实例,推送到tableThread,后者再转发给当前的State。
SwitchState消息一般是状态机自己产生的;TimeOut消息是计时系统产生的;Request是来自客户端的消息;Join虽然也是来自客户端,但是特殊一点,要先交给匹配系统MatchSystem;
Kick消息一般来自Redis消息通道,用户被封禁时产生;Quit消息是网关发来的;MagicCommand是内部指令,也来自Redis消息通道;Dummy是一个哑消息,无特别含义。
BigRoom
上面有一个模块叫做BigRoom,这个模块是玩法服务器与网关对接的模块,同时初始化了玩法运行的一个上下文环境。由于历史原因,命名不是特别好。