如何在skynet_fly_demo新增一个游戏?

简介

通常基于游戏大厅的对战类型游戏不会只有一款玩法,像英雄联盟会有匹配场,排位场,大乱斗,还有一些限时玩法,克隆,无限火力。这些特殊玩法,通常分开开服比较好,相互隔离不影响。
skynet_fly_demo利用了skynet_fly房间类游戏架构可以非常快速的搭建房间对战类游戏,非常适合这种架构模式。那么如何在skynet_fly_demo新增一个游戏?我将已新增一个数字炸弹游戏为例子,进行逐步讲解。

回顾

在上一节(用户是如何匹配进入到游戏的?)中,我们了解到了用户->匹配->匹配成功->进入游戏的过程。新增一款游戏,其实就是把新款游戏加入到这个过程中,不过前提是先有游戏。

新增游戏

stop 1 创建游戏服务项目

在games文件夹下创建名为digitalbomb数字炸弹的游戏,这个文件夹的名字就是cluster_name,集群中的服务名。

stop 2 新增入口文件 main.lua

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
local skynet = require "skynet"
local contriner_launcher = require "skynet-fly.contriner.contriner_launcher"

skynet.start(function()
skynet.error("start digitalbomb>>>>>>>>>>>>>>>>>")
contriner_launcher.run()
--启动集群连接入口
skynet.uniqueservice("frpc_server")
--启动room_game_login 登录服务
skynet.uniqueservice("room_game_login")

skynet.call('.logger','lua','add_hook','common.log_hook')

skynet.exit()
end)

启动入口文件跟象棋是一样的。

stop 3 编辑load_mods.lua 文件

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
39
40
41
42
local redis_cfg = loadfile("../../commonlualib/common/etc/redis_cfg.lua")()
local server_cfg = loadfile("../../commonlualib/common/etc/server_cfg.lua")()
local gate_cfg = loadfile("../../commonlualib/common/etc/gate_cfg.lua")()
local frpc_server_cfg = loadfile("../../commonlualib/common/etc/frpc_server_cfg.lua")()
local mysql_cfg = loadfile("../../commonlualib/common/etc/mysql_cfg.lua")()

return {
--共享配置
share_config_m = {
launch_seq = 1000, --启动顺序,从小到大
launch_num = 1, --启动数量
default_arg = { --默认配置
--room_game_login用的配置
room_game_login = {
gateservice = "ws_gate", --gate 或者 ws_gate
--gate连接配置
gateconf = gate_cfg.games.digitalbomb_1,
login_plug = "common.plug.login_plug", --login加载的插件lua模块文件名
},
--cluster_server用的配置
frpc_server = frpc_server_cfg.games.digitalbomb_1,

server_cfg = server_cfg.games.digitalbomb_1,
}
},

--日志切割
logrotate_m = {
launch_seq = 5000,
launch_num = 1,
default_arg = {
file_path = './logs_1/', --文件路径
filename = 'server.log', --文件名
limit_size = 0, --最小分割大小
max_age = 7, --最大保留天数
max_backups = 7, --最大保留文件数
sys_cmd = [[
/usr/bin/pkill -HUP -f skynet.digitalbomb_config.lua.load_mods_1.lua\n
]], --系统命令
}
},
}

为了方便讲解查看,我把跟象棋相同的配置项都删除了,留下了需要改动的配置项。
gateconf ws_gate连接入口的配置
frpc_server 集群入口配置
server_cfg 服务的环境参数配置
sys_cmd 日志轮换的系统命令

load_mods.lua 只需要调整这几个配置即可,多开数字炸弹也是调整这几个配置。

stop 3 login_plug.lua 配置登录插件

login_plug插件可以跟象棋公用 login_plug = "common.plug.login_plug", --login加载的插件lua模块文件名,登录协议也可以共用。

stop 4 hall_plug.lua 配置大厅插件

1
2
3
4
5
6
7
8
--大厅服
room_game_hall_m = {
launch_seq = 2000, --第二个启动
launch_num = 6, --启动6个
default_arg = {
hall_plug = "common.plug.hall_plug", --大厅加载的插件lua模块文件名
}
},

大厅的功能就是接收心跳包、处理玩家进入房间的消息,也可以通用。

在项目服务下创建hall/hall/lua文件,加载对应公共模块即可。

1
2
3
4
return {
require "gamecommon.hall.player.player",
require "gamecommon.hall.match.match",
}

stop5 table_plug.lua 房间配置插件

这里插件里编辑游戏的交互逻辑,通常不能通用,在这里实现核心逻辑。游戏实现我就不赘述了。

步骤:
创建 table/table_plug.lua 实现逻辑

在load_mods.lua 中新增房间服配置

1
2
3
4
5
6
7
8
9
10
11
12
--房间服
room_game_table_m = {
launch_seq = 4000, --第四个启动
launch_num = 6, --启动6个
default_arg = {
table_plug = "table.table_plug", --房间插件
instance_name = "default",
table_conf = {
player_num = 2, --2个人玩
}
}
},

到此游戏可以说是加好了。

接入匹配流程

stop1 用户->匹配

用户进哪个游戏是用户决定了,所以客户端需要告诉服务端,需要去匹配哪个游戏。

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
--请求匹配
function M.do_match_game(player_id, pack_body)
--log.info("do_match_game >>> ",player_id, pack_body)
local game_id = pack_body.game_id
local game_server = GAME_ID_ENUM[game_id]
if not game_server then
log.error("do_match_game not exists gameid ", game_id)
return nil, errorcode.GAME_NOT_EXISTS, "GAME_NOT_EXISTS"
end

local game_room_info = game_redis.get_game_room_info(player_id)
if game_room_info and next(game_room_info) then
log.error("exists game_room_info ",player_id, game_room_info)
return
end

--log.info("do_match_game2 >>> ",player_id, pack_body)
if not rpc_matchserver_match.match(game_server, player_id) then
return nil
end
--log.info("do_match_game3 >>> ",player_id, pack_body)
--回复匹配
match_msg:match_game_res(player_id, {game_id = game_id})

return true
end

客户端传递的game_id,我们需要通过game_id找到对应游戏服务的cluster_name也就是游戏服务的文件夹名字,我们在GAME_ID_ENUM这里枚举文件中添加映射关系。

1
2
3
4
5
6
7
8
local enum = {
[1] = 'chinese_chess',
chinese_chess = 1,
[2] = 'digitalbomb',
digitalbomb = 2,
}

return enum

添加完映射关系后就能通过 rpc_matchserver_match.match(game_server, player_id)告诉匹配服,我需要匹配数字炸弹游戏。

stop2 匹配->匹配成功

之前匹配只知道有象棋游戏,不知道有数字炸弹游戏,这时候去匹配肯定不成功。此时我们需要改动matchserver
我们在load_mods.lua 中修改match_m和cluster_client_m的配置

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

--集群客户端
frpc_client_m = {
launch_seq = 4,
launch_num = 1,
default_arg = {
node_map = {
['logserver'] = true, --日志服
['hallserver'] = true, --大厅服
['chinese_chess'] = true, --中国象棋
['centerserver'] = true, --中心服
['digitalbomb'] = true, --数字炸弹
},
watch = 'redis', --监听redis的方式做服务发现
}
},
--匹配逻辑
match_m = {
launch_seq = 5,
launch_num = 2,
mod_args = {
{instance_name = "chinese_chess"},
{instance_name = "digitalbomb"},
}
},

因为match_m需要rpc请求digitalbomb数字炸弹游戏服,所以需要在cluster_client_m->node_map中把digitalbomb添加进去。
把launch_num从1改为2,在 mod_args 中新增 digitalbomb 的配置项,这样match_m就会启动2个,一个match_m处理象棋的匹配,一个处理数字炸弹的匹配。

到这里,数字炸弹游戏已经接入到匹配了。

stop3 匹配成功->进入游戏

这个流程是通用的。

stop4 重连处理

因为在开发环境中,我们并不会妥善的关服,一般就是强行重启,可能有些玩家正在游戏中,这时会玩家会残留游戏房间信息在redis,因为hallserver处理了重连游戏,玩家登录后,会查询游戏房间信息,存在即发给客户端进去重连。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
local function check_join_room_game(player_id)
local game_room_info = game_redis.get_game_room_info(player_id)
if not game_room_info or not next(game_room_info) then
return
end
local cli = frpc_client:instance(game_room_info.svr_name, "room_game_alloc_m")
cli:set_svr_id(game_room_info.svr_id)
local ret = cli:one_mod_call("exists", game_room_info.table_id)
if #ret.result > 0 and ret.result[1] then
M.cmd_join_game(player_id, game_room_info.token, game_room_info.host, game_room_info.table_id)
else
--说明房间已经不存在了
--删除房间信息
game_redis.del_game_room_info(player_id)
end
end

那如果出现了强行重启的情况,实际上redis记录的游戏房间信息是脏数据了,就需要清除,怎么确认是脏数据,就需要去对应的游戏服查询该房间存不存在,不存在即删除。
所以大厅服也会访问对应的游戏服,大厅服也需要在frpc_client_m->node_map中把digitalbomb加上。


如何在skynet_fly_demo新增一个游戏?
https://huahua132.github.io/2023/05/03/skynet_fly_word/word_4/F_q/
作者
huahua132
发布于
2023年5月3日
许可协议