> ## Documentation Index
> Fetch the complete documentation index at: https://docs.xbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Devoluciones de llamada de la interfaz de usuario de Game Saves

> Implemente una interfaz de usuario de sincronización personalizada para PlayFab Game Saves registrando devoluciones de llamada, controlando la máquina de estados y llamando a las API de respuesta para conflictos y reintentos.

Game Saves proporciona un conjunto de devoluciones de llamada de la interfaz de usuario que permiten a su juego responder a los eventos durante las operaciones de sincronización. En XBOX y Windows, la plataforma proporciona una interfaz de usuario integrada para estos eventos. En otras plataformas (como Steam Deck), su juego debe implementar su propia interfaz de usuario controlando estas devoluciones de llamada.

Establecer devoluciones de llamada en XBOX y Windows reemplaza la interfaz de usuario proporcionada por la plataforma por su implementación. Esto resulta útil si su juego necesita una experiencia de jugador coherente en todas las plataformas. Registre las mismas devoluciones de llamada en todas partes y la interfaz de usuario integrada no aparecerá.

## Cómo funciona la máquina de estados

Game Saves usa una máquina de estados interna para coordinar las devoluciones de llamada de la interfaz de usuario con el ciclo de vida de la operación asincrónica. Cuando se activa una devolución de llamada de la interfaz de usuario, la operación asincrónica se pausa. La devolución de llamada de `XAsyncBlock` no se activa hasta que se resuelve la devolución de llamada. La máquina de estados no avanza hasta que el juego llama a la API de respuesta correspondiente o se cancela la operación asincrónica.

Esto significa que:

* Cada tipo de devolución de llamada tiene una API de respuesta correspondiente. Llame a la API de respuesta para indicar al sistema qué hacer a continuación.
* Las API de respuesta se pueden llamar dentro o fuera de la función de devolución de llamada.
* Si una acción de respuesta es `Retry`, la operación se reintenta y puede desencadenar de nuevo la misma devolución de llamada.
* La devolución de llamada de `XAsyncBlock` solo se activa una vez que la operación alcanza un estado terminal: éxito, cancelación o una alternativa sin conexión.

Por ejemplo, si una carga falla debido a los límites de frecuencia:

1. `PFGameSaveFilesUiSyncFailedCallback` se activa con el error.
2. La devolución de llamada de `XAsyncBlock` aún no se activa. La máquina de estados espera una respuesta.
3. Si el usuario selecciona `Retry` y el reintento también falla, la devolución de llamada de error de sincronización se activa de nuevo.
4. Si el usuario selecciona `Cancel`, la devolución de llamada de `XAsyncBlock` se activa con `E_PF_GAMESAVE_USER_CANCELLED`.
5. Si un reintento se realiza correctamente, la devolución de llamada de `XAsyncBlock` se activa con `S_OK`.

## Cuándo se desencadenan las devoluciones de llamada

Las devoluciones de llamada de la interfaz de usuario solo se activan durante dos operaciones asincrónicas:

| Operación | Devoluciones de llamada que pueden desencadenarse |
| - | - |
| `PFGameSaveFilesAddUserWithUiAsync` | Progreso, error de sincronización, contención de dispositivo activo, conflicto, sin espacio de almacenamiento |
| `PFGameSaveFilesUploadWithUiAsync` | Progreso, error de sincronización |

## Registro de devoluciones de llamada

Registre todas las devoluciones de llamada antes de llamar a `PFGameSaveFilesAddUserWithUiAsync` o `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);
```

## Referencia de devoluciones de llamada

### Progreso

Notifica el progreso de la carga o descarga. Use `PFGameSaveFilesUiProgressGetProgress` dentro de la devolución de llamada para recuperar el `PFGameSaveFilesSyncState` actual, los bytes completados y los bytes totales.

**Devolución de llamada**: `PFGameSaveFilesUiProgressCallback`

**API de respuesta**: `PFGameSaveFilesSetUiProgressResponse`

| Acción | Efecto |
| - | - |
| `Cancel` | Cancela la operación. La devolución de llamada de `XAsyncBlock` se activa con `E_PF_GAMESAVE_USER_CANCELLED`. |

> [!NOTE]
>
> La devolución de llamada de progreso no requiere una respuesta para continuar. La operación sigue avanzando por sí sola. Llame a la API de respuesta solo si el usuario quiere cancelar.

#### Estados de sincronización

La enumeración `PFGameSaveFilesSyncState` indica en qué fase se encuentra la operación:

| Estado | Descripción | ¿Es seguro escribir en la carpeta de guardado? |
| - | - | - |
| `NotStarted` | La operación no ha comenzado | Sí |
| `PreparingForDownload` | Preparándose para descargar desde la nube | Sí |
| `Downloading` | Descargando desde la nube | No |
| `PreparingForUpload` | Leyendo y comprimiendo los archivos locales | No |
| `Uploading` | Carga en la nube en curso (archivos locales capturados) | Sí |
| `SyncComplete` | Operación finalizada | Sí |

### Error de sincronización

Se activa cuando falla una operación de sincronización, por ejemplo debido a problemas de red o límites de frecuencia.

**Devolución de llamada**: `PFGameSaveFilesUiSyncFailedCallback`

**Parámetros**: Recibe `PFGameSaveFilesSyncState` (la fase que falló) y `HRESULT` (el código de error).

**API de respuesta**: `PFGameSaveFilesSetUiSyncFailedResponse`

| Acción | Efecto |
| - | - |
| `Cancel` | Cancela la operación. La devolución de llamada de `XAsyncBlock` se activa con `E_PF_GAMESAVE_USER_CANCELLED`. |
| `Retry` | Reintenta la operación con error. Si el reintento falla, esta devolución de llamada se activa de nuevo. |
| `UseOffline` | Solo es válida durante `PFGameSaveFilesAddUserWithUiAsync`. La devolución de llamada de `XAsyncBlock` se activa con `S_OK`, pero el sistema entra en modo sin conexión. Use `PFGameSaveFilesIsConnectedToCloud()` para detectar este estado. |

Para obtener más detalles sobre el comportamiento del modo sin conexión, consulte [Modo sin conexión de Game Saves](https://docs.xbox.com/es/services/playfab/player-progression/game-saves/offline.md).

### Contención de dispositivo activo

Se activa durante `PFGameSaveFilesAddUserWithUiAsync` cuando otro dispositivo ya es el dispositivo activo para este usuario. La devolución de llamada recibe estructuras `PFGameSaveDescriptor` de los datos de guardado locales y remotos, que incluyen nombres de dispositivo, marcas de tiempo y tamaños de guardado que puede mostrar para ayudar al usuario a decidir.

**Devolución de llamada**: `PFGameSaveFilesUiActiveDeviceContentionCallback`

**API de respuesta**: `PFGameSaveFilesSetUiActiveDeviceContentionResponse`

| Acción | Efecto |
| - | - |
| `Cancel` | Cancela la operación. La devolución de llamada de `XAsyncBlock` se activa con `E_PF_GAMESAVE_USER_CANCELLED`. |
| `Retry` | Reintenta: resulta útil si el usuario espera que el otro dispositivo se libere pronto. Si el otro dispositivo sigue activo, esta devolución de llamada se activa de nuevo. |
| `SyncLastSavedData` | Convierte el dispositivo local en activo y sincroniza. El dispositivo remoto ya no puede cargar y recibe una notificación de cambio de dispositivo activo. |

Para obtener más detalles sobre el comportamiento del dispositivo activo, consulte [Cambios de dispositivo activo en Game Saves](https://docs.xbox.com/es/services/playfab/player-progression/game-saves/activedevicechanges.md).

### Conflicto

Se activa durante `PFGameSaveFilesAddUserWithUiAsync` cuando los datos de guardado locales y en la nube han divergido. La devolución de llamada recibe estructuras `PFGameSaveDescriptor` de los datos de guardado locales y remotos.

**Devolución de llamada**: `PFGameSaveFilesUiConflictCallback`

**API de respuesta**: `PFGameSaveFilesSetUiConflictResponse`

| Acción | Efecto |
| - | - |
| `Cancel` | Cancela la operación. La devolución de llamada de `XAsyncBlock` se activa con `E_PF_GAMESAVE_USER_CANCELLED`. |
| `TakeLocal` | Conserva los datos de guardado locales y los carga en la nube. |
| `TakeRemote` | Descarta los cambios locales y descarga los datos de guardado en la nube. |

> [!NOTE]
>
> La resolución de conflictos se aplica a todo el guardado, no a archivos o carpetas individuales. Para obtener detalles sobre cómo se detectan los conflictos en el nivel de unidad atómica y se resuelven globalmente, consulte [Conflictos de Game Saves](https://docs.xbox.com/es/services/playfab/player-progression/game-saves/conflicts.md).

### Sin espacio de almacenamiento

Se activa durante `PFGameSaveFilesAddUserWithUiAsync` cuando el dispositivo local no tiene suficiente espacio en disco para descargar los datos de guardado desde la nube. La devolución de llamada recibe `requiredBytes`, que indica cuánto espacio se necesita.

**Devolución de llamada**: `PFGameSaveFilesUiOutOfStorageCallback`

**API de respuesta**: `PFGameSaveFilesSetUiOutOfStorageResponse`

| Acción | Efecto |
| - | - |
| `Cancel` | Cancela la operación. La devolución de llamada de `XAsyncBlock` se activa con `E_PF_GAMESAVE_USER_CANCELLED`. |
| `Retry` | Reintenta después de que el usuario libere espacio de almacenamiento local. Si sigue sin haber suficiente espacio, esta devolución de llamada se activa de nuevo. |

## En proceso frente a fuera de proceso (interfaz de usuario del sistema)

El lugar donde se ejecuta Game Saves depende de la plataforma, y esto afecta a cómo se controlan los eventos de la interfaz de usuario:

* **Fuera de proceso (XBOX y Windows)**: en XBOX y Windows, Game Saves siempre se ejecuta fuera de proceso. La plataforma (Connected Storage / GRTS) realiza la sincronización y proporciona cuadros de diálogo integrados de la interfaz de usuario del sistema para errores de sincronización, conflictos, contención de dispositivo activo y falta de espacio de almacenamiento. El jugador interactúa directamente con esos cuadros de diálogo, y la plataforma traduce el resultado a los mismos códigos de finalización asincrónica que recibe su juego en proceso. Aun así, puede registrar devoluciones de llamada para reemplazar la interfaz de usuario integrada.
* **En proceso (otras plataformas, como Steam Deck)**: donde el servicio de la plataforma no está disponible, su juego hospeda el motor de sincronización de Game Saves y controla los eventos de la interfaz de usuario mediante las devoluciones de llamada descritas anteriormente. Su juego controla por completo la máquina de estados con las API de respuesta.

### La cancelación siempre es un resultado posible

Independientemente de la ruta, **todos** los flujos de la interfaz de usuario pueden terminar con el usuario saliendo sin una sincronización correcta, por lo que su juego siempre debe controlar una cancelación definitiva:

| Intención del usuario | Finalización asincrónica | `IsConnectedToCloud()` | ¿Carpeta de guardado? |
| - | - | - | - |
| Continuar en línea (correcto) | `S_OK` | `true` | Sí |
| Jugar sin conexión | `S_OK` | `false` | Sí |
| Cancelar / Salir (jugador) | `E_PF_GAMESAVE_USER_CANCELLED` (`0x800704C7`) | n/a | **No** |
| Cancelar (el juego llamó a `XAsyncCancel`) | `E_ABORT` (`0x80004004`) | n/a | **No** |

La única acción de "salir" que aún permite al jugador continuar es **Use Offline** en el mensaje de error de sincronización (un resultado correcto). Cualquier otra cancelación es definitiva y no deja ninguna carpeta de guardado. Trátela como *no permitir jugar*. Consulte [Modo sin conexión de Game Saves](https://docs.xbox.com/es/services/playfab/player-progression/game-saves/offline.md#when-game-saves-enters-offline-mode-or-returns-an-error).

En la interfaz de usuario del sistema integrada (fuera de proceso), estas opciones aparecen con el texto de la plataforma. Por ejemplo, el cuadro de diálogo de error de sincronización ofrece **"Try again"** / **"Play offline"**, y el cuadro de diálogo de contención ofrece **"Stop sync & continue"** / **"Quit game"**. "Play offline" corresponde al modo sin conexión (`S_OK`, no conectado); "Quit game" corresponde a `E_PF_GAMESAVE_USER_CANCELLED`.

Cancelar un mensaje de **conflicto** es definitivo en ambas rutas. Se completa con `E_PF_GAMESAVE_USER_CANCELLED` y no pasa en cascada a un mensaje de error de sincronización.

Para una interfaz de usuario multiplataforma personalizada (por ejemplo, que coincida con su implementación de Steam Deck), registre devoluciones de llamada en todas partes y valide los flujos fuera de proceso en su hardware de destino. Independientemente de la ruta, condicione el juego al resultado de la finalización: `S_OK` + conectado → jugar en línea; `S_OK` + no conectado → jugar sin conexión (advierta al jugador); cancelación o error sin carpeta → bloquear el juego.

## Requisitos de plataforma

| Plataforma | Devoluciones de llamada de la interfaz de usuario |
| - | - |
| **XBOX y Windows** | Opcionales. Establezca devoluciones de llamada para reemplazar la interfaz de usuario integrada. |
| **Otras plataformas** (por ejemplo, Steam Deck) | **Obligatorias**. No hay interfaz de usuario integrada disponible; su juego debe controlar todas las devoluciones de llamada. |

Para obtener detalles de implementación en Steam Deck, consulte la [guía de implementación en Steam Deck](https://docs.xbox.com/es/services/playfab/player-progression/game-saves/steam-deck-implementation.md).

## Contenido relacionado

* [Inicio rápido de Game Saves](https://docs.xbox.com/es/services/playfab/player-progression/game-saves/quickstart.md)
* [Modo sin conexión de Game Saves](https://docs.xbox.com/es/services/playfab/player-progression/game-saves/offline.md)
* [Conflictos de Game Saves](https://docs.xbox.com/es/services/playfab/player-progression/game-saves/conflicts.md)
* [Cambios de dispositivo activo en Game Saves](https://docs.xbox.com/es/services/playfab/player-progression/game-saves/activedevicechanges.md)


## Related topics

- [Inicio rápido de Game Saves](https://docs.xbox.com/es/services/playfab/player-progression/game-saves/quickstart.md)
- [Preguntas frecuentes sobre el control de errores de Game Saves](https://docs.xbox.com/es/services/playfab/player-progression/game-saves/error-handling-faq.md)
- [Guía de implementación en Steam Deck para PlayFab Game Saves](https://docs.xbox.com/es/services/playfab/player-progression/game-saves/steam-deck-implementation.md)
- [Modo sin conexión de Game Saves](https://docs.xbox.com/es/services/playfab/player-progression/game-saves/offline.md)
- [Devoluciones de llamada de GameInput](https://docs.xbox.com/es/build/core-features/common/input/advanced/input-callbacks.md)
