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

# Juego de creación de objetos, parte 3: programación

> Parte 3 del tutorial del juego de creación de objetos de PlayFab Economy V2: escriba código C# que llame a la API de Economy V2 para administrar inventarios, recetas y objetos creados.

# Parte 3: programación + ejemplos

Ahora que tiene su entorno listo y está familiarizado con Game Manager, podemos empezar a programar nuestro juego.

## Requisitos previos

1. [Parte 1: configuración del entorno](/services/playfab/economy-monetization/economy-v2/tutorials/craftingGame/crafting-game-environment)
2. [Parte 2: uso de Game Manager](/services/playfab/economy-monetization/economy-v2/tutorials/craftingGame/crafting-game-game-manager)

## Paso 1: configurar los ajustes del entorno

Lo primero que le recomendamos hacer cuando empiece a programar es configurar los ajustes de su entorno. De esta forma puede tener la seguridad de que cada llamada que haga tendrá un vínculo con su título y usará su clave secreta de desarrollador específica.

Para quitarse este paso de encima, puede especificar en cualquier lugar de su código (idealmente en algún sitio fácil de encontrar) las variables TitleId y DeveloperSecretKey y asignarles sus valores.

Hágalo agregando dos líneas de código independientes como las siguientes:

```csharp theme={null}
PlayFabSettings.staticSettings.TitleId = "{Your Title ID}";
PlayFabSettings.staticSettings.DeveloperSecretKey = "{Your Developer Secret Key}";
```

## Paso 2: autenticarse

Una vez que tenga el entorno configurado, el paquete NuGet de PlayFab instalado y configurado en su proyecto, y tanto su estudio como su título creados, podemos empezar a programar nuestra autenticación.

<Note>
  Hay varias maneras en las que un usuario puede autenticarse. En este ejemplo, vamos a usar el método **LoginWithCustomId**. Existen otras formas de autenticarse, incluidas algunas específicas de cada plataforma. Para obtener más información, visite [Conceptos básicos de inicio de sesión](/services/playfab/identity/player-identity/login/login-basics-best-practices).
</Note>

A continuación se muestra un código de ejemplo hecho en C# en el que autenticamos a un usuario mediante **LoginWithCustomID**, que se clasifica como un inicio de sesión anónimo. Antes de llamar a la API para autenticarse, primero debemos declarar una variable global en la que almacenamos la **EntityKey** que se genera como parte del proceso de inicio de sesión.

La **EntityKey** se usa para hacer cualquier tipo de llamada a la API y es lo que vincula cada solicitud y respuesta con el usuario que ha iniciado sesión.

La declaración de la variable global EntityKey es la siguiente:

```csharp theme={null}
private static PlayFab.ClientModels.EntityKey entityKey;
```

***

A continuación, la lógica para autenticar a un usuario es:

### SDK de C\#

```csharp theme={null}
var request = new LoginWithCustomIDRequest { CustomId = username };
var loginTask = PlayFabClientAPI.LoginWithCustomIDAsync(request);
entityKey = loginTask.Result.Result.EntityToken.Entity;
```

### API

```json theme={null}
{
  "CustomId": "{{Username}}",
  "CreateAccount": false,
  "TitleId": "{{TitleId}}"
}
```

***

El código anterior busca cualquier jugador existente vinculado al título de su juego. Pero falla si no hay ningún usuario con un nombre de usuario coincidente. Para evitarlo, podemos agregar un parámetro "CreateAccount = true" al cuerpo de la solicitud. Esto hace que PlayFab cree un nuevo jugador si no hay ninguna coincidencia con lo que el usuario envíe como nombre de usuario. Esto daría como resultado un código con este aspecto:

### SDK de C\#

```csharp theme={null}
var request = new LoginWithCustomIDRequest { CustomId = username, CreateAccount = true };
var loginTask = PlayFabClientAPI.LoginWithCustomIDAsync(request);
entityKey = loginTask.Result.Result.EntityToken.Entity;
```

### API

```json theme={null}
{
  "CustomId": "{{Username}}",
  "CreateAccount": true,
  "TitleId": "{{TitleId}}"
}
```

***

Tras un inicio de sesión correcto, la API devolverá varios conjuntos de datos, como el **SessionTicket**, el **PlayFab ID** del usuario y el **EntityToken**. Estos se pueden ver en la respuesta directa de la API, que se detalla a continuación.

```json theme={null}
{
    "code": 200,
    "status": "OK",
    "data": {
        "SessionTicket": "{{SessionTicket}}",
        "PlayFabId": "{{PlayFabID}}",
        "NewlyCreated": false,
        "SettingsForUser": {
            "NeedsAttribution": false,
            "GatherDeviceInfo": true,
            "GatherFocusInfo": true
        },
        "LastLoginTime": "2023-08-01T17:09:54.508Z",
        "EntityToken": {
            "EntityToken": "{{EntityToken}}",
            "TokenExpiration": "2023-08-04T21:20:35Z",
            "Entity": {
                "Id": "{{Player ID}}",
                "Type": "title_player_account",
                "TypeString": "title_player_account"
            }
        },
        "TreatmentAssignment": {
            "Variants": [],
            "Variables": []
        }
    }
}
```

***

Una vez que obtenga el `"code":200` devuelto por la API o que reciba información en el `loginTask` del ejemplo de C# anterior, ¡ya está autenticado y puede pasar al siguiente paso!

## Paso 3: configurar su inventario inicial

Ahora que ha iniciado sesión con un jugador válido (o ha creado un nuevo jugador), su primer paso debería ser establecer el inventario inicial de ese jugador. Para ello, usaremos la llamada de API [ExecuteInventoryOperations](https://learn.microsoft.com/en-us/rest/api/playfab/economy/inventory/execute-inventory-operations).

<Note>
  La llamada ExecuteInventoryOperations nos permite ejecutar varias [InventoryOperations](https://learn.microsoft.com/en-us/rest/api/playfab/economy/inventory/execute-inventory-operations) por lotes en el inventario del jugador. Los tipos de operaciones admitidas son: - Add - Delete - Purchase - Subtract - Transfer - Update
</Note>

Para este ejemplo, agregaremos los objetos correspondientes a nuestro juego. Son tres instancias de Stone, una instancia de Cream y una instancia de Gold (esto suponiendo que ya haya creado más objetos; si no, hágalo antes de continuar). Pero en lugar de usar simplemente la operación **Add**, usamos la operación **Purchase** y compramos las instancias necesarias de forma gratuita.

<Note>
  Para que este paso funcione, primero debe haber creado los objetos en su título en Game Manager.
</Note>

Los siguientes fragmentos le mostrarán cómo hacer esas llamadas en bloque tanto en C# como con la API de PlayFab.

### SDK de C\#

En este ejemplo de C#, puede ver que empezamos estableciendo purchasePrice como un valor estándar para todas las transacciones; esto es porque haremos que todas tengan un precio de 0.

Cualquier objeto puede tener varios precios, y de ahí que la variable `purchasePrice` sea de tipo `List<PurchasePriceAmount>`.

El siguiente aspecto que puede observar es que la solicitud toma, además de la lista de `InventoryOperation`, una entidad (Entity), para la cual crearemos una nueva con los valores que obtuvimos del inicio de sesión que hicimos antes.

Por último, cada `InventoryOperation` toma un valor `Purchase`, aunque este podría ser cualquiera de los disponibles en la llamada **ExecuteInventoryOperations** (Add, Delete, Purchase, Subtract, Transfer y Update). En este caso usamos el identificador `Purchase`, por lo que necesitamos una `new PurchaseInventoryItemsOperation`.

También debe dejar claro cuál es el objeto que quiere comprar. Esto se hace mediante `InventoryItemReference`, que toma el identificador del objeto como único parámetro.

En nuestro código, tenemos un método llamado **SearchItem(\{itemName})**, pero puede reemplazarlo fácilmente por una cadena que represente el identificador del objeto. Asegúrese de hacer coincidir el nombre (o identificador) de cada objeto con la cantidad correspondiente.

```csharp theme={null}
var purchasePrice = new List<PurchasePriceAmount> { new PurchasePriceAmount { ItemId = freeItemId, Amount = 0 } };
var request = new ExecuteInventoryOperationsRequest 
{ 
    Entity = new PlayFab.EconomyModels.EntityKey { Id = entityKey.Id, Type = entityKey.Type },
    Operations = new List<InventoryOperation> {
        new InventoryOperation
        {
            Purchase = new PurchaseInventoryItemsOperation { 
                Item = new InventoryItemReference {AlternateId = new AlternateId { Type = "FriendlyId", Value = "Stone" } }, 
                Amount = 3, 
                PriceAmounts = purchasePrice
            }
        },
        new InventoryOperation
        {
            Purchase = new PurchaseInventoryItemsOperation {
                Item = new InventoryItemReference { AlternateId = new AlternateId { Type = "FriendlyId", Value = "Gold" } },
                Amount = 1,
                PriceAmounts = purchasePrice
            }
        },``
        new InventoryOperation
        {
            Purchase = new PurchaseInventoryItemsOperation {
                Item = new InventoryItemReference {AlternateId = new AlternateId { Type = "FriendlyId", Value = "Cream" }},
                Amount = 1,
                PriceAmounts = purchasePrice
            }
        }
    }
};
await PlayFabEconomyAPI.ExecuteInventoryOperationsAsync(request);
```

En el código anterior, para usar correctamente `AlternateId` y `FriendlyId` en su código, sus objetos deben tener esos valores configurados en Game Manager. Para ello, le sugiero que consulte la [Parte 2: uso de Game Manager](/services/playfab/economy-monetization/economy-v2/tutorials/craftingGame/crafting-game-game-manager), donde detallamos los pasos que debe seguir.

### API

Llame al punto de conexión de la API **ExecuteInventoryOperations** con el cuerpo de solicitud que se muestra a continuación, reemplazando los identificadores por los correspondientes. Tenga en cuenta que `Operations` es una matriz; puede rellenarla con varios tipos de operaciones simultáneamente.

Es importante entender que, para cada una de las llamadas a la API que haga, debe establecer un encabezado `X-EntityToken` con el **EntityToken** específico de su sesión activa o del usuario que ha iniciado sesión. En otras palabras, antes de hacer cualquier llamada a la API, primero debe ejecutar **LoginWithCustomID** (en este ejemplo) y, del mensaje de respuesta, obtener el **EntityToken** que se usará como encabezado en todas las llamadas a la API.

```json theme={null}
{
  "Operations": [
    {
      "Purchase": {
            "Item": {
                "Id": {Stone ID}
            },
            "Amount": 3,
            "PriceAmounts": [
                {
                "ItemId": {Free Item ID},
                "Amount": 0
                }
            ]
        }
    },
    {
      "Purchase": {
            "Item": {
                "Id": {Gold ID}
            },
            "Amount": 1,
            "PriceAmounts": [
                {
                "ItemId": {Free Item ID},
                "Amount": 0
                }
            ]
        }
    },
    {
      "Purchase": {
            "Item": {
                "Id": {Cream ID}
            },
            "Amount": 1,
            "PriceAmounts": [
                {
                "ItemId": {Free Item ID},
                "Amount": 0
                }
            ]
        }
    }
  ]
}
```

El siguiente JSON es un ejemplo de un mensaje de respuesta correcto después de hacer la llamada anterior. Verá que se devuelven tres identificadores de transacción distintos porque los identificadores se asignan por cada modificación, aunque esto no significa que haya tres transacciones separadas. Más bien al contrario: se maneja como una única transacción pero con tres modificaciones, por lo que solo devolvemos un único resultado de éxito o error para toda la transacción con independencia del número de modificaciones.

```json theme={null}
{
    "code": 200,
    "status": "OK",
    "data": {
        "IdempotencyId": {Idempotency ID},
        "TransactionIds": [
            "200",
            "201",
            "202"
        ],
        "ETag": "1/MjAy"
    }
}
```

***

## Paso 4: crear una agrupación

Las agrupaciones (bundles) le permiten agrupar varios objetos en un único objeto. Para obtener más información sobre las agrupaciones, consulte nuestra **documentación de agrupaciones** en [este vínculo](/services/playfab/economy-monetization/economy-v2/catalog/bundles).

Para nuestro ejemplo, usaremos una **agrupación** para agrupar los objetos devueltos por la **Kitchen**, lo que nos ayuda a conservar el objeto **Icebox**. La idea detrás de la nevera es que sea un objeto no consumible al comprar un helado, aunque la nevera sea uno de los materiales necesarios.

Una visión general de cómo funciona esto es la siguiente. Imagine un jugador que tiene una Cream y una Icebox en su inventario. Al acceder a la tienda Kitchen, dicho jugador debe usar ambos objetos para comprar/hacer un Ice Cream. Dado que la Icebox no es consumible, la función esperada es tener un inventario resultante de un Ice Cream y una Icebox, habiendo consumido únicamente el objeto Cream.

La forma en que lo manejamos entre bastidores es mediante una agrupación con un precio de una Icebox y una Cream, y cuyos objetos devueltos son un Ice Cream y una Icebox. Esto significa que la Icebox del inventario del jugador se consumirá, pero la misma transacción que la consume devuelve otra, dando al jugador la impresión de que la Icebox siempre está en el inventario, cuando en realidad las instancias de Icebox son diferentes, aunque invisibles para el jugador.

Para crear una agrupación, debe ir a la sección **Economy** de su título, como hizo al crear un nuevo objeto. Habrá una pestaña llamada **Bundles** junto a **Items**, **Currency** y otras. Una vez seleccionada, aparece un botón azul en la esquina superior derecha de la pantalla que dice **New bundle**.

A continuación se mostrará un formulario similar al de creación de un nuevo objeto, con la diferencia clave de que, si se desplaza hacia abajo, encontrará una sección titulada **Items**. Aquí puede agregar los objetos que quiera que contenga la agrupación, los cuales se transferirán al inventario del jugador cuando se compre.

Tras hacer clic en el botón **Add**, aparecerá una lista con capacidad de búsqueda de todos los objetos de su catálogo; aquí puede seleccionar los objetos que quiera incluir en la agrupación. En cuanto haya seleccionado sus objetos y los haya agregado, puede proceder a **Save and publish** y su agrupación quedará activa y seleccionable desde las tiendas como precio de compra.

## Paso 5: crear una tienda

Siguiendo nuestro ejemplo de juego de creación de objetos, debemos hacer que el jugador compre objetos en una tienda. Habrá tres tiendas distintas (en este caso, ubicaciones): la **Science Machine**, el **Alchemy Engine** y la **Kitchen**.

Nos centraremos en la **Kitchen**. Aquí, los jugadores pueden comprar un **Ice Cream** (nuevo objeto que debe crearse) por el precio de **1 Cream** y **1 Icebox** (nuevo objeto que debe crearse). Se ha elegido este caso concreto porque muestra cómo funcionan las **agrupaciones** junto con las tiendas y las transacciones.

Las tiendas solo pueden crearse desde [Game Manager](https://developer.playfab.com), yendo a la sección **Economy** de la barra de navegación izquierda; luego, entre las distintas pestañas, elija **Stores** y seleccione el botón azul **New store**.

Esto muestra un formulario similar al utilizado al crear nuevos objetos, en el que los únicos campos obligatorios son la fecha de inicio y el título que quiera dar a su tienda. Al desplazarse hacia abajo, verá

## Paso 6: agregar una agrupación a una tienda

Ahora que tiene su agrupación y su tienda creadas y publicadas, puede agregar la agrupación como un objeto obtenible en su tienda. Para ello, entre en su tienda, desplácese hacia abajo hasta ver el título **Items** y seleccione el botón **Add**.

Esto muestra la lista de objetos del catálogo. En el lado izquierdo de la barra de búsqueda habrá un menú desplegable con los distintos tipos de objetos, como **Items**, **UGC Items**, **Bundles** y **Subscription**. Si elige **Bundles**, la lista se filtra para reflejar solo los objetos de tipo agrupación; aquí debería ver la agrupación que creó anteriormente. Cuando seleccione el botón **Add** junto al nombre de la agrupación, y luego el botón **Add** al final de la ventana, la agrupación quedará agregada como posible objeto de transacción para esa tienda concreta.

Queda un último paso antes de continuar: establecer un precio para su agrupación. Este precio funciona como cualquier otro precio de objeto en el sentido de que requiere que el jugador tenga en su inventario los objetos del precio que se exijan antes de aceptar la compra. Para establecer un precio, puede seleccionar el botón **Add new price** a la derecha de su agrupación y, en la lista de objetos, seleccionar los objetos que quiera que sean el precio. En nuestro caso, queremos que el precio sea **1 Icebox** y **1 Cream**.

Ahora que su agrupación se ha agregado a su tienda y tiene el precio correspondiente, podemos pasar al siguiente paso.

## Paso 7: comprar una agrupación

Una vez que su agrupación y su tienda estén creadas, y su agrupación esté vinculada a su tienda, ya puede comprar esa agrupación y recibir los objetos resultantes en su inventario.

Para comprar una agrupación, desde la perspectiva de un jugador, puede usar **PurchaseInventoryItems** de la API de PlayFab, que funciona no solo con agrupaciones, sino también con objetos individuales.

### API

En el caso siguiente, queremos comprar **1 agrupación** con un precio de **1 Icebox** y **1 Cream**. Vamos a usar las propiedades de matriz de **PriceAmounts** para establecer más de 1 objeto como precio. Solo asegúrese de haber dado a su agrupación un **FriendlyId**.

```json theme={null}
{
  "Item": {
    "AlternateId": {
        "Type": "FriendlyId",
        "Value": "Ice Cream and Ice Box"
    }
  },
  "Amount": 1,
  "PriceAmounts": [
    {
        "ItemId": "0d2ab329-2fc5-4ae1-9e3c-19f9fc9bbf86",
        "Amount": 1
    },
    {
        "ItemId": "e5276289-f839-4bde-acce-309ea7959e45",
        "Amount": 1
    }
  ],
  "DeleteEmptyStacks": true,
  "StoreId": "f116f1d4-64f9-4be7-9660-a3c1f021100b"
}
```

El siguiente fragmento es la respuesta esperada tras una llamada correcta a la API.

```json theme={null}
{
    "code": 200,
    "status": "OK",
    "data": {
        "ETag": "1/MjEz",
        "IdempotencyId": "d710508f-defc-4382-bbd1-a3576417b3f7",
        "TransactionIds": [
            "212",
            "213"
        ]
    }
}
```

<Note>
  Observará en la respuesta que obtiene 2 `TransactionIds` diferentes. Esto se debe a que la propiedad `DeleteEmptyStacks` se maneja como una transacción adicional. En el ejemplo anterior, la transacción 212 corresponde a la compra de la agrupación, y la transacción 213 a la eliminación de la pila vacía de Cream (suponiendo que solo tuviera 1 Cream en su inventario).
</Note>

### SDK de C\#

En cuanto al aspecto que debería tener el código C#, a continuación puede encontrar un fragmento de nuestro ejemplo.

```csharp theme={null}
var purchaseRequest = new PurchaseInventoryItemsRequest
{
    Entity = new PlayFab.EconomyModels.EntityKey { Id = entityKey.Id, Type = entityKey.Type },
    Item = new InventoryItemReference { Id = "34167d9f-c8d7-4e17-9a87-b6af1fc389b2" }, //bundle id
    Amount = 1,
    PriceAmounts = new List<PurchasePriceAmount>() { 
        new PurchasePriceAmount { 
            ItemId = "e5276289-f839-4bde-acce-309ea7959e45", 
            Amount = 1 
        }, //cream id and quantity
        new PurchasePriceAmount { 
            ItemId =  "0d2ab329-2fc5-4ae1-9e3c-19f9fc9bbf86", 
            Amount = 1 
        } //icebox id and quantity
    }, 
    StoreId = "f116f1d4-64f9-4be7-9660-a3c1f021100b",
    DeleteEmptyStacks = true
};

var result = await PlayFabEconomyAPI.PurchaseInventoryItemsAsync(purchaseRequest);
```

***

## Consulte también

* [Información general de Economy v2](/services/playfab/economy-monetization/economy-v2/overview)
* [Configuración](/services/playfab/economy-monetization/economy-v2/settings)
* [Tiendas de Economy v2](/services/playfab/economy-monetization/economy-v2/catalog/stores#creating-a-store)


## Related topics

- [Juego de creación de objetos, parte 1: configuración](/es/services/playfab/economy-monetization/economy-v2/tutorials/craftingGame/crafting-game-environment.md)
- [Juego de creación de objetos, parte 2: Game Manager](/es/services/playfab/economy-monetization/economy-v2/tutorials/craftingGame/crafting-game-game-manager.md)
- [Juego de creación de objetos: contexto](/es/services/playfab/economy-monetization/economy-v2/tutorials/craftingGame/game-context.md)
- [Creación de una compilación de servidor de juegos](/es/services/playfab/multiplayer/servers/author-a-game-server-build.md)
- [Escalado mediante programación](/es/services/playfab/multiplayer/servers/scaling-programmatically.md)
