Custom Services #

Custom services are defined in the same manner as engine services and follow the exact same patterns. Custom services adapt all engine features such as gateway routing, authentication, service-to-service calls, and metrics. Service configuration is standardized so that custom services define and support configuration in the same way Pragma Engine services are configured.

Example

A game developer needs a custom service to implement a specific quest flow for their story-based campaign. Players select quest details during the Lobby flow within the game loop.

The developer implements a lobby plugin after defining the new Quest service. On lobby creation, the plugin makes a service-to-service RPC call to the Quest service to validate the player’s selection.

Quick Guides #

Using sample services to customize your game #

Our demo folder at 4-demo/demo/src/main/kotlin/demo has a library of examples that can be leveraged to extend Pragma Engine’s base functionality.

To view sample implementations of custom services, check out our full User Guides.

Defining a new custom service #

Use the @PragmaService annotation to define a new Pragma Engine service.

  • backendTypes determines whether it’s a Social or Game backend service
  • dependencies determines what the new service will interact with
@PragmaService(
   backendTypes = [BackendType.GAME],
   dependencies = [InventoryDaoNodeService::class]
)

Plugins are declared with a @PragmaPlugin annotation as a field within a service. The annotation includes a reference to the default implementation.

In this example, EmptyInstancedItemPlugin is used as the default name referencing the plugin in configuration, instancedItemPlugin.

@PragmaPlugin("EmptyInstancedItemPlugin", "instancedItemPlugin")
lateinit var instancedItemPlugin: InstancedItemPlugin

RPCs are declared with the @PragmaRPC annotation and include a session type.

In this example, we’re using a SessionType.Player session, which is handled on the Player Gateway. You can also use SessionType.Partner or SessionType.Operator.

The routing method can be any of the following:

routing methoddescription
RANDOMany service instance
REQUEST_FIELDprotobuf field used to determine service instance
SINGLETONalways use single service instance
DIRECTspecified service instance
GAME_SESSION_PARAMgame session attribute
SOCIAL_SESSION_PARAMsocial session attribute
SESSION_PRAGMA_IDplayer’s pragmaId
@Suppress("unused")
@PragmaRPC(
  sessionType = SessionType.PLAYER,
  routingMethod = RoutingMethod.SESSION_PRAGMA_ID
)
suspend fun getInventoryV2(
  session: PlayerSession,
  request: InventoryRpc.GetInventoryV2Request
): InventoryRpc.GetInventoryV2Response {
  return InventoryRpc.GetInventoryV2Response.newBuilder()

.setFull(playerInventoryProxy.getInventoryTransactionData(session.pragmaId.toUUID()).toProtoFull())
  .build()
}