Pragma Engine 0.0.93

May 25, 2023

Features #

[Game Flow] Methods in the Matchmaking Plugin have been updated to return a NewGameInstance. #

Description: The Matchmaking Plugin’s revised initialize and buildMatch methods, along with the new matchParties and endOfLoop methods, can create and return a NewGameInstance. This functionality replaces the startMatch and startMatchAndContinueMatchmaking methods on the Potential Match interface.

Details: When the matchmaking process is started using the Matchmaking Plugin makeParties method, one party is passed in as the anchor Matchable, and the other party as the other Matchable. This removes the need for a Potential Match object.

When logic defined in the Matchmaking Plugin determines that two Matchables have been matched, the Matchmaking Plugin can generate a NewGameInstance, add parties from the Matchable to it, and return the new NewGameInstance object to the caller.

Related notes: See integration notes on updating the Matchmaking Plugin.

[Game Flow] We’ve updated properties in the Matchable and Active Match objects to simplify Matchmaking Plugin implementations. #

Description:
The Active Match object no longer exposes the activePlayers property, as these values are listed in the players list.

The Active Match object now exposes parties, teams, ExtCreateMatchV1Request, gameServerZone, and secondsInQueue.

The Matchable object no longer exposes the matchmakingKey, gameServerVersion, and gameServerDetails properties, and no longer provides the getQueueKey(), assignPlayersToTeam(), and assignPartiesToTeam() functions.

Related notes: See the integration notes for Matchable and Active Match properties.

[Game Flow] Party and player data for Matchables and Active Matches are easily accessible from the Matchmaking Plugin. #

Description: The MatchParty and MatchPlayer objects used in Matchables and Active Matches have been renamed to Matchmaking.Party and Matchmaking.Player, respectively.

Details: The following additional changes have been made:

  • ActiveMatch.players returns a list of Matchmaking.Player objects for all players that have been added to the Active Match, regardless of whether the player in pending or not
  • Matchmaking.Party uses a list of Matchmaking.Player objects instead of MatchmakingPlayerInfo objects.
  • We’ve defined a new matchmaking extMatchmakingParty payload for matchmakingExt.proto to consolidate data in ExtEnterMatchmakingV2Request, ExtPartySelections, and ExtHiddenPartyData.

Related notes: See the doc and integration notes about Matchmaking.Party and Matchmaking.Player.

[Game Flow] movePartiesFrom() and moveAllPartiesFrom() is now takePartiesFrom(). #

Description: To make the Matchable types easier to use, the takePartiesFrom() method replaces the movePartiesFrom() and moveAllPartiesFrom() methods for all Matchable types.

Details: The new takePartiesFrom() method accepts a Matchable and a list of parties to add to the Matchable:

fun takePartiesFrom(
  matchable: Matchable, 
  parties: List<Matchmaking.Party>
)

[Game Flow] New GameLoopApi and MatchApi classes have been added to the SDK. #

Description: The new GameLoopApi and MatchApi classes are replacing the Party, MatchLifecycle, and MatchCapacity service classes in an effort to restructure the Unreal and Unity SDKs into more understandable and easy-to-use classes using the new “Api” naming convention at the end of the class name.

Related notes: See deprecation and integration notes on these new classes.

[Game Flow] Players now receive game server connection tokens so game servers can verify game clients. #

Description: Pragma Engine now provides connection tokens to players that game servers can use to verify if players belong in the match.

Details: Players now receive a single-use connection token on their MatchReadyV1Notification when they connect to the game server. If the game server determines that the token is valid, the game server can confidently allow the player into the match.

[Player Data] The Limited Grant feature now has a Limited Grant Plugin for determining whether a player can receive a grant. #

Description: Custom logic to determine if a grant should be given to a player can now be added to the new Limited Grant Plugin.

Details: Custom logic can be added to the Limited Grant Plugin’s shouldGrant() method. This function provides the limited grant content entry and a snapshot of the player’s inventory data.

Related notes: See docs note on the updated Limited Grant concepts page.

[Player Data] GetLoginData no longer returns the full inventory data. #

Description: GetLoginDataV3Response has been restructured to remove an unnecessary full inventory data transfer to the client.

Details: You can subscribe to the OnInventoryUpdated event to receive notifications about updates to the player’s inventory including when limited grants are processed as part of the GetLoginData flow.

Related notes: See deprecation note on GetLoginData.

[Player Data] You can now filter player inventory by providing a list of tags. #

Description: The Inventory Service endpoints GetInventoryOperatorV1 and GetInventoryPartnerV2 now support filtering.

Details: To filter player inventory, send a list of tags on the request. This is an optional field; hidden inventory items will be filtered out regardless of this field.

Related notes: See docs note on update to the Item concepts page.

[Player Data] The Provider Entitlement feature now supports additional Epic Games Store offer types. #

Description: The following Epic Games Store offer types are now supported: season pass, demo, and digital extra. You can now associate the ownership of these offers with item grants in Pragma Engine.

Related notes: See docs note on the updated Map Offerings to Pragma Engine section.

[Player Data] The Provider Entitlement feature now supports additional PlayStation 5 offer types. #

Description: Contact your Pragma Engine support representative for further details.

[Accounts] The Login Queue feature is now available. #

Description: Users logging in through a client will now be routed through a login queue. This ensures your authentication servers and game servers don’t become overloaded during times of increased load, like on launch days. As part of this launch you will be able to display the estimated time to login and the users position in the queue. To get started with Login Queues, see the Login & Session concepts page.

Related notes: See docs note on the new Login Queue feature.

[Infra & Tooling] Database configuration is now simpler. #

Description: You can now use simplified database configurations instead of existing verbose database configuration options.

Details: You must add the SharedDatabaseConfigNodeService::class dependency to all custom services that extend the PartitionedDaoNodeService or UnpartitionedDaoNodeService.

To use the simplified database configuration replace your existing database configuration with the new SharedDatabaseConfigServiceConfig. Inside of the SharedDatabaseConfigServiceConfig you must provide a unique identifier for your database such as testIdentifier. You can then use the identifier in your DAO configurations.

Examples:

  • Dependency
@Suppress("unused")
@PragmaService(
    backendTypes = [BackendType.GAME],
    dependencies = [SharedDatabaseConfigNodeService::class]
)
  • Configuration
serviceConfigs:
    # Collections of database configurations
    SharedDatabaseConfigServiceConfig:
      databaseConfigsByIdentifier:
        testIdentifier:
            username: "superuser"
            password: "password"
            host: "${databaseHost}"
    
    # PartitionedDaoNodeService configuration
    PaymentDaoConfig:
        databaseConfig:
            identifierSchemas:
                1:
                  identifier: "testIdentifier"
                  schema: "test_social_paymenthistory1"
                2:
                  identifier: "testIdentifier"
                  schema: "test_social_paymenthistory2"

    # UnpartitionedDaoNodeService configuration
    GameDaoConfig:
        databaseConfig:
            identifierSchema:
                identifier: "testIdentifier"
                schema: "test_social_game"

Related notes: See integration note for required steps for enabling this feature.

Deprecations #

[Game Flow] platform | Migrate any matchmaking logic located in MatchmakingStrategy to the Matchmaking Plugin. #

[Game Flow] sdk | Update SDK calls in the Party service classes to the GameLoopApi classes, and update calls in the MatchLifecycle and MatchCapacity services classes to the new MatchApi classes. #

originalreplacementremoval release
Party.CreatePartyGameLoopApi.CreateParty0.0.94
MatchLifecycle.MatchReadyMatchApi.MatchReady0.0.94
MatchCapacity.ReleaseCapacityMatchApi.ReleaseCapacity0.0.94

[Player Data] sdk | Replace references to GameDataService.GetLoginDataV2 with GameDataService.GetLoginDataV3. #

originalreplacementremoval release
GetLoginDataV2GetLoginDataV30.0.94

[Player Data] sdk | Replace references to InventoryService.GetLoginDataServiceV1 with InventoryService.GetLoginDataServiceV2. #

originalreplacementremoval release
GetLoginDataServiceV1GetLoginDataServiceV20.0.94

Integrations #

The integration notes related to the Matchmaking Plugin may require additional assistance. If you run into issues integrating these notes, contact your Pragma customer support representative.

[Game Flow] platform | Add a new message for ExtMatchmakingParty to the matchmakingExt.proto file. #

Description: Pragma Engine has created a new payload, so you need to create that same payload object in your copy of the matchmakingExt.proto.

Integration step: platform | Navigate to the matchmakingExt.proto file within the 5-ext/ext-protos/src/main/proto/shared folder, and paste the following empty message into the file:

message ExtMatchmakingParty {
}

[Game Flow] platform | Update MatchParty and MatchPlayer to Matchmaking.Party and Matchmaking.Player. #

Description: Player and party data available in Matchables and Active Matches have been simplified so they are easily accessible from the Matchmaking Plugin.

Integration steps: platform | Replace references to MatchParty with Matchmaking.Party, and references to MatchPlayer with Matchmaking.Player.

  • When migrating from MatchParty to Matchmaking.Party and MatchPlayer to Matchmaking.Player, many field changes occurred.
  • If you were using the MatchParty constructors, use the MatchmakingPartyImpl instead.
  • If you were using the MatchPlayer constructors, use the MatchmakingPlayerImpl instead.
  • In the new buildExtMatchmakingParty function in your Party Plugin implementation, consolidate ExtEnterMatchmakingV2Request, ExtPlayerSelections, ExtPrivatePlayerSelections, ExtPartySelections, ExtHiddenPlayerData, and ExtHiddenPartyData. These are no longer exposed directly, so sending custom data about the Matchmaking Plugin from the Party service requires defining matchmaking data within the new ExtMatchmakingParty and implementing PartyPlugin.buildExtMatchmakingParty.

[Game Flow] platform | Update the listed Matchmaking Plugin methods. #

Description: To clarify the matchmaking process, we’ve updated and added to the Matchmaking Plugin methods. For more information on this change, read the feature note on the changes to the Matchmaking Plugin methods.

Integration steps: Make the following changes to your Matchmaking Plugin:

  • platform | In the initialize method, change the second parameter from potentialMatch: PotentialMatch to party: Matchmaking.Party.

    • Before:
    fun initialize(
     queueKey: MatchmakingRpc.MatchmakingQueueKey, 
     potentialMatch: PotentialMatch
    )
    
    • After:
    fun initialize(
     queueKey: MatchmakingQueueKey, 
     party: Matchmaking.Party
    ): NewGameInstance? 
    
  • platform | In place of the buildMatch method that accepted a Potential Match object, use the matchParties method. This will require updating your matchmaking algorithm to return in a NewGameInstance all the changes that previously were done to a Potential Match or Matchable.

    • Before:
    fun buildMatch(
     queueKey: MatchmakingRpc.MatchmakingQueueKey,
     potentialMatch: PotentialMatch, 
     matchable: Matchable
    )
    
    • After:
    fun matchParties(
      queueKey: MatchmakingQueueKey, 
      anchor: Matchable, 
      matchable: Matchable
    ): NewGameInstance?
    
  • platform | Instead of using endLoop, use endOfLoop and have the code return a NewGameInstance if one should be created at the end of a matchmaking loop.

    • Before:
    fun endLoop(
      potentialMatch: PotentialMatch
    )
    
    • After:
    fun endOfLoop(
      queueKey: MatchmakingQueueKey, 
      anchor: Matchable
    ): NewGameInstance?
    
  • platform | If your Matchmaking Plugin methods previously called potentialMatch.startMatch, instead create a new NewGameInstance, add the party to it, and return the NewGameInstance.

  • platform | If you have tests on this code, update those tests to inspect the return value of the new methods, rather than performing verifications on the Potential Match or party.

Related notes: See feature note on the Matchmaking Plugin.

[Game Flow] platform | Update references to Matchable and Active Match properties. #

Description: Matchable and Active Match objects now expose different properties and methods to simplify Matchmaking Plugin implementations. Make the following changes based on your implementation.

Integration steps:

  • platform | Replace instances of ActiveMatch.activePlayers with ActiveMatch.players.
  • platform | To access the ExtMatchmakingKey and the GameServerVersion, which were previously stored on the GameServerDetails object, use the queueKey: MatchmakingQueueKey parameter passed into all Matchmaking Plugin methods. These properties are now set on the NewGameInstance when starting a new game.
  • platform | Remove calls to the Matchable assignPlayersToTeam()and assignPartiesToTeam() methods, and instead use the setTeamByPlayer() and setTeamByPlayers() methods when creating a NewGameInstance.

[Game Flow] platform | Replace movePartiesFrom() and moveAllPartiesFrom() with takePartiesFrom(). #

Integration steps: platform | Rename all usages of movePartiesFrom() and moveAllPartiesFrom() to takePartiesFrom() and provide a list of parties instead of a list of party IDs.

[Game Flow] sdk | Developers on the V2 SDK Sessions (Runtime Player & Runtime Server) should update their SDK calls to use the new GameLoopApi and MatchApi classes. #

Description: The new GameLoopApi and MatchApi classes are replacing the Party, MatchLifecycle, and MatchCapacity service classes in order to make the Unreal and Unity SDKs easier to use.

Integration steps: sdk | Update Player session calls from the Party service to the GameLoopApi service. To manually invoke the matchConnectionDetails endpoint in Unreal or Unity, make the following changes:

Replace player->Party()->MatchConnectionDetails with player->GameLoopApi()->MatchConnectionDetails
Replace player.Party.MatchConnectionDetails with player.GameLoopApi.MatchConnectionDetails

[Accounts] config | If you’re using the Google identity provider, add the clientId, encrypted clientSecret, and redirectUri to your configuration. #

Description: We’ve updated the Google identity provider to work for game clients as well as Portal, and we’ve standardized it on the existing authorization flow.

Integration step: config | Add the following fields for your Google OAuth app to the AccountService.identityProviderPlugins config: clientId, encrypted clientSecret, and redirectUri.

Example:

social:
  pluginConfigs:
    AccountService.identityProviderPlugins:
      plugins:
        Google:
          class: "pragma.account.GoogleIdentityProviderPlugin"
          config:
            clientId: "${googleClientId}"
            clientSecret: "${googleClientSecret}"
            redirectUri: "http://{accountServiceHostname}:11200/v1/account/google-redirect" # Use what is defined in your Google web developer tool

[Player Data] platform | Update usages of playersInventory to playerInventory in the Crafting Plugin. #

Description: The parameter playersInventory has been renamed to playerInventory for consistency.

Integration step: platform | Update usages of playersInventory to playerInventory in any implementation of the Crafting Plugin.

originalreplacement
playersInventoryplayerInventory

[Player Data] platform | Update usages of ext to requestExt in the Crafting Plugin. #

Description: The parameter ext has been renamed to requestExt in the CraftingPlugin.meetsRequirements to better describe where the data comes from.

Integration step: platform | Update usages of ext to requestExt in CraftingPlugin.meetsRequirements.

originalreplacement
extrequestExt

[Player Data] platform | Add new required inventory content ext protos. #

Description: New inventory content ext protos must be manually added to InventoryContentExt.proto. Projects will fail to build without these protos.

Integration steps: platform | Under the ext-protos module, in file ext-proto/src/main/proto/shared/InventoryContentExt.proto add the following messages and then run make ext-protos.

  • message ExtEntitlement {}
  • message ExtLimitedGrant {}

[Player Data] platform | If you’ve already implemented the Provider Entitlement feature, you’ll need to convert to the new content structure. #

Description: The content structure and files have been updated. The old content files with type ProviderEntitlementMappings can be deleted.

Integration steps:

  • platform | If you have not integrated with the Provider Entitlement feature:
    • Delete 5-ext/content/package/ProviderEntitlementMappings.json
    • Delete 5-ext/content/src/ProviderEntitlementMappings.json
    • Delete 5-ext/content/src/ProviderEntitlementMappings.metadata
  • platform | If you have integrated with the Provider Entitlement feature:
    • Copy templates/content/src/ProviderEntitlements.json and templates/content/src/ProviderEntitlements.metadata files to 5-ext/content/src/
    • Migrate data to follow the new Provider Entitlement mapping structure. See the updated Map Offerings in Pragma Engine section of the Integrate and Use Provider Entitlements concepts page for more information.
    • Delete 5-ext/content/package/ProviderEntitlementMappings.json
    • Delete 5-ext/content/src/ProviderEntitlementMappings.json
    • Delete 5-ext/content/src/ProviderEntitlementMappings.metadata

config | Implement the new PartnerClientConfig. #

Description: By moving your configuration values to the socialConnections configuration, you can reference one configuration for all of your connection needs.

Integration steps:

  • config | For managed customers: Retrieve your player, partner, and operator host names using the Homebase API and add them to the new PartnerClientConfig.
    • Navigate to api.homebase.{studioName}.pragmaengine.com.
    • Choose /management/shardConfigurationV0 under Management.
    • Provide the shardId and titleId of the configuration you’re updating and choose Execute.
    • Copy the social host names for each gateway to the new auth host and host in SocialConnectionConfig under PartnerClientConfig.
  • config | For self-managed customers: Copy the configuration values in GamePlayerGatewayConfig, GamePartnerGatewayConfig, and GameOperatorGatewayConfig to the new PartnerClientConfig.

[Infra & Tooling] platform & config | Add the SharedDatabaseConfigNodeService::class dependency to all custom services that extend the PartitionedDaoNodeService or UnpartitionedDaoNodeService. #

Description: You can now use simplified database configurations instead of the prior verbose database configuration options.

Adding this dependency will not implement the simplified database configuration until you have replaced your existing database configuration with the new SharedDatabaseConfigServiceConfig. Inside the SharedDatabaseConfigServiceConfig, you must include testIdentifier. You can then use the default identifier in your DAO configurations. See related feature note for implementation information.

Integration step:

  • platform | Add the ShareDatabaseConfigNodeService::class dependency to all custom services that extend the PartitionedDaoNodeService or UnpartitionedDaoNodeService. This change can be in both game and social configs.

Examples:

  • platform | Dependency
@Suppress("unused")
@PragmaService(
    backendTypes = [BackendType.GAME],
    dependencies = [SharedDatabaseConfigNodeService::class]
)
  • config | Configuration
    • Before
serviceConfigs:
    PaymentDaoConfig:
        databaseConfig:
            driver: "MYSQLDB"
            hostPortSchemas:
              1: "${databaseHost}:3306/test_social_paymenthistory1"
              2: "${databaseHost}:3306/test_social_paymenthistory2"
            username: "superuser"
            password: "password"
    GameDaoConfig:
        databaseConfig:
            driver: "MYSQLDB"
            hostPortSchema: "${databaseHost}:3306/test_social_game"
            username: "superuser"
            password: "password"
  • After
serviceConfigs:
    # Collections of database configurations
    SharedDatabaseConfigServiceConfig:
        testIdentifier:
            username: "superuser"
            password: "password"
            host: "${databaseHost}"
    
    # PartitionedDaoNodeService configuration
    PaymentDaoConfig:
        databaseConfig:
            identifierSchemas:
                1:
                  identifier: "testIdentifier"
                  schema: "test_social_paymenthistory1"
                2:
                  identifier: "testIdentifier"
                  schema: "test_social_paymenthistory2"

    # UnpartitionedDaoNodeService configuration
    GameDaoConfig:
        databaseConfig:
            identifierSchema:
                identifier: "testIdentifier"
                schema: "test_social_game"

[Infra & Tooling] config | Reorder configuration overrides if your configuration relies on the previous configuration load order. #

Description: We’ve updated the default order for configs to be run whenever Pragma Engine is run locally, with common.yml loaded before dev.yml. It now follows this order:

  1. config/dev-defaults.yml
  2. 5-ext/config/common.yml
  3. 5-ext/config/dev.yml
  4. 5-ext/config/local-dev.yml

Integration steps: config | If you’ve ordered configs to override relying on the previous version of the config load order, you’ll need to reorder them.

[SDKs] sdk | Update references to EPragmaBackendConnectionError. #

Description: EPragmaBackendConnectionError has been renamed to EPragmaConnectionError and has new values.

Integration steps:

  • sdk | Change all references from EPragmaBackendConnectionError to EPragmaConnectionError.
  • sdk | If you directly used values from the EPragmaBackendConnectionError enum, you will need to update your code to handle the new values in EPragmaConnectionError. Check the EPragmaConnectionError enum to see its values.

[Portal] portal | The pragma library imports in the provided table below will need to be changed. #

Description: These changes were made to resolve unexpected behavior due to some components being imported with duplicated names. We’ve refactored impacted elements.

Integration step: portal | The pragma library imports in the table below will need to be changed.

originalreplacement
pragma.ui.components.DateDisplay.DateDisplaypragma.ui.components.DateDisplay
pragma.ui.components.DateDisplay.dateFormatpragma.ui.helpers.dateHelpers.dateFormat
pragma.ui.components.DateDisplay.timeFormatpragma.ui.helpers.dateHelpers.timeFormat
pragma.ui.components.DateDisplay.timeFormatNoSecondspragma.ui.helpers.dateHelpers.timeFormatNoSeconds
pragma.ui.components.Pagination.Paginationpragma.ui.components.Pagination
pragma.ui.components.Pagination.PRAGMA_INDEX_OF_FIRST_PAGEpragma.ui.helpers.paginationHelpers.PRAGMA_INDEX_OF_FIRST_PAGE
pragma.ui.components.Pagination.DEFAULT_PAGE_SIZEpragma.ui.helpers.paginationHelpers.DEFAULT_PAGE_SIZE
pragma.ui.components.Pagination.PAGE_QUERY_KEYpragma.ui.helpers.paginationHelpers.PAGE_QUERY_KEY

Bugs and Fixes #

  • [Game Flow] Fixed a bug that allowed players that were removed from a match to retrieve their prior connection details.
  • [Player Data] Instanced item costs are now properly handled when making a Store Purchase request with an amount greater than 1.
  • [Portal] An unfinished feature for suspending accounts that was visible has been removed to prevent it from causing issues, and will be redeployed when the feature is ready.
  • [SDKs] Unreal SDK: Fixed an issue causing sessions to drop quietly after a period of inactivity due to heartbeats never starting.

Docs #

  • [New Concepts] New Portal section now available! This completely rewritten set of guides includes Key Concepts, Provided Functionality, and Customization.
  • [Updated Concepts] Updated the Player Data overview page with more information and examples of stores and crafting.
  • [Updated Concepts] Added a new section on the Store Plugin to the Store concepts page.
  • [Updated Concepts] Added a new section on the Limited Grants Plugin on the Limited Grants concepts page.
  • [Updated Concepts] Added a new section on the Crafting Plugin on the Crafting concepts page.
  • [Updated Concepts] Added a new section on Filtering by tags on the Items overview concepts page.
  • [Updated Concepts] Updated the Map offerings to Pragma Engine section on the Integrate and Use Provider Entitlements concepts page.
  • [Updated Concepts] Updated the Game Flow section with new information.
  • [Updated Concepts] Updated the Google configuration dropdown on the Identity Providers page.
  • [Updated Concepts] Added a new section about Login Queues to the Login and Session page.
  • [New Tech Blog] The new Custom Service series is live! Learn how to create and customize a custom service with these four articles.