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

# Uso del inventario del jugador

> Trabaje con el inventario del jugador de PlayFab mediante API de cliente y servidor con autoridad de servidor para comprar artículos, conceder moneda y administrar contenido respaldado por catálogo.

# Inventario del jugador

## Requisitos

Para usar el inventario del jugador, debe tener un catálogo definido para su título. Lea nuestro tutorial de [Catálogos](/services/playfab/economy-monetization/economy/items/catalogs) para obtener más información.

<Note>
  Opcionalmente, también puede definir tiendas para su catálogo.
</Note>

Mientras que un catálogo es la lista de todos los artículos disponibles en el juego, una tienda es un subconjunto de artículos del catálogo que tiene la opción de precios únicos.

Se pueden definir varias tiendas por catálogo, de modo que pueda tener conjuntos distintos de artículos para presentar al jugador, en función de la segmentación de usuarios u otros factores.

Una vez que haya definido un catálogo a través de [**Game Manager**](https://developer.playfab.com/), o a través de nuestras llamadas de API de administración **[SetCatalogItems](xref:titleid.playfabapi.com.admin.title-widedatamanagement.setcatalogitems)** o **[UpdateCatalogItems](xref:titleid.playfabapi.com.admin.title-widedatamanagement.updatecatalogitems)**, podrá usar una amplia variedad de llamadas de API de inventario en el cliente y el servidor.

## Información general de la API

Todas las llamadas de API de inventario están diseñadas para ser *con autoridad de servidor* y seguras. Cuando se usan correctamente, los clientes no podrán hacer trampas ni adquirir artículos que no hayan ganado.

**Clientes**:

* Comprar artículos con moneda virtual: **[PurchaseItem](xref:titleid.playfabapi.com.client.playeritemmanagement.purchaseitem)**
* Realizar compras con dinero 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)**
* Pueden ver los artículos que tiene un jugador: **[GetUserInventory](xref:titleid.playfabapi.com.client.playeritemmanagement.getuserinventory)**
* Pueden quitar artículos: **[ConsumeItem](xref:titleid.playfabapi.com.client.playeritemmanagement.consumeitem), [UnlockContainerInstance](xref:titleid.playfabapi.com.client.playeritemmanagement.unlockcontainerinstance)**
* Pueden intercambiar artículos: **[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**:

* Puede regalar/conceder artículos: **[GrantItemsToUser](xref:titleid.playfabapi.com.server.playeritemmanagement.grantitemstouser)**
* Puede ver los artículos: **[GetUserInventory](xref:titleid.playfabapi.com.server.playeritemmanagement.getuserinventory)**
* Puede modificar artículos: **[ModifyItemUses](xref:titleid.playfabapi.com.server.playeritemmanagement.modifyitemuses), [UpdateUserInventoryItemCustomData](xref:titleid.playfabapi.com.server.playeritemmanagement.updateuserinventoryitemcustomdata)**
* Puede quitar artículos: **[RevokeInventoryItem](xref:titleid.playfabapi.com.server.playeritemmanagement.revokeinventoryitem), [ConsumeItem](xref:titleid.playfabapi.com.server.playeritemmanagement.consumeitem), [UnlockContainerInstance](xref:titleid.playfabapi.com.server.playeritemmanagement.unlockcontainerinstance)**

El ejemplo que se muestra a continuación ilustra los bloques de código que llaman a estos métodos de API y configura casos de uso básicos para el inventario del jugador.

<Note>
  Como referencia, estos ejemplos proceden de **Unicorn Battle**, un juego que creamos como ejemplo para demostrar las características de PlayFab.
</Note>

La moneda virtual **AU** que se usa a continuación es el **oro**, una moneda gratuita que se gana luchando contra monstruos (consulte nuestro tutorial de [Monedas](/services/playfab/economy-monetization/economy-v2/tutorials/currencies)).

Antes de comenzar, definiremos algunas funciones de utilidad que se usarán y reutilizarán en la mayoría de los ejemplos de esta guía.

```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());
}
```

## Ejemplo solo de cliente: comprar y consumir una poción de salud

Orden de llamadas de la API de 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)

Primero debemos comenzar por definir el artículo en nuestro 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 - Economía - Editar artículo del catálogo" width="1280" height="1400" data-path="images/playfab/player-progression/player-data/tutorials/playfab-edit-catalog-item.png" />

Estos son los requisitos de `CatalogItem` para la **poción de salud**.

* `PurchaseItem` requiere un precio de artículo positivo (`5 AU`).
* `ConsumeItem` requiere que el artículo sea `Consumable`, con un recuento de artículos positivo (`3`).
* El jugador que realiza la compra debe tener cinco AU disponibles en su saldo de moneda virtual.

El código de cada llamada se proporciona a continuación.

```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);
}
```

## Ejemplo: se concede un contenedor al jugador y lo abre

Orden de llamadas de la API:

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

Primero, debemos comenzar con un contenedor definido en nuestro catálogo. Para nuestro contenedor de este ejemplo, seleccionamos un **CrystalContainer**.

Este ejemplo también demuestra la apertura del contenedor con una llave: un artículo *opcional* que también debe estar en el inventario del jugador para que la llamada `UnlockContainerInstance` se realice correctamente.

<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 - Economía - Editar contenedor del catálogo" width="1280" height="1400" data-path="images/playfab/player-progression/player-data/tutorials/playfab-edit-catalog-container.png" />

Los requisitos de `CatalogItem` para nuestro **CrystalContainer** en este ejemplo incluyen:

* Que **CrystalContainer** esté definido como un **Container**.

* Que los **contenedores** pueden definir opcionalmente un **Key Item**, que luego es necesario para desbloquear el **contenedor**; en este caso, una **CrystalKey**.

* Se recomienda encarecidamente que el **contenedor** y cualquier **llave** sean *ambos* **Consumable**, con un recuento de usos positivo, para que se quiten del inventario del jugador después de su uso.

### Código del 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 del 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);
}
```

### Consumo de llaves y contenedores

En el ejemplo anterior, se sugiere que la llave o el contenedor sean *consumibles*, aunque eso es solo una recomendación.

Pero si un contenedor y su llave (si la hay) *no son consumibles*, el contenedor se puede reabrir *infinitamente*, concediendo su contenido al jugador cada vez.

Dado que la capacidad del inventario del jugador *no* es infinita, este patrón está muy desaconsejado. Cuando se desbloquea un contenedor consumible, tanto el contenedor como la llave consumible que se usó verán automáticamente *reducido* su recuento de usos, y se quitarán del inventario del jugador cuando el recuento de usos llegue a cero.

### Opciones viables

**Contenedor consumible**, sin **llave**: el patrón más básico, en el que el contenedor se consume al abrirse y no hay llave.

**Contenedor consumible, llave consumible**: el caso sencillo del contenedor bloqueado, que permite al jugador abrir el contenedor con la llave. Se consumen *ambos*, y el jugador solo puede abrir un contenedor con usos restantes con una llave con usos restantes.

**Contenedor duradero, llave consumible**: esto permite a un jugador abrir el contenedor cada vez que encuentra una llave. La llave se consume, y el contenedor solo se abre mientras la llave tenga usos restantes.

**Contenedor consumible, llave duradera**: esto permite a un jugador conservar una llave que puede abrir *todos* los contenedores para los que es el artículo llave. El contenedor se consume, pero el jugador conserva la capacidad de abrir contenedores con la llave más adelante.

## Ejemplo: comprar artículos del inventario al jugador

No hay una API integrada para recomprar artículos del inventario al jugador, ya que el proceso es específico de cada juego. Sin embargo, puede usar los métodos de API *existentes* para crear su propia experiencia de **SellItem**:

* La API de servidor de PlayFab [RevokeInventoryItem](xref:titleid.playfabapi.com.server.playeritemmanagement.revokeinventoryitem)\*\* le permite quitar un artículo del inventario.

* La API de servidor de PlayFab [AddUserVirtualCurrency](xref:titleid.playfabapi.com.server.playeritemmanagement.adduservirtualcurrency)\*\* puede devolver una cantidad adecuada de moneda virtual. Actualmente no es posible devolver dinero real a través de los métodos de API de PlayFab.

<Note>
  Los artículos y las monedas virtuales tienen una relación estrecha. Para obtener más información, consulte nuestro tutorial de [Monedas](/services/playfab/economy-monetization/economy-v2/tutorials/currencies).
</Note>

La siguiente función de CloudScript combina las dos llamadas de servidor descritas en una única llamada accesible desde el 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);
};
```

### Procedimientos recomendados

* Asegúrese de verificar que toda la información de entrada del cliente sea *válida* antes de realizar cualquier cambio.

* CloudScript no es atómico, por lo que el orden de las llamadas importa: **AddUserVirtualCurrency** puede tener éxito y **RevokeInventoryItem** puede fallar.

<Tip>
  Por lo general, es mejor dar al jugador algo que *no* haya ganado en este proceso que quitarle algo *sin* compensación.
</Tip>

A continuación, se puede acceder a esta función de CloudScript desde el 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

- [Guía de inicio rápido del inventario del jugador](/es/services/playfab/economy-monetization/economy-v2/inventory/quickstart.md)
- [Uso de los datos de publicador del jugador para recompensar el juego en varios títulos](/es/services/playfab/player-progression/player-data/using-player-publisher-data.md)
- [Uso de los detalles del jugador](/es/services/playfab/player-progression/player-data/player-details.md)
- [Información general sobre artículos e inventario](/es/services/playfab/economy-monetization/economy-v2/inventory/items-and-inventory-overview.md)
- [Pilas de inventario](/es/services/playfab/economy-monetization/economy-v2/inventory/stacks.md)
