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

# Integración de Party con Lobby mediante el SDK de Multiplayer

> Tutorial para combinar el SDK de PlayFab Party con el SDK de PlayFab Multiplayer de modo que los jugadores de un lobby compartan una única red de chat de voz y datos.

PlayFab Lobby y PlayFab Party se usan a menudo de forma conjunta para crear y organizar grupos de jugadores antes de incorporarlos a una sesión en red. En este artículo se describe cómo usar los lobbies como un mecanismo cómodo para compartir descriptores de red de Party mediante la biblioteca de Party de C++ con la biblioteca de Multiplayer de C++.

## Configurar el SDK de Party y Multiplayer

Consulte los inicios rápidos de Party y Lobby para empezar.

### Party

[Inicio rápido de Party](/services/playfab/multiplayer/networking/quickstart)

### Lobby

[Inicio rápido de Lobby](/services/playfab/multiplayer/lobby/lobby-getting-started)

### Inicializar el SDK de PlayFab Multiplayer

Consulte el [inicio rápido de Lobby](/services/playfab/multiplayer/lobby/lobby-getting-started#initialize-the-playfab-multiplayer-sdk) para inicializar el SDK de PlayFab Multiplayer.

### Crear un lobby con una cadena de descriptor de red serializado

Cree un lobby y establezca el descriptor de red de Party estableciendo el descriptor de red de Party en formato de texto en las propiedades del lobby. Para convertir el descriptor de red de Party en una cadena de caracteres, use [PartyManager::SerializeNetworkDescriptor()](/services/playfab/multiplayer/networking/reference/classes/PartyManager/methods/partymanager_serializenetworkdescriptor).

Las definiciones siguientes son las propiedades del lobby y las claves y valores usados para buscar.

```cpp theme={null}
const char* c_propertyKey_LobbyName{ "LobbyName" };
const char* c_propertyKey_PartyDescriptor{ "PartyDescriptor" };

const char* c_searchKey_LobbyGroup{ "string_key1" };    // For Key to identify lobby group
const char* c_searchValue_LobbyGroup{ "PartySample" };  // Use a identifiable string for search lobby group

// The reason for setting this value is to get the lobby name only from the search results, 
// and in practice, change it appropriately for the your game.
const char* c_searchKey_LobbyName{ "string_key2" };
```

1. Llame a [PFMultiplayerCreateAndJoinLobby](/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pflobby/functions/pfmultiplayercreateandjoinlobby)
2. Compruebe la finalización asincrónica sondeando periódicamente [PFMultiplayerStartProcessingLobbyStateChanges](/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pflobby/functions/pfmultiplayerstartprocessinglobbystatechanges) en busca de un [PFLobbyCreateAndJoinLobbyCompletedStateChange](/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pflobby/functions/pfmultiplayerstartprocessinglobbystatechanges).

```cpp theme={null}
char descriptor[c_maxSerializedNetworkDescriptorStringLength + 1] = {};
// Serialize our local network descriptor for other peers to use
PartyError err = PartyManager::SerializeNetworkDescriptor(&networkDescriptor, descriptor);
if (PARTY_FAILED(err))
{
    // handle immediate create failure
    DEBUGLOG("SerializeNetworkDescriptor failed! %s\n", GetErrorMessage(err));
    return false;
}

std::vector<const char*> lobbyPropertyKeys;
std::vector<const char*> lobbyPropertyValues;
lobbyPropertyKeys.push_back(c_propertyKey_LobbyName);
lobbyPropertyValues.push_back(lobbyName);
lobbyPropertyKeys.push_back(c_propertyKey_PartyDescriptor);
lobbyPropertyValues.push_back(descriptor);

std::vector<const char*> searchPropertyKeys;
std::vector<const char*> searchPropertyValues;
searchPropertyKeys.push_back(c_searchKey_LobbyGroup);
searchPropertyValues.push_back(c_searchValue_LobbyGroup);
searchPropertyKeys.push_back(c_searchKey_LobbyName);
searchPropertyValues.push_back(lobbyName);

PFLobbyCreateConfiguration lobbyConfiguration{};
lobbyConfiguration.maxMemberCount = 16;
lobbyConfiguration.ownerMigrationPolicy = PFLobbyOwnerMigrationPolicy::Automatic;
lobbyConfiguration.accessPolicy = PFLobbyAccessPolicy::Public;
lobbyConfiguration.lobbyPropertyCount = static_cast<uint32_t>(lobbyPropertyKeys.size());
lobbyConfiguration.lobbyPropertyKeys = lobbyPropertyKeys.data();
lobbyConfiguration.lobbyPropertyValues = lobbyPropertyValues.data();
lobbyConfiguration.searchPropertyCount = static_cast<uint32_t>(searchPropertyKeys.size());
lobbyConfiguration.searchPropertyKeys = searchPropertyKeys.data();
lobbyConfiguration.searchPropertyValues = searchPropertyValues.data();

PFLobbyJoinConfiguration memberConfiguration{};

PFLobbyHandle lobby;
HRESULT hr = PFMultiplayerCreateAndJoinLobby(m_pfmHandle, &userEntity, &lobbyConfiguration, &memberConfiguration, nullptr, &lobby);
if (FAILED(hr))
{
    // handle immediate create failure
    DEBUGLOG("PFMultiplayerCreateAndJoinLobby failed! %s\n", PFMultiplayerGetErrorMessage(hr));
    return false;
}

// NOTE: to simplify this quickstart, we'll synchronously block waiting for the CreateAndJoinLobby operation
// to finish. In a real implementation, this polling would be done asynchronously on a background thread/worker.
bool createAndJoinLobbyFinished = false;
while (!createAndJoinLobbyFinished)
{
    uint32_t lobbyStateChangeCount;
    const PFLobbyStateChange* const* lobbyStateChanges;
    HRESULT hr = PFMultiplayerStartProcessingLobbyStateChanges(m_pfmHandle, &lobbyStateChangeCount, &lobbyStateChanges);
    if (FAILED(hr))
    {
        // handle the failure
        DEBUGLOG("PFMultiplayerStartProcessingLobbyStateChanges failed! %s\n", PFMultiplayerGetErrorMessage(hr));
        return false;
    }

    for (uint32_t i = 0; i < lobbyStateChangeCount; ++i)
    {
        const PFLobbyStateChange* stateChange = lobbyStateChanges[i];
        switch (stateChange->stateChangeType)
        {
        case PFLobbyStateChangeType::CreateAndJoinLobbyCompleted:
        {
            auto createAndJoinStateChange =
                static_cast<const PFLobbyCreateAndJoinLobbyCompletedStateChange*>(stateChange);

            if (SUCCEEDED(createAndJoinStateChange->result))
            {
                // lobby successfully created!
                DEBUGLOG("Lobby 0x%p successfully created!\n", createAndJoinStateChange->lobby);
            }
            createAndJoinLobbyFinished = true;
            break;
        }
        }
    }

    hr = PFMultiplayerFinishProcessingLobbyStateChanges(m_pfmHandle, lobbyStateChangeCount, lobbyStateChanges);
    if (FAILED(hr))
    {
        DEBUGLOG("PFMultiplayerFinishProcessingLobbyStateChanges failed! %s\n", PFMultiplayerGetErrorMessage(hr));
        return false;
    }
}
```

### Buscar lobbies

Para obtener detalles sobre cómo usar la búsqueda de lobbies, use el siguiente vínculo: [Buscar lobbies](/services/playfab/multiplayer/lobby/find-lobbies)

Ahora puede usar la API Find Lobbies para buscar el lobby creado anteriormente mediante `c_searchValue_LobbyType` para obtener el descriptor de red serializado.

1. Llame a [PFMultiplayerFindLobbies](/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pflobby/functions/pfmultiplayerfindlobbies)

```cpp theme={null}
std::string filterString;
filterString.append(c_searchKey_LobbyGroup);
filterString.append(" eq '");
filterString.append(c_searchValue_LobbyGroup);
filterString.append("'");

PFLobbySearchConfiguration searchConfiguration = { 0 };
searchConfiguration.filterString = filterString.c_str();

HRESULT hr = PFMultiplayerFindLobbies(m_pfmHandle, &localUser, &searchConfiguration, nullptr);
if (FAILED(hr))
{
    // handle immediate find lobbies failure
    printf("PFMultiplayerFindLobbies failed! %s\n", PFMultiplayerGetErrorMessage(hr));
    return false;
}

// NOTE: to simplify this quickstart, we'll synchronously block waiting for the FindLobbies operation
// to finish. In a real implementation, this polling would be done asynchronously on a background thread/worker.
bool findLobbiesFinished = false;
while (!findLobbiesFinished)
{
    uint32_t lobbyStateChangeCount;
    const PFLobbyStateChange* const* lobbyStateChanges;
    HRESULT hr = PFMultiplayerStartProcessingLobbyStateChanges(m_pfmHandle, &lobbyStateChangeCount, &lobbyStateChanges);
    if (FAILED(hr))
    {
        // handle the failure
        printf("PFMultiplayerStartProcessingLobbyStateChanges failed! %s\n", PFMultiplayerGetErrorMessage(hr));
        return false;
    }

    for (uint32_t i = 0; i < lobbyStateChangeCount; ++i)
    {
        const PFLobbyStateChange* stateChange = lobbyStateChanges[i];
        switch (stateChange->stateChangeType)
        {
            case PFLobbyStateChangeType::FindLobbiesCompleted:
            {
                auto findLobbiesStateChange =
                    static_cast<const PFLobbyFindLobbiesCompletedStateChange*>(stateChange);

                if (FAILED(findLobbiesStateChange->result))
                {
                    printf("PFLobbyStateChangeType::FindLobbiesCompleted failed! %s\n", PFMultiplayerGetErrorMessage(findLobbiesStateChange->result));
                    break;
                }

                for (uint32_t i = 0; i < findLobbiesStateChange->searchResultCount; ++i)
                {
                    const PFLobbySearchResult& searchResult = findLobbiesStateChange->searchResults[i];

                    // Use searchResult.connectionString for connecting a lobby later.
                    MyGame::GuiPostLobbySearchResultRow(searchResult); // defined elsewhere
                }
                findLobbiesFinished = true;
                break;
            }
        }
    }

    hr = PFMultiplayerFinishProcessingLobbyStateChanges(m_pfmHandle, lobbyStateChangeCount, lobbyStateChanges);
    if (FAILED(hr))
    {
        printf("PFMultiplayerFinishProcessingLobbyStateChanges failed! %s\n", PFMultiplayerGetErrorMessage(hr));
        return false;
    }
```

### Unirse a un lobby

Ahora únase al lobby obtenido de la operación "Find Lobbies" anterior mediante la cadena connectionString que forma parte de PFLobbySearchResult.

1. Llame a [PFMultiplayerJoinLobby](/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pflobby/functions/pfmultiplayerjoinlobby)

```cpp theme={null}
// Fill in the member properties of user for referencing in the game.
const char* playerColorPropertyKey = "PlayerColor";
const char* playerColorPropertyValue = MyGame::GetPlayerColorString(localUser);
std::vector<const char*> memberPropertyKeys;
std::vector<const char*> memberPropertyValues;
memberPropertyKeys.push_back(playerColorPropertyKey);
memberPropertyValues.push_back(playerColorPropertyValue);

PFLobbyJoinConfiguration joinConfig;
joinConfig.memberPropertyCount = static_cast<uint32_t>(memberPropertyKeys.size());
joinConfig.memberPropertyKeys = memberPropertyKeys.data();
joinConfig.memberPropertyValues = memberPropertyValues.data();

// Join the lobby using the connection string
HRESULT hr = PFMultiplayerJoinLobby(m_pfmHandle, &localUser, connectionString, &joinConfig, nullptr, &m_lobby);
if (FAILED(hr))
{
    // handle immediate join lobby failure
    DEBUGLOG("PFMultiplayerJoinLobby failed! %s\n", PFMultiplayerGetErrorMessage(hr));
    return false;
}

// NOTE: to simplify this quickstart, we'll synchronously block waiting for the JoinLobby operation
// to finish. In a real implementation, this polling would be done asynchronously on a background thread/worker.
bool joinLobbyFinished = false;
while (!joinLobbyFinished)
{
    uint32_t lobbyStateChangeCount;
    const PFLobbyStateChange* const* lobbyStateChanges;
    HRESULT hr = PFMultiplayerStartProcessingLobbyStateChanges(m_pfmHandle, &lobbyStateChangeCount, &lobbyStateChanges);
    if (FAILED(hr))
    {
        // handle the failure
        DEBUGLOG("PFMultiplayerStartProcessingLobbyStateChanges failed! %s\n", PFMultiplayerGetErrorMessage(hr));
        return false;
    }

    for (uint32_t i = 0; i < lobbyStateChangeCount; ++i)
    {
        const PFLobbyStateChange* stateChange = lobbyStateChanges[i];
        switch (stateChange->stateChangeType)
        {
        case PFLobbyStateChangeType::JoinLobbyCompleted:
        {
            auto joinStateChange =
                static_cast<const PFLobbyJoinLobbyCompletedStateChange*>(stateChange);

            if (SUCCEEDED(joinStateChange->result))
            {
                // lobby successfully joined!
                m_lobby = joinStateChange->lobby;

                uint32_t propertyCount;
                const char* const* keys;
                HRESULT hr = PFLobbyGetLobbyPropertyKeys(joinStateChange->lobby, &propertyCount, &keys);
                if (SUCCEEDED(hr))
                {
                    std::string descriptor;
                    for (uint32_t idx = 0; idx < propertyCount; idx++)
                    {
                        const char* value;
                        hr = PFLobbyGetLobbyProperty(joinStateChange->lobby, keys[idx], &value);
                        if (SUCCEEDED(hr))
                        {
                            if (strcmp(keys[idx], c_propertyKey_PartyDescriptor) == 0 && value)
                            {
                                descriptor = value;
                            }
                        }
                    }
                    if (!descriptor.empty())
                    {
                        partyDescriptor = descriptor;
                    }
                    else
                    {
                        // report asynchronous failure
                        DEBUGLOG("Failed to join lobby 0x%p! No Party descriptor found\n",
                            joinStateChange->lobby);
                    }
                }
            }
            joinLobbyFinished = true;
            break;
        }
        }
    }

    hr = PFMultiplayerFinishProcessingLobbyStateChanges(m_pfmHandle, lobbyStateChangeCount, lobbyStateChanges);
    if (FAILED(hr))
    {
        DEBUGLOG("PFMultiplayerFinishProcessingLobbyStateChanges failed! %s\n", PFMultiplayerGetErrorMessage(hr));
        return false;
    }
}
```

## Pasos siguientes

Obtenga más información en [Inicio rápido de Party: Conectarse a una red de Party](/services/playfab/multiplayer/networking/quickstart#connect-to-a-party-network) para conectarse a la red de Party.

## Consulte también

### SDK de Party

* [Características de Party](/services/playfab/multiplayer/networking/party-features)
* [SDK de Party](/services/playfab/multiplayer/networking/party-sdks/overview)
* [Servicios multijugador](/services/playfab/multiplayer/mpintro)
* [Objetos de Party y sus relaciones](/services/playfab/multiplayer/networking/concepts-objects)
* [Documentación de referencia de la API de Party](/services/playfab/multiplayer/networking/reference/party_members)

### SDK de Multiplayer

* [Referencia del SDK de Multiplayer](/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pflobby/pflobby_members)
* [SDK de Multiplayer](/services/playfab/multiplayer/lobby/lobby-matchmaking-sdks/lobby-matchmaking-sdks)
* [Crear un lobby](/services/playfab/multiplayer/lobby/create-a-lobby)
* [Operaciones asincrónicas y notificaciones](/services/playfab/multiplayer/lobby/lobby-and-matchmaking-client-sdk-async)
* [Crear lobbies que permitan búsquedas](/services/playfab/multiplayer/lobby/define-search-keywords)
* [Propiedades del lobby](/services/playfab/multiplayer/lobby/lobby-properties)


## Related topics

- [Integración con PlayFab Lobby y Match](/es/services/xbox-services/multiplayer/mpa/concepts/live-mpa-playfab-integration.md)
- [Integración de PlayFab para títulos de los servicios XBOX](/es/services/xbox-services/playfab-integration.md)
- [Integración del complemento de PlayFab del Marketplace de Unreal Engine](/es/services/playfab/multiplayer/networking/party-unreal-engine-oss-playfab-plugin-integration.md)
- [Inicio rápido (Windows): Party y Multiplayer](/es/services/playfab/sdks/unified-sdk/quickstart-windows-party.md)
- [Inicio rápido del SDK de Lobby](/es/services/playfab/multiplayer/lobby/lobby-getting-started.md)
