다음을 통해 공유


서버 백필 티켓 사용 - 멀티 플레이어 SDK

서버에서 호스트되는 게임은 경우에 따라 추가 플레이어를 검색해야 합니다. 대부분 이 경우는 게임 진행 중 한명 이상의 플레이어가 연결을 끊을 때 발생합니다. 서버 백필 티켓을 사용하면 게임 서버에서 현재 플레이 중인 게임에 맞는 추가 플레이어를 검색할 수 있습니다.

서버 backfill 티켓은 여러 가지 면에서 일반 매치 메이킹 티켓과 다릅니다.

  1. 매치 중
    • 백필 티켓은 서로 일치할 수 없습니다.
    • 백필 티켓은 검색하는 동안 우선 순위가 지정되어 플레이어 기반의 조각화를 줄입니다.
  2. 계약
    • 백필 티켓은 필드로 ServerDetails 만들 수 있습니다. 이렇게 하면 서버가 일치하는 플레이어를 어떻게 연결해야 하는지 나타내는 것을 허용합니다.
    • 백필 티켓은 팀 할당을 사용하여 만들 수 있습니다. 게임의 팀을 팀 정보와 함께 유지하도록 허용합니다.
  3. 대기 속성
    • 백필 티켓은 멀티 플레이어 서버 할당을 트리거하지 않습니다.
    • 백필 티켓은 플레이어가 이미 게임을 하고 있으며 대기 시간을 부정확하게 왜곡하기 때문에 큐 통계에 반영되지 않습니다.
  4. 소유권
    • backfill 티켓은 게임 유저가 아니라 서버가 소유합니다. 사용자는 어떤 식으로든 백필 티켓을 보거나 상호 작용할 수 없습니다.

필수 구성 요소

  • PlayFab 멀티 플레이어 SDK에 대한 기본적인 친숙함. 자세한 내용은 매치 메이킹 SDK 빠른 시작을 참조하세요.
  • 매치 메이킹 헤더를 포함하기 전에 정의 PFMULTIPLAYER_INCLUDE_SERVER_APIS 합니다. 예:
#define PFMULTIPLAYER_INCLUDE_SERVER_APIS
#include <PFMatchmaking.h>

서버 백필 티켓 구성

PFMatchmakingServerBackfillTicketConfiguration 구조체를 만들고 필요한 세부 정보로 채웁합니다.

  • timeoutInSeconds: 티켓을 채우는 데 걸리는 시간(초)입니다.

  • queueName: 일치 큐의 이름입니다.

  • memberCount: 현재 일치 항목에 있는 멤버 수입니다.

  • members: 현재 일치 중인 PFMatchmakingMatchMember 멤버입니다.

  • serverDetails (선택 사항): 클라이언트에 제공되는 서버(FQDN, IP 주소, 포트, 지역)에 대한 정보로 PFMultiplayerServerDetails 를 채웁니다.

참고 항목

필드의 유효성이 PFMultiplayerServerDetails::ipv4Address 검사되지 않으며 임의의 연결 문자열 정보를 클라이언트에 제공하는 데 사용할 수 있습니다.

// Define the server port configuration.
PFMultiplayerPort serverPorts[] = {
    { "portname", 12345, PFMultiplayerProtocolType::Udp }
};

// Populate the server details.
PFMultiplayerServerDetails serverDetails = {};
serverDetails.fqdn = "your.server.fqdn.com";
serverDetails.ipv4Address = "123.234.123.234";
serverDetails.ports = serverPorts;
serverDetails.portCount = sizeof(serverPorts) / sizeof(serverPorts[0]);
serverDetails.region = "EastUS";

// Set up the backfill ticket configuration.
PFMatchmakingServerBackfillTicketConfiguration backfillConfig = {};
backfillConfig.timeoutInSeconds = 60;                 // Try for 60 seconds
backfillConfig.queueName = "YourQueueName";
backfillConfig.memberCount = currentMatchMemberCount; // e.g., 4
backfillConfig.members = currentMatchMembers;         // Pointer to an array of PFMatchmakingMatchMember
backfillConfig.serverDetails = &serverDetails;        // Optional; can be nullptr if not needed

서버 backfill 티켓 생성하기

PFMultiplayerCreateServerBackfillTicket를 사용하여 서버 백필 티켓을 만들려면 이전 단계에서 만든 백필 구성과 함께 게임 서버의 엔터티(PFEntityKey)를 전달해야 합니다.

PFMatchmakingTicketHandle backfillTicket = nullptr;
HRESULT hr = PFMultiplayerCreateServerBackfillTicket(
    multiplayerHandle,            // The handle of the PFMultiplayer API instance.
    &serverEntity,                // PFEntityKey for your game server entity
    &backfillConfig,              // The backfill ticket configuration.
    nullptr,                      // Optional async context
    &backfillTicket               // The resulting ticket object.
);

if (FAILED(hr))
{
    // handle ticket creation failure
}

매치 메이킹 티켓의 상태 확인

PFMultiplayerStartProcessingMatchmakingStateChanges를 호출하여 상태 변경을 수신한 다음 이러한 상태 변경 처리를 완료하면 PFMultiplayerFinishProcessingMatchmakingStateChanges를 호출하여 티켓 업데이트를 확인해야 합니다.

SDK는 티켓 상태 변경될 때마다 TicketStatusChanged 상태가 변경되고 매치 메이킹이 완료되면 TicketCompleted 상태가 변경됩니다.

HRESULT hrTicketError = S_OK;

uint32_t stateChangeCount;
const PFMatchmakingStateChange * const * stateChanges;
HRESULT hr = PFMultiplayerStartProcessingMatchmakingStateChanges(g_pfmHandle, &stateChangeCount, &stateChanges);
if (FAILED(hr))  
{  
    return;  
}  

for (uint32_t i = 0; i < stateChangeCount; ++i)
{
    const PFMatchmakingStateChange& stateChange = *stateChanges[i];

    switch (stateChange.stateChangeType)
    {
        case PFMatchmakingStateChangeType::TicketStatusChanged:
        {
            const auto& ticketStatusChanged = static_cast<const PFMatchmakingTicketStatusChangedStateChange&>(stateChange);

            PFMatchmakingTicketStatus status;
            if (SUCCEEDED(PFMatchmakingTicketGetStatus(ticketStatusChanged.ticket, &status)))
            {
                printf("Ticket status is now: %i.\n", status);
            }

            break;
        }
        case PFMatchmakingStateChangeType::TicketCompleted:
        {
            const auto& ticketCompleted = static_cast<const PFMatchmakingTicketCompletedStateChange&>(stateChange);

            printf("PFMatchmaking completed with Result 0x%08x.\n", ticketCompleted.result);

            if (FAILED(ticketCompleted.result))
            {
                // On failure, we must record the HRESULT so we can return the state change(s) and then bail
                // out of this function.
                hrTicketError = ticketCompleted.result;
            }

            break;
        }
    }
}

hr = PFMultiplayerFinishProcessingMatchmakingStateChanges(g_pfmHandle, stateChangeCount, stateChanges);
if (FAILED(hr))  
{  
    return;  
}  

// Now that we've returned the state change(s), bail out if we detected ticket failure.
if (FAILED(hrTicketError))  
{  
    return;  
}  

매치 가져오기

PFMatchmakingStateChangeType::TicketCompleted 상태 변경을 수신한 후 PFMatchmakingTicketGetMatch를 호출하여 매치 세부 정보를 가져옵니다. 이러한 세부 정보에는 일치 ID, 함께 일치한 사용자 및 일치 항목에 대한 기본 설정 지역 및 일치 항목과 연결된 로비에 대한 정렬 문자열이 포함됩니다.

PFMatchmakingMatchDetails 구조체에서 필요한 정보를 검색하면 PFMultiplayerDestroyMatchmakingTicket를 사용하여 티켓이 삭제됩니다.

const PFMatchmakingMatchDetails* match;
HREULT hr = PFMatchmakingTicketGetMatch(ticket, &match);
if (FAILED(hr))  
{  
    return;  
}  

std::string matchId = match->matchId;
std::string lobbyArrangementString = match->lobbyArrangementString;

PFMultiplayerDestroyMatchmakingTicket(g_pfmHandle, ticket);

티켓 취소

에서 제한 시간이 설정 PFMatchmakingServerBackfillTicketConfiguration되기 전에 매치 메이킹 프로세스를 취소하려면 티켓 핸들을 사용하여 PFMatchmakingTicketCancel 을 호출합니다.

이 API를 호출해도 티켓이 취소되는 것은 아닙니다. 취소를 처리하기 전에 티켓이 완료되거나 네트워킹 또는 서비스 오류로 인해 취소 요청이 실패할 수 있습니다. 계속 진행하기 전에 티켓 취소가 완료되었는지 확인하려면 매치 메이킹 상태 변경을 처리하여 티켓의 결과를 가져올 수 있습니다. 그렇지 않으면 PFMultiplayerDestroyMatchmakingTicket를 즉시 호출할 수 있습니다.

HRESULT hr = PFMatchmakingTicketCancel(ticket);

PFMultiplayerDestroyMatchmakingTicket(g_pfmHandle, ticket);