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

# Portar o armazenamento do Steam Cloud para o XBOX GDK

> Substitua o Steam Cloud e o ISteamRemoteStorage pelo wrapper XGameSave do XBOX GDK, com exemplos de código lado a lado para ler, gravar e sincronizar salvamentos.

O Steam habilita o armazenamento em nuvem de uma de duas formas. Você pode fazer todas as leituras e gravações usando os métodos da API `ISteamRemoteStorage`, que gravam arquivos na pasta de armazenamento do jogo no disco rígido local e os sincronizam com a nuvem. Como alternativa, você pode fazer todas as leituras e gravações diretamente no sistema de arquivos do computador e, em seguida, usar o Steam Auto-Cloud para sincronizar a pasta local que contém os dados do jogo com a nuvem.

O Microsoft Game Development Kit (GDK) oferece suporte às duas abordagens:

* Para salvamentos em nuvem baseados em código, o GDK oferece um [wrapper simplificado](/pt-BR/reference/system/Wrappers/xgamesave_wrapper_members) da API `XGameSave`, mais complexa, que fornece funcionalidade semelhante à dos métodos de `ISteamRemoteStorage`.
* Para uma abordagem semelhante ao Steam Auto-Cloud, o GDK oferece suporte à [portabilidade de títulos anteriores para PC Game Saves com salvamentos em nuvem sem código](/pt-BR/build/core-features/common/game-save/game-saves-walkthroughs-and-samples#porting-previous-titles-to-pc-game-saves-with-no-code-cloud-saves), que sincroniza uma pasta local designada com a nuvem sem exigir alterações no seu código de E/S de arquivos.

<Warning>
  Os salvamentos em nuvem sem código não têm suporte em consoles XBOX nem no XBOX Cloud Gaming. Se o seu título se destina a console ou nuvem, além do PC com Windows, use o wrapper `XGameSave` ou a API `XGameSave` completa.
</Warning>

O wrapper baseado em código é o caminho recomendado para títulos lançados em console ou na nuvem. Ele corresponde de perto à gravação de arquivos localmente ou ao uso da API Steam Remote Storage. Este tópico se concentra no wrapper simplificado.

<Note>
  A API `XGameSave` completa, sem wrapper, oferece mais funcionalidade e flexibilidade do que o wrapper simples. Se você precisar de alguma dessas funcionalidades, não use o wrapper. Os jogos não devem alternar entre os dois nem misturar chamadas de API de ambos. Para obter mais informações sobre a API `XGameSave`, consulte [Salvamentos de jogos](/pt-BR/build/core-features/common/game-save/game-saves-overview).
</Note>

Os exemplos de código a seguir mostram como as operações básicas de arquivo funcionam no SDK do Steamworks e no Microsoft Game Development Kit (GDK), além de algumas diferenças sutis entre as duas APIs.

## Comparações de operações de arquivo

Os exemplos de código a seguir mostram como realizar operações básicas de arquivo na API Steamworks Remote Storage e no equivalente do GDK. Eles presumem que a variável `provider` contém um ponteiro para um objeto `Microsoft::Xbox::Wrappers::GameSave::Provider` inicializado.

Se você não estiver usando a API Steam Remote Storage, mas tiver optado por usar o Steam Auto-Cloud, substitua as chamadas da API Remote Storage pelas equivalentes da API do sistema de arquivos.

### Ler um arquivo

#### Steamworks

```cpp theme={null}
int32 size = SteamRemoteStorage()->GetFileSize("MyFile.json");
if (size > 0) 
{
    char *buffer = new char[size];
    bool result = SteamRemoteStorage()->FileRead("MyFile.json", buffer, size);
}           
```

ou

```cpp theme={null}
int32 size = GetFileSize("MyFile.json");
if (size > 0)
{
    m_readResult = SteamRemoteStorage()->FileReadAsync("MyFile.json", 0, size);
    // Check the value of m_readResult in callback for error handling.
    STEAM_CALLBACK(MyGameClass, OnFileReadCompleted, RemoteStorageFileReadAsyncComplete_t);
}
```

#### GDK

```cpp theme={null}
BlobData data = provider->Load("SaveSlot1", "MyData");
if(!data.empty())
{
    // Iterate over the data to read bytes from the file.
}
else
{
    // Couldn't find the container/blob name.
}
```

#### Documentação de referência

[Microsoft.Xbox.Wrappers.XGameSave.Provider.Load](/pt-BR/reference/system/Wrappers/xgamesave_wrapper_members)

### Gravar um arquivo

#### Steamworks

```cpp theme={null}
std::string saveData = "{progress: 25}";
SteamRemoteStorage()->FileWrite("MyFile.json", saveData.c_str(), saveData.size());
```

ou

```cpp theme={null}
std::string saveData = "{progress: 25}";
m_writeResult = SteamRemoteStorage()->FileWriteAsync("MyFile.json", saveData.c_str(), saveData.size());
STEAM_CALLBACK(MyGameClass, OnFileWriteCompleted, RemoteStorageFileWriteAsyncComplete_t);
```

#### GDK

```cpp theme={null}
std::vector<uint8_t> saveData; // Contains the player's data.
HRESULT hr = provider->Save("SaveSlot1", "MyData", saveData.size(), saveData.data());
if(FAILED(hr))
{
  if(hr == E_GS_QUOTA_EXCEEDED)
  {
     // Message that the user must clear out saves for this game.
  }
  else if(hr == E_GS_OUT_OF_LOCAL_STORAGE)
  {
     // Message to the user that they have run out of save space on the local device.
  }
  else if(hr == E_GS_UPDATE_TOO_BIG)
  {
     // Your save size was over 16 MB (GS_MAX_BLOB_SIZE).
  }
  else if(hr == E_GS_HANDLE_EXPIRED)
  {
     // Need to re-create the provider and try again.
     // This can happen if your game was suspended and, during that time, another
     // device initialized a provider for the same user.
  }
  else
  {
     // Log error.
  }
}
```

#### Documentação de referência

[Microsoft.Xbox.Wrappers.XGameSave.Provider.Save](/pt-BR/reference/system/Wrappers/xgamesave_wrapper_members)

### Excluir um arquivo

No Steam, você pode excluir um arquivo na nuvem, mas manter a cópia local (`FileForget`), ou excluir um arquivo dos dois locais (`FileDelete`). A API do wrapper `XGameSave` não tem um equivalente a `FileForget`. A função `Delete` dela funciona como `FileDelete` no Steamworks.

#### Steamworks

```cpp theme={null}
// Delete a file from the cloud but keep it locally.
bool result = SteamRemoteStorage()->FileForget("MyFile.json");
```

ou

```cpp theme={null}
// Delete a file locally AND from the cloud.
bool result = SteamRemoteStorage()->FileDelete("MyFile.json");
```

#### GDK

```cpp theme={null}
// Delete a specific file.
HRESULT hr = provider->Delete("MyContainer", "MyData");
```

ou

```cpp theme={null}
// Delete a set of files in a container. 
std::vector<std::string> toDelete = { "blob1", "blob2", "blob3" };
HRESULT hr = provider->Delete("MyContainer", toDelete);
```

ou

```cpp theme={null}
// Delete all the files in a container.
HRESULT hr = provider->Delete("MyContainer");
```

#### Documentação de referência

* [Microsoft.Xbox.Wrappers.XGameSave.Provider.Delete(std::string)](/pt-BR/reference/system/Wrappers/xgamesave_wrapper_members)
* [Microsoft.Xbox.Wrappers.XGameSave.Provider.Delete(std::string, std::string)](/pt-BR/reference/system/Wrappers/xgamesave_wrapper_members)
* [Microsoft.Xbox.Wrappers.XGameSave.Provider.Delete(std::string, BlobNames)](/pt-BR/reference/system/Wrappers/xgamesave_wrapper_members)

### Obter todos os arquivos

#### Steamworks

```cpp theme={null}
int32 fileCount = SteamRemoteStorage()->GetFileCount();
for ( int i = 0; i < fileCount; ++i ) {
    int32 fileSize;
    const char *fileName = SteamRemoteStorage()->GetFileNameAndSize( i, &fileSize );
    // Do something with fileSize and fileName.
}
```

#### GDK

```cpp theme={null}
// To get all the files across all containers for the game, make this = ""
// Otherwise, make it a prefix of whichever container's files you'd like.
std::string containerQuery = "";
std::vector<std::string> containers = provider->QueryContainers(containerQuery);

for (auto&& container : containers)
{
    BlobInfoSet blobs = provider->QueryContainerBlobs(container);
    for (auto&& blob : blobs)
    {
        uint32_t blobSize = blob.size;
        std::string blobName = blob.name;
        // Do something with blobSize and blobName.
    }
}
```

#### Documentação de referência

* [Microsoft.Xbox.Wrappers.XGameSave.Provider.QueryContainers](/pt-BR/reference/system/Wrappers/xgamesave_wrapper_members)
* [Microsoft.Xbox.Wrappers.XGameSave.Provider.QueryContainerBlobs](/pt-BR/reference/system/Wrappers/xgamesave_wrapper_members)

### Verificar o espaço disponível

Nos exemplos a seguir, `totalBytes` é a quantidade de espaço que seu jogo recebe no provedor de armazenamento em nuvem. `availableBytes` é a quantidade de espaço livre restante (ou seja, `availableBytes` = `totalBytes` – `bytesUsed`).

#### Steamworks

```cpp theme={null}
uint64 totalBytes, availableBytes;
SteamRemoteStorage()->GetQuota(&totalBytes, &availableBytes);
```

#### GDK

```cpp theme={null}
// totalBytes is always 256 MB.
int64_t availableBytes = provider->GetQuota();
```

#### Documentação de referência

[Microsoft.Xbox.Wrappers.XGameSave.Provider.GetQuota](/pt-BR/reference/system/Wrappers/xgamesave_wrapper_members)

## Diferenças de terminologia

No Steam, os dados do armazenamento remoto são gerenciados como arquivos, que funcionam como arquivos em um disco rígido local. Para ler ou gravar, você especifica o arquivo e, em seguida, obtém ou define os bytes que ele contém.

No Microsoft Game Development Kit (GDK), o equivalente aos arquivos do Steam são os *blobs*. Os blobs são agrupados em uma estrutura chamada *contêiner*. Um contêiner é um grupo nomeado de blobs. Por exemplo, você pode usar contêineres para oferecer suporte a vários slots de salvamento por usuário, com os mesmos nomes de arquivo em cada slot. Se você não precisar da camada organizacional extra que os contêineres fornecem, coloque todos os seus blobs (arquivos) no mesmo contêiner.

<Note>
  Os nomes de contêiner não podem incluir espaços. Tentar acessar ou criar um nome de contêiner que inclua um espaço faz com que o método do provedor retorne um HRESULT `0x80830001`: o volume especificado não oferece suporte a camadas de armazenamento.
</Note>

## Limites de armazenamento

O Microsoft Game Development Kit (GDK) tem um tamanho máximo de gravação de blob ou arquivo e um limite geral de armazenamento menores que os do Steam. No Steam, cada operação de gravação de arquivo é limitada a 100 mebibytes (MiB), e cada arquivo não pode ter mais de 200 MiB. Por outro lado, a API `XGameSave` e seu wrapper limitam cada blob a 16 MB e permitem no máximo 256 MB por usuário por jogo.

Se você precisar armazenar mais de 16 MB de dados em um blob, divida os dados em vários blobs. Em seguida, implemente uma função de leitura e gravação sequencial para processar os dados um blob por vez.

## As funções do wrapper são bloqueantes

A interface `ISteamRemoteStorage` oferece duas versões das funções de leitura e gravação: `FileRead` e `FileWrite`, além de `FileReadAsync` e `FileWriteAsync`. As versões `Async` fazem um retorno de chamada quando o arquivo é lido ou gravado. As funções do wrapper simplificado `XGameSave` não oferecem versões assíncronas de seus equivalentes a `FileRead` e `FileWrite`. `Provider::Load` e `Provider::Save` são bloqueantes, portanto, tenha esse comportamento em mente ao usá-las no seu jogo.

Por esse motivo, `Provider::Initialize` *gera uma exceção se você a chamar a partir do thread da interface do usuário*.

## Inicialização

Inclua o arquivo de cabeçalho do wrapper na solução do seu jogo antes de usar qualquer método do wrapper. Você pode encontrá-lo em *%GRDKLatest%\GameKit\Include\xgamesavewrappers.hpp*.

Antes de usar os métodos do wrapper `XGameSave`, crie uma instância da classe `Provider` e chame o método `Provider::Initialize`. Mantenha um ponteiro para a instância de `Provider` durante todo o tempo de vida do seu jogo. Chame `Provider::Initialize` a partir de um thread diferente do thread da interface do usuário. O método gera uma exceção se você o chamar a partir do thread da interface do usuário. Para inicializar o provedor do wrapper, você precisa de um `XUserHandle` para o usuário atual e do identificador de configuração de serviço (SCID) do seu jogo.

```cpp theme={null}
using namespace Microsoft::Xbox::Wrappers::GameSave;

Provider provider = new Provider();
if(SUCCEEDED(provider->Initialize(userHandle, mySCID)) {
    // Start using the XGameSave wrapper...
```

#### Documentação de referência

[Microsoft.Xbox.Wrappers.XGameSave.Provider.Initialize](/pt-BR/reference/system/Wrappers/xgamesave_wrapper_members)


## Related topics

- [Portar do Steam](/pt-BR/paths/porting/from-steam.md)
- [Portar do PC (não-Steam)](/pt-BR/paths/porting/from-pc.md)
- [Portar de outras plataformas](/pt-BR/paths/porting/from-console.md)
- [Armazenamento](/pt-BR/services/xbox-services/storage/index.md)
- [Visão geral do guia de portabilidade do Steam](/pt-BR/build/steam-porting-guide/overview.md)
