关于room_game可热更匹配房间类游戏架构的优化
前言
在用这种架构模式实现中国象棋游戏的过程中,发现之前的设计有些诟病的地方。
- gate和fd没必要暴露给业务层。
- 登录后连接大厅就行,不用强制进房间,这样能适配的业务功能更广泛,进不进房间应该由业务决定,退出房间也一样,退出不代表登出。
- 缺少通用的发消息接口。
- 消息处理函数不够优雅。
- 业务层缺少CMD命令注册入口。
- table缺少主动访问hall大厅和alloc的接口。
优化
新版本的room_game主要针对以上六点做了相关优化。
- 去掉gate,fd 对上层业务的传递,提供发消息的接口。
- 登录仅仅连接大厅,提供桌子的相关操作接口。
- login,hall,table都提供,并且接口保持统一,通用。
- 消息是否转发判断逻辑为,大厅服没有注册处理,转发到桌子服,还没有桌子服,或者桌子服没有处理,视为丢弃消息打印日志即可。
- 提供业务注册CMD消息的入口,并限制命令不可重复注册。
- 提供相关接口。
接口介绍
架构的接口可以分为回调接口和主动调用接口。
回调接口
就是模块挂载的插件需要实现的方法。
登录
init(interface_mgr)
,初始化。
参数:interface_mgr
是主动接口入口。unpack(msg,sz)
,解包。
参数:msg
网络包消息。sz
网络包长度。send(gate,fd,packname,pack_body)
,发包函数。
参数:gate
网关服务id。fd
连接绑定的id。packname
包名。pack_body
包内容。check(packname,pack_body)
,客户端建立连接后,第一条消息应该为登录消息,这里进行登录检查。
参数:packname
包名。pack_body
包内容。
返回值:
成功返回:player_id
玩家id。
失败返回:false
errorcode
失败错误码。errormsg
失败消息内容。login_failed(player_id,errcode,errmsg)
,登录失败。player_id
玩家id。errorcode
失败错误码。errormsg
失败消息内容。
参数传递为check失败或者hall大厅connect连接失败传递的错误码。
login_succ(player_id,login_res)
,登录成功。player_id
玩家id。login_res
大厅服返回的登录结果。login_out(player_id)
登出,玩家主动登出,或者玩家断线超时了被踢出。player_id
玩家id。disconnect(player_id)
掉线。player_id
玩家id。logining(player_id)
正在登录中,正在处理登录消息,通常客户端狂发登录消息导致。player_id
玩家id。repeat_login(player_id)
重复登录。多连接登录了,此处可以给旧连接发错误码,旧连接将被踢断开。player_id
玩家id。`register_cmd
` 注册命令表。
大厅
init(interface_mgr)
,初始化。
参数:interface_mgr
是主动接口入口。unpack(msg,sz)
,解包。
参数:msg
网络包消息。sz
网络包长度。send(gate,fd,packname,pack_body)
,发包函数。
参数:gate
网关服务id。fd
连接绑定的id。packname
包名。pack_body
包内容。connect(player_id)
,连接大厅。
参数:player_id
玩家id。
返回值:
不同意连接:false
errorcode
失败错误码。errormsg
失败消息内容。
传递到login_faild
同意连接:login_res
连接成功内容,将传递到login_succ
disconnect(player_id)
,掉线。
参数:player_id
玩家id。reconnect(player_id)
,重连。
参数:player_id
玩家id。
返回值:与connect相同即可。goout(player_id)
,登出,也就是agent对象要被删除了。player_id
玩家id。register_cmd
注册命令表。handle_end
消息处理结束。
分配
init(interface_mgr)
,初始化。
参数:interface_mgr
是主动接口入口。match(player_id)
,匹配。
参数:player_id
玩家id。
返回值:
匹配到:尝试进入桌子。table_id
没有匹配到:会尝试创建新桌子。nil
createtable(table_name, table_id, config, create_player_id)
创建桌子
参数:table_name
桌子名称,也就是mod_config参数里面填的instance_name。table_id
桌子唯一id。config
桌子在mod_config中的填写的配置。create_player_id
创建人,match匹配的创建人没有,表示是系统创建的。entertable(table_id,player_id)
玩家进入桌子。
参数:table_id
桌子唯一id。player_id
玩家id。leavetable(table_id,player_id)
离开桌子。
参数:table_id
桌子唯一id。player_id
玩家id。dismisstable(table_id)
解散桌子,所有玩家都离开后,调用。
参数:table_id
桌子唯一id。player_id
玩家id。tablefull()
桌子已满,创建桌子触发
返回值false
errorcode
失败错误码。errormsg
失败消息内容。table_not_exists()
桌子不存在,进入桌子触发
返回值false
errorcode
失败错误码。errormsg
失败消息内容。register_cmd
注册命令表。
桌子
init(interface_mgr)
,初始化。
参数:interface_mgr
是主动接口入口。send(gate,fd,packname,pack_body)
,发包函数。
参数:gate
网关服务id。fd
连接绑定的id。packname
包名。pack_body
包内容。table_creator(table_id)
桌子创建者。
参数:table_id
新建的table_id。
返回值:
table
字段:enter(player_id)
,进入玩家。
参数:player_id
玩家id。
返回值:
成功:true
失败:false
errorcode
失败错误码。errormsg
失败消息内容。
leave(player_id)
,离开玩家。
参数:player_id
玩家id。
返回值:
成功:true
失败:false
errorcode
失败错误码。errormsg
失败消息内容。
disconnect(player_id)
,玩家掉线。
参数:player_id
玩家id。
reconnect(player_id)
,重连。
参数:player_id
玩家id。
handle
消息处理表
table
key packname
包名
value handle_func(player_id,packname,pack_body)
处理函数
参数:player_id
玩家id。packname
包名。pack_body
包内容。
handle_end
消息处理结束。register_cmd
注册命令表。
主动调用接口
登录
is_online(player_id)
是否在线。send_msg(player_id,packname,pack_body)
发送消息。send_msg_by_player_list(player_list,packname,pack_body)
发送消息给部分玩家。broad_cast_msg(packname,pack_body)
广播发送消息。
大厅
is_online(player_id)
是否在线。create_join_table(player_id,table_name)
创建进入房间。match_join_table(player_id,table_name)
匹配进入房间。join_table(player_id,table_name,table_id)
进入房间。leave_table(player_id,table_name,table_id)
离开桌子。goout(player_id)
登出。handle(packname,func)
设置消息处理函数。send_msg(player_id,packname,pack_body)
发送消息。send_msg_by_player_list(player_list,packname,pack_body)
发送消息给部分玩家。broad_cast_msg(packname,pack_body)
广播发送消息。get_hall_server_id()
获取大厅id。get_alloc_server_id(player_id)
获取分配服id。get_table_server_id(player_id)
获取桌子服id。get_table_id()
获取桌子id。
分配
create_table(table_name)
创建桌子。dismisstable(table_id)
销毁桌子。get_empty_map()
获取空桌列表。
桌子
new(table_id)
创建绑定table_id的接口对象。kick_out_all()
踢出该桌子所有玩家。kick_player(player_id)
踢出单个玩家。send_msg(player_id,packname,pack_body)
发送消息。send_msg_by_player_list(player_list,packname,pack_body)
发送消息给部分玩家。broad_cast_msg(packname,pack_body)
广播发送消息。send_hall(player_id,cmd,...)
用send的方式给大厅发消息。call_hall(player_id,cmd,...)
用call的方式给大厅发消息。send_alloc(cmd,...)
用send的方式给分配服发消息。call_alloc(cmd,...)
用call的方式给分配服发消息。
总结
通过优化架构,提高了架构易用性,扩展性和使用便捷性。