Operations Overview #

Operations are a core part of the Player Data service. They allow the developer to author unique API endpoints for their player data features and define the Request and Response payloads. They also allow you to easily organize and maintain your endpoint business logic responsible for updating any type of defined player data. By defining the Operations yourself, you get to perfectly implement your designed player data features the way you want instead of fitting your design into a backend system that doesn’t align with your game.

 Boxes and line arrows showcasing an Operation flow.

Operations always belong to a Sub Service’s class, and typically a Sub Service class is organized based on the Operations within it. For example, a Sub Service that handles daily rewards would contain Operations solely for handling daily reward business logic, and a Sub Service for handling Hero or Champion unlocks would only contain Operations solely for unlocking new characters.

Operations are in charge of assigning live data (Entity) to players. They can also utilize content data in their business logic when handling any type of player’s data. Every Operation always has access to all of a player’s data, and all changes made to a player’s data in an Operation are applied in one database transaction. The Operations you define are generated into the PragmaSDK and belong to their respective Sub Service in the SDK. This means that the way Operations are defined in a Sub Service directly impacts what Operations are available in the Pragma SDK and how you interact with said Operations.

Continue reading for more information about the important classes, functions, and objects associated with Operations.

Request and Response Classes #

Operations for a Player Data Sub Service are defined as PlayerDataRequest and PlayerDataResponse type classes and given business logic inside a Sub Service Operation function. Every Operation class inherits the PlayerDataRequest and PlayerDataResponse interfaces so they can interact with Pragma Engine appropriately. Additionally, the Request and Response Kotlin classes are used to generate the protobufs that’ll be used between the engine layer and the PragmaSDK. You can see an example of what the classes for an Operation’s Request and Response type look like in the Create the Request and Response classes task.

Sub Service Class #

Sub Service classes are used to house and organize Operation functions. Every Sub Service class is constructed with a parameter for the PlayerDataContentLibrary, allowing Operations to interact with and utilize content data. All of the Operations belonging to a Sub Service class are generated into the Sub Service’s SDK class.

Operation Function #

An Operation’s business logic is written inside a Sub Service’s class using a specific Operation function. An Operation function must always have a property for request and context. The request property provides an instance of the Operation’s user-defined Request class (inheriting the PlayerDataRequest structure), and context gains access to other objects and functions for creating and modifying a player’s live data.

Note that an Operation’s functions name cannot overlap with any other Operation functions. The function must also always return the appropriate PlayerDataResponse type associated with the Operation.

To implement an Operation function, go to the Author an Operation function task for more implementation details.

Context #

context is an interface that provides useful data, objects, and helper functions for writing business logic in an Operation’s function. Every Operation has context as a parameter in its respective function which allows you to access context’s interface.

See the Context section on the Reference page for more details.

Snapshot #

PlayerDataSnapshot is a class that contains functions for retrieving, creating, modifying, and deleting Entities and their Components. These functions edit a data class within PlayerDataSnapshot called EntityData, which manages all data changes and processes made to an Entity. Anytime an Entity is called from an Operation, even if no change is made, EntityData runs through its mutableSetOf() functions to update the database and cache.

If you plan on updating Entities without using the helper functions in Snapshot, you’ll need to update the raw EntityData class by updating the mutableSetOf() for the changedEntities and entitiesToDelete parameters. Even if no changes occur for an Entity, you still need to update changedEntities.

See the Snapshot section on the Reference page for more details.

Unreal PragmaSDK #

All Request and Response classes, Sub Services, and Operations are generated in the Unreal PragmaSDK. The PragmaSDK has two classes that provide access to a Sub Service’s APIs and Operations:

  • The UPragmaPlayerDataService class provides access to game client Operations and will only contain a Sub Service’s APIs and Operations available on a player session.

  • The UPragmaPlayerDataPartnerService class provides access to game server Operations and will only contain a Sub Service’s APIs and Operations available on a partner session.

The Request and Response Unreal structs match the Kotlin Request and Response classes, and Every Sub Service’s Operation has a corresponding Unreal method. The Operation method’s parameters always correspond with the Request struct properties and include an additional parameter for a delegate. The Operation’s delegate has one parameter for TOptional that contains the Response struct’s properties. Note that if the TOptional is not set then an error will occur and you’ll need to check logs for more details

Below is an example of accessing the UPragmaPlayerDataService through a Pragma::FPlayerPtr:

Player->PlayerDataService().<SUB-SERVICE-CLASS-NAME>SubService().<OPERATION-NAME>(
    ...   
 /* Parameters that correspond with the Operation's request properties */
    ...
 /* Delegate contains one parameter for the Operation's response properties */
    FOn<SUB-SERVICE-CLASS><OPERATION>Delegate TOptional<OPERATIONS-RESPONSE-STRUCT> 
)

The UPragmaPlayerDataService also comes with a cache for players’ entities. The cache layer helps optimize and limit the transfer of data between the client and Pragma Engine. Anytime the client calls an Operation, the client side cache will get updated. After the cache is updated, the Operation’s delegate is called. We recommend you always fetch players’ entities through the UPragmaPlayerDataService.GetCache() method, which returns a pointer to an FPlayerDataCache instance.

See the Utilize an Operation in the PragmaSDK task and the Player Data Service SDK reference topic for more details.