Steamworks 文献库
Steam Matchmaking & Lobbies

概览

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

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

游戏匹配流程

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

搜索大厅

To have your game search for a lobby, you need to call: ISteamMatchmaking::RequestLobbyList
This function is asynchronous, returning a SteamAPICall_t handle which you can use to track the state of the request. Depending on the users connection to the Steam back-end, this call can take from 300ms to 5 seconds to complete, and has a timeout of 20 seconds.
The number of results returned is in the LobbyMatchList_t call result, which you can then use ISteamMatchmaking::GetLobbyByIndex to iterate over them all and get their IDs.
Up to 50 results may be returned, but usually it's no more than a couple. The results are returned ordered by geographical distance and based on any near filters set. By default, we will not return lobbies that are already full, and the distance filter is set to k_ELobbyDistanceFilterDefault (nearby). To add filters, before you call RequestLobbyList you need to call one or more of the filtering functions:

创建大厅

If you can't find an existing lobby for a user to join, this is when you'd typically create a lobby. Just call
ISteamMatchmaking::CreateLobby and wait for it to complete. The call result indicates whether or not it succeeded, and if it did, it will return the steamID of the lobby in a LobbyCreated_t struct, which can be used to set metadata on the lobby. The first thing you'll want to do after you create a lobby is set a data on the lobby, that other game clients can use to search for it (see below).

加入大厅

If you've found a good lobby, either from a search or from a friend, you can use ISteamMatchmaking::JoinLobby and wait for the LobbyEnter_t call result. Once in the lobby, you'll want to use the lobby data API to get details about the lobby to work out what to display (if there is any display).

When a user joins or leaves a lobby, a LobbyChatUpdate_t callback is posted to all members of that lobby, including the owner.

To iterate which users are currently in a lobby, use:

To get more information about another user in the lobby, you'll need to use the friends API, see 好友、邀请和大厅 for more information.

大厅元数据

Lobby Metadata allows you to set the arbitrary state of the lobby, including the lobbies name, current map, game mode, current state of the game, or anything else you can think of.

A user will automatically have the latest lobby data for any lobby they are a member of. For lobbies returned via search results, the user will have lobby data for at the point in time as to when they did the search. If it's a friends' lobby, there will be no lobby data available to look at until ISteamMatchmaking::RequestLobbyData is called and has successfully completed.

If lobby data is changed on a lobby, all lobby members will receive a LobbyDataUpdate_t callback (this callback is the same way you know a ISteamMatchmaking::RequestLobbyData call has completed).

These are the set of functions you can use to get and set lobby data. Only the lobby owner can set or delete the lobby data.

Functions which allow you to iterate over the metadata, (this is typically only used for debugging purposes):

Lobbies also allow members to set their own metadata that other members can receive updates for with the following functions.

大厅内交流

To send information around within a lobby (chat messages, game start signals, etc.) you need to call ISteamMatchmaking::SendLobbyChatMsg, this sends a simple binary message to all users in the lobby. Lobby members need to listen for the callback ISteamMatchmaking::LobbyChatMsg_t. After receiving the callback you then can use ISteamMatchmaking::GetLobbyChatEntry to retrieve the contents of the message.

好友、邀请和大厅

You can find out all the lobbies a user's friends are in with the friends 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 is a valid lobby, you can join it or use RequestLobbyData() get its metadata } }

You can invite a friend to a lobby with ISteamMatchmaking::InviteUserToLobby
That user will receive a chat dialog with a link to join the game. If the user clicks the link, and they are not currently running the game, it will launch the game with the command-line:
+connect_lobby <64-bit lobby id>

If the user is already in a game, a ISteamFriends::GameLobbyJoinRequested_t callback will be posted, which contains the Steam ID of the lobby the user wishes to join. It's up to your game to decide to obey it or not.

If you want the user to select from a list of friends to invite to a lobby, you can call ISteamFriends::ActivateGameOverlayInviteDialog.
This will activate the Steam in-game overlay to a dialog designed for inviting friends to the current lobby.

验证

Any user in a Steam lobby is already fully authenticated with the Steam back-end. There is no need for the game to do any more authentication steps with lobby users, unless it's looking to see if they're VAC banned (see Valve Anti-Cheat Technology). If a user tries to log in from a second location with the same account, their prior login will automatically be removed from any existing lobbies.

清理

Once the game has started, each user can just leave the lobby with:
ISteamMatchmaking::LeaveLobby
Once all the users have left, the lobby is automatically destroyed on the back-end.

Lobby Tips

  • In general, only create lobbies when needed. For example, when the user invites a friend to play, or triggers a manual action that requires a lobby
  • Do not update the metadata on lobbies at a high frequency. Only add in metadata and values that are used for search (for example, game type or game state). You will not need to put in player counts, as a lobby search will already look for lobbies with available slots
  • Do not join lobbies just to find out their metadata. Lobby metadata can be downloaded separately for all lobbies, which your game can then use to either show a list of lobbies for a user to pick from, or the game can automatically decide which search result to join

More Questions?

Ask questions on the Steam Matchmaking & Lobbies discussion forum.