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

# Usando o inventário do jogador

> Trabalhe com o inventário de jogadores do PlayFab usando APIs de cliente e de servidor autoritativas no servidor para comprar itens, conceder moedas e gerenciar conteúdo baseado em catálogo.

# Inventário do jogador

## Requisitos

Para usar o inventário do jogador, você precisa ter um catálogo definido para o seu título. Leia nosso tutorial sobre [Catálogos](/pt-BR/services/playfab/economy-monetization/economy/items/catalogs) para obter mais informações.

<Note>
  Opcionalmente, você também pode definir lojas para o seu catálogo.
</Note>

Enquanto um catálogo é a lista de todos os itens disponíveis no jogo, uma loja é um subconjunto de itens do catálogo que tem a opção de preços exclusivos.

Várias lojas podem ser definidas por catálogo, para que você possa ter conjuntos distintos de itens para apresentar ao jogador, com base na segmentação de usuários ou em outros fatores.

Depois de definir um catálogo pelo [**Game Manager**](https://developer.playfab.com/) ou pelas chamadas de API de administrador **[SetCatalogItems](xref:titleid.playfabapi.com.admin.title-widedatamanagement.setcatalogitems)** ou **[UpdateCatalogItems](xref:titleid.playfabapi.com.admin.title-widedatamanagement.updatecatalogitems)**, você poderá usar uma ampla variedade de chamadas da API de inventário no cliente e no servidor.

## Visão geral da API

Todas as chamadas da API de inventário foram projetadas para serem *autoritativas no servidor* e seguras. Quando usadas corretamente, os clientes não conseguirão trapacear nem adquirir itens que não conquistaram.

**Clientes**:

* Comprar itens com moeda virtual: **[PurchaseItem](xref:titleid.playfabapi.com.client.playeritemmanagement.purchaseitem)**
* Fazer compras com dinheiro real: **[StartPurchase](xref:titleid.playfabapi.com.client.playeritemmanagement.startpurchase), [PayForPurchase](xref:titleid.playfabapi.com.client.playeritemmanagement.payforpurchase), [ConfirmPurchase](xref:titleid.playfabapi.com.client.playeritemmanagement.confirmpurchase)**
* Podem ver os itens que um jogador tem: **[GetUserInventory](xref:titleid.playfabapi.com.client.playeritemmanagement.getuserinventory)**
* Podem remover itens: **[ConsumeItem](xref:titleid.playfabapi.com.client.playeritemmanagement.consumeitem), [UnlockContainerInstance](xref:titleid.playfabapi.com.client.playeritemmanagement.unlockcontainerinstance)**
* Podem trocar itens: **[OpenTrade](xref:titleid.playfabapi.com.client.trading.opentrade), [GetPlayerTrades](xref:titleid.playfabapi.com.client.trading.getplayertrades), [AcceptTrade](xref:titleid.playfabapi.com.client.trading.accepttrade), [CancelTrade](xref:titleid.playfabapi.com.client.trading.canceltrade)**

**Servidor**:

* Pode presentear/conceder itens: **[GrantItemsToUser](xref:titleid.playfabapi.com.server.playeritemmanagement.grantitemstouser)**
* Pode ver os itens: **[GetUserInventory](xref:titleid.playfabapi.com.server.playeritemmanagement.getuserinventory)**
* Pode modificar itens: **[ModifyItemUses](xref:titleid.playfabapi.com.server.playeritemmanagement.modifyitemuses), [UpdateUserInventoryItemCustomData](xref:titleid.playfabapi.com.server.playeritemmanagement.updateuserinventoryitemcustomdata)**
* Pode remover itens: **[RevokeInventoryItem](xref:titleid.playfabapi.com.server.playeritemmanagement.revokeinventoryitem), [ConsumeItem](xref:titleid.playfabapi.com.server.playeritemmanagement.consumeitem), [UnlockContainerInstance](xref:titleid.playfabapi.com.server.playeritemmanagement.unlockcontainerinstance)**

O exemplo mostrado abaixo ilustra os blocos de código que chamam esses métodos de API e configura casos de uso básicos para o inventário do jogador.

<Note>
  Para referência, esses exemplos vêm do **Unicorn Battle**, um jogo que criamos como exemplo para demonstrar os recursos do PlayFab.
</Note>

A moeda virtual **AU** usada abaixo é o **Gold**, uma moeda gratuita obtida ao lutar contra monstros (consulte nosso tutorial sobre [Moedas](/pt-BR/services/playfab/economy-monetization/economy-v2/tutorials/currencies)).

Antes de começarmos, definiremos algumas funções utilitárias que serão usadas e reutilizadas na maioria dos exemplos deste guia.

```csharp theme={null}
// **** Shared example utility functions ****

// This is typically NOT how you handle success
// You will want to receive a specific result-type for your API, and utilize the result parameters
void LogSuccess(PlayFabResultCommon result) {
    var requestName = result.Request.GetType().Name;
    Debug.Log(requestName + " successful");
}

// Error handling can be very advanced, such as retry mechanisms, logging, or other options
// The simplest possible choice is just to log it
void LogFailure(PlayFabError error) {
    Debug.LogError(error.GenerateErrorReport());
}
```

## Exemplo somente do cliente: comprar e consumir uma poção de vida

Ordem das chamadas de API do cliente: [PurchaseItem](xref:titleid.playfabapi.com.client.playeritemmanagement.purchaseitem), [GetUserInventory](xref:titleid.playfabapi.com.client.playeritemmanagement.getuserinventory), [ConsumeItem](xref:titleid.playfabapi.com.server.playeritemmanagement.consumeitem)

Primeiro, precisamos começar definindo o item no nosso catálogo.

<img src="https://mintcdn.com/microsoft-4404708b/N3T1ucKV7zIMBudj/images/playfab/player-progression/player-data/tutorials/playfab-edit-catalog-item.png?fit=max&auto=format&n=N3T1ucKV7zIMBudj&q=85&s=773db3352052dc2e8653fa2bca38fb0b" alt="PlayFab - Economia - Editar item do catálogo" width="1280" height="1400" data-path="images/playfab/player-progression/player-data/tutorials/playfab-edit-catalog-item.png" />

Veja os requisitos de `CatalogItem` para a **Health Potion**.

* `PurchaseItem` exige um preço de item positivo (`5 AU`).
* `ConsumeItem` exige que o item seja `Consumable`, com uma contagem de itens positiva (`3`).
* O jogador que faz a compra deve ter cinco AU disponíveis no saldo de moeda virtual.

O código de cada chamada é fornecido abaixo.

```csharp theme={null}
void MakePurchase() {
    PlayFabClientAPI.PurchaseItem(new PurchaseItemRequest {
        // In your game, this should just be a constant matching your primary catalog
        CatalogVersion = "CharacterClasses",
        ItemId = "MediumHealthPotion",
        Price = 5,
        VirtualCurrency = "AU"
    }, LogSuccess, LogFailure);
}

void GetInventory() {
    PlayFabClientAPI.GetUserInventory(new GetUserInventoryRequest(), LogSuccess, LogFailure);
}

void ConsumePotion() {
    PlayFabClientAPI.ConsumeItem(new ConsumeItemRequest {
        ConsumeCount = 1,
        // This is a hex-string value from the GetUserInventory result
        ItemInstanceId = "potionInstanceId"
    }, LogSuccess, LogFailure);
}
```

## Exemplo: o jogador recebe e abre um contêiner

Ordem das chamadas de API:

* API de servidor do PlayFab [GrantItemsToUser](xref:titleid.playfabapi.com.server.playeritemmanagement.grantitemstouser)
* API de cliente do PlayFab [UnlockContainerInstance](xref:titleid.playfabapi.com.client.playeritemmanagement.unlockcontainerinstance)

Primeiro, precisamos começar com um contêiner definido no nosso catálogo. Para o nosso contêiner neste exemplo, selecionamos um **CrystalContainer**.

Este exemplo também demonstra a abertura do contêiner com uma chave, um item *opcional* que também deve estar no inventário do jogador para que a chamada a `UnlockContainerInstance` tenha êxito.

<img src="https://mintcdn.com/microsoft-4404708b/N3T1ucKV7zIMBudj/images/playfab/player-progression/player-data/tutorials/playfab-edit-catalog-container.png?fit=max&auto=format&n=N3T1ucKV7zIMBudj&q=85&s=9de90fda3309e3046ca2835412f738cd" alt="PlayFab - Economia - Editar contêiner do catálogo" width="1280" height="1400" data-path="images/playfab/player-progression/player-data/tutorials/playfab-edit-catalog-container.png" />

Os requisitos de `CatalogItem` para o nosso **CrystalContainer** neste exemplo incluem:

* Que o **CrystalContainer** seja definido como um **Container**.

* Que os **Containers** possam opcionalmente definir um **Key Item**, que então será necessário para desbloquear o **Container**; neste caso, um **CrystalKey**.

* É altamente recomendável que o seu **Container** e qualquer **Key** sejam *ambos* **Consumable**, com uma contagem de usos positiva, para que sejam removidos do inventário do jogador após o uso.

### Código do servidor

```csharp theme={null}
void GrantItem() {
    PlayFabServerAPI.GrantItemsToUser(new GrantItemsToUserRequest {
        // In your game, this should just be a constant
        CatalogVersion = "CharacterClasses",
        // Servers must define which character they're modifying in every API call
        PlayFabId = "playFabId",
        ItemIds = new List<string> { "CrystalContainer" }
    }, LogSuccess, LogFailure);
}
```

### Código do cliente

```csharp theme={null}
void OpenContainer() {
    PlayFabClientAPI.UnlockContainerInstance(new UnlockContainerInstanceRequest {
        // In your game, this should just be a constant matching your primary catalog
        CatalogVersion = "CharacterClasses",
        ContainerItemInstanceId = "containerInstanceId",
        KeyItemInstanceId = "keyInstanceId"
    }, LogSuccess, LogFailure);
}
```

### Consumindo chaves e contêineres

No exemplo anterior, sugere-se que a chave e/ou o contêiner sejam *consumíveis*, embora isso seja apenas uma recomendação.

Mas, se um contêiner e sua chave (se houver) *não forem consumíveis*, o contêiner poderá ser reaberto *infinitamente*, concedendo seu conteúdo ao jogador a cada vez.

Como a capacidade do inventário do jogador *não* é infinita, esse padrão é fortemente desencorajado. Quando um contêiner consumível é desbloqueado, tanto o contêiner quanto a chave consumível usada terão automaticamente sua contagem de usos *diminuída*, sendo removidos do inventário do jogador quando a contagem de usos chegar a zero.

### Opções viáveis

**Container consumível**, sem **Key**: o padrão mais básico, no qual o contêiner é consumido ao ser aberto e não há chave.

**Container consumível, Key consumível**: o caso simples de contêiner trancado, que permite ao jogador abrir o contêiner com a chave. *Ambos* são consumidos, e o jogador só pode abrir um contêiner com usos restantes usando uma chave com usos restantes.

**Container durável, Key consumível**: permite que o jogador abra o contêiner sempre que encontrar uma chave. A chave é consumida, e o contêiner só é aberto enquanto a chave tiver usos restantes.

**Container consumível, Key durável**: permite que o jogador mantenha uma chave capaz de abrir *todos* os contêineres para os quais ela é o item de chave. O contêiner é consumido, mas o jogador mantém a capacidade de abrir contêineres com a chave mais tarde.

## Exemplo: comprar itens do inventário do jogador

Não há uma API interna para recomprar itens do inventário do jogador, pois o processo é específico de cada jogo. No entanto, você pode usar os métodos de API *existentes* para criar sua própria experiência de **SellItem**:

* A API de servidor do PlayFab [RevokeInventoryItem](xref:titleid.playfabapi.com.server.playeritemmanagement.revokeinventoryitem)\*\* permite remover um item do inventário.

* A API de servidor do PlayFab [AddUserVirtualCurrency](xref:titleid.playfabapi.com.server.playeritemmanagement.adduservirtualcurrency)\*\* pode devolver uma quantidade apropriada de moeda virtual. No momento, não é possível devolver dinheiro real por meio dos métodos de API do PlayFab.

<Note>
  Os itens e as moedas virtuais têm uma relação próxima. Para obter mais informações, consulte nosso tutorial sobre [Moedas](/pt-BR/services/playfab/economy-monetization/economy-v2/tutorials/currencies).
</Note>

A função do CloudScript a seguir combina as duas chamadas de servidor descritas em uma única chamada acessível pelo cliente.

```javascript theme={null}
var SELL_PRICE_RATIO = 0.75;
function SellItem_internal(soldItemInstanceId, requestedVcType) {
    var inventory = server.GetUserInventory({ PlayFabId: currentPlayerId });
    var itemInstance = null;
    for (var i = 0; i < inventory.Inventory.length; i++) {
        if (inventory.Inventory[i].ItemInstanceId === soldItemInstanceId)
            itemInstance = inventory.Inventory[i];
    }
    if (!itemInstance)
        throw "Item instance not found"; // Protection against client providing incorrect data
    var catalog = server.GetCatalogItems({ CatalogVersion: itemInstance.CatalogVersion });
    var catalogItem = null;
    for (var c = 0; c < catalog.Catalog.length; c++) {
        if (itemInstance.ItemId === catalog.Catalog[c].ItemId)
            catalogItem = catalog.Catalog[c];
    }
    if (!catalogItem)
        throw "Catalog Item not found"; // Title catalog consistency check (You should never remove a catalog/catalogItem if any player owns that item
    var buyPrice = 0;
    if (catalogItem.VirtualCurrencyPrices.hasOwnProperty(requestedVcType))
        buyPrice = catalogItem.VirtualCurrencyPrices[requestedVcType];
    if (buyPrice <= 0)
        throw "Cannot redeem this item for: " + requestedVcType; // The client requested a virtual currency which doesn't apply to this item
    // Once we get here all safety checks are passed - Perform the sell
    var sellPrice = Math.floor(buyPrice * SELL_PRICE_RATIO);
    server.AddUserVirtualCurrency({ PlayFabId: currentPlayerId, Amount: sellPrice, VirtualCurrency: requestedVcType });
    server.RevokeInventoryItem({ PlayFabId: currentPlayerId, ItemInstanceId: soldItemInstanceId });
}

handlers.SellItem = function (args) {
    if (!args || !args.soldItemInstanceId || !args.requestedVcType)
        throw "Invalid input parameters, expected soldItemInstanceId and requestedVcType";
    SellItem_internal(args.soldItemInstanceId, args.requestedVcType);
};
```

### Práticas recomendadas

* Verifique se todas as informações de entrada do cliente são *válidas* antes de fazer qualquer alteração.

* O CloudScript não é atômico, portanto, a ordem das chamadas importa: **AddUserVirtualCurrency** pode ter êxito e **RevokeInventoryItem** pode falhar.

<Tip>
  Em geral, é melhor dar ao jogador algo que ele *não* conquistou nesse processo do que tirar algo dele *sem* compensação.
</Tip>

Essa função do CloudScript pode então ser acessada a partir do cliente.

```csharp theme={null}
void SellItem()
{
    PlayFabClientAPI.ExecuteCloudScript(new ExecuteCloudScriptRequest
    {
        // This must match "SellItem" from the "handlers.SellItem = ..." line in the CloudScript file
        FunctionName = "SellItem",
        FunctionParameter = new Dictionary<string, string>{
            // This is a hex-string value from the GetUserInventory result
            { "soldItemInstanceId", "sellItemInstanceId" },
            // Which redeemable virtual currency should be used in your game
            { "requestedVcType", "AU" },
        }
    }, LogSuccess, LogFailure);
}
```


## Related topics

- [Início rápido do inventário do jogador](/pt-BR/services/playfab/economy-monetization/economy-v2/inventory/quickstart.md)
- [Usando os detalhes do jogador](/pt-BR/services/playfab/player-progression/player-data/player-details.md)
- [Documentação do PlayFab Economy v2](/pt-BR/services/playfab/economy-monetization/index.md)
- [Serviços de criptografia do jogador](/pt-BR/services/playfab/identity/player-identity/encryption/player-encryption-services.md)
- [Coleções do Inventário](/pt-BR/services/playfab/economy-monetization/economy-v2/inventory/collections.md)
