Upgrading Instanced Items #
In this section, we’ll demonstrate how to upgrade a custom, unique instanced item type called gear with stackable runestone items. To upgrade gear we’ll go over the following steps:
- Create the
updateEntriesused to updateextdata ingearwith specific stackablerunestones. - Define the catalog of stackable
runestoneitems used to upgradegearinstanced items. - Customize an
InstancedItemPluginin Kotlin that can build and upgradeextdata ingear. - Test the
InstancedItemPlugin,gear, andrunestonesby running service calls in Postman.
Prerequisites:
- The previous Instanced Items tutorial sections for Creating Instanced Items and Customizing the Instanced Item Plugin must be completed.
Get started #
Run the following commands in the terminal from the platform directory to build the engine and make 5-ext if it doesn’t already exist:
make skip-tests protos enginemake ext
Create the stackable runestones #
One way to upgrade instanced items is by requiring the player to use specific items for the upgrade. Stackable items are great for this purpose, as they are identical to one another like crafting or currency materials.
In this section we’ll create three stackable runestone items used to upgrade gear-type instanced items.
Edit the stackable specs catalog #
Define a runestone_fire, runestone_water, and runestone_earth for upgrading gear-type items.
- Go to
5-ext/content/src/StackableSpecs.json. - Add the following code block to create three different types of runestones:
[
{
"catalogId": "runestone_fire",
"name": "Fire Runestone",
"tags": ["fire", "socketable", "runestones"],
"limit": 10,
"removeIfNone": true
},
{
"catalogId": "runestone_water",
"name": "Ice Runestone",
"tags": ["water", "socketable", "runestones"],
"limit": 10,
"removeIfNone": true
},
{
"catalogId": "runestone_earth",
"name": "Earth Runestone",
"tags": ["earth", "socketable", "runestones"],
"limit": 10,
"removeIfNone": true
}
]
Define the update entries #
Update entries catalog different types of item-updates that require some type of cost for client or server based RPCs. ext data for updateEntries can be defined in protos, but the entries themselves are defined in a JSON catalog.
In this section we’ll author the ext fields for three updateEntries in protos and catalog the update entries in a JSON catalog.
Edit the inventory content ext file #
- Open
5-ext/ext-protos/src/main/proto/shared/inventoryContentExt.proto. - In the
ExtUpdateEntrymessage, add the following code to define an update entry for upgrading gear withrunestones:
message ExtUpdateEntry {
oneof data {
string socketed_runestone_catalog_id = 1;
}
}
Apply proto changes #
Run the following make command using platform as the working directory to apply protobuf changes:
make ext-protos
Create the Update Entries catalog #
- Open
5-ext/content/src/UpdateEntries.json. - Add the following code block to define three different
UpdateEntriesfor eachrunestone:
[
{
"id": "socket_runestone_fire",
"costByCatalogId": {
"runestone_fire": {
"cost": 1
}
},
"ext": {
"socketedRunestoneCatalogId": "runestone_fire"
}
},
{
"id": "socket_runestone_water",
"costByCatalogId": {
"runestone_water": {
"cost": 1
}
},
"ext": {
"socketedRunestoneCatalogId": "runestone_water"
}
},
{
"id": "socket_runestone_earth",
"costByCatalogId": {
"runestone_earth": {
"cost": 1
}
},
"ext": {
"socketedRunestoneCatalogId": "runestone_earth"
}
}
]
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.
Customize the Instanced Item Plugin #
In this section, we’ll customize the Instanced Item Plugin to update ext data in gear-type instanced items using stackable runestones. Make sure you already have logic to build gear in the plugin’s newInstanced() function from the previous tutorial.
- Go to
5-ext/ext/src/main/kotlin/InstancedItemTutorialPlugin.kt. - Replace the plugin’s
update()function with the following code to enablegearupgrades from stackablerunestones:
override suspend 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()
val extItem: ExtInstancedItem = initialInstancedItem.ext
return when (extItem.dataCase) {
ExtInstancedItem.DataCase.GEAR -> {
val updateExt: ExtUpdateEntry = updateEntry.ext
//Updates gear with the new attribute value and socketed runestones.
val gearBuilder = extInstancedItemBuilder.gearBuilder
gearBuilder.attributeValue = extItem.gear.attributeValue
gearBuilder.addSocketedRunestones(updateExt.socketedRunestoneCatalogId)
InstancedItemPlugin.InstancedItemPluginResult(
extInstancedItemBuilder.setGear(gearBuilder).build(),
InventoryModifications()
)
}
else -> error("Unknown item!")
}
}
Build plugin changes #
Run the following make command using platform as the working directory to register plugin changes:
make ext
Test the plugin #
In this section, we’ll test if the plugin logic uses runestones to upgrade unique gear items with more custom ext data by running API calls in Postman.
Start Pragma Engine #
Run Pragma Engine via one of the following methods.
Once the engine has started successfully, it prints the message [main] INFO main - Pragma server startup complete.
Grant a player three runestones #
- Open Postman.
- Navigate to the two service calls
PragmaDev ➨ Public ➨ Operator - AuthenticateOrCreateV2 and PragmaDev ➨ Public ➨ Player - AuthenticateOrCreateV2. - Click Send for both service calls and check that the response body for each call has
pragmaTokenswith a filledpragmaGameTokenandpragmaSocialToken. - Open
PragmaDev ➨ Game ➨ RPC - Operator ➨ Inventory ➨ GrantItemsOperatorV1and open the service call’s body. - Insert the following code block in the payload’s
itemGrants’s square brackets forrunestone_fire,runestone_water, andrunestone_earth:
{
"requestId": 1,
"type": "InventoryRpc.GrantItemsOperatorV1Request",
"payload": {
"playerId": "{{test01PlayerId}}",
"itemGrants": [
{
"stackable": {
"catalogId": "runestone_fire",
"amount": 1,
"tags": []
}
},
{
"stackable": {
"catalogId": "runestone_water",
"amount": 1,
"tags": []
}
},
{
"stackable": {
"catalogId": "runestone_earth",
"amount": 1,
"tags": []
}
}
]
}
}
- Click Send to grant the player their
runestones. - Confirm the player has their three instanced items by using the call
PragmaDev ➨ Game ➨ RPC - Operator ➨ Inventory ➨ GetInventoryOperatorV1.
Upgrade three gear-type items #
Go to
PragmaDev ➨ Game ➨ RPC - Player ➨ Inventory ➨ UpdateItemV4. In the payload’sinstancedItemUpdate’s curly brackets, make three separate instanced item update calls by filling theinstanceIdwith each gear’sinstanceId(which can be found by runningGetInventoryOperatorV1). Then add the correctupdateEntryIdsfor eachitemUpdate(check eachupdateEntryIdwith yourUpdateEntries.jsoncatalog).Run three separate calls so that the player’s
metal_sword_1has arunestone_fire,metal_chest_2has arunestone_water, andmetal_hat_3has arunestone_earth.
Below is an example of what socketing arunestone_fireto ametal_sword_1looks like:
{
"payload": {
"instancedItemUpdate": {
"instanceId": "2e9404ab-c970-4e16-9542-8358819846a4",
"updateEntryId": "socket_runestone_fire",
"tags": [""]
}
}
}
- Confirm the player has a
metal_sword_1with arunestone_fire,metal_chest_2with arunestone_water, andmetal_hat_3with arunestone_earthby using theGetInventoryOperatorV1call.