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

# Retornos de chamada de interface do Game Saves

> Implemente uma interface de sincronização personalizada para o PlayFab Game Saves registrando retornos de chamada, tratando a máquina de estados e chamando APIs de resposta para conflitos e repetições.

O Game Saves fornece um conjunto de retornos de chamada de interface que permitem que seu jogo responda a eventos durante as operações de sincronização. No XBOX e no Windows, a plataforma fornece uma interface interna para esses eventos. Em outras plataformas (como o Steam Deck), seu jogo precisa implementar sua própria interface tratando esses retornos de chamada.

Definir retornos de chamada no XBOX e no Windows substitui a interface fornecida pela plataforma pela sua implementação. Isso é útil se o seu jogo precisar de uma experiência de jogador consistente em todas as plataformas. Registre os mesmos retornos de chamada em todos os lugares e a interface interna não será exibida.

## Como a máquina de estados funciona

O Game Saves usa uma máquina de estados interna para coordenar os retornos de chamada de interface com o ciclo de vida da operação assíncrona. Quando um retorno de chamada de interface é acionado, a operação assíncrona é pausada. O retorno de chamada de `XAsyncBlock` não é acionado até que o retorno de chamada seja resolvido. A máquina de estados não avança até que o jogo chame a API de resposta correspondente ou a operação assíncrona seja cancelada.

Isso significa que:

* Cada tipo de retorno de chamada tem uma API de resposta correspondente. Chame a API de resposta para informar ao sistema o que fazer em seguida.
* As APIs de resposta podem ser chamadas dentro ou fora da função de retorno de chamada.
* Se uma ação de resposta for `Retry`, a operação será repetida e poderá acionar o mesmo retorno de chamada novamente.
* O retorno de chamada de `XAsyncBlock` só é acionado quando a operação atinge um estado final: êxito, cancelamento ou fallback offline.

Por exemplo, se um upload falhar devido a limites de taxa:

1. `PFGameSaveFilesUiSyncFailedCallback` é acionado com o erro.
2. O retorno de chamada de `XAsyncBlock` ainda não é acionado. A máquina de estados aguarda uma resposta.
3. Se o usuário selecionar `Retry` e a nova tentativa também falhar, o retorno de chamada de falha de sincronização será acionado novamente.
4. Se o usuário selecionar `Cancel`, o retorno de chamada de `XAsyncBlock` será acionado com `E_PF_GAMESAVE_USER_CANCELLED`.
5. Se uma nova tentativa tiver êxito, o retorno de chamada de `XAsyncBlock` será acionado com `S_OK`.

## Quando os retornos de chamada são acionados

Os retornos de chamada de interface só são acionados durante duas operações assíncronas:

| Operação | Retornos de chamada que podem ser acionados |
| - | - |
| `PFGameSaveFilesAddUserWithUiAsync` | Progresso, Falha de sincronização, Contenção de dispositivo ativo, Conflito, Armazenamento insuficiente |
| `PFGameSaveFilesUploadWithUiAsync` | Progresso, Falha de sincronização |

## Registrando retornos de chamada

Registre todos os retornos de chamada antes de chamar `PFGameSaveFilesAddUserWithUiAsync` ou `PFGameSaveFilesUploadWithUiAsync`:

```cpp theme={null}
PFGameSaveUICallbacks callbacks{};
callbacks.progressCallback = MyProgressCallback;
callbacks.progressContext = nullptr;
callbacks.syncFailedCallback = MySyncFailedCallback;
callbacks.syncFailedContext = nullptr;
callbacks.activeDeviceContentionCallback = MyActiveDeviceContentionCallback;
callbacks.activeDeviceContentionContext = nullptr;
callbacks.conflictCallback = MyConflictCallback;
callbacks.conflictContext = nullptr;
callbacks.outOfStorageCallback = MyOutOfStorageCallback;
callbacks.outOfStorageContext = nullptr;

HRESULT hr = PFGameSaveFilesSetUiCallbacks(&callbacks);
```

## Referência de retornos de chamada

### Progresso

Informa o progresso do upload ou download. Use `PFGameSaveFilesUiProgressGetProgress` dentro do retorno de chamada para obter o `PFGameSaveFilesSyncState` atual, os bytes concluídos e o total de bytes.

**Retorno de chamada**: `PFGameSaveFilesUiProgressCallback`

**API de resposta**: `PFGameSaveFilesSetUiProgressResponse`

| Ação | Efeito |
| - | - |
| `Cancel` | Cancela a operação. O retorno de chamada de `XAsyncBlock` é acionado com `E_PF_GAMESAVE_USER_CANCELLED`. |

<Note>
  O retorno de chamada de progresso não exige uma resposta para continuar. A operação continua avançando por conta própria. Chame a API de resposta somente se o usuário quiser cancelar.
</Note>

#### Estados de sincronização

A enumeração `PFGameSaveFilesSyncState` indica em qual fase a operação está:

| Estado | Descrição | É seguro gravar na pasta de salvamento? |
| - | - | - |
| `NotStarted` | A operação não começou | Sim |
| `PreparingForDownload` | Preparando para baixar da nuvem | Sim |
| `Downloading` | Baixando da nuvem | Não |
| `PreparingForUpload` | Lendo e compactando arquivos locais | Não |
| `Uploading` | Upload para a nuvem em andamento (arquivos locais capturados) | Sim |
| `SyncComplete` | Operação concluída | Sim |

### Falha de sincronização

É acionado quando uma operação de sincronização falha, por exemplo, devido a problemas de rede ou limites de taxa.

**Retorno de chamada**: `PFGameSaveFilesUiSyncFailedCallback`

**Parâmetros**: recebe `PFGameSaveFilesSyncState` (a fase que falhou) e `HRESULT` (o código de erro).

**API de resposta**: `PFGameSaveFilesSetUiSyncFailedResponse`

| Ação | Efeito |
| - | - |
| `Cancel` | Cancela a operação. O retorno de chamada de `XAsyncBlock` é acionado com `E_PF_GAMESAVE_USER_CANCELLED`. |
| `Retry` | Repete a operação que falhou. Se a nova tentativa falhar, este retorno de chamada será acionado novamente. |
| `UseOffline` | Válido somente durante `PFGameSaveFilesAddUserWithUiAsync`. O retorno de chamada de `XAsyncBlock` é acionado com `S_OK`, mas o sistema entra no modo offline. Use `PFGameSaveFilesIsConnectedToCloud()` para detectar esse estado. |

Para obter mais detalhes sobre o comportamento do modo offline, consulte [Modo offline do Game Saves](/pt-BR/services/playfab/player-progression/game-saves/offline).

### Contenção de dispositivo ativo

É acionado durante `PFGameSaveFilesAddUserWithUiAsync` quando outro dispositivo já é o dispositivo ativo para este usuário. O retorno de chamada recebe structs `PFGameSaveDescriptor` para os dados de salvamento local e remoto, que incluem nomes de dispositivos, carimbos de data/hora e tamanhos de salvamento que você pode exibir para ajudar o usuário a decidir.

**Retorno de chamada**: `PFGameSaveFilesUiActiveDeviceContentionCallback`

**API de resposta**: `PFGameSaveFilesSetUiActiveDeviceContentionResponse`

| Ação | Efeito |
| - | - |
| `Cancel` | Cancela a operação. O retorno de chamada de `XAsyncBlock` é acionado com `E_PF_GAMESAVE_USER_CANCELLED`. |
| `Retry` | Tenta novamente; útil se o usuário espera que o outro dispositivo seja liberado em breve. Se o outro dispositivo ainda estiver ativo, este retorno de chamada será acionado novamente. |
| `SyncLastSavedData` | Torna o dispositivo local ativo e sincroniza. O dispositivo remoto não poderá mais fazer upload e receberá uma notificação de alteração do dispositivo ativo. |

Para obter mais detalhes sobre o comportamento do dispositivo ativo, consulte [Alterações de dispositivo ativo do Game Saves](/pt-BR/services/playfab/player-progression/game-saves/activedevicechanges).

### Conflito

É acionado durante `PFGameSaveFilesAddUserWithUiAsync` quando os dados de salvamento local e na nuvem divergiram. O retorno de chamada recebe structs `PFGameSaveDescriptor` para os dados de salvamento local e remoto.

**Retorno de chamada**: `PFGameSaveFilesUiConflictCallback`

**API de resposta**: `PFGameSaveFilesSetUiConflictResponse`

| Ação | Efeito |
| - | - |
| `Cancel` | Cancela a operação. O retorno de chamada de `XAsyncBlock` é acionado com `E_PF_GAMESAVE_USER_CANCELLED`. |
| `TakeLocal` | Mantém os dados de salvamento locais e os envia para a nuvem. |
| `TakeRemote` | Descarta as alterações locais e baixa os dados de salvamento da nuvem. |

<Info>
  A resolução de conflitos se aplica ao salvamento inteiro, não a arquivos ou pastas individuais. Para obter detalhes sobre como os conflitos são detectados no nível da unidade atômica e resolvidos globalmente, consulte [Conflitos do Game Saves](/pt-BR/services/playfab/player-progression/game-saves/conflicts).
</Info>

### Armazenamento insuficiente

É acionado durante `PFGameSaveFilesAddUserWithUiAsync` quando o dispositivo local não tem espaço em disco suficiente para baixar os dados de salvamento da nuvem. O retorno de chamada recebe `requiredBytes`, que indica quanto espaço é necessário.

**Retorno de chamada**: `PFGameSaveFilesUiOutOfStorageCallback`

**API de resposta**: `PFGameSaveFilesSetUiOutOfStorageResponse`

| Ação | Efeito |
| - | - |
| `Cancel` | Cancela a operação. O retorno de chamada de `XAsyncBlock` é acionado com `E_PF_GAMESAVE_USER_CANCELLED`. |
| `Retry` | Tenta novamente depois que o usuário libera espaço de armazenamento local. Se ainda não houver espaço suficiente, este retorno de chamada será acionado novamente. |

## No processo versus fora do processo (interface do sistema)

O local em que o Game Saves é executado depende da plataforma, e isso afeta como os eventos de interface são tratados:

* **Fora do processo (XBOX e Windows)**: no XBOX e no Windows, o Game Saves sempre é executado fora do processo. A plataforma (Connected Storage / GRTS) executa a sincronização e fornece caixas de diálogo internas da interface do sistema para falhas de sincronização, conflitos, contenção de dispositivo ativo e armazenamento insuficiente. O jogador interage diretamente com essas caixas de diálogo, e a plataforma converte o resultado nos mesmos códigos de conclusão assíncrona que seu jogo recebe no processo. Você ainda pode registrar retornos de chamada para substituir a interface interna.
* **No processo (outras plataformas, como o Steam Deck)**: onde o serviço da plataforma não está disponível, seu jogo hospeda o mecanismo de sincronização do Game Saves e trata os eventos de interface por meio dos retornos de chamada descritos acima. Seu jogo controla totalmente a máquina de estados com as APIs de resposta.

### O cancelamento é sempre um resultado possível

Independentemente do caminho, **todo** fluxo de interface pode terminar com o usuário desistindo sem uma sincronização bem-sucedida, portanto seu jogo deve sempre tratar um cancelamento final:

| Intenção do usuário | Conclusão assíncrona | `IsConnectedToCloud()` | Pasta de salvamento? |
| - | - | - | - |
| Continuar online (êxito) | `S_OK` | `true` | Sim |
| Jogar offline | `S_OK` | `false` | Sim |
| Cancelar / Sair (jogador) | `E_PF_GAMESAVE_USER_CANCELLED` (`0x800704C7`) | n/a | **Não** |
| Cancelar (o jogo chamou `XAsyncCancel`) | `E_ABORT` (`0x80004004`) | n/a | **Não** |

A única ação de "desistir" que ainda permite que o jogador continue é **Use Offline** no aviso de falha de sincronização (um resultado de êxito). Todos os outros cancelamentos são finais e não deixam uma pasta de salvamento. Trate-os como *não permitir jogar*. Consulte [Modo offline do Game Saves](/pt-BR/services/playfab/player-progression/game-saves/offline#when-game-saves-enters-offline-mode-or-returns-an-error).

Na interface interna do sistema (fora do processo), essas opções aparecem com a terminologia da plataforma. Por exemplo, a caixa de diálogo de falha de sincronização oferece **"Try again"** / **"Play offline"**, e a caixa de diálogo de contenção oferece **"Stop sync & continue"** / **"Quit game"**. "Play offline" corresponde ao modo offline (`S_OK`, não conectado); "Quit game" corresponde a `E_PF_GAMESAVE_USER_CANCELLED`.

Cancelar um aviso de **conflito** é final em ambos os caminhos. Ele é concluído com `E_PF_GAMESAVE_USER_CANCELLED` e não passa para um aviso de falha de sincronização.

Para uma interface multiplataforma personalizada (por exemplo, igual à sua implementação para o Steam Deck), registre retornos de chamada em todos os lugares e valide os fluxos fora do processo no hardware de destino. Independentemente do caminho, condicione o jogo ao resultado da conclusão: `S_OK` + conectado → jogar online; `S_OK` + não conectado → jogar offline (avise o jogador); cancelamento/falha sem pasta → bloquear o jogo.

## Requisitos de plataforma

| Plataforma | Retornos de chamada de interface |
| - | - |
| **XBOX e Windows** | Opcionais. Defina retornos de chamada para substituir a interface interna. |
| **Outras plataformas** (por exemplo, Steam Deck) | **Obrigatórios**. Nenhuma interface interna está disponível; seu jogo deve tratar todos os retornos de chamada. |

Para obter detalhes de implementação para o Steam Deck, consulte o [Guia de implementação para o Steam Deck](/pt-BR/services/playfab/player-progression/game-saves/steam-deck-implementation).

## Conteúdo relacionado

* [Início rápido do Game Saves](/pt-BR/services/playfab/player-progression/game-saves/quickstart)
* [Modo offline do Game Saves](/pt-BR/services/playfab/player-progression/game-saves/offline)
* [Conflitos do Game Saves](/pt-BR/services/playfab/player-progression/game-saves/conflicts)
* [Alterações de dispositivo ativo do Game Saves](/pt-BR/services/playfab/player-progression/game-saves/activedevicechanges)


## Related topics

- [Perguntas frequentes sobre tratamento de erros do Game Saves](/pt-BR/services/playfab/player-progression/game-saves/error-handling-faq.md)
- [Modo offline do Game Saves](/pt-BR/services/playfab/player-progression/game-saves/offline.md)
- [Início rápido do Game Saves](/pt-BR/services/playfab/player-progression/game-saves/quickstart.md)
- [Guia de implementação do PlayFab Game Saves no Steam Deck](/pt-BR/services/playfab/player-progression/game-saves/steam-deck-implementation.md)
- [Implementação do Game Saves com o GDK de outubro de 2025](/pt-BR/services/playfab/player-progression/game-saves/october-2025-gdk-changes.md)
