> ## Documentation Index
> Fetch the complete documentation index at: https://devdocs.xbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 多人游戏任务

> 常见 2015 多人游戏任务的代码示例:订阅 MPSD 更改、创建会话、发送邀请、加入、匹配票证和活动。

<a id="top" />

本主题介绍如何实现与使用 2015 多人游戏相关的特定任务。

本主题涵盖以下内容:

* [订阅多人游戏会话目录 (MPSD) 会话更改通知](#sfmscn)
* [创建 MPSD 会话](#cams)
* [为 MPSD 会话设置仲裁者](#set-an-arbiter-for-an-mpsd-session)
* [管理标题激活](#mta)
* [使用户可加入](#mtuj)
* [发送游戏邀请](#sgi)
* [从大厅会话加入游戏会话](#jagsfals)
* [从标题激活加入 MPSD 会话](#jamsfata)
* [设置用户的当前活动](#stuca)
* [更新 MPSD 会话](#update-an-mpsd-session)
* [离开 MPSD 会话](#lams)
* [在匹配期间填补空闲会话位置](#fossdm)
* [创建匹配票证](#camt)
* [获取匹配票证状态](#gmts)

<a id="sfmscn" />

## 订阅多人游戏会话目录 (MPSD) 会话更改通知

<Note>订阅会话更改要求关联的玩家在会话中处于活动状态。还必须在会话的 `/constants/system/capabilities` 对象中将 `connectionRequiredForActiveMembers` 字段设置为 `true`。此字段通常在会话模板中设置。有关详细信息,请参阅[多人游戏会话模板](/services/xbox-services/multiplayer/mpsd/concepts/live-session-templates)和[多人游戏会话目录概述](/services/xbox-services/multiplayer/mpsd/live-mpsd-overview)。</Note>

要接收 MPSD 会话更改通知,标题可以使用以下过程。

1. 对同一用户的所有调用使用相同的 `XblContextHandle` 对象。订阅与此对象的生存期绑定。如果有多个本地用户,请为每个用户使用单独的 `XblContextHandle` 对象。

2. 为 [XblMultiplayerAddSessionChangedHandler](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayeraddsessionchangedhandler) 和 [XblMultiplayerSessionSubscriptionLostHandler](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayersessionsubscriptionlosthandler) 实现事件处理程序。

3. 如果要订阅多个用户的更改,请向您的 `XblMultiplayerAddSessionChangedHandler` 事件处理程序添加代码以避免不必要的工作。使用 [XblMultiplayerSessionChangeEventArgs](/reference/live/xsapi-c/multiplayer_c/structs/xblmultiplayersessionchangeeventargs)`::Branch` 属性和 [XblMultiplayerSessionChangeEventArgs](/reference/live/xsapi-c/multiplayer_c/structs/xblmultiplayersessionchangeeventargs)`::ChangeNumber` 属性。使用这些属性可以跟踪看到的最后一次更改并忽略较旧的更改。

4. 调用 [XblMultiplayerSetSubscriptionsEnabled](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayersetsubscriptionsenabled) 以允许订阅。

5. 创建本地会话对象,然后作为活动加入该会话。

6. 为每个用户调用 `XblMultiplayerAddSessionChangedHandler`,传入要通知的会话更改类型。

7. 按照本主题中的[更新 MPSD 会话](#update-an-mpsd-session)部分所述,将会话写入 MPSD。

以下流程图显示如何通过订阅上一过程中所述的事件启动多人游戏。

<img src="https://mintcdn.com/microsoft-4404708b/gzrdvT5kpqAXKEQt/images/gdk/services/Multiplayer_2015_Start_Multiplayer.png?fit=max&auto=format&n=gzrdvT5kpqAXKEQt&q=85&s=69f53200e2e51e3d975a3e5e7c9967fe" alt="流程图图片,展示了如何通过订阅上一过程中所述的事件启动多人游戏。" width="493" height="456" data-path="images/gdk/services/Multiplayer_2015_Start_Multiplayer.png" />

### 解析重复的会话更改通知

当有多个用户订阅同一会话的通知时,对该会话的每次更改都会触发每个用户的提醒通知。
除了其中一个,所有这些提醒通知都是重复的。

尽管我们仍建议标题为会话中的每个用户订阅通知,但标题应忽略已经收到通知的任何更改。您可以使用 `Branch` 和 `ChangeNumber` 属性执行此操作。

要检测多个提醒通知,标题应执行以下操作:

* 为每个评估的 `Branch` 属性值存储最新的 `ChangeNumber` 属性值。

* 如果提醒通知的 `ChangeNumber` 属性值高于该 `Branch` 属性值的最新存储值,则处理该提醒通知,然后更新最新的 `ChangeNumber` 属性值。

* 如果提醒通知的 `ChangeNumber` 属性值对于该 `Branch` 属性值不更高,则跳过处理该提醒通知。该会话更改已被处理。

<Note>`ChangeNumber` 属性值需要按 `Branch` 属性值跟踪,而不是按会话跟踪。`Branch` 属性值可以在会话的生存期内更改,重置 `ChangeNumber` 属性值。</Note>

[返回本主题顶部。](#top)

<a id="cams" />

## 创建 MPSD 会话

<Note>默认情况下,当第一个成员加入 MPSD 会话时,该会话就会创建。如果您的标题逻辑期望在加入时该标题存在或不存在,它可以在会话更新期间将适当的写入模式值传递给写入方法。</Note>

标题必须执行以下操作才能创建新会话。

1. 创建一个新的 `XblContextHandle` 对象。您的标题创建一次此对象,存储它,并根据源代码中的需要重用它。必须使用完全相同的上下文,尤其是在处理会话订阅时。

2. 使用 [XblMultiplayerSessionCreateHandle](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayersessioncreatehandle) 创建一个新的 `XblMultiplayerSessionHandle`,以准备 MPSD 创建新会话所需的所有会话数据。

3. 在将会话写入 MPSD 之前进行必要的更改。例如,当通过调用 [XblMultiplayerSessionJoin](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayersessionjoin) 将成员加入会话时,客户端会添加隐藏的本地请求数据,告知 MPSD 在调用更新会话时加入。

4. 完成本地更改后,按照本主题中的[更新 MPSD 会话](#update-an-mpsd-session)部分所述将它们写入 MPSD。

5. 从 MPSD 接收新的 `XblMultiplayerSessionHandle` 对象,其中填充了许多字段。

6. 之后使用新的会话对象。丢弃包含创建新会话的隐藏请求的旧副本。

### 示例

**平面 C API**

```cpp theme={null}
auto asyncBlock = std::make_unique<XAsyncBlock>();
asyncBlock->queue = queue;
asyncBlock->context = nullptr;
asyncBlock->callback = [](XAsyncBlock* asyncBlock)
{
    std::unique_ptr<XAsyncBlock> asyncBlockPtr{ asyncBlock }; // Take over ownership of the XAsyncBlock*.

    XblMultiplayerSessionHandle sessionHandle;
    HRESULT hr = XblMultiplayerWriteSessionResult(asyncBlock, &sessionHandle);
    if (SUCCEEDED(hr))
    {
        // Process multiplayer session handle.
    }
    else
    {
        // Handle failure.
    }
};

XblMultiplayerSessionReference ref;
pal::strcpy(ref.Scid, sizeof(ref.Scid), SCID);
pal::strcpy(ref.SessionTemplateName, sizeof(ref.SessionTemplateName), SESSION_TEMPLATE_NAME);
pal::strcpy(ref.SessionName, sizeof(ref.SessionName), SESSION_NAME);

XblMultiplayerSessionInitArgs args = {};

XblMultiplayerSessionHandle sessionHandle = XblMultiplayerSessionCreateHandle(XUID, &ref, &args);

auto hr = XblMultiplayerSessionJoin(
    sessionHandle,
    memberCustomConstantsJson.c_str(),
    initializeRequested,
    joinWithActiveStatus);
    
 hr = XblMultiplayerWriteSessionAsync(xblContextHandle, sessionHandle, XblMultiplayerSessionWriteMode::CreateNew, asyncBlock.get());
if (SUCCEEDED(hr))
{
    // The call succeeded, so release the std::unique_ptr ownership of XAsyncBlock* because the callback will take over ownership.
    // If the call fails, std::unique_ptr will keep ownership and delete XAsyncBlock*.
    asyncBlock.release();
}
```

有关详细信息,请参阅以下内容:

* [XAsyncBlock](/reference/system/xasync/structs/xasyncblock)

* [XblMultiplayerSessionCreateHandle](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayersessioncreatehandle)

* [XblMultiplayerSessionInitArgs](/reference/live/xsapi-c/multiplayer_c/structs/xblmultiplayersessioninitargs)

* [XblMultiplayerSessionReference](/reference/live/xsapi-c/multiplayer_c/structs/xblmultiplayersessionreference)

* [XblMultiplayerSessionWriteMode](/reference/live/xsapi-c/multiplayer_c/enums/xblmultiplayersessionwritemode)

* [XblMultiplayerWriteSessionAsync](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayerwritesessionasync)

* [XblMultiplayerWriteSessionResult](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayerwritesessionresult)

[返回本主题顶部。](#top)

<a id="set-an-arbiter-for-an-mpsd-session" />

## 为 MPSD 会话设置仲裁者

标题使用以下过程为已创建的会话设置仲裁者。

<Note>成员(潜在主机)的设备令牌在成员加入会话并包含其安全设备地址之前不可用。</Note>

1. 通过调用 [XblMultiplayerSessionMembers](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayersessionmembers) 从 MPSD 检索主机候选者的设备令牌。

   > \[!NOTE]
   > 如果会话是由 SmartMatch 匹配创建的,您的客户端可以通过调用 [XblMultiplayerSessionHostCandidates](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayersessionhostcandidates) 使用来自 MPSD 的可用主机候选者。

2. 从主机候选者列表中选择所需的主机。

3. 调用 [XblMultiplayerSessionSetHostDeviceToken](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayersessionsethostdevicetoken) 在 MPSD 的本地缓存中设置设备令牌。如果设置主机设备令牌的调用成功,则本地设备令牌将替换主机的令牌。

4. 如果在尝试设置主机设备令牌时收到 HTTP/412 状态代码,请查询会话数据。查看主机设备令牌是否用于本地主机。如果不是本地主机,则表示另一台主机已被指定为仲裁者。

   > \[!NOTE]
   > 您的客户端应将 HTTP/412 状态代码与其他 HTTP 代码分开处理,因为 HTTP/412 不表示标准失败。有关此状态代码的详细信息,请参阅[多人游戏会话状态代码](/services/xbox-services/multiplayer/mpsd/how-to/live-mpsd-status-codes)。

5. 按照本主题中的[更新 MPSD 会话](#update-an-mpsd-session)部分所述更新 MPSD 中的会话。

   > \[!NOTE]
   > 如果您没有更好的算法,则客户端可以实现贪婪算法,其中每个主机候选者尝试将自己设置为主机(如果尚未有人这样做)。有关详细信息,请参阅“多人游戏会话高级主题”主题中的[会话仲裁者](/services/xbox-services/multiplayer/mpsd/concepts/live-mpsd-details#session-arbiter)部分。

[返回本主题顶部。](#top)

<a id="mta" />

## 管理标题激活

XBOX One(或更高版本)在协议激活期间触发 `CoreApplicationView.Activated` 事件。
在多人游戏 API 的上下文中,当用户接受邀请或加入另一个用户时,会触发此事件。
这些操作会触发激活,标题必须通过将加入的用户带入与目标用户的游戏中来做出反应。

<Note>您的标题应该随时预料到新的激活参数,并且永远不应针对长度进行编码。</Note>

标题必须执行以下主要步骤来处理标题激活。

1. 为 `CoreApplicationView.Activated` 事件设置事件处理程序。每当发生协议激活时,此处理程序都会触发,即使标题已经在运行也是如此。

2. 在标题激活时,启动会话并订阅会话更改通知。有关详细信息,请参阅本主题中的[订阅 MPSD 会话更改通知](#sfmscn)。

3. 将用户作为活动加入会话。有关详细信息,请参阅本主题中的[从标题激活加入 MPSD 会话](#jamsfata)。

4. 将大厅会话设置为通过个人资料 UI 公开的活动会话。有关详细信息,请参阅本主题中的[设置用户的当前活动](#stuca)。

5. 将用户作为活动加入游戏会话。用户现在可以连接到对等方并进入游戏或大厅。

以下流程图显示如何处理标题激活。

<img src="https://mintcdn.com/microsoft-4404708b/gzrdvT5kpqAXKEQt/images/gdk/services/Multiplayer_2015_OnActivation.png?fit=max&auto=format&n=gzrdvT5kpqAXKEQt&q=85&s=12c7da4ee04fdc9fe5c78471826cb9ed" alt="流程图图片,展示了如何处理标题激活。" width="982" height="1272" data-path="images/gdk/services/Multiplayer_2015_OnActivation.png" />

[返回本主题顶部。](#top)

<a id="mtuj" />

## 使用户可加入

要使用户可加入,标题必须执行以下操作:

1. 创建会话对象,然后根据需要修改属性。

2. 将用户作为活动加入会话。有关详细信息,请参阅本主题中的[从标题激活加入 MPSD 会话](#jamsfata)。

3. 确定用户是否已被指定为会话仲裁者。

4. 如果用户不是仲裁者,则转到步骤 7。

5. 如果用户是仲裁者,则调用 [XblMultiplayerSessionSetHostDeviceToken](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayersessionsethostdevicetoken)。

6. 尝试通过调用 [XblMultiplayerWriteSessionAsync](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayerwritesessionasync) 写入会话。

7. 将会话设置为活动会话。有关详细信息,请参阅本主题中的[设置用户的当前活动](#stuca)。

以下流程图显示了允许用户在游戏期间被其他玩家加入的步骤。

<img src="https://mintcdn.com/microsoft-4404708b/gzrdvT5kpqAXKEQt/images/gdk/services/Multiplayer_2015_Become_Joinable.png?fit=max&auto=format&n=gzrdvT5kpqAXKEQt&q=85&s=2b2f2be1ab3913793e41659a356e5aa1" alt="流程图图片,展示了允许用户在游戏期间被其他玩家加入的步骤。" width="607" height="869" data-path="images/gdk/services/Multiplayer_2015_Become_Joinable.png" />

[返回本主题顶部。](#top)

<a id="sgi" />

## 发送游戏邀请

标题可以通过以下方式使玩家能够发送游戏邀请。

* 为大厅会话发送邀请。
* 使用带游戏会话引用的通用 XBOX 平台邀请 UI 发送邀请。

要为玩家发送游戏邀请,标题必须执行以下操作:

1. 使邀请游戏玩家可加入。有关详细信息,请参阅本主题中的[使用户可加入](#mtuj)。

2. 确定邀请是通过大厅会话发送还是使用邀请 UI 发送。

3. 如果使用大厅会话,则通过调用 [XblMultiplayerSendInvitesAsync](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayersendinvitesasync) 发送邀请。此方法可能需要通过调用 [XGameUiShowPlayerPickerAsync](/reference/system/xgameui/functions/xgameuishowplayerpickerasync) 来构建游戏内 UI 名单。

4. 如果使用邀请 UI,则调用 [XGameUiShowSendGameInviteAsync](/reference/system/xgameui/functions/xgameuishowsendgameinviteasync) 显示邀请 UI。

5. 在远程玩家加入后为本地玩家处理 [XblMultiplayerAddSessionChangedHandler](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayeraddsessionchangedhandler)。

6. 对于远程玩家,实现标题激活代码。有关详细信息,请参阅本主题中的[管理标题激活](#mta)。

以下流程图显示如何发送邀请。

<img src="https://mintcdn.com/microsoft-4404708b/gzrdvT5kpqAXKEQt/images/gdk/services/Multiplayer_2015_Send_Invites.png?fit=max&auto=format&n=gzrdvT5kpqAXKEQt&q=85&s=98dd44729bea6ad14c2cc7f54f7c30a2" alt="流程图图片,展示了如何发送邀请。" width="922" height="736" data-path="images/gdk/services/Multiplayer_2015_Send_Invites.png" />

[返回本主题顶部。](#top)

<a id="jagsfals" />

## 从大厅会话加入游戏会话

如果 Windows 10 设备上的游戏玩法会话不是大型会话,则必须将 `userAuthorizationStyle` 功能设置为 `true`。因此,`joinRestriction` 属性不能为 `none`,这意味着该会话不能公开直接加入。

一个常见的场景是创建大厅会话以聚集玩家,然后将这些玩家移动到游戏玩法会话或匹配会话。但是,如果游戏玩法会话不能公开加入,则除非游戏客户端满足 `joinRestriction` 设置,否则它们无法加入游戏玩法会话。在大多数情况下,这对于此场景来说过于严格。

解决方案是使用转移句柄将大厅会话和游戏会话链接起来。标题可以通过执行以下操作实现:

1. 创建游戏会话时,使用 [XblMultiplayerSetTransferHandleAsync](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayersettransferhandleasync) API 创建将大厅会话和游戏会话链接起来的转移句柄。

2. 将转移句柄 GUID 存储在大厅会话中,而不是游戏会话的会话引用中。

3. 当标题想要将成员从大厅会话移动到游戏会话时,每个客户端使用大厅会话中的转移句柄通过 [XblMultiplayerWriteSessionByHandleAsync](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayerwritesessionbyhandleasync) API 加入游戏会话。

4. MPSD 查找大厅会话以验证尝试使用转移句柄加入游戏会话的成员是否也在大厅会话中。

5. 如果成员在大厅会话中,则他们可以访问游戏会话。

[返回本主题顶部。](#top)

<a id="jamsfata" />

## 从标题激活加入 MPSD 会话

当用户选择使用 XBOX shell UI 加入朋友的活动或接受邀请时,将使用参数激活标题,这些参数指示用户希望加入哪个会话。标题必须处理此激活并将用户添加到相应的会话中。

以下是标题应遵循的步骤。

1. 为 `CoreApplicationView.Activated` 事件实现事件处理程序。它通知标题的激活。

2. 当处理程序触发时,检查 `IActivatedEventArgs.Kind` 属性。如果设置为 `Protocol`,则将事件参数强制转换为 `ProtocolActivatedEventArgs` 类。

3. 检查 `ProtocolActivatedEventArgs` 对象。如果 `ProtocolActivatedEventArgs.Uri` 属性中指示的 URI 与 `inviteHandleAccept`(对应于已接受的邀请)或 `activityHandleJoin`(对应于通过 shell UI 加入)匹配,则解析 URI 的查询字符串。它的格式为带有键/值对的正常 URI 查询字符串,提取以下字段。
   * 对于已接受的邀请:
     1. `handle`
     2. `invitedXuid`
     3. `senderXuid`
   * 对于加入:
     1. `handle`
     2. `joinerXuid`
     3. `joineeXuid`

4. 启动标题的多人游戏代码,应该包括调用 [XblMultiplayerSetSubscriptionsEnabled](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayersetsubscriptionsenabled)。

5. 通过调用 [XblMultiplayerSessionCreateHandle](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayersessioncreatehandle) 创建本地 `XblMultiplayerSessionHandle` 对象。

6. 调用 [XblMultiplayerSessionJoin](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayersessionjoin) 加入会话。使用以下参数设置,以便将加入设置为活动。
   * `memberCustomConstantsJson` = `null`
   * `initializeRequested` = `false`
   * `joinWithActiveStatus` = `true`

7. 调用 [XblMultiplayerSessionSetSessionChangeSubscription](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayersessionsetsessionchangesubscription) 以在加入后会话更改时收到提醒通知。

8. 使用步骤 3 中所述获取的句柄调用 [XblMultiplayerWriteSessionByHandleAsync](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayerwritesessionbyhandleasync)。用户现在是会话的成员,可以使用会话中的数据连接到游戏。

[返回本主题顶部。](#top)

<a id="stuca" />

## 设置用户的当前活动

用户的当前活动显示在标题的 XBOX 仪表板用户体验中。用户的活动可以通过会话或通过标题激活来设置。在后一种情况下,用户通过匹配或通过启动游戏进入会话。

<Note>通过会话设置的活动可以通过调用 [XblMultiplayerClearActivityAsync](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayerclearactivityasync) 删除。</Note>

要将会话设置为用户的当前活动,标题会调用 [XblMultiplayerSetActivityAsync](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayersetactivityasync)。它传递会话的会话引用。

要通过标题激活设置用户的当前活动,请参阅本主题中的[从标题激活加入 MPSD 会话](#jamsfata)。

[返回本主题顶部。](#top)

<a id="update-an-mpsd-session" />

## 更新 MPSD 会话

<Note>当您的标题使用多人游戏 API 更新现有会话时,请记住,它在进行写入会话的调用之前一直在处理本地副本。</Note>

要更新现有会话,标题必须执行以下操作:

1. 根据需要对当前会话进行更改,例如,通过调用 [XblMultiplayerSessionLeave](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayersessionleave)。

2. 完成所有更改后,使用以下任一方法将本地更改写入 MPSD。

   * [XblMultiplayerWriteSessionAsync](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayerwritesessionasync)
   * [XblMultiplayerWriteSessionByHandleAsync](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayerwritesessionbyhandleasync)

   如果您正在写入其他标题也可以修改的共享部分,请将写入模式设置为 [XblMultiplayerSessionWriteMode](/reference/live/xsapi-c/multiplayer_c/enums/xblmultiplayersessionwritemode)`::SynchronizedUpdate`。有关详细信息,请参阅“多人游戏会话目录概述”主题中的[会话更新的同步](/services/xbox-services/multiplayer/mpsd/live-mpsd-overview#synchronization-of-session-updates)部分。

   写入方法将加入写入服务器,并获取最新会话,从中发现其他会话成员及其主机的安全设备地址 (SDA)。有关在这些主机之间建立网络连接的详细信息,请参阅 XBOX One 上 Winsock 简介。

3. 丢弃旧的本地会话对象。使用新检索到的会话对象,以便未来的操作基于最新的已知会话状态。

[返回本主题顶部。](#top)

<a id="lams" />

## 离开 MPSD 会话

要允许用户离开会话,标题必须执行以下操作:

1. 为游戏会话调用 [XblMultiplayerSessionLeave](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayersessionleave)。

2. 按照本主题中的[更新 MPSD 会话](#update-an-mpsd-session)部分所述更新 MPSD 中的游戏会话。

3. 如有必要,为大厅会话调用 `XblMultiplayerSessionLeave` 方法,然后更新该会话。

4. 如果大厅会话需要,请通过调用 [XblMultiplayerRemoveSubscriptionLostHandler](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayerremovesubscriptionlosthandler) 和 [XblMultiplayerRemoveSessionChangedHandler](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayerremovesessionchangedhandler) 取消注册来关闭多人游戏 API。

以下流程图显示如何离开会话并关闭多人游戏。

<img src="https://mintcdn.com/microsoft-4404708b/gzrdvT5kpqAXKEQt/images/gdk/services/Multiplayer_2015_Shut_Down.png?fit=max&auto=format&n=gzrdvT5kpqAXKEQt&q=85&s=1b43ed2e21a28db2347eb8fd9f831aef" alt="流程图图片,展示了如何离开会话并关闭多人游戏。" width="694" height="787" data-path="images/gdk/services/Multiplayer_2015_Shut_Down.png" />

[返回本主题顶部。](#top)

<a id="fossdm" />

## 在匹配期间填补空闲会话位置

要在匹配期间填补票证会话中的空闲位置,标题必须遵循类似以下的步骤:

1. 访问匹配期间创建的票证会话的最新会话状态。

2. 从大厅会话中添加可用于游戏玩法的玩家。

3. 确定票证会话是否已满。

4. 如果会话已满,则继续游戏。

5. 如果会话尚未满,请按照本主题中的[创建匹配票证](#camt)所述创建匹配票证。请务必将 `preserveSession` 参数设置为 `Always` 创建票证。

6. 继续匹配。有关详细信息,请参阅[匹配概述](/services/xbox-services/multiplayer/matchmaking/live-matchmaking-overview)。

以下流程图显示如何在匹配期间填补空闲会话位置。

<img src="https://mintcdn.com/microsoft-4404708b/gzrdvT5kpqAXKEQt/images/gdk/services/Multiplayer_2015_Fill_Open_Slots.png?fit=max&auto=format&n=gzrdvT5kpqAXKEQt&q=85&s=536853a998a165affa7552a02f87d778" alt="流程图图片,展示了如何在匹配期间填补空闲会话位置。" width="794" height="716" data-path="images/gdk/services/Multiplayer_2015_Fill_Open_Slots.png" />

[返回本主题顶部。](#top)

<a id="camt" />

## 创建匹配票证

要创建匹配票证,匹配侦察员必须执行以下操作:

1. 调用 [XblMatchmakingCreateMatchTicketAsync](/reference/live/xsapi-c/matchmaking_c/functions/xblmatchmakingcreatematchticketasync),传入对票证会话的引用。该方法从 MPSD 读取票证会话并为会话中的用户启动匹配。在内部,该方法调用 `POST (/serviceconfigs/{scid}/hoppers/{hoppername})`。

2. 如果匹配服务要将会话成员匹配到新会话或另一个现有会话,请将 `preserveSession` 参数设置为 `Never`。将 `preserveSession` 参数设置为 `Always` 以允许标题重用现有游戏会话作为票证会话来继续游戏玩法。然后,匹配服务可以确保保留提交的会话,并将任何匹配的玩家添加到该会话。

3. 使用 `CreateMatchTicketResponse` 对象中返回的 [XblCreateMatchTicketResponse](/reference/live/xsapi-c/matchmaking_c/structs/xblcreatematchticketresponse)`::EstimatedWaitTime` 来设置用户对匹配时间的期望。

4. 如果需要,使用响应对象中返回的 [XblCreateMatchTicketResponse](/reference/live/xsapi-c/matchmaking_c/structs/xblcreatematchticketresponse)`::MatchTicketId` 通过删除票证来取消会话的匹配。票证删除使用 [XblMatchmakingDeleteMatchTicketAsync](/reference/live/xsapi-c/matchmaking_c/functions/xblmatchmakingdeletematchticketasync)。

[返回本主题顶部。](#top)

<a id="gmts" />

## 获取匹配票证状态

您的标题应执行以下操作以检索匹配票证状态。

1. 获取票证会话的 `XblMultiplayerSessionHandle` 对象。

2. 调用 [XblMultiplayerSessionMatchmakingServer](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayersessionmatchmakingserver) 以访问匹配中使用的 [XblMultiplayerMatchmakingServer](/reference/live/xsapi-c/multiplayer_c/structs/xblmultiplayermatchmakingserver) 对象。

3. 检查 `XblMultiplayerMatchmakingServer` 对象以确定匹配过程的状态、会话的典型等待时间以及目标会话引用(如果已找到匹配)。
