从零开始的MMORPG游戏服务器(20) - Visualize Server(3) - 获取玩家角色列表

160 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第13天,点击查看活动详情


本系列代码仓库:Stargazers · dyzdyz010/ex_mmo_cluster (github.com)

本节我将为 SceneServer 建立接口,用来向 VisulizeServer 提供数据。

SceneServer 中,各个玩家角色是以进程的形式存在的,所以没有一个天然的结构统一存放所有的角色数据。我的方案是再创建一个新的进程 PlayerManager ,用来存放所有的玩家角色进程,以及它们和各自 cid 的对应关系。每当一个角色进入场景的时候,网关服务器向 PlayerManager 发请求,由 PlayerManager 来创建角色进程,并将其存储到自身的状态里。同样地,当一个玩家断开连接时,角色进程在完全销毁前先通知 PlayerManager 把自己从角色进程列表中删除,然后自己再完成销毁。

所以思路就有了。PlayerManager 存放着所有玩家角色的索引,我们从这里获取完整列表,然后再分别向各个角色进程获取具体数据就行。我们只需要给 PlayerManager 增加一个接口:

@impl true
def handle_call(:get_all_players, _from, %{players: players} = state) do
  {:reply, {:ok, players}, state}
end

非常简单。让 VisualizeServer 调用一下试试看。先运行几个客户端,让服务器能有数据,否则获取的就是空的。之后在我们之前创建的 :data_update 消息处理函数中调用接口:

result =
      GenServer.call(
        {SceneServer.PlayerManager, :"scene1@127.0.0.1"},
        :get_all_players
      )
Logger.debug("玩家获取结果:#{inspect(result, pretty: true)}")

这里 :"scene1@127.0.0.1" 是场景服务器 SceneServer节点名称。按照 BEAM 节点集群要求,一个节点要想访问另一个节点,首先得知道 节点名称,其次自己节点的 cookie 得和要连接的节点一致。

Pasted image 20221204203535.png

可以看到已经完美获取了玩家角色列表,结构是一个 Map,键为 cid,值为对应角色进程 ID,即 pid

下一步

接下来我们按照已经获取到的进程列表,分别获取具体数据,并将数据打包发给前端用于展示。