Setting Up the Item Catalog and Store #

In this section, we’ll be defining the item catalog, store, and associated type definitions.


Define the item catalog #

The ItemCatalog defines the specification for game content managed by the platform. Item definitions include a shared identifier between the platform and game code, and allow custom inventory details for any kind of content managed by the platform.

This section covers creating instanced Unique items where two copies of the same item can have different qualities. and stackable item Identical items where all copies of the same item are fully interchangeable. specs, which are customizable by defining custom types within extension (ext) fields.

Get started #

Run the following command in the terminal from the platform directory:

make skip-tests protos engine ext

Define item types with protobufs #

The structure of instanced and stackable items are defined in protobuf A format for efficiently serializing structured data that's cross-platform and compatible with several languages. files defined by the engine. Custom protobuf definitions can be added to extension (ext) fields. These are predefined protobuf types that can be modified to extend engine functionality.

In this section, we’ll be defining the instanced item spec for pets, along with the pet evolution specs. These proto definitions will match the JSON content we defined below, allowing the engine to load and process the custom data types.

Edit the inventory content ext file #

This is where we’ll define the pet and pet evolution specifications. The inventory content ext file is where content specs are defined. You can think of these as blueprints that your plugin will use to build the actual items.

  1. Open 5-ext/ext-protos/src/main/proto/shared/inventoryContentExt.proto.
  2. Edit ExtInstancedSpec:
Note that certain protos already exist and require editing. Other protos require you to create them. In this case, the ExtInstancedSpec proto already exists and must be edited to match the given example.
message ExtInstancedSpec {
  string name = 1;
  oneof data {
      PetSpec pet_spec = 2;
  }
}
The oneof data is what will later become DataCase. If you name it something like info, your protos will have an InfoCase instead.
  1. Create the PetSpec and PetBonus protos beneath the ExtInstancedSpec message:
message PetSpec {
  repeated PetBonus bonuses = 1;
  int64 bonus_min = 2;
  int64 bonus_max = 3;
}

enum PetBonus {
  UNUSED = 0;
  XP_BONUS = 1;
  GOLD_BONUS = 2;
  LUCK_BONUS = 3;
}
  1. Edit ExtPurchaseRequirements:
message ExtPurchaseRequirements {
  oneof data {
    PetEvolutionRequirements pet_evolution_requirements = 1;
  }
}
  1. Create the PetEvolutionRequirements proto:
message PetEvolutionRequirements {
  string required_pet_catalog_id = 1;
  string required_player_location = 2;
}
  1. Edit ExtCraftingEntry:
message ExtCraftingEntry {
  oneof data {
    PetEvolutionSpec pet_evolution_spec = 1;     
  }
}
  1. Create the PetEvolutionSpec proto:
message PetEvolutionSpec {
  string target_pet_catalog_id = 1;
  int64 bonus_increment = 2;
}
  1. Edit ExtUpdateEntry:
message ExtUpdateEntry {
  oneof data {
    PetEvolutionSpec pet_evolution_spec = 1;
  }
}

Edit the inventory ext file #

This is where we’ll define attributes for our pets. This represents the actual item that our plugin will create and the engine will manage in the player’s inventory.

  1. Open 5-ext/ext-protos/src/main/proto/shared/inventoryExt.proto.
  2. Add the following imports:
import "shared/inventoryContentExt.proto";
  1. Edit ExtInstancedItem:
message ExtInstancedItem  {
  oneof data {
    Pet pet = 2;
  }
}
  1. Create the Pet proto:
message Pet {
  PetBonus bonus = 1;
  int64 bonus_amount = 2;
}

Edit the inventory RPC ext file #

This is where we define request parameters that are passed when calling APIs to grant content. This file contains request objects for APIs called by untrusted sources (such as the game client) and trusted sources (such as the admin operator APIs). The trusted request objects are easier to test with, so we’ll use them in this example.

  1. Open 5-ext/ext-protos/src/main/proto/shared/inventoryExt.proto.
  2. Add the following imports:
import "shared/inventoryExt.proto";
  1. Edit ExtCraftRequest:
message ExtCraftRequest {
  oneof data {
    PetEvolutionRequest pet_evolution_request = 1;
  }
}
  1. Create the PetEvolutionRequest proto:
message PetEvolutionRequest {
  string crafting_location = 1;
}
  1. Edit ExtInstancedItemServerGrant by inserting the following:
message ExtInstancedItemServerGrant {
  oneof data {
    PetEvolution pet_evolution = 1;
  }
}
  1. Create the PetEvolution proto:
message PetEvolution {
  ext.Pet pet = 1;
}

Run make ext using a terminal from the platform directory.

Define instanced item specs #

If you haven’t yet initialized your 5-ext content, you’ll need to run the following command to create the content JSON files. Run make init-inventory-content using a terminal from the platform directory.

Replace the contents of platform/5-ext/content/src/InstancedSpecs.json with the following code:

[
  {
    "catalogId": "fireDragon",
    "name": "fireDragon",
    "tags": ["avatar", "dragon", "fire"],
    "ext": {
      "petSpec": {
        "bonuses": ["XP_BONUS", "GOLD_BONUS", "LUCK_BONUS"],
        "bonusMin": 5,
        "bonusMax": 10
      }
    }
  },
  {
    "catalogId": "fireDragon2",
    "name": "fireDragon2",
    "tags": ["avatar", "dragon", "fire"]
  }
]

In this section, we’re defining two different fireDragons.

The base fireDragon has additional properties defined in the ext field, which will be used by the pet crafting plugin to generate specific instances of fireDragon.

fireDragon2 does not have exts field for the purposes of this example—fireDragon is obtainable from the store while fireDragon2 is only obtainable via crafting.

Define stackable item specs #

Next we’ll define an in-game currency and the materials necessary to purchase the pet familiar.

Replace the contents of platform/5-ext/content/src/StackableSpecs.json with the following code:

[
  {
    "catalogId": "gold",
    "name": "gold",
    "limit": 1000000,
    "tags": ["currency"],
    "removeIfNone": false
  },
  {
    "catalogId": "fireShard",
    "name": "fireShard",
    "limit": 10000,
    "tags": ["material"]
  },
  {
    "catalogId": "fireGem",
    "name": "fireGem",
    "limit": 10,
    "tags": ["material"]
  }
]

Stackable items are items with no special properties. Each item in the stack is identical.

Define the store #

We’ll use the store API to purchase the pet. In a game, this could be presented as interacting with a dragon caretaker or using an altar. The store API can be leveraged for many interactions beyond just basic NPC shopkeepers.

Replace the contents of platform/5-ext/content/src/Stores.json with the following code:

[
  {
    "id": "materialShop",
    "name": "Material Shop",
    "storeEntries": [
      {
        "id": "craftingKit",
        "receivedQuantityByCatalogId": {
          "gold": 2000,
          "fireShard": 2000,
          "fireGem": 2,
          "fireDragon": 1
        }
      }
    ]
  }
]

In this section, we’re defining a store with only one purchasable entry. This entry costs nothing and grants the purchaser everything necessary to craft a fireDragon2.

Define the crafting catalog #

While we used the store API to purchase our dragon from a caretaker, we need to use the more flexible crafting API to power the dragon evolution step.

Replace the contents of platform/5-ext/content/src/CraftingEntries.json with the following code:

[
  {
    "id": "fireDragon2Evolution",
    "stackableCostByCatalogId": {
      "gold": {
        "cost": 2000
      },
      "fireShard": {
        "cost": 2000
      },
      "fireGem": {
        "cost": 2
      }
    },
    "ext": {
      "petEvolutionSpec": {
        "targetPetCatalogId": "fireDragon2",
        "bonusIncrement": 2
      }
    },
    "requirements": {
      "ext": {
        "petEvolutionRequirements": {
          "requiredPetCatalogId": "fireDragon",
          "requiredPlayerLocation": "fireLake"
        }
      }
    }
  }
]

In this section, we define a crafting catalog that allows the player to evolve their fireDragon into a fireDragon2 when they have the necessary materials and initiate crafting from the fireLake.

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.