Freigeben über


Integrieren von Party in Lobby

PlayFab Lobby und PlayFab Party werden häufig zusammen verwendet, um Gruppen von Spielern zu erstellen und zu orchestrieren, bevor sie in eine vernetzte Sitzung gebracht werden. In diesem Artikel wird beschrieben, wie Sie Lobbies als praktischen Mechanismus zum Freigeben von Party-Netzwerkbeschreibungen verwenden, indem Sie die C++-Partybibliothek mit der C++-Multiplayer-Bibliothek verwenden.

Einrichten des Party- und Multiplayer-SDK

Informationen zu den ersten Schritten finden Sie in den Schnellstartanleitungen zu Partys und Lobbys.

Party

Schnellstart für Partys

Lobby

Schnellstart: Lobby

Initialisieren des PlayFab Multiplayer SDK

Informationen zum Initialisieren des PlayFab Multiplayer SDK finden Sie unter Lobby-Schnellstart .

Erstellen eines Wartebereichs mit einer serialisierten Netzwerkdeskriptorzeichenfolge

Erstellen Sie einen Wartebereich, und legen Sie den Partynetzwerkdeskriptor fest, der den Parteinetzwerkdeskriptor in Textform in den Wartebereichseigenschaften festlegt. Um den Party-Netzwerkdeskriptor in eine char-Zeichenfolge zu konvertieren, verwenden Sie PartyManager::SerializeNetworkDescriptor().

Im Folgenden werden die Lobbyeigenschaften und die Schlüssel und Werte für die Suche definiert.

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. PfMultiplayerCreateAndJoinLobby aufrufen
  2. Überprüfen Sie die asynchrone Vervollständigung, indem Sie in regelmäßigen Abständen PFMultiplayerStartProcessingLobbyStateChanges für eine PFLobbyCreateAndJoinLobbyCompletedStateChange abfragen.
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 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;
    }
}

Suchen von Lobbies

Ausführliche Informationen zur Verwendung von "Lobbies suchen" finden Sie unter dem folgenden Link: Suchen von Lobbies.

Jetzt können Sie die API "Lobbies suchen" verwenden, um nach dem oben erstellten Wartebereich zu suchen, indem Sie den c_searchValue_LobbyType serialisierten Netzwerkdeskriptor abrufen.

  1. PfMultiplayerFindLobbies aufrufen
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 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;
    }

Treten Sie einer Lobby bei

Schließen Sie sich nun dem Wartebereich an, der aus dem vorherigen Vorgang "Lobbies suchen" abgerufen wurde, indem Sie den connectionString verwenden, der Teil von PFLobbySearchResult ist.

  1. PfMultiplayerJoinLobby aufrufen
// 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 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;
    }
}

Weitere Schritte

Weitere Informationen finden Sie unter Party-Schnellstart: Herstellen einer Verbindung mit einem Partynetzwerk , um das Parteinetzwerk zu verbinden.

Weitere Informationen

Party SDK

Multiplayer SDK