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

> 了解如何透過 Multiplayer SDK 建立及使用 PlayFab 伺服器回填票證，以填補進行中配對遊戲工作階段的空缺位置。

裝載在伺服器上的遊戲有時會發現需要搜尋額外的玩家。最常見的情況是在遊戲進行期間有一或多位玩家中斷連線。伺服器回填票證可讓遊戲伺服器搜尋適合目前進行中遊戲的額外玩家。

伺服器回填票證與一般配對票證在多個方面有所不同：

1. 配對
   * 回填票證無法彼此配對。
   * 回填票證在搜尋期間會獲得優先權，以減少玩家群的分散。
2. 合約
   * 建立回填票證時可以包含 `ServerDetails` 欄位。這可讓伺服器指出配對成功的玩家應如何連線到伺服器。
   * 建立回填票證時可以包含隊伍指派。這可讓有隊伍的遊戲保留其隊伍資訊。
3. 佇列屬性
   * 回填票證不會觸發 [Multiplayer Server 配置](/zh-TW/services/playfab/multiplayer/matchmaking/multiplayer-servers)。
   * 回填票證不會反映在[佇列統計資料](/zh-TW/services/playfab/multiplayer/matchmaking/display-statistics)中，因為其玩家已經在玩遊戲，會不正確地扭曲等候時間。
4. 擁有權
   * 回填票證由遊戲伺服器擁有，而非使用者。使用者無法以任何方式檢視回填票證或與之互動。

## 先決條件

* 基本熟悉 PlayFab Multiplayer SDK。如需詳細資訊，請參閱 [Matchmaking SDK 快速入門](/zh-TW/services/playfab/multiplayer/matchmaking/quickstart-client-sdk)。
* 在包含配對標頭之前，先定義 `PFMULTIPLAYER_INCLUDE_SERVER_APIS`。例如：

```cpp theme={null}
#define PFMULTIPLAYER_INCLUDE_SERVER_APIS
#include <PFMatchmaking.h>
```

## 設定伺服器回填票證

建立 [PFMatchmakingServerBackfillTicketConfiguration](/zh-TW/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/structs/pfmatchmakingserverbackfillticketconfiguration) 結構，並填入必要的詳細資料：

* **`timeoutInSeconds`**：嘗試填滿票證的時間長度 (以秒為單位)。

* **`queueName`**：比賽佇列的名稱。

* **`memberCount`**：目前在比賽中的成員數目。

* **`members`**：目前在比賽中的 [PFMatchmakingMatchMember](/zh-TW/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/structs/pfmatchmakingmatchmember) 成員。

* **`serverDetails`** (選用)：在 [PFMultiplayerServerDetails](/zh-TW/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/structs/pfmultiplayerserverdetails) 中填入要提供給用戶端的伺服器資訊 (FQDN、IP 位址、連接埠、區域)。

<Note>
  `PFMultiplayerServerDetails::ipv4Address` 欄位不會經過驗證，可用來將任意連線字串資訊提供給用戶端。
</Note>

```cpp theme={null}
// 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
```

## 建立伺服器回填票證

使用 [PFMultiplayerCreateServerBackfillTicket](/zh-TW/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/functions/pfmultiplayercreateserverbackfillticket) 建立伺服器回填票證時，需要傳遞遊戲伺服器的實體 (作為 [PFEntityKey](/zh-TW/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmultiplayer/pfentitykey_clientsdk))，以及在上一個步驟中建立的回填設定。

```cpp theme={null}
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](/zh-TW/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/functions/pfmultiplayerstartprocessingmatchmakingstatechanges) 來接收狀態變更，以檢查票證的更新，並在處理完這些狀態變更後呼叫 [PFMultiplayerFinishProcessingMatchmakingStateChanges](/zh-TW/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/functions/pfmultiplayerfinishprocessingmatchmakingstatechanges)。

每當票證狀態變更時，SDK 都會傳回 **TicketStatusChanged** 狀態變更；配對完成時，則會傳回 **TicketCompleted** 狀態變更。

```cpp theme={null}
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](/zh-TW/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/functions/pfmatchmakingticketgetmatch) 以取得比賽的詳細資料。這些詳細資料包含比賽識別碼、已配對在一起的使用者、比賽的偏好區域，以及與比賽相關聯之大廳的安排字串。

從 **PFMatchmakingMatchDetails** 結構中擷取所需的任何資訊之後，應使用 [PFMultiplayerDestroyMatchmakingTicket](/zh-TW/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/functions/pfmultiplayerdestroymatchmakingticket) 終結票證。

```cpp theme={null}
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](/zh-TW/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/functions/pfmatchmakingticketcancel)。

呼叫此 API 不保證票證會被取消。票證仍可能在取消作業處理之前完成，或取消要求可能因網路或服務錯誤而失敗。如果您想要在繼續之前確認票證取消已完成，仍可處理配對狀態變更以取得票證的結果。否則，您可以立即呼叫 [PFMultiplayerDestroyMatchmakingTicket](/zh-TW/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/functions/pfmultiplayerdestroymatchmakingticket)。

```cpp theme={null}
HRESULT hr = PFMatchmakingTicketCancel(ticket);

PFMultiplayerDestroyMatchmakingTicket(g_pfmHandle, ticket);
```


## Related topics

- [使用伺服器回填票證 - REST API](/zh-TW/services/playfab/multiplayer/matchmaking/backfill-tickets.md)
- [取消伺服器回填票證](/zh-TW/services/playfab/api-references/rest/multiplayer/matchmaking/cancel-server-backfill-ticket.md)
- [取得伺服器回填票證](/zh-TW/services/playfab/api-references/rest/multiplayer/matchmaking/get-server-backfill-ticket.md)
- [建立伺服器回填票證](/zh-TW/services/playfab/api-references/rest/multiplayer/matchmaking/create-server-backfill-ticket.md)
- [列出玩家的伺服器回填票證](/zh-TW/services/playfab/api-references/rest/multiplayer/matchmaking/list-server-backfill-tickets-for-player.md)
