Xbox Live 도우미 라이브러리 개요

PlayFab 파티용 Xbox Live 도우미 라이브러리는 PlayFab 파티를 사용하는 게임이 통신(XR-015 및 XR-045)과 관련된 Xbox Live 정책을 충족하도록 설계되었습니다. Xbox Live 도우미 라이브러리는 Nuget.org에서 사용할 수 있습니다.

PlayFab 파티 라이브러리와 호환성

API의 호환성이 손상되는 변경을 최소화하기 위해 노력하지만 PlayFab 파티 API의 일부 변경 사항으로 인해 Xbox Live 도우미 라이브러리가 잘못된 값을 반환할 수 있습니다. 라이브러리의 버전이 호환되는지 확인하려면 아래 표를 참조하세요.

Xbox Live 도우미 라이브러리
버전
PlayFab 파티 버전
1.0.1
PlayFab 파티 버전
1.3.0+
1.0.1
1.1.0
1.2.0
1.2.5

Xbox Live 사용자 추적

PlayFab 파티 Xbox Live 도우미 라이브러리는 현재 파티 세션에 참여하고 있는 Xbox Live 사용자에 대해 명시적으로 알려야 합니다. 타이틀은 멀티플레이어 세션 문서의 변경 내용을 수신하고 PartyXblManager::CreateLocalChatUserPartyXblManager::CreateRemoteChatUser를 통해 Xbox Live 도우미 라이브러리에 해당 목록을 반영하여 라이브러리에 알리는 것이 좋습니다.

로컬 사용자의 경우:

void
OnLocalXboxUserAddedToMPSD(
    uint64_t xboxUserId
    )
{
    PartyXblLocalChatUser* localChatUser;
    PartyError err = PartyXblManager::GetSingleton().CreateLocalChatUser(xboxUserId, nullptr, &localChatUser);
    if (PARTY_FAILED(err))
    {
        DEBUGLOG("CreateLocalChatUser failed: %s\n", PartyXblManager::GetErrorMessage(err));
        return;
    }
}

이 시점에서 해당 로컬 Xbox 사용자에 대해 PartyLocalChatControl이 이미 존재하는 경우 SetCustomContext 메서드를 통해 이를 이 PartyXblLocalChatUser와 연결할 수 있습니다.

    localChatControl->SetCustomContext(localChatUser);
    localChatUser->SetCustomContext(localChatControl);

그렇지 않으면 이 새 PartyXblLocalChatUser를 사용하여 채팅 컨트롤을 생성한 후 연결할 수 있습니다. 자세한 내용은 PartyXblLocalChatUsers에서 PartyLocalChatControls 만들기를 참조하세요.

원격 사용자의 경우:

void
OnRemoteXboxUserAddedToMPSD(
    uint64_t xboxUserId
    )
{
    PartyXblChatUser* remoteChatUser;
    PartyError err = PartyXblManager::GetSingleton().CreateRemoteChatUser(remoteXboxUserId, &remoteChatUser);
    if (PARTY_FAILED(err))
    {
        DEBUGLOG("CreateRemoteChatUser failed: %s\n", PartyXblManager::GetErrorMessage(err));
        return;
    }

이 시점에서 해당 원격 Xbox 사용자에 대한 PartyChatControl이 이미 존재하는 경우 SetCustomContext 메서드를 통해 이를 이 PartyXblChatUser와 연결할 수 있습니다.

    remoteChatControl->SetCustomContext(remoteChatUser);
    remoteChatUser->SetCustomContext(remoteChatControl);

세션 문서에 대한 업데이트와 원격 채팅 컨트롤 목록에 대한 업데이트는 주문되지 않을 수 있으며 원격 채팅 컨트롤에 대한 PartyChatControlCreatedStateChange 업데이트를 처리할 때 유사한 연결 논리가 필요할 수 있다는 점에 유의하세요.

로컬 및 원격 채팅 사용자 모두 핵심 파티 라이브러리는 PlayFab 엔터티 ID를 통해 사용자와 채팅 컨트롤을 식별하고 Xbox Live 도우미 라이브러리는 Xbox 사용자 ID로 채팅 사용자를 식별한다는 점을 명심하는 것이 중요합니다. 따라서 둘 사이를 변환해야 하는 경우가 있습니다. 자세한 내용은 Xbox Live 사용자 ID와 PlayFab 엔터티 ID 간 매핑을 참조하세요.

PartyXblLocalChatUsers에서 PartyLocalChatControls 만들기

PartyXblLocalChatUser 개체는 파티 라이브러리의 PartyLocalUserPartyLocalChatControl 개체와 연결된 경우에만 유용합니다. PartyLocalUserPartyLocalChatControl 개체를 생성하려면 타이틀이 사용자를 PlayFab에 로그인하고 사용자의 entityIdtitlePlayerEntityToken을(를) 검색해야 합니다. PlayFab CPP SDK통해 로그인할 수 있지만, 타이틀이 Xbox Live 자격 증명을 사용하여 PlayFab에 로그인하려고 할 경우 추가 종속성이 발생하지 않도록 PartyXblManager::LoginToPlayFab을(를) 사용할 수 있습니다.

다음 샘플에서는 Xbox Live 도우미 라이브러리를 사용하여 PartyXblLocalChatUser 개체에서 PartyLocalUserPartyLocalChatControl 개체를 만드는 방법을 보여줍니다. PartyXblLocalChatUser 개체를 만드는 방법에 대한 자세한 내용은 Xbox Live 사용자 추적을 참조하세요.

    err = PartyXblManager::GetSingleton().LoginToPlayFab(localChatUser, nullptr);
    if (PARTY_FAILED(err))
    {
        DEBUGLOG("LoginToPlayFab failed: %s\n", PartyXblManager::GetErrorMessage(err));
        return;
    }

PartyXblManager::LoginToPlayFab을(를) 호출한 직후에 로그인 작업의 결과가 포함된 PartyXblLoginToPlayFabCompletedStateChange을(를) 받게 됩니다.

    PartyLocalUser* partyLocalUser;
    if (stateChange->stateChangeType == PartyXblStateChangeType::LoginToPlayFabCompleted)
    {
        auto loginToPlayFabCompleted = static_cast<PartyXblLoginToPlayFabCompletedStateChange*>(stateChange);
        if (loginToPlayFabCompleted->result == PartyXblStateChangeResult::Succeeded)
        {
            err = PartyManager::GetSingleton().CreateLocalUser(
                loginToPlayFabCompleted->entityId,
                loginToPlayFabCompleted->titlePlayerEntityToken,
                partyLocalUser));
            if (PARTY_FAILED(err))
            {
                DEBUGLOG("CreateLocalUser failed: %s\n", PartyManager::GetErrorMessage(err));
                return;
            }
        }
    }

    PartyLocalDevice* localDevice;
    err = PartyManager::GetSingleton().GetLocalDevice(&localDevice);
    if (PARTY_FAILED(err))
    {
        DEBUGLOG("GetLocalDevice failed: %s\n", PartyManager::GetErrorMessage(err));
        return;
    }

    PartyLocalChatControl* localChatControl;
    err = localDevice->CreateChatControl(partyLocalUser, nullptr, nullptr, &localChatControl);
    if (PARTY_FAILED(err))
    {
        DEBUGLOG("CreateChatControl failed: %s\n", PartyManager::GetErrorMessage(err));
        return;
    }

    // We can use the custom context on the PartyXblLocalChatUser to store the PartyLocalChatControl for easy access
    // in the future.
    localChatUser->SetCustomContext(localChatControl);

Xbox Live 사용자의 접근성 기본 설정 준수

PartyXblLocalChatUser 개체는 파티 채팅 세션과 관련된 Xbox Live 사용자의 접근성 기본 설정 중 일부를 노출합니다. 타이틀은 이 정보를 통해 파티의 접근성 기능 중 일부를 즉시 사용하도록 설정하여 플레이어에게 더 나은 환경을 제공할 수 있습니다.

    PartyXblAccessibilitySettings accessibilitySettings;
    err = localChatUser->GetAccessibilitySettings(&accessibilitySettings);
    if (PARTY_FAILED(err))
    {
        DEBUGLOG("GetAccessibilitySettings failed: %s\n", PartyXblManager::GetErrorMessage(err));
        return;
    }

    if (accessibilitySettings.speechToTextEnabled)
    {
        PartyVoiceChatTranscriptionOptions option = PartyVoiceChatTranscriptionOptions::TranscribeOtherChatControlsWithMatchingLanguages;
        m_localChatControl->SetTranscriptionOptions(option, nullptr);
    }

Xbox Live 사용자의 개인 정보 설정 및 사용 권한 준수

Xbox Live 정책에 따라 사용자의 개인 정보 또는 권한이 허용하지 않는 경우 타이틀은 Xbox Live를 통한 통신을 허용해서는 안 됩니다. Xbox Live 도우미 라이브러리를 사용하면 Xbox Live 정책에서 허용하는 두 사용자 간에 가장 제한적인 PartyChatPermissionOptions을 쿼리할 수 있어 이를 달성할 수 있습니다. 이 값이 변경될 때마다 라이브러리에서 PartyXblRequiredChatPermissionInfoChangedStateChange이(가) 생성됩니다. PartyXblLocalChatUser::GetRequiredChatPermissionInfo()을(를) 호출하여 업데이트된 PartyChatPermissionOptions을(를) 가져올 수 있습니다.

    PartyXblChatUser* remoteChatUser;
    PartyError err = PartyXblManager::GetSingleton().CreateRemoteChatUser(remoteXboxUserId, &remoteChatUser);
    if (PARTY_FAILED(err))
    {
        DEBUGLOG("CreateRemoteChatUser failed: %s\n", PartyXblManager::GetErrorMessage(err));
        return;
    }

    // Once the chat control representing this remote Xbox Live user joins a network, we can use the custom context
    // on the PartyXblChatUser to store the chat control object for quick access in the future.
    remoteChatUser->SetCustomContext(m_remotePartyChatControl);

Xbox Live 도우미 라이브러리는 Xbox Live 개인 정보 서비스와 통신하여 각 로컬 채팅 사용자와 관련하여 각 원격 채팅 사용자의 개인 정보 및 권한 설정을 추적합니다. 또한 라이브러리는 실시간 활동 업데이트를 구독하여 이러한 설정의 변경 내용을 수신합니다. 새 원격 채팅 사용자가 추가되거나 로컬 채팅 사용자와 기존 원격 채팅 사용자 간의 개인 정보 및 권한 관계가 변경되면 업데이트된 PartyChatPermissionOptions 값을 사용할 수 있다는 것을 알리는 PartyXblRequiredChatPermissionInfoChangedStateChange이(가) 생성됩니다.

    // Wait for PartyXblRequiredChatPermissionInfoChangedStateChange
    if (stateChange->stateChangeType == PartyXblStateChangeType::RequiredChatPermissionInfoChanged)
    {
        auto chatPermissionChanged = static_cast<PartyXblRequiredChatPermissionInfoChangedStateChange*>(stateChange);

        PartyXblLocalChatUser* localChatUser = chatPermissionChanged->localChatUser;
        PartyXblChatUser* targetChatUser = chatPermissionChanged->targetChatUser;

        PartyXblChatPermissionInfo chatPermissionInfo;
        PartyError err = localChatUser->GetRequiredChatPermissionInfo(targetChatUser, &chatPermissionInfo);
        if (PARTY_FAILED(err))
        {
            DEBUGLOG("GetRequiredChatPermissionInfo failed: %s\n", PartyXblManager::GetErrorMessage(err));
            return;
        }

        PartyLocalChatControl* localChatControl;
        localChatUser->GetCustomContext(reinterpret_cast<void**>(&localChatControl));
        if (PARTY_FAILED(err))
        {
            DEBUGLOG("GetCustomContext failed: %s\n", PartyXblManager::GetErrorMessage(err));
            return;
        }

        PartyChatControl* targetChatControl;
        targetChatUser->GetCustomContext(reinterpret_cast<void**>(&targetChatControl));
        if (PARTY_FAILED(err))
        {
            DEBUGLOG("GetCustomContext failed: %s\n", PartyXblManager::GetErrorMessage(err));
            return;
        }

        localChatControl->SetPermission(targetChatControl, chatPermissionInfo.chatPermissionMask);
        if (PARTY_FAILED(err))
        {
            DEBUGLOG("SetPermission failed: %s\n", PartyXblManager::GetErrorMessage(err));
            return;
        }
    }

PartyXblChatPermissionInfo 구조에는 다음 두 가지 정보가 포함됩니다.

  • PartyChatPermissionOptions 마스크 - PartyLocalChatControl::SetPermission()에 있는 그대로 전달할 수 있으며, PartyChatPermissionOptions 값이 이미 있지만 Xbox Live 정책을 준수하는지 확인하려는 경우 이진 마스크로 사용할 수 있습니다.
  • PartyXblChatPermissionMaskReason 값 - PartyXblChatPermissionInfo::chatPermissionMask 값에 대한 추가 정보를 제공합니다.
PartyXblChatPermissionMaskReason 설명
NoRestriction 현재 이 채팅 권한에 적용되는 제한 사항은 없습니다.
결정 로컬 사용자의 통신 권한 및 개인 정보 설정이 결정되는 동안 통신이 제한됩니다.
권한 로컬 사용자의 통신 권한으로 인해 통신이 제한됩니다.
개인 정보 보호 대상 채팅 사용자와 관련된 로컬 사용자의 개인 정보 설정으로 인해 통신이 제한됩니다.
InvalidTargetUser 대상 사용자가 Xbox Live 서비스에서 유효한 것으로 인식되지 않아 통신이 제한됩니다.
XboxLiveServiceError Xbox Live 서비스 문제로 인해 필요한 채팅 권한을 확인할 수 없습니다.
UnknownError 알 수 없는 내부 오류로 인해 필요한 채팅 권한을 확인할 수 없습니다.

네트워크 간 통신 권한 준수

Xbox Live 플레이어와 Xbox Live 플레이어 이외의 플레이어 간의 교차 네트워크 플레이 및 통신을 지원하는 타이틀은 해당 플레이어 간의 통신을 허용하기 전에 통신 권한을 확인해야 합니다. Xbox Live 도우미 라이브러리는 PartyXblLocalChatUser::GetCrossNetworkCommunicationPrivacySetting()을(를) 통해 이 정보를 제공합니다. 이 메서드는 다음과 같은 세 가지 값이 가능한 PartyXblCrossNetworkCommunicationPrivacySetting 열거형을 반환합니다.

PartyXblCrossNetworkCommunicationPrivacySetting 설명
허용됨 이 Xbox Live 사용자의 권한이 모든 네트워크 간 플레이어와의 통신을 허용하도록 설정됩니다.
FriendsOnly 이 Xbox Live 사용자의 권한이 네트워크 간 친구와의 통신만 허용하도록 설정됩니다.
허용되지 않음 이 Xbox Live 사용자의 권한이 네트워크 간 친구와의 통신을 허용하지 않습니다.
    PartyXblCrossNetworkCommunicationPrivacySetting crossNetworkSetting;
    localChatUser->GetCrossNetworkCommunicationPrivacySetting(&crossNetworkSetting);

    if (crossNetworkSetting == PartyXblCrossNetworkCommunicationPrivacySetting::Disallowed)
    {
        m_localChatControl->SetPermissions(crossNetworkChatControl, PartyChatPermissionOptions::None);
    }

XR-015에 대한 자세한 내용과 XR-015가 네트워크 간 플레이 및 통신과 어떤 관련이 있는지 알아보려면 여기를 참조하세요.

Xbox Live 사용자 ID와 PlayFab 엔터티 ID 간의 매핑

PlayFab 파티를 사용하는 많은 Xbox Live 타이틀은 Xbox Live 사용자 ID(Xbox Live 에코시스템 전체에서 사용됨)와 PlayFab 엔터티 ID(PlayFab 파티에서 사용됨) 간에 변환해야 합니다. PartyXblManager::GetEntityIdsFromXboxLiveUserIds을(를) 사용하여 타이틀은 지정된 Xbox Live 사용자 ID 목록에 해당하는 PlayFab 엔터티 ID 목록을 검색할 수 있습니다. 타이틀에는 멀티 플레이어 세션 디렉터리와 같은 외부 명단 서비스를 사용하여 Xbox Live 사용자 ID 목록이 이미 있어야 합니다. 명단의 Xbox Live 사용자 ID를 PlayFab 엔터티 ID와 연결하여 게임 세션의 명단에 해당하는 모든 PlayFab 엔터티 ID의 매핑을 구성할 수 있습니다. 그런 다음 이 매핑을 사용하여 PartyEndpointPartyChatControl 개체를 해당 Xbox Live 사용자와 연결할 수 있습니다.

참고 항목

각 Xbox Live 사용자 ID는 이 Xbox Live 사용자가 이미 PlayFab 계정에 연결된 경우에만 PlayFab 엔터티 ID에 매핑됩니다. 지정된 Xbox 사용자에 대해 PartyXblManager::LoginToPlayFab을(를) 처음으로 호출하면 PlayFab 계정이 자동으로 생성되어 연결됩니다. PlayFab SDK 소비자는 LoginWithXbox API를 사용하여 동일한 결과를 얻을 수 있습니다.

로컬 PartyXblLocalChatUser은(는) PlayFab을 통해 인증하는 데 사용됩니다. 사용자가 이전에 PartyXblManager::LoginToPlayFab을(를) 호출하여 PlayFab에 로그인하지 않은 경우 Xbox Live 도우미 라이브러리는 백그라운드에서 사용자를 인증해야 합니다.

    uint32_t userCount;
    PartyXblChatUserArray chatUsers;
    PartyError err = PartyXblManager::GetSingleton().GetChatUsers(&userCount, &users);
    if (PARTY_FAILED(err))
    {
        DEBUGLOG("GetChatUsers failed: %s\n", PartyXblManager::GetErrorMessage(err));
        return;
    }

    // The list of remote Xbox Live User IDs. This can be populated with arbitrary IDs
    // std::vector<uint64_t> remoteXboxLiveUserIds = {2533274792693551, 2814659110958830};
    //
    // but can also be pulled from the list of remote chat users
    std::vector<uint64_t> remoteXboxLiveUserIds;
    for (uint32_t i = 0; i < userCount; ++i)
    {
        PartyXblChatUser* chatUser = users[i];

        PartyXblLocalChatUser* localChatUser;
        err = chatUser->GetLocal(&localChatUser);
        if (PARTY_FAILED(err))
        {
            DEBUGLOG("PartyChatUser(0x%p)::GetLocal failed: %s\n", chatUser, PartyXblManager::GetErrorMessage(err));
            return;
        }

        if (localChatUser != nullptr)
        {
            continue; // ignore local users
        }

        uint64_t userId;
        err = chatUser->GetXboxUserId(&userId);
        if (PARTY_FAILED(err))
        {
            DEBUGLOG("PartyChatUser(0x%p)::GetXboxUserId failed: %s\n", chatUser, PartyXblManager::GetErrorMessage(err));
            return;
        }

        remoteXboxLiveUserIds.push_back(userId);
    }

    err = PartyXblManager::GetSingleton().GetEntityIdsFromXboxLiveUserIds(
        remoteXboxLiveUserIds.size(),
        remoteXboxLiveUserIds.data(),
        localChatUser,
        nullptr);
    if (PARTY_FAILED(err))
    {
        DEBUGLOG("GetEntityIdsFromXboxLiveUserIds failed: %s\n", PartyXblManager::GetErrorMessage(err));
        return;
    }

PartyXblManager::GetEntityIdsFromXboxLiveUserIds을(를) 호출한 직후에 작업의 결과가 포함된 PartyXblGetEntityIdsFromXboxLiveUserIdsCompletedStateChange을(를) 받게 됩니다. 이 결과를 사용하여 매핑을 구성하거나 업데이트할 수 있습니다.

    // Wait for PartyXblGetEntityIdsFromXboxLiveUserIdsCompletedStateChange
    if (stateChange->stateChangeType == PartyXblStateChangeType::GetEntityIdsFromXboxLiveUserIdsCompleted)
    {
        std::vector<std::pair<uint64_t, std::string>> cachedXboxUserIdToPlayFabEntityIdMap;

        auto getEntityIdsFromXboxLiveUserIdsResult = static_cast<PartyXblGetEntityIdsFromXboxLiveUserIdsCompletedStateChange*>(stateChange);
        for (uint32_t i = 0; i < getEntityIdsFromXboxLiveUserIdsResult.entityIdMappingCount; ++i)
        {
            const PartyXblXboxUserIdToPlayFabEntityIdMapping& idMapping = getEntityIdsFromXboxLiveUserIdsResult.entityIdMappings[i];

            Log("   Xbox Live User ID: %llu", idMapping.xboxLiveUserId);
            if (strlen(idMapping.playfabEntityId)) != 0)
            {
                Log("    PlayFab Entity ID: %s", idMapping.playfabEntityId);
                cachedXboxUserIdToPlayFabEntityIdMap.emplace_back(idMapping.xboxLiveUserId, idMapping.playfabEntityId);
            }
            else
            {
                // This Xbox Live User did not have a linked PlayFab Account.
                Log("    PlayFab Entity ID: NOT FOUND");
            }
        }

        m_cachedXboxUserIdToPlayFabEntityIdMap = std::move(cachedXboxUserIdToPlayFabEntityIdMap);

이러한 매핑을 사용하여 타이틀은 Party 개체가 Xbox Live 사용자를 나타낼 경우 이를 인식할 수 있습니다.

uint64_t
GetXboxUserIdFromPlayFabEntityId(
    PartyString entityId
    )
{
    for (const std::pair<uint64_t, std::string>& idMapping : m_cachedXboxUserIdToPlayFabEntityIdMap)
    {
        const std::string& entityIdForXboxUserId = idMapping.second;
        if (entityIdForXboxUserId == entityId)
        {
            return idMapping.first;
        }
    }

    // Failed to find a matching Xbox User ID. This Entity ID does not represent an Xbox Live user.
    return 0;
}

Windows에 대한 특별 고려사항

Windows에서 Xbox Live 도우미 라이브러리가 Xbox Live 토큰을 가져오려면 타이틀의 도움이 필요합니다. 라이브러리는 PartyXblTokenAndSignatureRequestedStateChange을(를) 생성하여 토큰을 요청합니다. 타이틀은 XAL(Xbox 인증 라이브러리)을 사용하여 이러한 요청을 수행할 수 있습니다. 이 작업을 타이틀에 오프로드하여 일반적으로 사용자 인증과 연결된 모든 UI 처리 및 동의 프롬프트를 완전히 제어할 수 있는지 확인합니다.

    if (stateChange->stateChangeType == PartyXblStateChangeType::TokenAndSignatureRequested)
    {
        auto tokenAndSignatureRequested = static_cast<PartyXblTokenAndSignatureRequestedStateChange*>(stateChange);

        // Convert the headers to the format XAL expect
        std::vector<XalHttpHeader> xalHeaders;
        for (uint32_t i = 0; i < stateChange.headerCount; ++i)
        {
            xalHeaders.push_back({stateChange.headers[i].name, stateChange.headers[i].value});
        }

        XalUserGetTokenAndSignatureArgs args = {};
        args.method = stateChange.method;
        args.url = stateChange.url;
        args.headerCount = static_cast<uint32_t>(xalHeaders.size());
        args.headers = xalHeaders.data();
        args.bodySize = stateChange.bodySize;
        args.body = static_cast<const uint8_t*>(stateChange.body);
        args.forceRefresh = stateChange.forceRefresh != 0;
        args.allUsers = stateChange.allUsers != 0;

        XAsyncBlock* asyncBlock = new XAsyncBlock;
        asyncBlock->queue = m_queue;
        HRESULT hr = XalUserGetTokenAndSignatureSilentlyAsync(m_userHandle, &args, asyncBlock);
    }

XAL을 사용하여 토큰 및 서명을 검색하는 방법에 대한 자세한 지침은 Xbox 인증 라이브러리 설명서를 참조하세요.

토큰과 서명이 있으면 상태 변경을 통해 타이틀에 제공된 것과 동일한 correlationId(으)로 PartyXblManager::CompleteGetTokenAndSignatureRequest()을(를) 호출하여 Xbox Live 도우미 라이브러리에 해당 토큰 및 서명을 제공할 수 있습니다.