Virtual Items

Integration Guide

Introduction

Virtual items are game items, that can be purchased using game currency or can be rewarded as completing a certain threshold using Achievements

For example:

  • Racing Game: It can be different types of cars.

  • Puzzle game: It can be a bunch of hints pack.

  • Match-3 game: There can be different types of power-ups.

  • Shooting Game: Different types of guns, ammo etc

Virtual Items can be added using the READYgg Dev Dashboard. In order to retrieve your list of virtual items you can use the following API.

Get All Virtual Items for current app :

using System.Collections.Generic;
using RGN.Modules.VirtualItems;
using RGN.Utility;
using UnityEngine;

namespace SomeNamespace
{
    internal sealed class GetAllVirtualItems
    {
        public async void GetVirtualItemsForCurrentAppAsync()
        {
            List<VirtualItem> virtualItems =
                await VirtualItemsModule.I.GetVirtualItemsAsync();
            for (int i = 0; i < virtualItems.Count; ++i)
            {
                VirtualItem item = virtualItems[i];
                var sb = new System.Text.StringBuilder();
                sb.Append("id: ").AppendLine(item.id);
                sb.Append("name: ").AppendLine(item.name);
                sb.Append("description: ").AppendLine(item.description);
                sb.Append("createdAt: ").AppendLine(
                    DateTimeUtility.UnixTimeStampToISOLikeStringNoMilliseconds(
                        item.createdAt));
                sb.Append("updatedAt: ").AppendLine(
                    DateTimeUtility.UnixTimeStampToISOLikeStringNoMilliseconds(
                        item.updatedAt));
                sb.Append("createdBy: ").AppendLine(item.createdBy);
                sb.Append("updatedBy: ").AppendLine(item.updatedBy);
                sb.Append("isStackable: ").AppendLine(item.isStackable.ToString());
                Debug.Log(sb.ToString());
            }
        }
    }
}

There is also a method overload for pagination requests. The pagination means you request not all items at once for the project, but in packs. For example every request can contain maximal 10 items. When you request the first time the startAfter need to by null or empty. For the subsequent requests you need to provide as the startAfter parameter the id of the last loaded virtual item:

using System.Collections.Generic;
using RGN.Modules.VirtualItems;

namespace SomeNamespace
{
    internal sealed class GetVirtualItemsPagination
    {
        public async void GetVirtualItemsPaginationAsync()
        {
            List<VirtualItem> allLoadedItems = new List<VirtualItem>();
            {
                List<VirtualItem> virtualItems =
                    await VirtualItemsModule.I.GetVirtualItemsAsync(
                        10,
                        null);
                allLoadedItems.AddRange(virtualItems);
            }
            {
                VirtualItem lastLoadedItem =
                    allLoadedItems[allLoadedItems.Count - 1];
                List <VirtualItem> virtualItems =
                    await VirtualItemsModule.I.GetVirtualItemsAsync(
                        10,
                        lastLoadedItem.id);
                allLoadedItems.AddRange(virtualItems);
            }
        }
    }
}
Virtual Item description
using System;
using System.Collections.Generic;
using RGN.Utility;

namespace RGN.Modules.VirtualItems
{
    [Serializable]
    public class VirtualItem
    {
        /// <summary>
        /// Unique id of the virtual item
        /// </summary>
        public string id;
        /// <summary>
        /// Virtual item name
        /// Is used also to store localization key for the name
        /// </summary>
        public string name;
        /// <summary>
        /// Virtual item description
        /// Is used also to store localization key for the description
        /// </summary>
        public string description;
        /// <summary>
        /// Date and time when the virtual item was created
        /// This field is automatically populated by the backend
        /// </summary>
        public long createdAt;
        /// <summary>
        /// Date and time when the virtual item data was last time updated
        /// This field is automatically populated by the backend
        /// </summary>
        public long updatedAt;
        /// <summary>
        /// User Id who created the virtual item
        /// This field is automatically populated by the backend
        /// </summary>
        public string createdBy;
        /// <summary>
        /// User Id who last time updated the item
        /// This field is automatically populated by the backend
        /// </summary>
        public string updatedBy;
        /// <summary>
        /// This field is used to indicate if an item can be stacked
        /// When you add stackable items to user inventory, the items count is increased
        /// When you add non stackable items to user inventory, this operation creates
        /// a new item in inventory
        /// Only non stackable items can be upgraded
        /// </summary>
        public bool isStackable;
        /// <summary>
        /// Indicates if the virtual item is a NFT.
        /// Please use IsNFT() method to check if item is a NFT.
        /// The NFT virtual items require primary user wallet
        /// For more information see the API in WalletsModule
        /// </summary>
        public bool isNFT;
        /// <summary>
        /// List of application ids where this item is used
        /// </summary>
        public List<string> appIds = new List<string>();
        /// <summary>
        /// List of tags to filter the items
        /// You can place multiple items into one category tag
        /// For example in a shooter game: "guns", "rifles"
        /// </summary>
        public List<string> tags = new List<string>();
        /// <summary>
        /// List of childs of the current virtual item. Virtual items ids list.
        /// It is used to build tree structure hierarchies.
        /// </summary>
        public List<string> childs = new List<string>();
        /// <summary>
        /// List of addressable ids for the virtual item binary data
        /// </summary>
        public List<AddressableInfo> addressableIds;
        /// <summary>
        /// List of virtual item custom json. It is used to store game specific
        /// json in json format.
        /// For example: you can attach some json like "damage", "range",
        /// "fireRate" attached to this item
        /// </summary>
        public List<Properties> properties;
        /// <summary>
        /// Array of prices for the virtual item
        /// A virtual item can be sold for different currencies with different prices
        /// It is also possible to combine two and more currencies to sell the item
        /// </summary>
        public List<PriceInfo> prices;
        /// <summary>
        /// How much quantity of the goods left (use only for NFT items)
        /// </summary>
        public int totalQuantity;

        // Not obsolete! Needed to query every compatible childs
        public List<string> compatibleItemIds = new List<string>(); // List of parent ID
        // Not obsolete! Cannot have the material info inside json, because the material is needed in every games
        public List<MaterialInfo> materialInfos = new List<MaterialInfo>(); // if the items as custom texture

        /// <summary>
        /// Checks if the item is NFT. It means the item was minted.
        /// The purchase process for NFT items goes throught blockchain
        /// </summary>
        /// <returns></returns>
        public bool IsNFT();

        /// <summary>
        /// Returns Virtual Item RGNCoin (rgn-coin) price.
        /// If the price can not be found throws InvalidOperationException
        /// </summary>
        /// <returns></returns>
        /// <exception cref="InvalidOperationException"></exception>
        public int GetRGNCoinPrice();
        /// <summary>
        /// Returns Custom Currency Price with provided currency name.
        /// If the price with currency name can not be found throws InvalidOperationException
        /// </summary>
        /// <param name="currencyName">Valid currency name for current app/game</param>
        /// <returns></returns>
        /// <exception cref="InvalidOperationException"></exception>
        public int GetCustomCoinPrice(string currencyName);
    }
}

Different ways to retrieve virtual items :

Get by tags :

using System.Collections.Generic;
using RGN.Modules.VirtualItems;

namespace SomeNamespace
{
    internal sealed class GetVirtualItemsByTags
    {
        public async void GetVirtualItemsAsync()
        {
            var tags = new List<string> { "guns", "rifles" };
            List<VirtualItem> virtualItems =
                await VirtualItemsModule.I.GetByTagsAsync(tags);
        }
    }
}

You can also provide an optional parameter appId to the GetByTagsAsync method call. This parameter works in combination with the method SetTagsAsync. The SetTagsAsync method has also an optional appId parameter. When this parameter is provided, we automatically attach appId to every tag in the tags array and query the database. This is specifically done to allow app developers to have unique tags for virtual items per app id.

Get by ids :

using System.Collections.Generic;
using RGN.Modules.VirtualItems;

namespace SomeNamespace
{
    internal sealed class GetVirtualItemsByIds
    {
        public async void GetVirtualItemsAsync()
        {
            var ids = new List<string> { "item_one_id", "item_two_id" };
            List<VirtualItem> virtualItems =
                await VirtualItemsModule.I.GetVirtualItemsByIdsAsync(ids);
        }
    }
}

Updating Virtual Items data :

It is possible to update the name, description and tags for virtual items:

using System.Collections.Generic;
using RGN.Modules.VirtualItems;
using UnityEngine;

namespace SomeNamespace
{
    internal sealed class UpdatingVirtualItemsData
    {
        public async void UpdateNameAndDescriptionAsync()
        {
            string virtualItemId = "some_virtual_item";
            await VirtualItemsModule.I.SetNameAsync(virtualItemId,
                "New Virtual Item Name");
            await VirtualItemsModule.I.SetDescriptionAsync(virtualItemId,
                "New Virtual Item Description");
        }
        public async void UpdateTagsAsync()
        {
            string virtualItemId = "some_virtual_item";
            var tags = new List<string> { "tag_one", "tag_two", "etc" };

            // This will store "tag_one_my_unique_string",
            // "tag_two_my_unique_string", "etc_my_unique_string"
            // in the database
            await VirtualItemsModule.I.SetTagsAsync(virtualItemId, tags);
        }
    }
}

Storing and getting custom json data :

It is possible the store and retrieve custom properties json string associated with virtual item. The data is stored in the virtual items data. The json string should be UTF8 formatted string not longer than 100k characters.

using RGN.Modules.VirtualItems;
using UnityEngine;

namespace SomeNamespace
{
    internal sealed class SetAndGetProperties
    {
        [System.Serializable]
        internal sealed class Serializable
        {
            public int Integer;
            public string String;
            public string[] StringArray;
        }

        public async void UpdateCustomGamePropertiesAsync()
        {
            string virtualItemId = "some_virtual_item";

            var gameSpecificData = new Serializable() {
                Integer = 42,
                String = "Hello World",
                StringArray = new string[] { "Some important game specific data" }
            };
            string propertiesJson = JsonUtility.ToJson(gameSpecificData);
            // Stores json string in virtual items data:
            await VirtualItemsModule.I.SetPropertiesAsync(
                virtualItemId,
                propertiesJson);
            // Retrieves the json properties string from the backend
            var jsonProperties =
                await VirtualItemsModule.I.GetPropertiesAsync(virtualItemId);
            Serializable deserialized =
                JsonUtility.FromJson<Serializable>(jsonProperties);
            Debug.Log(deserialized.Integer);
        }
    }
}

Updating and downloading the virtual item image :

using RGN.Modules.VirtualItems;
using UnityEngine;

namespace SomeNamespace
{
    internal sealed class UpdatingVirtualItemImage
    {
        public async void UpdateVirtualItemImageAsync(
            string virtualItemId,
            UnityEngine.Texture2D itemImage)
        {
            byte[] bytes = itemImage.EncodeToPNG();
            bool success = await VirtualItemsModule.I.UploadImageAsync(
                virtualItemId,
                bytes);
        }
    }
}

To download virtual item image you can use following code:

using System.Threading.Tasks;
using RGN.Model;
using RGN.Modules.VirtualItems;
using UnityEngine;

namespace SomeNamespace
{
    internal sealed class DownloadingVirtualItemImage
    {
        public async Task<Texture2D> DownloadVirtualItemImageAsync(
            string virtualItemId)
        {
            byte[] bytes = await VirtualItemsModule.I.DownloadImageAsync(
                virtualItemId, ImageSize.Small);
            Texture2D toReturn = new Texture2D(1, 1);
            toReturn.LoadImage(bytes);
            toReturn.Apply();
            return toReturn;
        }
    }
}