ActorModel学习(四)--房间节点设计
房间模块设计
Room Factory
房间工厂,单例Actor(Main Actor / 对于Main Actor的定义可以参见之前的文章),职责是创建、查询、删除房间和保存房间的必要上下文。外界可通过此创建和获得房间的actor ref。
对外只需要暴露一个接口即可 / GetRoomReq。
Room Actor 的唯一引用如何设计,这里不打算内部定义,由用户自己考虑房间Id的唯一性
Game Room
框架中的房间节点的设计的宗旨是全,做所有功能的全量,让用户自行选择使用什么功能,从而提高框架的可适配性,不会出现独特的必要的房间功能导致房间节点不可用。
首先设计的对象是通用房间接口,由通用房间结构实现这个接口。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
type IGameRoom interface {
Init()
GetId() string
GetAllUsers() []string
GetAllPlayers() []string
CheckIsPlayer(uid string) bool //是否已加入游戏
CheckGameIsStart() bool // 游戏是否已经开始
GetRoomUser(uid string) (*gamepb.GamePlayer, *errors.Error)
DeletePlayer(uid string)
GetGamePlayer(uid string) (IGamePlayer, *errors.Error)
JoinGameCheck(uid string) *errors.Error
QuitGameCheck(uid string) *errors.Error
KickPlayerCheck(operUid, targetuid string) *errors.Error
JoinRoom(uid string, req *gamepb.JoinRoomReq) *errors.Error
QuitRoom(uid string) *errors.Error
GameOver()
CheckEnd() bool
AddDisConnectPlayer(uid string, tid uint64)
ReConnectPlayer(uid string)
ClearDisConnectPlayer(uid string)
CheckConnectPlayer(uid string) bool
OnGameEnd()
GetStateBroad() proto.Message
OnJoinGame(uid string, req *gamepb.JoinGameReq, isReady bool, autoStartNum int32) (*gamepb.PushRes, *errors.Error)
OnQuitGame(uid string) (*gamepb.PushRes, *errors.Error)
OnStartGame(uid string, force bool) (*gamepb.PushRes, *errors.Error)
OnGameSetting(uid string, json string) (*gamepb.PushRes, *errors.Error)
OnCloseGame(uid string, clearSeat bool) (*gamepb.PushRes, *errors.Error)
OnKickPlayer(operUid, targetuid string) (*gamepb.PushRes, *errors.Error)
OnJoinRoom(uid string, req *gamepb.JoinRoomReq) (*gamepb.PushRes, *errors.Error)
OnQuitRoom(uid string) (*gamepb.PushRes, *errors.Error)
OnReloadRoom(uid string) (*gamepb.PushRes, *errors.Error)
OnAutoGame(uid string) (bool, *errors.Error)
}
房间最重要的能力就是维护房间内用户的信息,房间只维护基本的用户信息,当用户进入游戏时,会产生游戏状态,身份也就进化为玩家,玩家信息维护在逻辑节点而不是房间节点。玩家信息是用户的超集,在逻辑节点产生用户快照的时候,需要向房间申请玩家的基本信息。
1
2
3
4
5
6
7
8
9
10
11
type User struct {
Uid string
UserInfo map[string]interface{}
MType MemberType
SType MemberType
}
type Player struct {
Uid string
}
房间内玩家类型分为用户和玩家。用户是指进入房间但没进入游戏的群体(市场上称之为观众),玩家是指进入房间同时进入游戏的群体(市场上称之为玩家)。房间内的玩家和游戏逻辑服内的玩家不一样,房间内的玩家结构带有的状态只与房间相关,游戏逻辑服内的玩家结构带有游戏的逻辑信息,用来生成快照、响应用户请求等用途,注意区分。
房间操作
加入房间操作
加入房间操作主要的任务就是初始化User对象,并记录在房间中。而初始化User对象的重点是向SDK获取User的Information。
开始游戏操作
开始游戏是个重要的操作节点,需要大量房间的信息和房间状态的更新。首先是游戏开始的前置检查:
- 检查房间状态、已开始的房间不可重复开启
- 检查玩家数量是否满足游戏开始条件
- 检查玩家状态、所有玩家是否全部准备
游戏快照同步中房间的地位
在开始游戏前,客户端需要获取快照以同步玩家位置信息和身份信息。但是玩家的位置信息和身份信息按照职责原则应该处于房间节点中,但是快照是通过游戏节点发出的。
第一个方案是房间和游戏节点共享玩家基本信息,但是维护一致性是非常麻烦的事情。
第二个方案是把游戏视为快照发送器,对房间开放接口向客户端推送快照。房间发送消息,带上快照需要的玩家信息即可。这样的方案显然比在房间和游戏节点中维护状态一致性要来的简单,效率也更高。