Post

ActorModel学习(四)--房间节点设计

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。

开始游戏操作

开始游戏是个重要的操作节点,需要大量房间的信息和房间状态的更新。首先是游戏开始的前置检查:

  • 检查房间状态、已开始的房间不可重复开启
  • 检查玩家数量是否满足游戏开始条件
  • 检查玩家状态、所有玩家是否全部准备

游戏快照同步中房间的地位

在开始游戏前,客户端需要获取快照以同步玩家位置信息和身份信息。但是玩家的位置信息和身份信息按照职责原则应该处于房间节点中,但是快照是通过游戏节点发出的。

第一个方案是房间和游戏节点共享玩家基本信息,但是维护一致性是非常麻烦的事情。

第二个方案是把游戏视为快照发送器,对房间开放接口向客户端推送快照。房间发送消息,带上快照需要的玩家信息即可。这样的方案显然比在房间和游戏节点中维护状态一致性要来的简单,效率也更高。

This post is licensed under CC BY 4.0 by the author.