Steamworks 文献库
Steam 匹配与大厅

概览

Steam 的对等匹配建立在大厅的概念之上。 大厅是 Steam 后端服务器上与聊天室非常类似的实体。 用户可以创建新大厅,将数据与大厅关联、基于该数据搜索大厅、加入大厅,并与大厅中的其他用户共享信息。 每个大厅可以容纳多达 250 个用户,但多数游戏里一个大厅通常至多有 2 至 16 名玩家。 基于水平的匹配便建立在此系统之上。

Steam 对等匹配 API 是能让用户找到其他用户一起玩游戏的一组函数。 匹配函数都在 ISteamMatchmaking 之中,此 API 包含有各函数之参数的更多详情。 大厅与玩家或游戏服务器一样,通过独一无二的 Steam ID 进行识别。 Steamworks 示例有一整套关于大厅的工作实现。

游戏匹配流程

让一组玩家共同玩游戏的常见模式如下:
  1. 玩家在游戏中选择玩多人游戏,以及想玩的多人游戏类型(规则、场景等)。
  2. 游戏会利用大厅搜索 API 寻找规则相同的大厅。
  3. 如果找到大厅,游戏便会让用户加入该大厅;如果找不到,便会创建新大厅。
  4. 用户待在大厅内等待有足够玩家启动游戏。 大厅成员之间就希望玩的角色或其他用户设置进行数据交流。 如果大厅中有需执行的规则(例如,只有一个玩家能玩某个角色),则由且仅能由一个大厅所有者进行决断。
  5. 大厅可以有也可以没有相关玩家接口。如果有,大厅数据交流函数可以用于在大厅成员间发送聊天消息。 也可以发送语音数据,但是需要使用 Steam 网络 API。
  6. 游戏一旦就绪,玩家均加入游戏服务器,或连接至主持游戏的指定用户处,之后离开大厅。 当所有玩家离开大厅后,大厅便会自动销毁。

搜索大厅

要让您的游戏搜索大厅,您需要调用:ISteamMatchmaking::RequestLobbyList
此异步函数返回 SteamAPICall_t 句柄,您可以用于跟踪请求的状态。 视用户与 Steam 后端的连接状况而定,此调用可能需要 300 毫秒至 5 秒完成,20 秒则超时。
结果数量返回在 LobbyMatchList_t 调用结果中,然后您可以使用 ISteamMatchmaking::GetLobbyByIndex 进行循环访问,获得所有 ID。
可以返回多达 50 个结果,但一般不会超过几个。 结果以地理距离为序返回,并且基于任何临近位置筛选器。 默认情况下,我们不会返回已满员的大厅,并且距离筛选器被设置为k_ELobbyDistanceFilterDefault(附近)。 要添加筛选器,在调用 RequestLobbyList 之前,您需要调用一个或多个以下函数:

创建大厅

如果您无法找到用户能加入的既有大厅,通常这时候您就需要创建一个大厅。 只需要调用
ISteamMatchmaking::CreateLobby,待其完成。 调用结果将显示其是否成功。如果成功,将在 LobbyCreated_t 结构中返回大厅的 SteamID,可用于设置该大厅的元数据。 您创建大厅之后首先要做的是设置该大厅的数据,以便其他游戏客户端能用来进行搜索(参见下文)。

加入大厅

如果您通过搜索或好友找到了一个好大厅,您可以使用 ISteamMatchmaking::JoinLobby,等待 LobbyEnter_t 调用结果。 一旦进入大厅,您会想要使用大厅数据 API 以获得大厅详情,以决定显示些什么(若有显示)。

用户加入或离开大厅时,该大厅内的所有成员都会收到 LobbyChatUpdate_t 回调,包括大厅所有者。

要循环访问当前在大厅中的用户,请使用:

要获得大厅中其他用户的更多信息,您需要使用好友 API,请参见好友、邀请和大厅,了解更多。

大厅元数据

大厅元数据允许您设置大厅的任意状态,包括大厅名称、当前地图、游戏模式、当前游戏状态或其他任何内容。

用户将自动获得他们所隶属大厅的最新大厅数据。 对通过搜索结果返回的大厅,用户将获得他们进行搜索时的大厅数据。 如果为好友大厅,只有在调用并成功完成 ISteamMatchmaking::RequestLobbyData 后,才能查看大厅数据 。

如果一个大厅的数据发生了变动,所有大厅成员将收到 LobbyDataUpdate_t 回调(此回调与您获知 ISteamMatchmaking::RequestLobbyData 调用已完成的方式相同)。

以下为您可以用于获得并设置大厅数据的一组函数。 只有大厅所有者能够设置或删除大厅数据。

以下函数能让您循环访问元数据(通常仅用于调试目的):

使用以下函数,大厅也允许成员设置属于自己的元数据,供其他成员获取更新。

大厅内交流

在大厅内发送信息(聊天消息、游戏开始信号等),您需要调用 ISteamMatchmaking::SendLobbyChatMsg。这将向大厅内的所有用户发送一条简单的二进制消息。 大厅成员需要听取 ISteamMatchmaking::LobbyChatMsg_t 回调。 收到回调后,您可以使用 ISteamMatchmaking::GetLobbyChatEntry 获取消息内容。

好友、邀请和大厅

使用好友 API,您就可以找到一名用户的好友们所处的所有大厅。
int cFriends = SteamFriends()->GetFriendCount( k_EFriendFlagImmediate ); for ( int i = 0; i < cFriends; i++ ) { FriendGameInfo_t friendGameInfo; CSteamID steamIDFriend = SteamFriends()->GetFriendByIndex( i, k_EFriendFlagImmediate ); if ( SteamFriends()->GetFriendGamePlayed( steamIDFriend, &friendGameInfo ) && friendGameInfo.m_steamIDLobby.IsValid() ) { // friendGameInfo.m_steamIDLobby 为有效大厅,您可以加入其中或使用 RequestLobbyData() 获取其元数据 } }

使用 ISteamMatchmaking::InviteUserToLobby,您可以邀请一个好友至一个大厅。
该用户将收到一个带有链接的聊天对话,以加入该游戏。 如果该用户点击该链接,但当时并未运行该游戏,这将通过以下命令行启动游戏:
+connect_lobby <64-bit lobby id>. 确保您的应用实现了 ISteamApps::GetLaunchCommandLine ,以便您可以在通过命令行启动时禁用弹出警告。

如果用户已在游戏中,将提交 ISteamFriends::GameLobbyJoinRequested_t 回调,其中包含了用户希望加入的大厅的 Steam ID。 这将由您的游戏决定是否接受。

如果您希望用户从好友列表中选择好友邀请加入大厅,您可以调用 ISteamFriends::ActivateGameOverlayInviteDialog
这将激活 Steam 游戏内叠加界面,转至一个对话,用于邀请好友至当前大厅。

验证

Steam 大厅中的所有用户都已由 Steam 后端完全验证。 游戏无需再与大厅用户进行任何验证步骤,除非是查看是否用户受到了 VAC 封禁(参见 Valve 反作弊技术)。 如果一名用户试图使用同一个帐户在其他地方登录,其之前的登录将自动从任何现存大厅中移除。

清理

游戏一旦开始,各用户可以使用此函数离开大厅:
ISteamMatchmaking::LeaveLobby
一旦所有用户离开大厅,该大厅将在后端自动销毁。

大厅提示

  • 一般情况下,只在需要时才创建大厅, 例如,用户要求好友一起玩游戏时,或触发了需要大厅的手动操作时。
  • 不要频繁地更新大厅的元数据。 只添加用于搜索的元数据和值(例如游戏类型或游戏状态)。 您不需要加入玩家数量,因为进行大厅搜索时已经查找了有空位的大厅。
  • 不要只是为了查找大厅的元数据而加入大厅。 所有大厅的元数据均可分别下载,以便您的游戏用于显示大厅列表,供用户从中选择,或游戏可自动决定应加入哪个搜索结果。

更多问题?

请在 Steam 匹配与大厅论坛进行咨询。