Updating Items #

Games often allow players to upgrade or reforge their items. Pragma Engine can handle this scenario via the InstancedItemPlugin.update() method.


Create the proto definitions and store entry #

  1. Complete the Setting Up the Item Catalog and Store and Purchasing Items sections, then shut down the engine if it’s still running.
  2. In IntelliJ, define the update-related protos in 5-ext/ext-protos/src/main/proto/shared/inventoryContentExt.proto:
message ExtUpdateEntry {
  oneof data {
    WeaponUpdateSpec weapon_update_spec = 1;
  }
}

message WeaponUpdateSpec {
  int64 damage_upgrade = 1;
  int32 awesomeness_upgrade = 2;
}
  1. Edit 5-ext/content/src/UpdateEntries.json to provide actual upgrade data. The following json states that each upgrade will cost 350 of catalogId coins, will upgrade the damage by 3, and will upgrade the awesomeness by 1.
[
  {
    "ext": {
      "weaponUpdateSpec": {
        "damageUpgrade": 3,
        "awesomenessUpgrade": 1
      }
    },
    "id": "upgradeWeapon",
    "costByCatalogId": {
      "coins": {
        "cost": 350
      }
    },
    "tags": []
  }
]
  1. Run make ext from a terminal. Make sure the working directory is the platform directory.

Apply content data #

In order to register the content you just defined with Pragma Engine, you must apply your content data changes. You may apply content data either using the command line with make or via an IntelliJ run configuration.

Applying content data using Make

In a terminal with platform as the working directory, run:

make ext-contentdata-apply
Applying content data using IntelliJ
From the IntelliJ toolbar in the upper right, ensure contentdata apply is selected, then click the play button.

Update the Instanced Item Plugin #

  1. Implement the update method in DemoInstancedItemPlugin:
Due to known issues with IntelliJ performing type inferences on protos, using a value nested in an ext field can cause false syntax error. Create a local variable with a manually assigned type to hold proto ext fields, as we’ve done with specExt, updateExt, and initialInstancedItemExt below.
override fun update(
  initialInstancedItem: InstancedItem,
  instancedSpec: InventoryContent.InstancedSpec,
  updateEntry: InventoryContent.UpdateEntry,
  inventoryContent: InventoryServiceContent,
  startingInventory: InventoryData,
  pendingInventory: InventoryData,
  clientRequestExt: ExtInstancedItemUpdate?,
  serverRequestExt: ExtInstancedItemServerUpdate?
): InstancedItemPlugin.InstancedItemPluginResult {
  val extInstancedItemBuilder = ExtInstancedItem.newBuilder()

  // check which item type is being processed
  val specExt: ExtInstancedSpec = instancedSpec.ext
  return when (specExt.dataCase) {
    ExtInstancedSpec.DataCase.LASER_SWORD_SPEC -> {

      // this describes specific attributes of a laser sword
      val laserSwordSpec = specExt.laserSwordSpec

      // this describes how to update weapons, including the laser sword.
      val updateExt: ExtUpdateEntry = updateEntry.ext
      val weaponUpdateSpec = updateExt.weaponUpdateSpec

      // calculate updates
      val initialInstancedItemExt: ExtInstancedItem = initialInstancedItem.ext
      val existingLaserSword = initialInstancedItemExt.laserSword
      val updatedDamage = existingLaserSword.damage + weaponUpdateSpec.damageUpgrade
      val currentAwesomenessIndex =
        laserSwordSpec
          .awesomenessList
          .indexOf(existingLaserSword.awesomeness)
      val updatedAwesomenessIndex = min(
        currentAwesomenessIndex + weaponUpdateSpec.awesomenessUpgrade,
        laserSwordSpec.awesomenessCount - 1
      )

      // build laser sword data with the updated values
      val laserSwordBuilder = extInstancedItemBuilder.laserSwordBuilder
      val updatedLaserSword = laserSwordBuilder
        .setAwesomeness(laserSwordSpec.getAwesomeness(updatedAwesomenessIndex))
        .setDamage(updatedDamage)
        .build()
      InstancedItemPlugin.InstancedItemPluginResult(
        extInstancedItemBuilder.setLaserSword(updatedLaserSword).build(),
        InventoryModifications()
      )
    }

    else -> error("Unknown item!")
  }
}
The update() method can be extended to support additional items by adding conditions to the when statement.
  1. Run make ext using a terminal from the platform directory.
  2. Run Pragma Engine via one of the following methods.
Running via Make
Run make run to start the platform. Run this in a terminal with platform as the working directory.
Running in IntelliJ

From the IntelliJ toolbar in the upper right, ensure MainKt - LocalConfigured is selected, then click the play button.

If MainKt - LocalConfigured isn’t available, you will need to configure it. In the IntelliJ toolbar, click the dropdown next to the run button, then click Edit Configurations…. In the Run/Debug Configurations window that appears, expand Kotlin in the left hand side, then select MainKt - LocalConfigured. Click OK. Click the play button in the IntelliJ toolbar to start Pragma Engine.

Once the engine has started successfully, it prints the message [main] INFO main - Pragma server startup complete.

  1. Open Postman, then send PragmaDev ➨ Public ➨ GetInQueuev1 to enter the login queue.
  2. Send PragmaDev ➨ Public ➨ Player - AuthenticateOrCreateV2 to log into the engine as a player.
  3. Send PragmaDev ➨ Game ➨ RPC - Player ➨ Inventory ➨ storePurchaseV4 with the following request body to get coins:
{
  "requestId": 1,
  "type": "InventoryRpc.StorePurchaseV4Request",
  "payload": {
    "data" : {
     "ext": {},
     "storeId": "freeVendor",
      "storeEntryId": "starterBundle",
      "amount": 1
    }
  }
}
  1. Change the storeId to shopkeeper and the storeEntryId to laserSword, then resend the storePurchaseV4 call to purchase a laserSword. Copy the instanceId of the laserSword from the body of the response as this will be used in the next step.
{
  "requestId": 1,
  "type": "InventoryRpc.StorePurchaseV4Request",
  "payload": {
    "data" : {
     "ext": {},
     "storeId": "shopkeeper",
      "storeEntryId": "laserSword",
      "amount": 1
    }
  }
}
  1. In Postman, navigate to PragmaDev ➨ Game ➨ RPC - Player ➨ Inventory ➨ updateItemV4. Edit the instanceId in the body of the request with the value copied from the previous step. Also change the value of updateEntryId to "upgradeWeapon". Send the service call to upgrade the laserSword.
{
  "requestId": 1,
  "type": "InventoryRpc.UpdateItemV4Request",
  "payload": {
    "itemUpdate": {
      "instanced":
      {
        "ext": {},
        "instanceId": "your item's instanceId here",
        "updateEntryId": "upgradeWeapon",
        "tags": [""]
      }
    }
  }
}
  1. Confirm that the damage of the laserSword increased by 3 and the awesomeness was incremented from a little to somewhat.