Creating a Content Data Catalog #

This guide will walk you through creating a catalog to use with unlocking heroes. The catalog will contain the list of heroes players can unlock and the heroes’ corresponding costs.

By the end of this guide, you’ll have:

  • A type definition for hero unlock data
  • A Content Data catalog of hero unlock entries

Getting Started #

Start with a successful clean build of your project.

Define the protobuf type definition #

Steps #

Pragma Engine defines Content Data using protobufs. These protos must always include a unique string property.

  1. Create a new protobuf file at: [project]/[project]-protos/src/main/proto/customcontent/ContentDataDefinitions.proto.
ContentDataDefinitions.proto
syntax = "proto3";

package customcontent;

import "pragmaOptions.proto";

option csharp_namespace = "CustomContent";
option (pragma.unreal_namespace) = "CustomContent";

message HeroUnlock {
   string hero_id = 1;
   int32 cost = 2; 
}
  1. Generate the Java types.
./pragma build project-protos
  1. Next, define a Content Handler. Content Handlers are Pragma Engine classes responsible for loading, validating, and providing access to content.

    Create a new kotlin file at: [project]/[project-lib]/src/main/kotlin/customcontent/ContentHandlers.kt
ContentHandlers.kt
package customcontent

class HeroUnlockCatalog: ContentHandler<HeroUnlock>(HeroUnlock::class) {
    companion object {
        const val HERO_UNLOCKS = "HeroUnlocks.json"
    }

    override fun idFromProto(proto: HeroUnlock): String {
        return proto.heroId
    }
}

Create the Content Data catalog #

Steps #

  1. Build the project. This is required before running contentdata CLI commands.
./pragma build project -s
  1. Run the contentdata init command to generate some JSON files for your catalog. You can find these files under [project]/content/src/
java -jar [project]/target/pragma.jar contentdata init -d [project]/content -c HeroUnlockCatalog HeroUnlocks
  1. Add the following JSON into the [project]/content/src/HeroUnlocks.json file.
HeroUnlocks.json
[
  {
    "heroId": "heroA",
    "cost": 100
  },
  {
    "heroId": "heroB",
    "cost": 200
  },
  {
    "heroId": "heroC",
    "cost": 500
  }
]
Proto definitions use snake_case, but the generated Java types follow Java conventions and use camelCase. Use camelCase in your JSON catalogs because the entries are marshalled into the Java types.
  1. Register the catalog by running the following command. This command will generate a file at: [project]/content/package/HeroUnlocks.json
./pragma content apply
  1. Commit the Content Data catalogs in your project.

Access the Content catalog #

Outcome #

Utilize Content Data catalogs in Plugins, Services, and Player Data Operations.

Examples #

Plugins and Custom Services use the ContentDataNodeService for accessing Content Data:

val heroD : HeroUnlock? =
contentDataNodeService.getHandler<HeroUnlock>("HeroUnlocks.json").get("heroD")
if (heroD == null) {
   // customize resposne to missing content entry
}
// or use getOrThrow if you want an error returned if content entry is missing
val heroB : HeroUnlock =  contentDataNodeService.getHandler<HeroUnlock>("HeroUnlocks.json").getOrThrow("heroB")

The Player Data service uses PlayerDataContentLibrary for accessing Content Data catalogs.

@PlayerDataOperation(sessionTypes = [SessionType.PLAYER])
    fun unlockHero(
        request: UnlockHero,
        context: Context,
    ): HeroUnlocked {
        val heroUnlockCatalog  = contentLibrary.getContentData("HeroUnlocks.json")
        val heroUnlockContentEntry = heroUnlockCatalog.getOrThrow(request.heroId) 
        // Use the content entry to validate and update player's data.

        return HeroUnlocked()
    }