Skip to content

Orders and Inventory Updates


Example Loot and Price Setup In Dev Portal

Orders are the primary method for manipulating a players inventory. Orders can originate from a user’s client, a server, or other API calls. Orders use the Vendor and Loot system to make inventory changes based on pre-determined loot rules. Orders have a variety of FillTypes which dictate how the API processes them and what all credentials are needed to complete the order. Once an order has been completed, the player’s inventory is updated and a response is sent back to the origination point. Order history can be queried via the API as needed.

Direct Inventory Create and Update can be used as well, these have specific permission requirements that typically only an instance server would have. With the direct calls you specificy the exact changes to an existing inventory record or create a new one with specific data. This processes circumvents the need for Vendor and Loot system as the calls are providing all the data for the final Inventory Record. These changes still create an order to represent the changes that were requested for the players Order History.

Custom Data is a field that can be used with Orders as well ad Direct Inventory manipulation. Custom Data is an array of Key/Value pairs of data that allows for adding additional game driven fields to an Inventory Record that are not part of the standard Inventory information. This can be used for custom stats on an item, etc. URH_PlayerOrderEntry, FRH_CreateInventory, and FRH_UpdateInventory support adding custom data to the request.

Permissions on Calls

Permissions have a few levels to them. If a user has inv:*, it can do all of the following without additional checks.

It checks the player you would like to create an order for:

  • If it is your player, then inv:create_order:player:self is required
  • If it is any other player, then inv:create_order:player:any is required

It checks the source of the order:

  • If the source is INSTANCE, then inv:create_order:source:instance is required
  • If the source is CLIENT, then no permission is required
  • If the source is anything else, then inv:create_order:source:any is required.


Player Order Creation

Orders for a player are created using URH_PlayerInventory::CreateNewPlayerOrder(). The bulk of a creation comes through the configuration of the OrderEntries which takes an array of URH_PlayerOrderEntry.

OrderSourceThe source of the order, typically Client from a client and Instance from an Instance server.
IsTransactionIf true, the whole order will be rolled back if any entry fails to be completed.
OrderEntriesArray of orders being requested.

The following are some common examples of how to fill our a PlayerOrderEntry

Client Purchasing with Virtual Currency

TArray<URH_PlayerOrderEntry*> PlayerOrderEntries;
URH_PlayerOrderEntry* NewPlayerOrderEntry = NewObject<URH_PlayerOrderEntry>();
NewPlayerOrderEntry->FillType = ERHAPI_PlayerOrderEntryType::PurchaseLoot;
NewPlayerOrderEntry->LootItem = LootItem;
NewPlayerOrderEntry->Quantity = 1;
NewPlayerOrderEntry->ExternalTransactionId = "Purchase With Virtual Currency Example";
NewPlayerOrderEntry->PriceItemId = 12;
NewPlayerOrderEntry->Price = 200;
PlayerInfo->GetPlayerInventory()->CreateNewPlayerOrder(ERHAPI_Source::Client, true, PlayerOrderEntries);

The FillType for a player initiated purchase is always set to ERHAPI_PlayerOrderEntryType::PurchaseLoot. The Price needs to be the price per unit being purchased, thus if you are buying 5 items at a price of 1000. Quantity will be set to 5, and Price will be set to 200.

It is recommended that the PriceItemId and Price are filled out using data pulled directly from the display in the UI to the user. These values are used by the API to verify that the request the client made is spending the currency item as well and the currency amount that the API expects to be used to purchase the loot. If the PriceItemId or Price does not match the expectation from the API, a price mismatch error will be returned and the order will not complete. This is done to prevent a sudden price change, or display error to cause a user to spend something they were not expecting.

Client Claiming IsClaimableByClient Loot

TArray<URH_PlayerOrderEntry*> PlayerOrderEntries;
URH_PlayerOrderEntry* NewPlayerOrderEntry = NewObject<URH_PlayerOrderEntry>();
NewPlayerOrderEntry->FillType = ERHAPI_PlayerOrderEntryType::PurchaseLoot;
NewPlayerOrderEntry->LootId = 12;
NewPlayerOrderEntry->Quantity = 1;
NewPlayerOrderEntry->ExternalTransactionId = "Client Claimable Loot Example";
PlayerInfo->GetPlayerInventory()->CreateNewPlayerOrder(ERHAPI_Source::Client, false, PlayerOrderEntries);

If a Loot entry is setup to be IsClaimableByClient, then the client is able to request for the API to do a FillLoot on the record. In general if you are setting something to be freely claimable by the client, then you will want the Loot recipe to build in internal protections to make sure the user can’t request it over and over for infinite rewards. Some example uses of this could be a quest that the user has to claim their reward when they complete it, and the Loot recipe checks that the user had enough progress on the quest to claim the reward as well as they do not have a redeemed indicator, then grants the reward along with an indicator that this has been redeemed.

Instance Granting Rewards

TArray<URH_PlayerOrderEntry*> PlayerOrderEntries;
NewPlayerOrderEntry = NewObject<URH_PlayerOrderEntry>();
NewPlayerOrderEntry->FillType = ERHAPI_PlayerOrderEntryType::FillLoot;
NewPlayerOrderEntry->LootId = 1;
NewPlayerOrderEntry->Quantity = 214;
NewPlayerOrderEntry->ExternalTransactionId = "End of Match Rewards Example";
PlayerInfo->GetPlayerInventory()->CreateNewPlayerOrder(ERHAPI_Source::Instance, false, PlayerOrderEntries);

The FillType for instance initiated orders should be set to ERHAPI_PlayerOrderEntryType::FillLoot. The instance then provides the loot id and quantity of that lood it to grant the player.

Client Redeeming Promo Code

The player Promo Code redemption also uses the order system, and while you could use CreateNewPlayerOrder() with the proper Entry filled out, it is easier to use the helper function URH_PlayerInventory::RedeemPromoCode().

PlayerInfo->GetPlayerInventory()->RedeemPromoCode("Promo Code String");

The API Promo Code system will lookup if the promo code is valid, if the user is eligible for the promo code and then grant the user their rewards if any based on the promo codes configuration.

Direct Inventory Modification

There are two main functions to help with direct inventory modification URH_PlayerInventory::UpdateInventory() and URH_PlayerInventory::CreateInventory(). These are called used with an array of InventoryOperations to execute.

Instance Create Inventory

TArray<FRH_CreateInventory> CreateInventoryEntries;
FRH_CreateInventory NewCreateInventoryEntry{};
NewCreateInventoryEntry.Count = 1;
NewCreateInventoryEntry.InventoryType = ERHAPI_InventoryType::Persistent;
NewCreateInventoryEntry.ItemId = 10;
PlayerInfo->GetPlayerInventory()->CreateInventory(FGuid(), CreateInventoryEntries, ERHAPI_Source::Instance);

This is a basic example of directly adding an inventory record for a player. This will create a new InventoryId with all of the data provided.

Instance Update Inventory

TArray<FRH_UpdateInventory> UpdateInventoryEntries;
FRH_UpdateInventory NewUpdateInventoryEntry{};
NewUpdateInventoryEntry.InventoryId = FGuid("f8c994c5-6f9e-4156-ad6a-32e49782a807");
NewUpdateInventoryEntry.Count = 15;
NewUpdateInventoryEntry.ItemId = 10;
PlayerInfo->GetPlayerInventory()->UpdateInventory(FGuid(), UpdateInventoryEntries, ERHAPI_Source::Instance);

This is a basic example of directly updating an existing inventory record of a player by its Inventory Id. This is a direct write over the top of the inventory record, it will change the InventoryId’s entry to the new provided data, which could be an entirely new item.