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

# Rappels d'interface utilisateur de Game Saves

> Implémentez une interface utilisateur de synchronisation personnalisée pour PlayFab Game Saves en inscrivant des rappels, en gérant la machine à états et en appelant les API de réponse pour les conflits et les nouvelles tentatives.

Game Saves fournit un ensemble de rappels d'interface utilisateur qui permettent à votre jeu de réagir aux événements pendant les opérations de synchronisation. Sur XBOX et Windows, la plateforme fournit une interface utilisateur intégrée pour ces événements. Sur les autres plateformes (comme Steam Deck), votre jeu doit implémenter sa propre interface utilisateur en gérant ces rappels.

La définition de rappels sur XBOX et Windows remplace l'interface utilisateur fournie par la plateforme par votre implémentation. Cela est utile si votre jeu doit offrir une expérience de joueur cohérente sur toutes les plateformes. Inscrivez les mêmes rappels partout, et l'interface utilisateur intégrée ne s'affichera pas.

## Fonctionnement de la machine à états

Game Saves utilise une machine à états interne pour coordonner les rappels d'interface utilisateur avec le cycle de vie de l'opération asynchrone. Lorsqu'un rappel d'interface utilisateur se déclenche, l'opération asynchrone est suspendue. Le rappel `XAsyncBlock` ne se déclenche pas tant que le rappel n'est pas résolu. La machine à états ne progresse pas tant que le jeu n'appelle pas l'API de réponse correspondante ou que l'opération asynchrone n'est pas annulée.

Cela signifie que :

* Chaque type de rappel possède une API de réponse correspondante. Appelez l'API de réponse pour indiquer au système ce qu'il doit faire ensuite.
* Les API de réponse peuvent être appelées à l'intérieur ou à l'extérieur de la fonction de rappel.
* Si une action de réponse est `Retry`, l'opération est retentée et peut déclencher de nouveau le même rappel.
* Le rappel `XAsyncBlock` ne se déclenche qu'une fois que l'opération atteint un état final : réussite, annulation ou basculement hors connexion.

Par exemple, si un téléversement échoue en raison de limites de débit :

1. `PFGameSaveFilesUiSyncFailedCallback` se déclenche avec l'erreur.
2. Le rappel `XAsyncBlock` ne se déclenche pas encore. La machine à états attend une réponse.
3. Si l'utilisateur sélectionne `Retry` et que la nouvelle tentative échoue également, le rappel d'échec de synchronisation se déclenche de nouveau.
4. Si l'utilisateur sélectionne `Cancel`, le rappel `XAsyncBlock` se déclenche avec `E_PF_GAMESAVE_USER_CANCELLED`.
5. Si une nouvelle tentative réussit, le rappel `XAsyncBlock` se déclenche avec `S_OK`.

## Moment de déclenchement des rappels

Les rappels d'interface utilisateur ne se déclenchent que pendant deux opérations asynchrones :

| Opération | Rappels pouvant se déclencher |
| - | - |
| `PFGameSaveFilesAddUserWithUiAsync` | Progression, échec de synchronisation, conflit d'appareil actif, conflit, stockage insuffisant |
| `PFGameSaveFilesUploadWithUiAsync` | Progression, échec de synchronisation |

## Inscription des rappels

Inscrivez tous les rappels avant d'appeler `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);
```

## Référence des rappels

### Progression

Signale la progression du téléversement ou du téléchargement. Utilisez `PFGameSaveFilesUiProgressGetProgress` dans le rappel pour obtenir le `PFGameSaveFilesSyncState` actuel, le nombre d'octets traités et le nombre total d'octets.

**Rappel** : `PFGameSaveFilesUiProgressCallback`

**API de réponse** : `PFGameSaveFilesSetUiProgressResponse`

| Action | Effet |
| - | - |
| `Cancel` | Annule l'opération. Le rappel `XAsyncBlock` se déclenche avec `E_PF_GAMESAVE_USER_CANCELLED`. |

<Note>
  Le rappel de progression n'a pas besoin de réponse pour continuer. L'opération progresse d'elle-même. N'appelez l'API de réponse que si l'utilisateur souhaite annuler.
</Note>

#### États de synchronisation

L'énumération `PFGameSaveFilesSyncState` indique la phase dans laquelle se trouve l'opération :

| État | Description | Écriture sécuritaire dans le dossier de sauvegarde? |
| - | - | - |
| `NotStarted` | L'opération n'a pas commencé | Oui |
| `PreparingForDownload` | Préparation du téléchargement à partir du nuage | Oui |
| `Downloading` | Téléchargement à partir du nuage | Non |
| `PreparingForUpload` | Lecture et compression des fichiers locaux | Non |
| `Uploading` | Téléversement vers le nuage en cours (fichiers locaux capturés) | Oui |
| `SyncComplete` | Opération terminée | Oui |

### Échec de synchronisation

Se déclenche lorsqu'une opération de synchronisation échoue, par exemple en raison de problèmes réseau ou de limites de débit.

**Rappel** : `PFGameSaveFilesUiSyncFailedCallback`

**Paramètres** : reçoit `PFGameSaveFilesSyncState` (la phase qui a échoué) et `HRESULT` (le code d'erreur).

**API de réponse** : `PFGameSaveFilesSetUiSyncFailedResponse`

| Action | Effet |
| - | - |
| `Cancel` | Annule l'opération. Le rappel `XAsyncBlock` se déclenche avec `E_PF_GAMESAVE_USER_CANCELLED`. |
| `Retry` | Retente l'opération ayant échoué. Si la nouvelle tentative échoue, ce rappel se déclenche de nouveau. |
| `UseOffline` | Valide uniquement pendant `PFGameSaveFilesAddUserWithUiAsync`. Le rappel `XAsyncBlock` se déclenche avec `S_OK`, mais le système passe en mode hors connexion. Utilisez `PFGameSaveFilesIsConnectedToCloud()` pour détecter cet état. |

Pour plus de détails sur le comportement du mode hors connexion, consultez [Mode hors connexion de Game Saves](/fr-CA/services/playfab/player-progression/game-saves/offline).

### Conflit d'appareil actif

Se déclenche pendant `PFGameSaveFilesAddUserWithUiAsync` lorsqu'un autre appareil est déjà l'appareil actif pour cet utilisateur. Le rappel reçoit des structures `PFGameSaveDescriptor` pour les données de sauvegarde locales et distantes, qui comprennent les noms des appareils, les horodatages et la taille des sauvegardes, que vous pouvez afficher pour aider l'utilisateur à prendre une décision.

**Rappel** : `PFGameSaveFilesUiActiveDeviceContentionCallback`

**API de réponse** : `PFGameSaveFilesSetUiActiveDeviceContentionResponse`

| Action | Effet |
| - | - |
| `Cancel` | Annule l'opération. Le rappel `XAsyncBlock` se déclenche avec `E_PF_GAMESAVE_USER_CANCELLED`. |
| `Retry` | Effectue une nouvelle tentative; utile si l'utilisateur s'attend à ce que l'autre appareil se libère bientôt. Si l'autre appareil est toujours actif, ce rappel se déclenche de nouveau. |
| `SyncLastSavedData` | Fait de l'appareil local l'appareil actif et lance la synchronisation. L'appareil distant ne peut plus téléverser et reçoit une notification de changement d'appareil actif. |

Pour plus de détails sur le comportement de l'appareil actif, consultez [Changements d'appareil actif de Game Saves](/fr-CA/services/playfab/player-progression/game-saves/activedevicechanges).

### Conflit

Se déclenche pendant `PFGameSaveFilesAddUserWithUiAsync` lorsque les données de sauvegarde locales et infonuagiques ont divergé. Le rappel reçoit des structures `PFGameSaveDescriptor` pour les données de sauvegarde locales et distantes.

**Rappel** : `PFGameSaveFilesUiConflictCallback`

**API de réponse** : `PFGameSaveFilesSetUiConflictResponse`

| Action | Effet |
| - | - |
| `Cancel` | Annule l'opération. Le rappel `XAsyncBlock` se déclenche avec `E_PF_GAMESAVE_USER_CANCELLED`. |
| `TakeLocal` | Conserve les données de sauvegarde locales et les téléverse dans le nuage. |
| `TakeRemote` | Abandonne les modifications locales et télécharge les données de sauvegarde infonuagiques. |

<Info>
  La résolution des conflits s'applique à l'ensemble de la sauvegarde, et non à des fichiers ou dossiers individuels. Pour plus de détails sur la façon dont les conflits sont détectés au niveau de l'unité atomique et résolus globalement, consultez [Conflits de Game Saves](/fr-CA/services/playfab/player-progression/game-saves/conflicts).
</Info>

### Stockage insuffisant

Se déclenche pendant `PFGameSaveFilesAddUserWithUiAsync` lorsque l'appareil local ne dispose pas de suffisamment d'espace disque pour télécharger les données de sauvegarde à partir du nuage. Le rappel reçoit `requiredBytes`, qui indique l'espace nécessaire.

**Rappel** : `PFGameSaveFilesUiOutOfStorageCallback`

**API de réponse** : `PFGameSaveFilesSetUiOutOfStorageResponse`

| Action | Effet |
| - | - |
| `Cancel` | Annule l'opération. Le rappel `XAsyncBlock` se déclenche avec `E_PF_GAMESAVE_USER_CANCELLED`. |
| `Retry` | Effectue une nouvelle tentative après que l'utilisateur a libéré de l'espace de stockage local. S'il n'y a toujours pas assez d'espace, ce rappel se déclenche de nouveau. |

## En processus ou hors processus (interface utilisateur système)

L'endroit où Game Saves s'exécute dépend de la plateforme, ce qui influe sur la gestion des événements d'interface utilisateur :

* **Hors processus (XBOX et Windows)** : sur XBOX et Windows, Game Saves s'exécute toujours hors processus. La plateforme (Connected Storage / GRTS) effectue la synchronisation et fournit des boîtes de dialogue d'interface utilisateur système intégrées pour les échecs de synchronisation, les conflits, les conflits d'appareil actif et le stockage insuffisant. Le joueur interagit directement avec ces boîtes de dialogue, et la plateforme traduit le résultat en codes de fin d'opération asynchrone identiques à ceux que votre jeu reçoit en processus. Vous pouvez tout de même inscrire des rappels pour remplacer l'interface utilisateur intégrée.
* **En processus (autres plateformes, comme Steam Deck)** : lorsque le service de la plateforme n'est pas disponible, votre jeu héberge le moteur de synchronisation de Game Saves et gère les événements d'interface utilisateur au moyen des rappels décrits ci-dessus. Votre jeu pilote entièrement la machine à états à l'aide des API de réponse.

### L'annulation est toujours un résultat possible

Quel que soit le chemin, **chaque** flux d'interface utilisateur peut se terminer par l'abandon de l'utilisateur sans synchronisation réussie; votre jeu doit donc toujours gérer une annulation finale :

| Intention de l'utilisateur | Fin de l'opération asynchrone | `IsConnectedToCloud()` | Dossier de sauvegarde? |
| - | - | - | - |
| Continuer en ligne (réussite) | `S_OK` | `true` | Oui |
| Jouer hors connexion | `S_OK` | `false` | Oui |
| Annuler / Quitter (joueur) | `E_PF_GAMESAVE_USER_CANCELLED` (`0x800704C7`) | s.o. | **Non** |
| Annuler (le jeu a appelé `XAsyncCancel`) | `E_ABORT` (`0x80004004`) | s.o. | **Non** |

La seule action d'« abandon » qui permet tout de même au joueur de continuer est **Use Offline** dans l'invite d'échec de synchronisation (un résultat réussi). Toute autre annulation est finale et ne laisse aucun dossier de sauvegarde. Traitez-la comme *ne pas permettre de jouer*. Consultez [Mode hors connexion de Game Saves](/fr-CA/services/playfab/player-progression/game-saves/offline#when-game-saves-enters-offline-mode-or-returns-an-error).

Dans l'interface utilisateur système intégrée (hors processus), ces choix s'affichent avec le libellé de la plateforme. Par exemple, la boîte de dialogue d'échec de synchronisation propose **« Try again »** / **« Play offline »**, et la boîte de dialogue de conflit d'appareil actif propose **« Stop sync & continue »** / **« Quit game »**. « Play offline » correspond au mode hors connexion (`S_OK`, non connecté); « Quit game » correspond à `E_PF_GAMESAVE_USER_CANCELLED`.

L'annulation d'une invite de **conflit** est finale sur les deux chemins. Elle se termine avec `E_PF_GAMESAVE_USER_CANCELLED` et ne mène pas à une invite d'échec de synchronisation.

Pour une interface utilisateur multiplateforme personnalisée (par exemple, pour correspondre à votre implémentation Steam Deck), inscrivez des rappels partout et validez les flux hors processus sur votre matériel cible. Quel que soit le chemin, conditionnez le jeu au résultat de fin d'opération : `S_OK` + connecté → jeu en ligne; `S_OK` + non connecté → jeu hors connexion (avertissez le joueur); annulation ou échec sans dossier → bloquez le jeu.

## Exigences des plateformes

| Plateforme | Rappels d'interface utilisateur |
| - | - |
| **XBOX et Windows** | Facultatifs. Définissez des rappels pour remplacer l'interface utilisateur intégrée. |
| **Autres plateformes** (par exemple, Steam Deck) | **Obligatoires**. Aucune interface utilisateur intégrée n'est disponible; votre jeu doit gérer tous les rappels. |

Pour les détails de l'implémentation sur Steam Deck, consultez le [Guide d'implémentation pour Steam Deck](/fr-CA/services/playfab/player-progression/game-saves/steam-deck-implementation).

## Contenu connexe

* [Démarrage rapide de Game Saves](/fr-CA/services/playfab/player-progression/game-saves/quickstart)
* [Mode hors connexion de Game Saves](/fr-CA/services/playfab/player-progression/game-saves/offline)
* [Conflits de Game Saves](/fr-CA/services/playfab/player-progression/game-saves/conflicts)
* [Changements d'appareil actif de Game Saves](/fr-CA/services/playfab/player-progression/game-saves/activedevicechanges)


## Related topics

- [Démarrage rapide de Game Saves](/fr-CA/services/playfab/player-progression/game-saves/quickstart.md)
- [Guide d'implémentation de PlayFab Game Saves sur Steam Deck](/fr-CA/services/playfab/player-progression/game-saves/steam-deck-implementation.md)
- [FAQ sur la gestion des erreurs de Game Saves](/fr-CA/services/playfab/player-progression/game-saves/error-handling-faq.md)
- [Mode hors connexion de Game Saves](/fr-CA/services/playfab/player-progression/game-saves/offline.md)
- [Modes d'affichage de fenêtre et boîtes de dialogue d'interface utilisateur appelables par le titre](/fr-CA/build/gdk-and-engines/guides/window-display-modes-tcui.md)
