Live Data Tasks #

Entities and Components always use the same classes and interfaces in the Player Data service, but the way you model Component and Entity data varies depending on your desired feature. This page describes how to create a Component class and author and Entity containing Components, as well as helpful tips when data modeling your scenarios.

Common tasks when modeling live data include:

Define a Component class #

A Component class is created in Kotlin using the provided Component interface.

To create an Entity, you need to first define the Component classes that will be used in the Entity. A Component class allows you to define specific fields attached to the class so you can fully customize your data modeling structure. Every user-defined Component implements the Component interface belonging to the Player Data service.

Author the Component class by giving it a unique class name compared to any other Component declarations you may have, and by inheriting the Component structure. The class’s properties, which house the Component’s data, are defined purely by the developer using @FieldNumbers. Components can use variables for properties that should be mutable and values for properties that should never change during the lifetime of a live Component.

Below is an example of a Component with custom user-defined properties:

data class ExampleComponentData(
  @FieldNumber(1)var stringData: String,
  @FieldNumber(2)var intData: Int
): Component

Once you’ve defined at least one Component, you need to create a separate Kotlin file that has a function with the annotation @ComponentOrdering. This function is responsible for assigning all of your defined Components a unique integer for code generation. Make sure you do not change a Components unique integer once you’ve defined it, and any new Components added to the function must have an unused integer.

Below is an example of a @ComponentOrdering function with a list of Components:

@ComponentOrdering
fun components(): Map<KClass<out Component>, Int> {
    return mapOf(
      ExampleComponentData::class to 1,
      AnotherExampleComponentData::class to 2,
      BonusExampleComponentData::class to 3
    )
}

A Component and its associated properties are not live until it is defined as part of an Entity and created in an Operation function’s logic.

Define a Component class for hidden data #

Specific properties in a Component class can hide data from being sent to the player and game client.

If you want to have a Component that contains data that shouldn’t be sent to the player and game clients, you can use the HiddenComponent interface when authoring a Component class. An Entity containing a hidden Component and an unhidden Component will only send the unhidden Component to the player and game client. If an Entity only has hidden Components, the entire Entity will not be sent to the player and game client.

Author the Component class with a unique class name, inheriting the HiddenComponent interface, and define the class’s properties for the Component’s data.

Below is an example of a HiddenComponent with custom user-defined properties:

data class ExampleHiddenComponentData(
  var stringData: String,
  var intData: Int
): HiddenComponent

Author an Entity containing a list of Components #

The Operation function’s business logic authors Entities with pre-existing Components.

When creating an Entity, you need to know which Sub Service’s Operation will assign the Entity to players, and whether or not you want the player to have multiples of the Entity. Not every Entity has to have a Component, especially if they are utilized as some type of data or progression tracker, but most of the time you’ll need to have already authored the Component classes that the Entity will have.

If you authored your Components in a different Kotlin file or package other than the one containing your Sub Service, make sure you import the package so you can utilize the Components in the Operation function’s logic.

First, you’ll need to create vals or vars for the Components that will be attached to the Entity. Then, make sure you have some logic setup for creating the Entity’s name. Lastly, create a val or var that uses a helper function from context.snapshot to do your desired Entity creation step.

To see a full list of all the helper functions you can use for authoring Entities, check out the Snapshot Reference page for Operations.

Below is an example of an Operation function defining an Entity with Components:

class ExampleSubService(contentLibrary: PlayerDataContentLibrary): PlayerDataSubService(contentLibrary) {


    @PlayerDataOperation(sessionTypes = [SessionType.PLAYER])
    fun exampleOperation(
        request: ExampleRequest,
        context: Context
    ): ExampleResponse {

       val componentOne = CustomData("example-string", 100)
       val componentTwo = CustomData("second-example-string", 200)
       val components = listOf(componentOne, componentTwo)

       val name = "{ENTITY_NAME}"
       val entity = context.snapshot.createEntity(name, components)
       ...
       return ExampleResponse()
    }
}