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.
- Create a new protobuf file at:
[project]/[project]-protos/src/main/proto/customcontent/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;
}
- Generate the Java types.
./pragma build project-protos
- 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
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 #
- Build the project. This is required before running
contentdata
CLI commands.
./pragma build project -s
- Run the
contentdata init
command to generate some JSON files for your catalog. The files will be generated under[project]/content/src/
.
java -jar [project]/target/pragma.jar contentdata init -d [project]/content -c HeroUnlockCatalog HeroUnlocks
- Add the following JSON into the
[project]/content/src/HeroUnlocks.json
file.
[
{
"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.
- Register the catalog by running the following command. This command will generate a file at:
[project]/content/package/HeroUnlocks.json
./pragma content apply
- 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) {
// can customize behavior when missing the content entry
}
// Use getOrThrow when you would like an ApplicationErrorException to be thrown when the content entry is missing.
// The ApplicationErrorException will contain an errorMessage with a ContentApplicationError proto.
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()
}