Pragma Engine 0.0.97

November 2023

Contents #

Summaries | Summarized release notes.

Full Notes | Full notes including descriptions and additional details.

Summaries #

Features #

  • [Multiplayer] New Fleet service works alongside Match Capacity service. | full note
  • [Multiplayer] Pragma now supports managing game server fleet capabilities outside of Pragma. | full note
  • [Multiplayer] You can now host multiple game instances from a single game server. | full note
  • [Player Data] All Inventory Service plugins can now easily make service-to-service calls when determining player inventory changes. | full note
  • [Accounts] You can now change the keys used for token signing and verification without disrupting existing sessions or forcing users to reauthenticate. | full note
  • [Accounts] For the Epic identity provider, you can now restrict access by game ownership. | full note
  • [Infra & Tooling] Added platform command for generating JWT public and private keys. | full note
  • [Infra & Tooling] New Telemetry Plugin using S3 as event storage. | full note
  • [Infra & Tooling] A new version of the protoc-custom-plugins package has been integrated. | full note
  • [SDKs] Unreal: You can now exclude specific RPCs and notifications from being logged. | full note
  • [Portal] Added pagination to the account and player overview filter endpoints. | full note
  • [Portal] Operators can now log into Portal using the Epic identity provider. | full note
  • [Portal] Page Builder API now supports header components. | full note
  • [Portal] Current annotated platform config now shown in the Development Tools section. | full note

Deprecations #

  • [Multiplayer] MatchApi.ReleaseCapacity method deprecated in favor of MatchApi.ReportFreedCapacity | full note

Integrations #

  • [Multiplayer] sdk | Update GameLoopApi SDK methods and events related to parties and party players.| full note
  • [Multiplayer] sdk | Replace references to CanSetPartyPreferredGameServerZone with CanSetPartyPreferredGameServerZones. | full note
  • [Multiplayer] platform | (Optional) If using the Match Capacity test factory, reimport references to MatchCapacityProtoTestFactory with FleetProtoTestFactory. | full note
  • [Multiplayer] platform, sdk, config | (Optional) Manage game server fleet capabilities outside Pragma. | full note
  • [Player Data] platform | If you’re using any Inventory service plugin, update the plugin’s functions so they have the suspend modifier. | full note
  • [Accounts] platform | If you call the filter endpoints for retrieving account and player information, you’ll now need to pass in two new additional values: page_index and page_size. | full note
  • [Accounts] config |Add DataRightsDaoConfig to your Social config. | full note
  • [Accounts] config | Update the structure for defining public and private keys used for token decoding and signing. | full note
  • [Infra & Tooling] platform | Update the private key argument options for crypto remoteServiceToken. | full note
  • [Infra & Tooling] platform | If you’re using BaseServerIT::getServer, you’ll need to update the method calls. | full note
  • [Infra & Tooling] config | Configure nodes with gateways to point to Game/Social Session services. | full note
  • [Infra & Tooling] config | Contact your Pragma support representative when you update to 0.0.97 with a list of shards that interface with the engine. | full note
  • [Portal] portal | If you’re using a custom Portal configuration, update *.dirMatch to *.parentDirMatch. | full note

Patches #

  • [Portal] portal | If you’re using the Player Inventory tables and operations in the Portal, a patch needs to be applied after upgrading to 0.0.97. | full note

Bugs and Fixes #

  • Fixed incorrect logging parameters and messages in the PS4 and PS5 identity providers.
  • Fixed incorrect config parameters reported to the Portal causing Unsafe to always show in the Portal when it was enabled for authentication. The config value Portal uses to determine if the Unsafe login button is shown was incorrectly set to the canAuthenticate field. Now it’s been updated to the showPortalLoginButton config value.
  • Fixed all number inputs in the Portal to support larger Kotlin numbers to match the JavaScript maximum integer.
  • Fixed a bug in the Unreal SDK related to callbacks that were not properly unregistered on client logout or disconnect.

Docs #

  • [New Feature] Docs site versioning is now live! You can view documentation for a specific version by selecting the release number in the top right corner dropdown.
  • [New Tech Blog Article] The article Parties in the Platform: Enabling Backend Party Services is now live! This article overviews best practices for building a successful backend party feature and how Pragma Engine has built its Party service.
  • [New Concepts] New concepts section on Fleet Service.
  • [Updated Concepts] New section in SDK logging for Unreal on the Logging page.
  • [Updated Concepts] New section on SDK configuration for Unreal on the Configuration page.
  • [Updated Concepts] New section on S3 event storage on the Telemetry Plugin page.
  • [Updated Concepts] Added diagrams and a cross-play section to the Cross Platform Accounts page.
  • [Updated Concepts] Added diagrams and details to the Account Plugin page.
  • [Updated Concepts] Added additional details to the Accounts Overview page.
  • [Updated Concepts] Cleaned up the Player Groups page and added more details.
  • [Updated Tutorials] Updated the Crafting tutorial with up-to-date instructions and removed the out of date Crafting: Time-Based tutorial.


Full Notes #

Features #

[Multiplayer] New Fleet service works alongside the Match Capacity service. #

Description: We developed a new Fleet service that allows users to better manage their fleet of game servers. This service is intended to eventually replace the Match Capacity service, although both services are available for the time being.

Details: The Fleet service introduces the concept of server pools to manage homogenous groups of servers for different contexts. The Fleet service automatically manages game server capacity by server pool, based on defined management policies. With these features you no longer have to manually track capacity.

Related notes:

[Multiplayer] Pragma now supports managing game server fleet capabilities outside of Pragma. #

Description:You can choose to manage your game server capacity explicitly without using Pragma’s Fleet service or Match Capacity service.

Related notes: See integration note on managing game server capacity manually.

[Multiplayer] You can now host multiple game instances from a single game server. #

Description: To allow developers to host multiple game instances per server, we added a new parameter, maxGameInstanceCount, to the MatchApi.StartReportCapacityPolling function in the Unreal and Unity SDKs. We also added a new SDK function MatchApi.UpdateMaxGameInstanceCount(maxGameInstanceCount).

Details:

  • The MatchApi.StartReportCapacityPolling function now accepts a maxGameInstanceCount value to specify how many game instances the server can host. This value defaults to 1. If set higher than 1, Pragma Engine will allocate multiple game instances to host, up to the specified maxGameInstanceCount.
  • The new MatchApi.UpdateMaxGameInstanceCount(maxGameInstanceCount) function allows for a game server to reconfigure its max game instance count after report capacity polling has started.

[Player Data] All Inventory service plugins can now easily make service-to-service calls when determining player inventory changes. #

Description: All Inventory service plugin functions have been updated to suspend functions. This unblocks developers by no longer restricting custom Inventory service calls to be authored solely in Inventory service Plugins. For example, a custom service can now house a service call that influences decisions on item grants or updates, while previously that call needed to be authored in a plugin.

Related notes: See integration note on updating Inventory Service plugin functions.

[Accounts] You can change the keys used for token signing and verification without disrupting existing sessions or forcing users to reauthenticate. #

Description: You can now rotate keys by updating the TokenConfig. For more information, see Key Rotation.

Related notes: See the integration note on updating the structure for defining public and private keys.

[Accounts] For the Epic identity provider, you can now restrict access by game ownership. #

Description: You can now specify an Epic game ID or other catalog item that the user must own on their Epic account in order to authenticate with the Pragma Engine using the Epic identity provider. For more details, see the Identity Providers page.

Details: There are new config fields that can be set to enable game ownership validation. The new config field restrictByCatalogItemOwnership determines whether to reject users if they do not own the catalog item specified. If set to true, the following configs must be configured: sandboxId and catalogItemId.

[Infra & Tooling] Added platform command for generating JWT public and private keys. #

Description: A new command has been added to the platform command line underneath the cryptography tools. This new command generates and displays a Base64-encoded public and private key to be used in the public and private fields in the following config under jwtCurrentKeys. Note that this can be used in game or social.

game:
  serviceConfigs:
    TokenConfig:
      jwtCurrentKeys:
        public: "jwt-public-key"
        private: "jwt-private-key"

Details: You can run this through the pragma.jar with the following command:

java -jar pragma.jar crypto jwtkey

[Infra & Tooling] New Telemetry Plugin using S3 as event storage. #

Description: A new Telemetry Plugin has been added for the Telemetry service to write files to an S3 bucket based on the following naming scheme: <shard>/'yyyy/MM/dd/kk/<service-instance-id>/yyyyMMdd-kkmmss_SSS'.jsonl. You can learn more on the Telemetry Plugin concepts page.

Example:

game:
  pluginConfigs:
    TelemetryService.telemetryPlugin:
      class: "pragma.telemetry.s3.S3TelemetryPlugin"
      config:
        eventBatchSize: 10000
        timeWindowPerBatchMillis: 60000
        s3BucketName: "your-best-bucket"
        shardName: "your-best-shard-name"

[Infra & Tooling] A new version of the protoc-custom-plugins package has been integrated. #

Description: The Pragma Engine project depends on the protoc-custom-plugins package, which is a separate artifact that is publicly available. We now use v1.0.32.

[SDKs] Unreal: You can now exclude specific RPCs and notifications from being logged. #

Description: We’ve started excluding noisy Pragma RPCs and notifications by default. You can read more about how to reenable these logs in the SDK logging documentation.

[Portal] Added pagination to the account and player overview filter endpoints. #

Description: Each page in Portal will now request and load only the data it needs for the current page instead of loading the data for all the pages. When using the table sorts, it will sort only the values on the current page.

Details: Endpoints used for populating the landing overview pages for Social and Game portals now take in two additional parameters.

Related notes: See integration note on updating the endpoints used for retrieving account information.

[Portal] Operators can now log into Portal using the Epic identity provider. #

Description: To enable Portal login, you’ll need to supply an Epic clientId and clientSecret, as well as enable operator portal login by setting the following configs to true: showPortalLoginButton and operatorLoginEnabled. If you enable restrictByCatalogItemOwnership, you’ll need to configure the deploymentId field.

Example: Below is an example Epic Identity Provider config:

pluginConfigs:
  AccountService.identityProviderPlugins:
    plugins:
      Epic:
        class: "pragma.account.EpicIdentityProviderPlugin"
        config:
          clientId: "epic-client-id"
          clientSecret: "encrypted-epic-client-secret"
          redirectUri: "http://localhost:11200/v1/account/oauth-redirect/EPIC"
          showPortalLoginButton: true
          operatorLoginEnabled: true

Below is an example Epic Identity Provider config with restrictByCatalogItemOwnership enabled:

pluginConfigs:
  AccountService.identityProviderPlugins:
    plugins:
      Epic:
        class: "pragma.account.EpicIdentityProviderPlugin"
        config:
          restrictByCatalogItemOwnership: true
          deploymentId: "epic-deployment-id"
          sandboxId: "epic-sandbox-id"
          catalogItemId: "epic-catalog-item-id"

[Portal] Page Builder API now supports header components. #

Description: When defining a portlet page using the Builder API, Vue.js components can now also be added to the page header using the new page.addHeaderComponent method. This works just like page.addComponent, with the only difference that the component is added to the header instead of the body.

[Portal] Current annotated platform config now shown in the Development Tools section. #

Description: A new page has been added to the Development Tools section which shows the configuration of the engine node that the Portal is running on.

Deprecations #

[Multiplayer] sdk | MatchApi.ReleaseCapacity method deprecated in favor of MatchApi.ReportFreedCapacity. #

Description: The MatchApi.ReleaseCapacity SDK method has been deprecated in Pragma Engine version 0.0.97 in favor of MatchApi.ReportFreedCapacity. The new function name better communicates what the function does, which is to report to Pragma Engine that the game server has freed up a unit of game instance capacity. This method should be migrated before updating to version 0.0.98.

originalreplacement
MatchApi.ReleaseCapacity();MatchApi.ReportFreedCapacity();

Integrations #

[Multiplayer] sdk | Update GameLoopApi SDK methods and events related to parties and party players. #

Description: The GameLoopApi SDK methods and events in the following ‘Original’ column were deprecated and updated in version 0.0.96. The renames provide clarity around parties and party members now that the client interface has been aggregated to a single interaction point (GameLoopApi).

Integration step: sdk | If you haven’t already updated the values to reflect those in the ‘Replacement’ column, do so before updating to version 0.0.97.

GameLoopApi methods

Originalreplacement
GetPendingInvitesGetPendingPartyInvites
GetInviteByInviteIdGetPartyInviteByInviteId
GetInviteByInviterIdGetPartyInviteByInviterId
JoinWithInviteCodeJoinPartyWithInviteCode
JoinWithPartyIdJoinPartyWithId
SendInvite/CanSendInviteSendPartyInvite/CanSendPartyInvite
RespondToInvite/CanRespondToInviteRespondToPartyInvite/CanRespondToPartyInvite
KickPlayer/CanKickPlayerKickPlayerFromParty/CanKickPlayerFromParty
SetPreferredGameServerZones/CanSetPreferredGameServerZoneSetPartyPreferredGameServerZones/CanSetPartyPreferredGameServerZone
SetGameServerZoneToPing/CanSetGameServerZoneToPingSetPartyPlayerGameServerZoneToPing/CanSetPartyPlayerGameServerZoneToPing
SetReadyState/CanSetReadyStateSetPartyPlayerReady/CanSetPartyPlayerReady

GameLoopApi events

Originalreplacement
OnInviteCodeChangedOnPartyInviteCodeChanged
OnPreferredGameServerZonesChangedOnPartyPreferredGameServerZonesChanged
OnPartyJoinedOnJoinedParty
OnPartyLeftOnLeftParty
OnPlayerJoinedOnPlayerJoinedParty
OnPlayersChangedOnPartyPlayersChanged
OnPlayerChanged (Unreal)OnPartyPlayerDataChanged (Unreal)
OnPlayerDataChanged (Unity)OnPartyPlayerDataChanged (Unity)
OnPlayerLeftOnPlayerLeftParty
OnInvitesChangedOnPartyInvitesChanged
OnInviteReceivedOnPartyInviteReceived
OnInviteRevokedOnPartyInviteRevoked
OnInviteAcceptedOnPartyInviteAccepted
OnInviteDeclinedOnPartyInviteDeclined

[Multiplayer] sdk | Replace references to CanSetPartyPreferredGameServerZone with CanSetPartyPreferredGameServerZones. #

Description: We renamed GameLoopApi.CanSetPartyPreferredGameServerZone to CanSetPartyPreferredGameServerZones (added an ‘s’) to enforce continuity with the GameLoopApi.SetPartyPreferredGameServerZones method.

Integration step:

  • sdk | Replace references to the following:
    originalreplacement
    GameLoopApi.CanSetPartyPreferredGameServerZoneGameLoopApi.CanSetPartyPreferredGameServerZones

[Multiplayer] platform | (Optional) If using the Match Capacity test factory, reimport references to MatchCapacityProtoTestFactory with FleetProtoTestFactory. #

Description: We renamed the MatchCapacityProtoTestFactory.kt file to FleetProtoTestFactory.kt.

Integration step:

  • platform | If you’re using the MatchCapacityProtoTestFactory.kt file, reimport references to point to FleetProtoTestFactory.kt.
originalreplacement
MatchCapacityProtoTestFactoryFleetProtoTestFactory.kt

[Multiplayer] platform, sdk, config | (Optional) Manage game server fleet capabilities outside Pragma. #

Description: You can choose to manage your game server capacity explicitly without using Pragma’s Fleet service or Match Capacity service.

Integration steps:

  • platform | To prevent the Game Instance service from calling the Fleet service and/or Match Capacity service after a game instance is created, return null in the new GameInstanceHostPlugin.findHostForGameInstance method. Instead, use this method to integrate with your game server provider in order to allocate a game server for this game instance.
  • sdk | Do not allow game servers to poll to report their capacity. To request game start data for a known game instance, use the new MatchApi.RequestStartGame SDK method.
  • config | Add the following nodeByInstanceId to your configuration file. This configuration will tell Pragma to not create any instances of the Fleet service/Match Capacity service:
    • Fleet service configuration:
    game:
        core:
        distributedServices:
        FleetService:
            nodeByInstanceId:
            0: ~
    
    • Match Capacity service configuration:
    game:
    core:
        distributedServices:
        MatchCapacityService:
            nodeByInstanceId:
            0: ~
    

[Player Data] platform | If you’re using any Inventory service plugin, update the plugin’s functions so they have the suspend modifier. #

Description: All Inventory service plugin functions have been updated with the suspend modifier.

Integration step:

  • platform | Add the suspend modifier to all functions implemented by the following plugins:
    PluginFunction
    InstancedItemPluginnewInstanced, update, onDelete
    StackableItemPluginonUpdate
    CraftingPluginmeetsRequirements, craft
    StorePluginmeetsRequirements
    InventoryOperationsPlugingetInventoryOperationsFromMatchEnd
    LimitedGrantPluginshouldGrant

Related notes: See feature note on Inventory service plugins.

[Accounts] platform | If you call the filter endpoints for retrieving account and player information, you’ll now need to pass in two new additional values: page_index and page_size. #

Description: Endpoints used for populating the landing overview pages for Social and Game portals now take in two additional parameters:

  • page_index: page number starting at 0
  • page_size: number of items per page

Integration step:

  • platform | The following endpoints now require you to pass in a page_index and page_size:
  • GetPragmaAccountOverviewsOperatorV1Request
  • GetPragmaAccountOverviewsPartnerV1Request
  • GetPragmaAccountOverviewsServiceV1Request
  • GetPragmaPlayerOverviewsOperatorV1Request

[Accounts] config |Add DataRightsDaoConfig to your Social config. #

Description: This integration is required to enable an upcoming Accounts feature. Any existing configs must now also define the defaults for this DaoNode for the Pragma Engine to start up properly.

Integration step:

  • config | Under social add DataRightsDaoConfig:
social:
  serviceConfigs:
    DataRightsDaoConfig:
      databaseConfig:
        driver: "MYSQLDB"
        username: "superuser"
        password: "password"
        hostPortSchema: "localhost:3306/local_social_data_rights"

[Accounts] config | Update the structure for defining public and private keys used for token decoding and signing. #

Description: You’ll need to update the structure of your config for token decoding and signing. The public and private keys under jwtCurrentKeys must be a valid RSA key pair.

Integration step:

  • Replace your TokenDecoderConfig and TokenSignerConfig as follows:

    • Before:
    game:
      serviceConfigs:
        TokenDecoderConfig:
          jwtPublicKey: "RSA-public-key"
        TokenSignerConfig:
          jwtPrivateKey: "RSA-private-key"
    social:
      serviceConfigs:
        TokenDecoderConfig:
          jwtPublicKey: "RSA-public-key"
        TokenSignerConfig:
          jwtPrivateKey: "RSA-private-key"
          partnerExpirationHours: 876000
          operatorExpirationMinutes: 2880
          emailTokenExpirationMinutes: 10080
          playerTokenExpirationMinutes: 1440
          playerTokenRefreshMinutes: 45
          playerTokenRefreshVarianceWindowMinutes: 5
    
    • After:
    game:
      serviceConfigs:
        TokenConfig:
          jwtCurrentKeys:
            public: "RSA-public-key"
            private: "RSA-private-key"
    social:
      serviceConfigs:
        TokenConfig:
          jwtCurrentKeys:
            public: "RSA-public-key"
            private: "RSA-private-key"
          partnerExpirationHours: 876000
          operatorExpirationMinutes: 2880
          emailTokenExpirationMinutes: 10080
          playerTokenExpirationMinutes: 1440
          playerTokenRefreshMinutes: 45
          playerTokenRefreshVarianceWindowMinutes: 5
    

[Infra & Tooling] platform | Update the private key argument options for crypto remoteServiceToken. #

Description: A Pragma Engine command remoteServiceToken has changed–the private key argument options have been renamed. In addition, the public key now needs to be specified because the key ID is generated based on this key when signing tokens.

Integration steps:

  • platform | Rename the following private key option arguments:

    OriginalReplacement
    --key-base64--private-key-base64
    --key-base64-filepath--private-key-base64-filepath
    --key-filepath--private-key-filepath
  • This command now also requires a public key to be specified through one of the following new argument options:

    • --public-key-base64
    • --public-key-base64-filepath
    • --public-key-filepath

Related notes: See feature note on key rotation.

[Infra & Tooling] platform | If you’re using BaseServerIT::getServer, you’ll need to update the method calls. #

Description: The BaseServerIT::getServer which used to start both the Game and Social servers has been updated. Previously this method returned only the Game server. Now we have two separate methods:

  • BaseServerIT::startServers: starts the Game and Social servers
  • BaseServerIt::getServer: returns the started TestServer for the given config and backend type

Integration step:

  • platform | Migrate your BaseServerIT::getServer calls into the appropriate new methods:

    • Before:
    fun getServer(gameConfig: String, socialConfig: String, contentPath: String): TestServer
    
    • After:
    fun startServers(gameConfig: String, socialConfig: String, contentPath: String)
    
    fun getServer(config: String, type: BackendType): TestServer
    

[Infra & Tooling] config | Configure nodes with gateways to point to Game/Social Session services. #

Description: Gateways will now start on any Pragma node that has a corresponding configured Session service. The gatewayManager block in the config has been removed, and the Session services have been split into Game and Social versions.

Integration steps:

  • If you’re on managed infrastructure, reach out to us when you update to this release to ensure we have you on the updated configurations.
  • config | If you’re not on managed infrastructure:
    • Remove the gatewayManager block in the config.
    • Add the GameOperatorSessionService and SocialOperatorSessionService.
    • Make sure that every node that has a gateway is configured to have the corresponding Game or Social Session services instead. Nodes that do not have gateways should not have any Session service configured. See table below for renames:
      OriginalReplacement
      PlayerSessionServiceGamePlayerSessionService & SocialPlayerSessionService
      PartnerSessionServiceGamePartnerSessionService & SocialPartnerSessionService

[Infra & Tooling] config | Contact your Pragma support representative when you update to 0.0.97 with a list of shards that interface with the engine. #

Description: We’re adding an engine version field to shard config YAML files, so all shards that interface with the upgraded engine must be updated as well. If you’d like to keep a shard on a previous version, we won’t need to update that YAML file, and you can deploy a previous version.

Integration step:

  • config | Contact your Pragma support representative when you’re ready to update to this release version, and provide a list of shards for us to upgrade to the new version for you.

[Portal] portal | If you’re using a custom Portal configuration, update *.dirMatch to *.parentDirMatch. #

Description: This change allows for better control over which resources should be included in the final build, as the matchers are now tested against the whole relative path of a parent folder instead of just the folder name.

Integration step:

  • If you’re using a custom Portal configuration, update *.dirMatch to *.parentDirMatch in the Portal configuration file.

Patches #

[Portal] portal | If you’re using the Player Inventory tables and operations in the Portal, a patch needs to be applied after upgrading to 0.0.97. #

Description: This patch will fix the RPC calls that are made from the Portal in the Player Inventory pages, which after upgrading to 0.0.97 are using the wrong pragmaSocialId instead of the pragmaPlayerId.

Integration steps:

  • Apply the patch found in /pragmaplatform/pragma-patches/blob/main/patches/portal-inventory-0.0.97, using ./pragma patch install -n portal-inventory-0.0.97 -p 5-ext.
  • If you have custom Portal work, run make portal-package to repackage the Portal.
  • If you don’t have custom Portal work, run make portal-setup && make portal-package PROJECT=web.