Integrations and Deprecations 0.4.x #

This topic includes integrations and deprecations for Pragma Version 0.4.0.

Behavioral integrations #

This section describes changes in behavior due to new/updated functionality. Extra care should be taken when implementing changes to avoid unexpected behaviors or regressions.

Process change for engine pom.xml files #

If you modify pom files in the engine, you must make the mod in the pom.xml.template file and run an engine build. Changes made directly to pom.xml files will be overwritten by the generated template file and lost.

Run ./pragma build engine -s -m buildplan:list to test your pom file validity without waiting for an entire pragma engine build.

Syntax integrations #

This section describes changes in naming, file locations, and other syntactical updates.

New CLI #

This integration guide includes using the new tool to identify your 5-ext project and automatically configure itself. The integration steps below include regenerating your project pom files to adopt the new, simpler, Maven structure.

All instructions are run in git-bash from the platform dir:

cd pragma-engine/platform

Init pragma cli #

The following command will generate a project config file and update Maven pom files to the new structure:

./pragma update init-5-ext

Run the update script #

The following command will run a script specific to perform some integration steps automatically, such as generating new ext proto messages:

./pragma update 0-4-0

Reconcile 5-ext Maven files #

After initializing the CLI, your 5-ext pom files will be overwritten with the updated structure. Use a diff tool to compare your 5-ext pom files, keeping the new changes while restoring any intended modifications your team has made, such as additional lib dependencies or additional maven projects you’ve added.

We suggest adding engine mod start/end markers to your pom changes to help make future pom updates easier to reconcile.

Note: Do not restore any test-jar dependencies pointed at proto projects; these have been removed intentionally and will cause your build to fail if added.

Reconcile removed engine-settings.xml file #

If you modified the engine-setings.xml file, migrate your modifications to the top-level platform/pom.xml.template file.

Run ./pragma build engine-code -s to regenerate the pom.xml from the template and confirm the engine builds successfully.

Update custom/additional Maven projects #

If you have custom/additional Maven projects within your 5-ext project, follow these steps to update your project pom.xml files to the new structure:

  1. Update parent xml block in your pom.xml files:

    Old:

    <parent>
        <groupId>[company]</groupId>
        <artifactId>5-ext</artifactId>
        <version>${revision}</version>
    </parent>
    

    New:

    <parent>
        <groupId>[company_lower]</groupId>
        <artifactId>5-ext</artifactId>
        <version>[COMPANY_UPPER]-LOCAL-SNAPSHOT</version>
    </parent>
    

    Old:

    <version>DEFAULT-LOCAL-SNAPSHOT</version>
    

    New:

    <version>[COMPANY_UPPER]-LOCAL-SNAPSHOT</version>
    
  2. Add Maven profile files.

    The new structure relies on a named text file to trigger the correct build profile.

    Copy mvn-profile-engine from 5-ext/ext-server into your custom Maven project directories (next to the pom.xml for that project).

Complete the rest of your integration #

Once your project structure has been updated, proceed with the rest of your platform-side integrations. Once integration notes are complete, return here and follow the remaining steps to build and run.

Build your project to confirm changes #

Run these build steps in order to confirm all pom upgrades have been completed successfully

  1. ./pragma build engine-protos

  2. ./pragma build engine-code -s

  3. ./pragma build project-protos

  4. ./pragma build project-code

    Note: Use ./pragma build to rebuild your project on an ongoing basis. Use ./pragma build engine -s only when engine sources change.

  5. After successfully building on the command line, reload all Maven projects within Intellij and build the project within Intellij.

  6. Make sure the pragma-cli.ini file and updated pom files are checked in once the integration steps have been completed.

Adjust update-pragma-sdk.sh #

Make the following edits to your copy of the update-pragma-sdk.sh file:

Unreal:

Replace make gen-sdk-types-unreal4 with ./pragma sdk generate

Unity:

Replace make gen-sdk-types-unity with ./pragma sdk generate

Multiplayer integrations #

[Multiplayer] Update NewGameInstance construction #

To support creating a game instance directly from backend services, the NewGameInstance constructor now includes a ExtBackendCreateRequest parameter.

See the Migrate ExtGameInstance section of this deprecation note for instructions on migrating data from ExtGameInstance to the new ExtBackendCreateRequest.

If you do not want to migrate to the new ExtBackendCreateRequest yet, you can continue to provide the ExtGameInstance in the NewGameInstance constructor with a default ExtBackendCreateRequest, however this flow is deprecated and will be unavailable in a future release.

[Multiplayer] Migrate ExtGameParty data to the player and game instance data stores #

To support adding players to a game instance directly, we removed the ExtGameParty ext. Instead, define the data directly on the player and game instance data store.

In gameInstanceExt.proto:

  • Move data from ExtGameParty to ExtData, which defines data store information for game instances and their players
  • For ExtGameParty data created during matchmaking, put that data in the new ExtBackendCreateRequest and ExtBackendAddPlayer exts, as well as on ExtData.
  • Remove ExtGameParty

In your matchmaking plugin:

  • When creating a NewGameInstance or GameInstanceUpdate use the requestExt constructor parameter (ExtBackendCreateRequest), or the setExtForPlayer() method with ExtBackendAddPlayer. See the Matchmaking tasks for instructions and examples.
  • Remove calls to setExtGameParty()

In your game instance plugin:

  • Add data from ExtBackendCreateRequest and ExtBackendAddPlayer to the game instance and/or player data store. See the Create ExtData task for instructions and examples.

Before in gameInstanceExt.proto:

message ExtGameParty {
    int32 mmr_average = 1;
}

After in gameInstanceExt.proto:

message ExtData {
    oneof data {
        Map<Fixed128, int32> party_mmr_averages = 1;
    } 
}
message ExtBackendCreateRequest {
    Map<Fixed128, int32> party_mmr_averages = 1;
}
You can also choose to temporarily move data from ExtGameParty to ExtGamePlayer and ExtGameInstance, however these exts have been deprecated and will be removed in a future release.

[Multiplayer] Migrate ExtMatchmakingGameParty data to player or game instance exts #

To support adding players to a game instance directly, we removed the ExtMatchmakingGameParty ext. Instead, define the data on ExtMatchmakingGamePlayer or ExtMatchmakingGameInstance.

  1. Move ExtMatchmakingGameParty data to another ext:

    • Move player-specific data to ExtMatchmakingGamePlayer
    • Move game instance data to ExtMatchmakingGameInstance
    • Remove ExtMatchmakingGameParty from your matchmakingExt.proto file
  2. Update ext build and set methods:

    • Move player-specific data to buildExtMatchmakingGamePlayer()
    • Move game instance data to buildExtMatchmakingGameInstance()
    • Remove ExtMatchmakingGameParty from your matchmakingExt.proto file
    • Remove implementations of GameInstanceMatchmakingPlugin.buildExtMatchmakingGameParty()
    • Update buildExtMatchmakingGamePlayer(), as it no longer takes a GameInstance.GameParty parameter. Use the new GameInstance.getPlayersByPartyId() method to organize data by party ID.

[Multiplayer] Update references for new way of getting party information from game instances #

We removed the GameParty object from the GameInstance and Matchmaking interfaces. You can now access a list of players organized by party ID using the getPlayersByPartyId() method on the GameInstance and Matchmaking interfaces.

BeforeAfter
In your GameInstancePlugin:
GameInstance.parties
GameInstance.getPlayersByPartyId()
In your MatchmakingPlugin:
MatchmakingGameInstance.parties
MatchmakingGameInstance.getPlayersByPartyId()

[Multiplayer] Update service configs #

To account for game instance allocation improvements, do the following:

  • Replace references to GameInstanceServiceConfig.gameReadyTimeoutMillis with GameInstanceServiceConfig.gameServerAllocationTimeoutMillis (default: 3 minutes).

  • Replace references to GameInstanceServiceConfig.reconnect with GameInstanceServiceConfig.removePlayersOnDisconnect and provide a boolean value (default false) instead of a GameInstanceReconnect enum.

    • If previously using reconnect = GameInstanceReconnect.OFF, use removePlayersOnDisconnect = true
    • If previously using reconnect = GameInstanceReconnect.ON, use removePlayersOnDisconnect = false
    • If previously using reconnect = GameInstanceReconnect.OPTIONAL, use removePlayersOnDisconnect = false and continue using the deprecated client SDK GameInstanceApi.DeclineReconnect() method.
  • Optionally, override the default for GameInstanceServiceConfig.connectPlayersTimeoutMillis (default: 30 seconds)

[Multiplayer] Do not use GameServerPlayer SDK class to retrieve display names and social IDs #

To support adding players to a game instance directly, we removed the DisplayName, SocialId, and ClientVersion properties from the GameServerPlayer classes in the SDKs for Unreal and Unity, as fetching these values could become cumbersome.

To retrieve display names and social IDs, use PragmaAccountPartnerServiceRaw.GetPlayerIdentitiesPartnerV1() with the corresponding player IDs and shard ID.

[Multiplayer] Update references to renamed Matchmaking methods #

The following Matchmaking methods were renamed:

Previous methodNew method
Matchmaking.Matchable.findPlayer()Matchmaking.Matchable.getPlayer()
Matchmaking.GameInstance.findPlayer()Matchmaking.GameInstance.getPlayer()

[Multiplayer] Update metrics #

  • New GameInstance and PartyCache graphs were added to the Grafana Multiplayer dashboard.
  • The PartyCache metric uses a standard cashing system with built-in metrics, so the PartyCount method is no longer required.
  • The session lifespan metric type was changed from a distributed summary to a timer to better reflect the information being observed. In custom Grafana graphs change reference to pragma_session_lifespanOnTermination_bucket to pragma_session_lifespanOnTermination_seconds_bucket.

Reach out to Pragma to update your infrastructure to the latest version so you can receive the new graphs.

[Multiplayer] Add new multiplayer ext messages #

Define the following new protos in your gameInstanceExt.proto file:

/**
* Create payload for a game instance. Populated by game servers and/or backend services and used in
* [GameInstancePlugin.handleBackendCreateRequest].
*/
message ExtBackendCreateRequest {
}

/**
* Request payload when creating a game instance. Populated by game clients and used in [GameInstancePlugin.handlePlayerCreateRequest].
*/
message ExtPlayerCreateRequest {
}

/**
* Request payload when adding players to a game instance. Populated when using the [GameInstanceApi] and used in
* [GameInstancePlugin.handleBackendAddPlayersRequest].
*/
message ExtBackendAddPlayersRequest {
}

/**
 * Payload for a specific player sent on a request to add players to a game instance. Populated when using the [GameInstanceApi] and used
 * in the [GameInstancePlugin].
 */
message ExtBackendAddPlayer {
}

/**
* Request payload when joining a game instance. Populated by game clients and used in [GameInstancePlugin.handlePlayerJoinRequest].
*/
message ExtPlayerJoinGameInstanceRequest {
}

/**
* Request payload when removing players from a game instance. Populated by game servers or when using the [GameInstanceApi] and used in
* [GameInstancePlugin.handleBackendRemovePlayersRequest].
*/
message ExtBackendRemovePlayersRequest {

}
/**
* Payload for a specific player sent on a request to remove players from a game instance. Populated by game servers or when using the
* [GameInstanceApi] and used in the [GameInstancePlugin].
*/
message ExtBackendRemovePlayer {
}

/**
* Request payload when leaving a game instance. Populated by game clients and used in [GameInstancePlugin.handlePlayerLeaveRequest].
*/
message ExtPlayerLeaveRequest {
}

Define the following new protos in your partyRpcExt.proto file:

/**
* Update payload for a party. Populated when using the [PartyApi] and used in [PartyPlugin.handleBackendUpdateRequest].
*/
message ExtBackendUpdatePartyRequest {
}

Social integrations #

[Social] Change game server and backend presence calls to update rich presence by player ID #

We updated the MatchApi.SetRichPresence() and backend PresenceApi.SetRichPresence() methods to accept a player’s PlayerId instead of the SocialId.

Before MatchApi SDK

void SetRichPresence(
    const FString& SocialId,
    const FPragma_Presence_ExtRichPresenceBackendRequest& RichPresenceRequest,
    const FOnCompleteDelegate& OnComplete);

After MatchApi SDK

void SetRichPresence(
    const FString& PlayerId,
    const FPragma_Presence_ExtRichPresenceBackendRequest& RichPresenceRequest,
    const FOnCompleteDelegate& OnComplete);

Before PresenceApi.kt

class PresenceApi(
    private val service: Service,
) {
    suspend fun setRichPresence(
        socialId: SocialId,
        richPresenceRequest: ExtRichPresenceBackendRequest
    )
}

After PresenceApi.kt

class PresenceApi(
    private val service: Service,
) {
    suspend fun setRichPresence(
        playerId: PlayerId,
        richPresenceRequest: ExtRichPresenceBackendRequest
    )
}

Update references accordingly.

Engine integrations #

[Engine] Update any usages of PragmaClient’s APIs #

We have simplified PragmaClient’s APIs with the following version:

OriginalNew
makeGameRequest and gameRequestgameRequestV2: PragmaResult<Response, GeneratedMessageV3>
makeSocialRequest and socialRequestsocialRequestV2: PragmaResult<Response, GeneratedMessageV3>

Patch integrations #

This section describes integrations necessary for specific patches.

[0.4.3] Update handleBackendCreateRequest() and handleBackendAddPlayersRequest() to use new PlayerToAdd data class #

To provide the plugins with additional context about the new player being added, we created the PlayerToAdd data class.

Integration steps:

Update the following methods to use the updated playersToAdd parameter:

Originals

handleBackendCreateRequest(
   gameInstanceSnapshot:  
      GameInstance.GameInstance,
   requestExt: 
      ExtBackendCreateRequest,
   playersToAdd: Map<PlayerId, 
      ExtBackendAddPlayer>
)

handleBackendAddPlayersRequest(
   gameInstanceSnapshot: 
      GameInstance.GameInstance,
   requestExt: 
      ExtBackendAddPlayersRequest,
   playersToAdd: Map<PlayerId, 
      ExtBackendAddPlayer>
)

Replacements

handleBackendCreateRequest(
   gameInstanceSnapshot:  
      GameInstance.GameInstance,
   requestExt: 
      ExtBackendCreateRequest,
   playersToAdd: List<PlayerToAdd>
)

handleBackendAddPlayersRequest(
   gameInstanceSnapshot: 
      GameInstance.GameInstance,
   requestExt: 
      ExtBackendAddPlayersRequest,
   playersToAdd: List<PlayerToAdd>
)

Deprecations #

[Multiplayer] Migrate game instance and player data to data stores #

To streamline and consolidate game instance and game player data, we are deprecating the following exts in favor of using the data stores:

  • ExtAddedToGame
  • ExtGameInstance
  • ExtGamePlayer

Migrate ExtAddedToGame data:

  1. Move data from ExtAddedToGame to the GameInstance.GamePlayer’s data store

    Before:

    message ExtAddedToGame {
    string current_game_phase = 1;
    }
    

    After:

    message ExtData {
    oneof data {
        string current_game_phase = 1;
    }
    }
    
  2. Populate the player’s data store using a Game Instance Plugin method, depending on how the player is entering the game instance.

    For example, instead of using the buildExtAddedToGame() method, set the relevant data on the game instance ExtData when creating the game instance from matchmaking:

    Before:

    CustomGameInstancePlugin.kt
    
    override suspend fun buildExtAddedToGame(
        gameInstanceSnapshot: GameInstance.GameInstance,
        player: GamePlayer
    ): ExtAddedToGame {
        val ext: ExtGameInstance = gameInstanceSnapshot.ext
        return ExtAddedToGame.newBuilder()
            .setCurrentGamePhase(ext.gamePhase)
            .build()
    }
    

    After:

    CustomGameInstancePlugin.kt
    
    override suspend fun handleBackendCreateByMatchmakingRequest(
        gameInstanceSnapshot: GameInstance.GameInstance,
    ) {
        val phaseExtData = ExtData.newBuilder()
            .setCurrentGamePhase(BEGIN_GAME_PHASE).build()
    
        gameInstanceSnapshot.dataStore
            .create("game_phase", phaseExtData , PlayerSync.Public)
    }
    
  3. Remove your GameInstancePlugin’s buildExtAddedToGame() implementation.

Migrate ExtGameInstance data:

Previously, you populated ExtGameInstance in matchmaking and then Pragma Engine automatically stored it on the newly created game instance. Now, do the following:

  1. Send game instance data from matchmaking to a new game instance via the ExtBackendCreateRequest when constructing a NewGameInstance.
  2. Store data that should persist for the life of the game instance on the game instance’s data store by defining the data in the ExtData proto.

For example, when creating a NewGameInstance from the matchmaking plugin:

val newGameInstance = NewGameInstance(
    requestExt = ExtBackendCreateRequest.getDefaultInstance(),
    gameServerZone = "North America"
)
The deprecated ext is still the first argument of the NewGameInstance constructor. Make sure you name your parameters to ensure you’re correctly providing the ExtBackendCreateRequest.

See also: Match parties

Migrate ExtGamePlayer data:

Previously, you populated ExtGamePlayer in matchmaking and then Pragma Engine automatically stored it on the newly created game instance. Now, do the following:

  1. Send game player data from matchmaking to a game instance via ExtBackendAddPlayer when adding a player to a game instance.
  2. Store data that should persist for the duration of the player’s time in the game instance on the player’s data store by defining the data in the ExtData proto.

For example, when adding a player to a game instance from the matchmaking plugin:

val newGameInstance = NewGameInstance(...)
newGameInstance.addParties(anchor.parties)

for (player in anchor.players) {
    newGameInstance.setExtForPlayer(player, ExtBackendAddPlayer.newBuilder().build)   
}

[Multiplayer] Use the new PartyApi.update() method instead of the Party plugin returnFromGameInstance() method to update party data from a game instance #

To streamline updating party data, you can now use the new PartyApi.kt class update() method. The Party plugin returnFromGameInstance() method, which was used to update party data when a game instance ends, has been deprecated. Now, to update end-of-game-instance data, have the GameInstancePlugin.onEndGame() method invoke the PartyApi.update() method with the ExtBackendUpdatePartyRequest payload.

Integration steps:

  1. Define ExtBackendUpdatePartyRequest to include information previously present in the returnFromGameInstance() call.
  2. Remove the PartyPlugin.returnFromGameInstance() override and migrate functionality to PartyPlugin.handleBackendUpdateRequest().
  3. Change GameInstancePlugin.onEndGame() to call PartyApi.update() with the ExtBackendUpdatePartyRequest.

The returnFromGameInstance() method is expected to be removed in version 0.6.0.

[Multiplayer] Replace decline reconnect methods and listeners #

To better reflect actions taken, we’ve deprecated the following methods and events related to declining reconnections:

  • The server SDK OnPlayerDeclinedReconnect event has been deprecated in favor of OnPlayersRemove
  • The client SDK GameInstanceApi.DeclineReconnect() method has been deprecated in favor of GameInstanceApi.Leave()

Updating to the new event and method should be done in sync to avoid duplicated events.

[Multiplayer] Replace OnAddPlayers listeners with OnPlayersAdded #

We deprecated the Match API OnAddPlayers event and replaced it with the OnPlayersAdded event to maintain consistent naming across events. We recommend you replace occurrences of OnAddPlayers with OnPlayersAdded in your code.

The OnAddPlayers event is expected to be removed in version 0.5.0.

[Multiplayer] Update use of Match API RemovePlayers() method to use new ext #

We deprecated the MatchApi.RemovePlayers() method that accepts the ExtRemovePlayersRequest payload in favor of a RemovePlayers() method that accepts the ExtBackendRemovePlayersRequest payload. This decision was made to better align the Match API method with the backend APIs that accept the ExtBackendRemovePlayersRequest.

Deprecated MatchApi.RemovePlayers():

public void RemovePlayers(
    PragmaId gameInstanceId,
    IEnumerable<PlayerToRemove> players,
    ExtRemovePlayersRequest ext,
    CompleteDelegate onComplete)

New MatchApi.RemovePlayers():

public void RemovePlayers(
    PragmaId gameInstanceId,
    IEnumerable<BackendPlayerToRemove> players,
    ExtBackendRemovePlayersRequest ext,
    CompleteDelegate onComplete)

[Social] Update references of methods in the SocialBackendPartnerClientNodeService class #

The request RPC methods in the SocialBackendPartnerClientNodeService class are being deprecated in favor of two new methods with clearer naming and method signatures. The new methods perform the same request to the social backend as the old methods.

OriginalNew
requestRpcmakeSocialRequest
requestRpcV2makeSocialRequestV2

[Portal] Portal component library version updated to latest major version #

We are upgrading the ant-design-vue library version 3.2.6 to the latest major version 4.2.1 for improved styling and customization options.

Integration steps:

  1. Run the following command in the terminal from the platform directory to install new required packages:

    ./pragma portal setup
    
  2. Any custom Pragma Portlets or custom components that use Ant Design components may need to be updated. Reference the Ant Design version 4 migration guide for more details.

  3. Use LESS variables instead of CSS variables.

    Before (CSS variable) color: var(–primary);

    After (LESS variable) color: @colorPrimary;

    • If you are currently using .css files for styling of custom components change the file extension to .less. Pragma will automatically compile the file into CSS as part of the build process.
    • CSS variables are scheduled to be removed in Pragma Version 0.5.0.