Pragma Engine 0.0.90

January 13, 2023

Changes from 0.0.89 have been integrated into this release.

Features #

The updated Matchmaking service is live! #

Description: Our new version of the Matchmaking service currently supports the same features as the previous iteration, but with easier ways to write core matchmaking logic in the plugin, and improved implementation for custom games and other game types that don’t require matching with incoming parties. We’ll continue to add new functionality to this service.

Related note: See Docs note on the new Matchmaking page.

You can now send an idempotency key on the Apply Inventory Operations endpoints to ensure the data operations are applied only once. #

Description: These Apply Inventory Operations endpoints include:

  • InventoryRpc.ApplyInventoryOperationsOperatorV1Request
  • InventoryRpc.ApplyInventoryOperationsPartnerV1Request
  • InventoryRpc.ApplyInventoryOperationsServiceV1Request If you assign an idempotency key, all Apply Inventory Operations’ requests with DataOperations will only be applied to the player one time. All following requests with the same idempotency key will do nothing and return an empty response.

You can now return a null ExtInstancedItem in the InstancedItemPluginResult. #

Description: The update to InstancedItemPluginResult now allows you to return a null on the ExtInstancedItem field. This allows for a lot more flexibility and control of instanced item creation and updating.

You can now set a time window on limited grants. #

Description: This allows you to define a limited grant that will only be granted to a player within a specified time window.

Related note: See related Docs note on the Limited Grant tutorial.

Game client inventory is now updated automatically when player inventory is changed. #

Description: Game client inventory is now updated automatically when player inventory is changed using Operator, Partner, or Service inventory endpoints. The existing Pragma Engine InventoryService.OnInventoryUpdated notifications on both Unreal and Unity SDKs are broadcast when updates are received.

Added a new Service endpoint for deleting a player’s inventory. #

Description: Services can now delete player inventories by using the new endpoint DeletePlayerInventoryServiceV1Request. Note that this functionality already existed as a Player endpoint, and is now additionally available as a Service endpoint.

Added a new annotate command to output fully resolved Pragma Engine configurations. #

Description: A new annotate command has been added to the pragma.jar to enable viewing the fully resolved configuration.

For more information, run the following command:

java -jar 5-ext/target/pragma.jar config annotate --help

Example: The following command returns a full output of the configurations annotated with the source file that the values originated from.

java -jar 5-ext/target/pragma.jar config annotate --backend-type game --configuration-filepaths config/dev-defaults.yml,5-ext/config/dev.yml,5-ext/config/common.yml,5-ext/config/local-dev.yml

SDKs: You can now specify Partner Session Authentication Tokens via an SDK’s command line. #

Description: Specifying Partner Session Authentication Tokens for game servers can now be done during your SDK app startup. Before this feature, users had to put partner tokens into a config file. Users can now specify those tokens via the SDK command line.

PragmaPartnerSessionSocialAuthToken="<social token>"
PragmaPartnerSessionGameAuthToken="<game token>"

Jobs in the Dependent Job Incoming Queue Length graph in Grafana are now split into subsets of jobs. #

Description: In the Dependent Job Incoming Queue Length graph in Grafana, jobs are now split into subsets of jobs specified by a group identifier. This new group argument can be added to pragma.jobs.runAsDependentJobs; existing usages can be updated to use this feature.

SDKs: You can now reuse a game server for multiple matches by releasing the capacity of the MatchCapacityService after match completion. #

Description: When calling ReleaseCapacity, the MatchCapacity service sets the used capacity to 0, which is then reported to Pragma Engine in the ReportCapacity poll. To reuse this game server state, pass in the OnComplete handler that was used in the StartReportCapacityPolling call.

void UPragmaMatchCapacityService::ReleaseCapacity(const FMatchAllocatedDelegate& OnComplete)

TFuture<TPragmaResult<FPragma_MatchLifecycle_MatchDataV2>> UPragmaMatchCapacityService::ReleaseCapacity()
public void ReleaseCapacity(MatchAllocatedDelegate onComplete)

public void ReleaseCapacity(MatchAllocatedDelegate onComplete)

Unreal SDK: You can now override Pragma.ini’s location via the Unreal SDK’s command line. #

Description: The Pragma.ini configuration file can now be specified in a command line instead of hardcoded to its specific destination. Make sure that you specify a filename and include the .ini extension when changing the file’s location.

PragmaIni="path/to/pragma.ini"

Unreal SDK: Added future version to the StartReportCapacityPolling function. #

Description: To maintain consistency with SDKs having both callback and future versions of async functions, we’ve added a version of the StartReportCapacityPolling function that returns a future alongside the existing version of the function that takes in a callback.

Example: UPragmaMatchCapacityService:

TFuture<TPragmaResult<FPragma_MatchLifecycle_MatchDataV2>> UPragmaMatchCapacityService::StartReportCapacityPolling(FString ServerId, FString GameVersion, FString GameServerZone, float Timeout)

Unreal SDK: New HasSession() method added to Pragma Subsystems. #

Description: You can now check if Pragma Engine has been initialized without needing to hit the assert inside GetSession(). Use the new HasSession() method on Pragma LocalPlayer and GameServer Subsystems instead.

Unreal SDK: Program type Unreal apps can now be used without an engine dependency. #

Description: The PragmaSDK module no longer has an engine module dependency, which means it can be built by Unreal apps that don’t depend on it. Engine-dependent functionality is now in PragmaSDKAux, so if you’re using Subsystems or are planning on future engine-dependent code, you’ll need to include that module in your dependency list. Related note: See related Integration note about the PragmaSDKAux dependency.

Portal: Added Tree view alongside Rich and Raw views in Content Catalogs. #

Description: We’ve added a structured JSON editor under the Tree tab on the Content Catalogs page. This editor includes several formatting tools, such as sort, transform, and duplicate.

Portal: Content Catalogs Editor now enabled by default. #

Description: The Content Catalogs Editor portlet is now enabled by default. Adding 4: null to your config will disable this portlet.

game:
  pluginConfigs:
    GameOperatorGatewayNodeService.portalPlugin:
      class: "pragma.gateway.FilePortalModulePlugin"
      config:
        modules:
          4: null

Deprecations #

Replace GrantItemsPartnerV1, DestroyItemsPartnerV1, DestroyItemsServiceV1, and GetInventoryPartnerV1 with their newer versions. #

Description: The GrantItemsPartnerV1, DestroyItemsPartnerV1, DestroyItemsServiceV1, and GetInventoryPartnerV1 endpoints weren’t filtering content into hidden vs player-facing inventory items, which meant game servers could be sent hidden inventory. The responses for these endpoints are now filtered into a ServiceUpdateItemsResponse with two UpdateItemsResponses, one for hidden inventory and one for player-visible items.

Replace the request and response calls for the following endpoints with their newer versions by release 0.0.90. Note that you can use the separate updates.hidden and updates.player to access filtered data.

originalreplacementremoval release
GrantItemsPartnerV1GrantItemsPartnerV20.0.91
DestroyItemsPartnerV1DestroyItemsPartnerV20.0.91
DestroyItemsServiceV1DestroyItemsServiceV20.0.91
GetInventoryPartnerV1GetInventoryPartnerV20.0.91

Unity SDK: Switch to using the cached inventory returned by InventoryService.GetInventory. #

Description: Unity SDK developers need to switch to using cached inventory returned by InventoryService.GetInventory, or force the cache to update and use the result returned to the callback provided to the new InventoryServiceForceGetInventory. To find stackable and instanced inventory within this data, you can subscribe an event handler to InventoryService.OnInventoryUpdated.

Replace usages of InventoryService.GetInventoryV2 with InventoryService.GetInventory. If you require the client to forcibly refresh itself, you can use InventoryService.ForceGetInventory.

originalreplacementremoval release
InventoryService.GetInventoryV2InventoryService.GetInventory0.0.91

Integrations #

Update unit tests to be compatible with the JUnit upgrade. #

Description: We’ve upgraded JUnit from version 5.6.2 to 5.9.1 to take advantage of some new test parallelization features. As a result, you may need to make changes to some of your unit tests.

Integration steps:

  • Remove the private modifier from @BeforeEach/@AfterEach/@BeforeAll/@AfterAll methods in your unit tests.
  • If you’re using @BeforeEach/@AfterEach/@BeforeAll/@AfterAll methods with inheritance, you may need to make some changes to preserve intended behavior due to a bugfix.

Update unit tests because they now run in parallel. #

Description: Tests now run in parallel by default in order to shorten build times. This affects tests running via make/mvn and IntelliJ.

Integration steps: Some tests may not be compatible with parallelization.

  • Use @ResourceLock to prevent multiple tests from using a particular resource simultaneously.
    • Example: Tests that use Ktor’s withTestApplication do not interact well with parallelization and should use a @ResourceLock(Resources.KTOR_TEST) annotation to ensure only one is run at a time.
  • Use @Isolated to ensure a test runs entirely alone.
    • Example: Any tests that use mockkStatic should use @Isolated.
  • Using delays in integration tests is more dangerous with parallelization. Use the new TestUtils.repeatUntilSuccess function instead of hardcoded sleeps to make your tests more robust.
  • maven-surefire-plugin often reports incorrect numbers of tests run in each class (this is a known issue).

Update your usage of the PartyTestFactory. #

Description: The party() and partyWithPlayers() methods have been combined. The new method is named party() and preserves the functionality of both methods.

Integration steps:

  • Replace usages of partyWithPlayers() with party().
  • If you’re using party() and want a party with zero players, pass in numPlayers = 0.

Copy your Social node’s configuration for TokenSignerConfig into the Game node configuration. #

Description: Pragma Engine can now send Partner game tokens to Nomad game servers on startup. To enable this, Game node configurations now require a TokenSignerConfig.

Integration step: Copy the existing configuration from social.serviceConfigs.TokenSignerConfig and create a new entry at game.serviceConfigs.TokenSignerConfig.

game:
    serviceConfigs:
        TokenSignerConfig:
            jwtPrivateKey: "myPrivateKey"

If you’re using Nomad as a capacity provider, the config for the PragmaNomadCapacityProvider needs to be updated to use jobDatacenter instead of jobName. #

Description: To support the Nomad changes that improve the capacity provider flow, you need to update the config as we move towards a simpler pattern for spawning jobs.

Integration step: If you’re using Nomad as a capacity provider, the config for the matchcapacity.PragmaNomadCapacityProvider needs to be updated to use jobDatacenter instead of jobName. You’ll also need to remove -exec from the config value.

Self-hosted customers will need to upgrade their environments using the following Terraform module: internal-shard-with-nomad-v5. Managed customers should reach out to Pragma for support for this change. #

Description: Partner tokens no longer need to be encoded into Nomad game binaries, because the Nomad capacity provider now sends them automatically on addCapacity calls–this change requires an update to the Nomad infrastructure. The game server shell invocation script is invoked by Nomad with the following command line parameters: PragmaPartnerSessionSocialAuthToken and PragmaPartnerSessionGameAuthToken. The SDK prioritizes these over values set in Pragma.ini files.

Integration step: Terraform environments must be upgraded using the following shared Terraform module: internal-shard-with-nomad-v5. You won’t be able to use your Nomad provider until this integration is complete. Managed customers should reach out to their Pragma support team to have this work completed.

If you’re using the token refresh feature for the Discord ID provider, reach out to your support representative. #

Description: To simplify the extra features on supported ID providers, we’ve removed the following endpoints: /v1/account/discord-token-refresh & discordTokenRefreshV1.

Integration step: If you’re using the token refresh feature for the Discord ID provider, reach out to your support representative.

If your game is integrated with the Inventory service, you need to assign a value to InventoryCacheConfig. #

Description: The Inventory service now runs a sweep of the cache in the background to help with the eviction logic for the Inventory service cache. We have added configurations around the frequency and requirements to evict.

Integration steps:

  • Assign an InventoryCacheConfig under InventoryServiceConfig for all deployed environments. The following parameters must be assigned values: sizeBeforeExpirationEnforced, maxTimeBetweenAccessMillis, and sweepIntervalMillis. We have provided local/dev defaults under pragma-engine/platform/config/dev-defaults.yml, but must be manually set for all other environments.
  • We recommend using the values in the example below. If you’re currently integrated with the Inventory service and running playtests with over 10,000 players, please reach out to Pragma for support.

Example: Config under game:

InventoryServiceConfig:
	inventoryCacheConfig:
		sizeBeforeExpirationEnforced: 10000
		maxTimeBetweenAccessMillis: 720000
		sweepIntervalMillis: 900000

If you’re returning instancedItemGrants from InventoryOperationsPlugin.InventoryOperations, you need to update server type. #

Description: The return result from InventoryOperationsPlugin.getInventoryOperationsFromMatchEnd() no longer has a field for InstancedItemGrants.

Integration step: Convert from InstancedItemGrant to InstancedItemServerGrant in your plugin implementation.

If you’re not using Pragma Engine’s SDK’s game servers and you’re using the Keep Alive feature, you must configure the Keep Alive interval. #

Description: The Keep Alive feature is now enabled by default, so a Keep Alive interval must be set. Game servers using Pragma Engine’s SDKs will do this automatically.

Integration step: If MatchReadyV2Response.enable_keep_alive is set to true, a MatchKeepAliveV1Request must be sent from the game server on an interval defined by MatchReadyV2Response.keep_alive_interval_millis.

Related note: See Docs note on the Keep Alive feature.

If you want to use match reconnect, you must set SessionConfig.enableMatchReconnect to true. #

Description: To simplify the basic match loop setup, the default value for enableMatchReconnect has been changed to false. If you had match connect implemented already, you will need to reenable it in the config.

**Integration step:**To enable match reconnect, make sure match reconnect SDK handlers are implemented, and then enable match reconnect functionality in your configuration for that environment.

game:
  core:
    session:
      enableMatchReconnect: true

If you’re using the version properties endpoint in /v1/info, you’ll need to update it to platformVersion. #

Description: We’ve added version properties to /v1/info for each artifact type (platformVersion, portalVersion, contentVersion, and configVersion).

Integration step: If you’re using the version properties endpoint in /v1/info, you need to update it to platformVersion.

originalreplacement
versionplatformVersion

Unreal SDK: If you use the ErrorCode result of the LogIn method, you’ll need to update your code to reference enum errors instead of the previous strings. #

Description: The LogIn method was originally written before the SDK began using enum errors, and therefore used arbitrary strings. With this change, UAccountService::LogIn uses EPragma_SdkError enum values like Unauthorized, PlatformUnavailable, and AlreadyLoggedIn instead of those strings.

Integration step: If you use the ErrorCode result of UAccountService::LogIn, the string value has changed. See the EPragma_SdkError enum for possible errors–UAccountService::LoginError_* strings have been removed.

New strings will look like: EPragma_SdkError::PlatformUnavailable. You can also use the enum itself by using Result.Error() instead of Result.ErrorCode().

Unreal SDK: Update references to PartyService.ResetParty to expect a return value of void instead of a boolean. #

Description: The ResetParty function no longer returns a boolean indicating whether the function actually reset the party. This change was made to simplify some internal code around changing party state. The function still guarantees that the party state is reset every time it is called. Note that the corresponding ForceReset function was changed to return void instead of a boolean, but this was for internal code and should not cause errors, so please let us know if this change impacts you.

Integration step: Update references to PartyService.ResetParty to expect a return value of void instead of a boolean.

Unreal SDK: Update references to the listed renamed Inventory service calls. See included table for details. #

Description: We’ve renamed/removed several Inventory service calls for clarity.

Integration step: Update references to the listed renamed Inventory service calls.

originalreplacement
UPragmaInventoryService::GetInstancedItemsV1 UPragmaInventoryService::GetStackableItemsV1UPragmaInventoryService::GetInventory: You can see the instanced and stackable items within the response of this call.
UPragmaInventoryService::GetInventoryV1UPragmaInventoryService::GetInventory
UPragmaInventoryService::DeletePlayerInventoryV2UPragmaInventoryService::DeletePlayerInventory

Unreal SDK: Add the PragmaSDKAux dependency to any [ProjectName].Build.cs files that depend on PragmaSDK. #

Description: The Unreal SDK has been split into two modules so you will need to add the new module to project dependencies.

Integration step: Add the PragmaSDKAux dependency to any [ProjectName].Build.cs files that depend on PragmaSDK.

Example:

  • Before: PrivateDependencyModuleNames.AddRange(new string[] { "PragmaSDK"});
  • After: PrivateDependencyModuleNames.AddRange(new string[] { "PragmaSDK", "PragmaSDKAux" });

Related note: See related Feature note about Program type apps.

Portal: Add the previously hard-coded authentication config values into your YAML file. #

Description: The Portal plugin FilePortalModulePlugin previously used hard-coded Pragma-specific app information used by Portal for authentication, for the Google, Discord, and Twitch client IDs. These have been moved to dev-defaults.yml. This means anyone running Pragma Engine locally will still be able to authenticate to the Portal using Pragma Engine apps, but production environments will need to separately specify these config values.

Integration step: Add in the proper config values for authentication in your shard- or common.yml files. An example can be found below or in the platform/config/dev-defaults.yml file.

If you’re using your own app credentials for Portal authentication, you should be unaffected.

Example:

game:
  pluginConfigs:
    GameOperatorGatewayNodeService.portalPlugin:
      class: "pragma.gateway.FilePortalModulePlugin"
      config:
        authenticationIdProviders:
          1: UNSAFE
        discordClientId: ""
        googleClientId: ""
        twitchClientId: ""
...

social:
  pluginConfigs:
    SocialOperatorGatewayNodeService.portalPlugin:
      class: "pragma.gateway.FilePortalModulePlugin"
      config:
        authenticationIdProviders:
          1: UNSAFE
        discordClientId: ""
        googleClientId: ""
        twitchClientId: ""
...

Bugs and Fixes #

  • Stopped onComplete callbacks for various functions being executed before inventory update events are fired in the Inventory SDK.

  • Unreal SDK: Fixed a bug where the Disconnect event would not be fired when both sockets were considered Degraded and the full disconnect timer had elapsed.

Docs #