> ## 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.

# 使用 Multiplayer Manager 与好友玩多人游戏

> 使用 Multiplayer Manager 初始化大厅会话、发送 XBOX Live 邀请以及让好友加入正在进行的游戏的分步指南。

<a id="top" />

在一个简单的多人游戏场景中,你游戏的玩家可以与好友在线一起玩。本主题介绍使用 Multiplayer Manager 支持此场景所需实现的基本步骤。

## 发送和接受邀请的步骤

以下步骤使用 Multiplayer Manager 向用户的好友发送邀请,以便该好友可以加入正在进行的游戏。

1. [初始化 Multiplayer Manager](#initialize-multiplayer-manager)
2. [通过添加本地用户创建大厅会话](#create-lobby)
3. [向好友发送邀请](#send-invites)
4. [接受邀请](#accept-invites)
5. [从大厅加入游戏会话](#join-game)

步骤 1、2、3 和 5 在执行邀请的设备上完成。
步骤 4 通常在被邀请者的设备上启动,在通过协议激活启动应用之后。

有关详细信息,请参阅[与好友玩游戏(流程图)](/services/xbox-services/multiplayer/mpm/concepts/flowcharts/live-mpm-play-with-friends)。

## 初始化 Multiplayer Manager <a id="initialize-multiplayer-manager" />

当使用有效的会话模板名称初始化 Multiplayer Manager 时,会自动创建大厅会话对象。会话模板在服务配置中定义。

<Note>在添加用户之前,服务上的大厅会话实例不会被创建。</Note>

#### 扁平 C API

```cpp theme={null}
HRESULT hr = XblMultiplayerManagerInitialize(lobbySessionTemplateName, queueUsedByMultiplayerManager);
```

有关详细信息,请参阅 [XblMultiplayerManagerInitialize](/reference/live/xsapi-c/multiplayer_manager_c/functions/xblmultiplayermanagerinitialize)。

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

## 通过添加本地用户创建大厅会话 <a id="create-lobby" />

将本地登录的 XBOX 服务用户添加到大厅会话。当添加第一个用户时,会承载一个新的大厅。所有其他用户以次要用户身份被添加到现有大厅。

Multiplayer Manager 在系统外壳中通告该大厅,以便好友加入。
只有在你添加了本地用户之后,才能通过 `lobby()` 发送邀请、设置大厅属性以及访问大厅成员。

当本地用户加入大厅时,我们建议设置他们的连接地址和任何自定义属性。

你必须对所有本地登录的用户重复此过程。

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

### 添加单个本地用户

#### 扁平 C API

```cpp theme={null}
HRESULT hr = XblMultiplayerManagerLobbySessionAddLocalUser(xblUserHandle);

if (!SUCCEEDED(hr))
{
    // Handle failure.
}

// Set member connection address.
const char* connectionAddress = "1.1.1.1";
hr = XblMultiplayerManagerLobbySessionSetLocalMemberConnectionAddress(
    xblUserHandle, connectionAddress, context);

if (!SUCCEEDED(hr))
{
    // Handle failure.
}

// Set custom member properties.
const char* propName = "Name";
const char* propValueJson = "{}";
hr = XblMultiplayerManagerLobbySessionSetProperties(propName, propValueJson, context);

if (!SUCCEEDED(hr))
{
    // Handle failure.
}
...
```

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

* [XblMultiplayerManagerLobbySessionAddLocalUser](/reference/live/xsapi-c/multiplayer_manager_c/functions/xblmultiplayermanagerlobbysessionaddlocaluser)
* [XblMultiplayerManagerLobbySessionSetLocalMemberConnectionAddress](/reference/live/xsapi-c/multiplayer_manager_c/functions/xblmultiplayermanagerlobbysessionsetlocalmemberconnectionaddress)
* [XblMultiplayerManagerLobbySessionSetProperties](/reference/live/xsapi-c/multiplayer_manager_c/functions/xblmultiplayermanagerlobbysessionsetproperties)

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

### 添加多个本地用户

#### 扁平 C API

```cpp theme={null}
std::vector<XblUserHandle> xblUsers;
for (XblUserHandle xblUserHandle : xblUsers)
{
    HRESULT hr = XblMultiplayerManagerLobbySessionAddLocalUser(xblUserHandle);

    if (!SUCCEEDED(hr))
    {
        // Handle failure.
    }

    // Set member connection address.
    const char* connectionAddress = "1.1.1.1";
    hr = XblMultiplayerManagerLobbySessionSetLocalMemberConnectionAddress(
        xblUserHandle, connectionAddress, context);

    if (!SUCCEEDED(hr))
    {
        // Handle failure.
    }

    // Set custom member properties.
    const char* propName = "Name";
    const char* propValueJson = "{}";
    hr = XblMultiplayerManagerLobbySessionSetProperties(propName, propValueJson, context);
    ...
}
```

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

* [XblMultiplayerManagerLobbySessionAddLocalUser](/reference/live/xsapi-c/multiplayer_manager_c/functions/xblmultiplayermanagerlobbysessionaddlocaluser)
* [XblMultiplayerManagerLobbySessionSetLocalMemberConnectionAddress](/reference/live/xsapi-c/multiplayer_manager_c/functions/xblmultiplayermanagerlobbysessionsetlocalmemberconnectionaddress)
* [XblMultiplayerManagerLobbySessionSetProperties](/reference/live/xsapi-c/multiplayer_manager_c/functions/xblmultiplayermanagerlobbysessionsetproperties)

这些更改在下一次 [XblMultiplayerManagerDoWork](/reference/live/xsapi-c/multiplayer_manager_c/functions/xblmultiplayermanagerdowork) 调用时被批处理。
每次将用户添加到大厅会话时,Multiplayer Manager 都会触发 [XblMultiplayerEventType](/reference/live/xsapi-c/multiplayer_manager_c/enums/xblmultiplayereventtype)::UserAdded 事件。

我们建议检查事件的错误代码,以查看该用户是否已成功添加。
如果失败,错误消息会提供失败原因的详细信息。

Multiplayer Manager 执行以下功能,以通过添加本地用户来创建大厅会话。

* 向 XBOX 服务多人游戏服务注册 Real-Time Activity 和多人游戏订阅。
* 创建大厅会话。
* 将所有本地玩家加入为活动状态。
* 上传安全设备地址 (SDA)。
* 设置成员属性。
* 注册会话变更事件。
* 将大厅会话设置为活动会话。

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

## 向好友发送邀请 <a id="send-invites" />

显示标准 XBOX UI,玩家可以从中选择好友或最近玩过的玩家邀请加入游戏。
当玩家确认选择时,Multiplayer Manager 会向所选玩家发送邀请。

游戏也可以使用 [XblMultiplayerManagerLobbySessionInviteUsers](/reference/live/xsapi-c/multiplayer_manager_c/functions/xblmultiplayermanagerlobbysessioninviteusers) 方法向一组由 XBOX 服务用户 ID 定义的人员发送邀请。
如果你使用自己的游戏内 UI 而不是标准 XBOX UI,则此方法很有用。

#### 扁平 C API

```cpp theme={null}
size_t xuidsCount = 1;
uint64_t xuids[1] = {};
xuids[0] = 1234567891234567;
HRESULT hr = XblMultiplayerManagerLobbySessionInviteUsers(
    xblUserHandle, 
    xuids, 
    xuidsCount, 
    nullptr,    // ContextStringId 
    nullptr     // CustomActivationContext
);
```

有关详细信息,请参阅 [XblMultiplayerManagerLobbySessionInviteUsers](/reference/live/xsapi-c/multiplayer_manager_c/functions/xblmultiplayermanagerlobbysessioninviteusers)。

Multiplayer Manager 执行以下功能以向好友发送邀请。

* 显示 XBOX 标准游戏可调用 UI (TCUI)
* 直接向所选玩家发送邀请

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

## 接受邀请 <a id="accept-invites" />

当受邀玩家接受游戏邀请或通过外壳 UI 加入好友的游戏时,系统会在其设备上启动游戏。

在基于 Microsoft Game Development Kit (GDK) 的游戏中,游戏启动后,通过调用 [XGameActivationRegisterForEvent](/reference/system/xgameactivation/functions/xgameactivationregisterforevent) 监听邀请事件。

在基于 XBOX One 软件开发套件和通用 Windows 平台 (UWP) 的游戏中,游戏启动后,Multiplayer Manager 可以使用协议激活的事件参数加入大厅。

如果未通过 [XblMultiplayerManagerLobbySessionAddLocalUser](/reference/live/xsapi-c/multiplayer_manager_c/functions/xblmultiplayermanagerlobbysessionaddlocaluser) 添加受邀用户,则 [XblMultiplayerManagerJoinLobby](/reference/live/xsapi-c/multiplayer_manager_c/functions/xblmultiplayermanagerjoinlobby) 会失败,并通过 `JoinLobbyCompleted` 事件调用 [XblMultiplayerEventArgsXuid](/reference/live/xsapi-c/multiplayer_manager_c/functions/xblmultiplayereventargsxuid) 提供邀请所针对的 xuid。

加入大厅后,我们建议设置本地成员的连接地址以及该成员的任何自定义属性。
如果不存在主机,你还可以通过 [XblMultiplayerManagerLobbySessionSetSynchronizedHost](/reference/live/xsapi-c/multiplayer_manager_c/functions/xblmultiplayermanagerlobbysessionsetsynchronizedhost) 设置主机。

最后,如果游戏已在进行中且有空位容纳被邀请者,Multiplayer Manager 会自动将用户加入游戏会话。
游戏会通过 `JoinGameCompleted` 事件收到通知,并提供相应的错误代码和消息。

错误或成功结果通过 `JoinLobbyCompleted` 事件处理。

#### 扁平 C API

```cpp theme={null}

void CALLBACK MyXGameInviteEventCallback(
    _In_opt_ void* context,
    _In_ const XGameActivationInfo* activationInfo)
{
    UNREFERENCED_PARAMETER(context);
    if (activationInfo->type == XGameActivationType::AcceptedGameInvite)
    {
        if (activationInfo->inviteUri != nullptr)
        {
            std::string inviteString(activationInfo->inviteUri);
            auto pos = inviteString.find("handle=");
            auto inviteHandleId = inviteString.substr(pos + 7, 36);

            // Now use inviteHandleId when calling XblMultiplayerManagerJoinLobby().  
            // See the example call as follows.
        }
    }
}

XTaskQueueRegistrationToken token = { 0 };
HRESULT hr = XGameActivationRegisterForEvent(
    queue,
    nullptr,
    MyXGameInviteEventCallback,
    &token);

```

```cpp theme={null}
HRESULT hr = XblMultiplayerManagerJoinLobby(inviteHandleId, xblUserHandle);
if (!SUCCEEDED(hr))
{
    // Handle failure.
}

// Set member connection address.
const char* connectionAddress = "1.1.1.1";
hr = XblMultiplayerManagerLobbySessionSetLocalMemberConnectionAddress(
    xblUserHandle, connectionAddress, context);
```

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

* [XblMultiplayerManagerJoinLobby](/reference/live/xsapi-c/multiplayer_manager_c/functions/xblmultiplayermanagerjoinlobby)
* [XblMultiplayerManagerLobbySessionSetLocalMemberConnectionAddress](/reference/live/xsapi-c/multiplayer_manager_c/functions/xblmultiplayermanagerlobbysessionsetlocalmemberconnectionaddress)

Multiplayer Manager 执行以下功能以接受邀请。

* 注册 Real-Time Activity 和多人游戏订阅。
* 加入大厅会话。
* 清理现有的大厅状态。
* 将所有本地玩家加入为活动状态。
* 上传 SDA。
* 设置成员属性。
* 注册会话变更事件。
* 将大厅会话设置为活动会话。
* 加入游戏会话(如果存在)。
* 使用传输句柄。

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

## 从大厅加入游戏会话 <a id="join-game" />

在邀请被接受并且主机准备开始游戏后,你可以通过调用 [XblMultiplayerManagerJoinGameFromLobby](/reference/live/xsapi-c/multiplayer_manager_c/functions/xblmultiplayermanagerjoingamefromlobby) 启动包含大厅会话成员的新游戏。

错误或成功结果通过 `JoinGameCompleted` 事件处理。

#### 扁平 C API

```cpp theme={null}
HRESULT hr = XblMultiplayerManagerJoinGameFromLobby(gameSessionTemplateName);
if (!SUCCEEDED(hr))
{
    // Handle error.
}
```

有关详细信息,请参阅 [XblMultiplayerManagerJoinGameFromLobby](/reference/live/xsapi-c/multiplayer_manager_c/functions/xblmultiplayermanagerjoingamefromlobby)。

Multiplayer Manager 执行以下功能以从大厅加入游戏会话。

* 创建游戏会话。
* 将所有本地玩家加入为活动状态。
* 上传 SDA。
* 设置成员属性。
* 注册会话变更事件。
* 通过大厅会话通告游戏。

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


## Related topics

- [与好友一起玩游戏(流程图)](/zh-CN/services/xbox-services/multiplayer/mpm/concepts/flowcharts/live-mpm-play-with-friends.md)
- [常见的多人游戏方案](/zh-CN/services/xbox-services/multiplayer/overviews/live-common-multiplayer-scenarios.md)
- [Multiplayer Manager 示例代码](/zh-CN/services/xbox-services/multiplayer/mpm/how-to/live-mm-howto-nav.md)
- [操作指南](/zh-CN/services/xbox-services/multiplayer/mpm/how-to/index.md)
- [Multiplayer Manager 概述](/zh-CN/services/xbox-services/multiplayer/mpm/live-multiplayer-manager-overview.md)
